From b91f48ced232c5bbc299eef6740d45c3659c4859 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 27 Aug 2014 18:41:48 -0700 Subject: [PATCH] Call handle_error even when error occurs exactly where expected Previously, if an error happened right at the beginning of an error production, the error node would be immediately shifted onto the stack without calling the error handling function. --- spec/runtime/languages/json/errors.txt | 2 +- src/runtime/parser.c | 38 +++++++++++++++----------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/spec/runtime/languages/json/errors.txt b/spec/runtime/languages/json/errors.txt index 2acf95bd..2ecd6327 100644 --- a/spec/runtime/languages/json/errors.txt +++ b/spec/runtime/languages/json/errors.txt @@ -3,7 +3,7 @@ recovers from top-level errors ========================================== [} --- -(ERROR '}') (ERROR '}') +(ERROR '}') ========================================== recovers from unexpected tokens diff --git a/src/runtime/parser.c b/src/runtime/parser.c index c1ca2efb..8a3f7536 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -135,6 +135,21 @@ static int handle_error(TSParser *parser) { for (;;) { + /* + * If there is no state in the stack for which we can recover with the + * current lookahead token, advance to the next token. If no characters + * were consumed, advance the lexer to the next character. + */ + size_t prev_position = ts_lexer_position(&parser->lexer); + lex(parser, ts_lex_state_error); + if (ts_lexer_position(&parser->lexer) == prev_position) + if (!ts_lexer_advance(&parser->lexer)) { + DEBUG_PARSE("FAIL TO RECOVER"); + ts_stack_push(&parser->stack, 0, error); + ts_tree_release(error); + return 0; + } + /* * Unwind the parse stack until a state is found in which an error is * expected and the current lookahead token is expected afterwards. @@ -158,20 +173,6 @@ static int handle_error(TSParser *parser) { } } } - - /* - * If there is no state in the stack for which we can recover with the - * current lookahead token, advance to the next token. If no characters - * were consumed, advance the lexer to the next character. - */ - size_t prev_position = ts_lexer_position(&parser->lexer); - lex(parser, ts_lex_state_error); - if (ts_lexer_position(&parser->lexer) == prev_position) - if (!ts_lexer_advance(&parser->lexer)) { - ts_stack_push(&parser->stack, 0, error); - ts_tree_release(error); - return 0; - } } } @@ -227,8 +228,13 @@ const TSTree *ts_parser_parse(TSParser *parser, TSInput input, switch (action.type) { case TSParseActionTypeShift: - DEBUG_PARSE("SHIFT %d", action.data.to_state); - shift(parser, action.data.to_state); + if (parser->lookahead->symbol == ts_builtin_sym_error) { + if (!handle_error(parser)) + return get_root(parser); + } else { + DEBUG_PARSE("SHIFT %d", action.data.to_state); + shift(parser, action.data.to_state); + } break; case TSParseActionTypeShiftExtra: