Fix bug in parser error handling
This commit is contained in:
parent
4541332c2b
commit
df223d566e
3 changed files with 24 additions and 14 deletions
|
|
@ -45,7 +45,6 @@ typedef struct {
|
|||
ts_state lex_state;
|
||||
ts_stack_entry *stack;
|
||||
size_t stack_size;
|
||||
ts_tree *result;
|
||||
} ts_parser;
|
||||
|
||||
static void ts_lex(ts_parser *parser);
|
||||
|
|
@ -58,7 +57,6 @@ static ts_parser ts_parser_make(const char *input) {
|
|||
.lex_state = 0,
|
||||
.stack = calloc(INITIAL_STACK_SIZE, sizeof(ts_stack_entry)),
|
||||
.stack_size = 0,
|
||||
.result = NULL,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
|
@ -123,7 +121,7 @@ static void ts_parser_reduce(ts_parser *parser, ts_symbol symbol, int immediate_
|
|||
|
||||
static void ts_parser_advance(ts_parser *parser, ts_state lex_state) {
|
||||
DEBUG_LEX("character: '%c' \n", ts_parser_lookahead_char(parser));
|
||||
if (ts_parser_lookahead_char(parser) != '\0')
|
||||
if (ts_parser_lookahead_char(parser))
|
||||
parser->position++;
|
||||
parser->lex_state = lex_state;
|
||||
}
|
||||
|
|
@ -143,14 +141,11 @@ static void ts_parser_skip_whitespace(ts_parser *parser) {
|
|||
parser->position++;
|
||||
}
|
||||
|
||||
static void ts_parser_handle_error(ts_parser *parser, size_t count, const ts_symbol *expected_symbols) {
|
||||
if (parser->error_mode) {
|
||||
parser->lex_state = ts_lex_state_error;
|
||||
ts_lex(parser);
|
||||
} else {
|
||||
parser->error_mode = 1;
|
||||
parser->lookahead_node = ts_tree_make_error(ts_parser_lookahead_char(parser), count, expected_symbols);
|
||||
}
|
||||
static int ts_parser_handle_error(ts_parser *parser, size_t count, const ts_symbol *expected_symbols) {
|
||||
parser->error_mode = 1;
|
||||
ts_tree *error = ts_tree_make_error(ts_parser_lookahead_char(parser), count, expected_symbols);
|
||||
parser->stack[0].node = error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma mark - DSL
|
||||
|
|
@ -220,9 +215,12 @@ goto next_state; \
|
|||
|
||||
#define PARSE_ERROR(count, inputs) \
|
||||
{ \
|
||||
static const ts_symbol expected_inputs[] = inputs; \
|
||||
ts_parser_handle_error(parser, count, expected_inputs); \
|
||||
goto next_state; \
|
||||
static const ts_symbol expected_inputs[] = inputs; \
|
||||
if (ts_parser_handle_error(parser, count, expected_inputs)) { \
|
||||
goto next_state; \
|
||||
} else { \
|
||||
goto done; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LEX_PANIC() \
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ describe("json", []() {
|
|||
ts_document_set_text(doc, "[1, 2, 3]");
|
||||
AssertThat(string(ts_document_string(doc)), Equals("(value (array (value (number)) (value (number)) (value (number))))"));
|
||||
});
|
||||
|
||||
describe("errors", [&]() {
|
||||
it("reports errors in the top-level node", [&]() {
|
||||
ts_document_set_text(doc, "[");
|
||||
AssertThat(string(ts_document_string(doc)), Equals("(ERROR)"));
|
||||
|
||||
ts_document_set_text(doc, "{ \"key1\": 1, ");
|
||||
AssertThat(string(ts_document_string(doc)), Equals("(ERROR)"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
END_TEST
|
||||
|
|
@ -33,6 +33,7 @@ ts_tree * ts_tree_make_node(ts_symbol symbol, size_t child_count, ts_tree **chil
|
|||
|
||||
ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs) {
|
||||
ts_tree *result = new ts_tree();
|
||||
result->symbol = ts_symbol_error;
|
||||
result->data.error = {
|
||||
.lookahead_char = lookahead_char,
|
||||
.expected_input_count = expected_input_count,
|
||||
|
|
@ -84,6 +85,7 @@ size_t ts_tree_child_count(const ts_tree *tree) {
|
|||
|
||||
static string __tree_to_string(const ts_tree *tree, const char **symbol_names) {
|
||||
if (!tree) return "#<null-tree>";
|
||||
if (tree->symbol == ts_symbol_error) return "(ERROR)";
|
||||
string result = string("(") + symbol_names[tree->symbol];
|
||||
for (int i = 0; i < tree->data.children.count; i++)
|
||||
result += " " + __tree_to_string(tree->data.children.contents[i], symbol_names);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue