Perform all possible reductions recursively upon detecting an error

This commit is contained in:
Max Brunsfeld 2016-08-29 09:34:08 -07:00
parent a3c943d88e
commit 1b8843dd41
2 changed files with 116 additions and 191 deletions

View file

@ -1,177 +1,67 @@
============================================
Invalid statements
============================================
===================================================
one invalid token right after the viable prefix
===================================================
what the heck !
y();
if (a b) {
c d
}
e f
if (x) {
>>>
var y = right
---
(program
(if_statement
(identifier)
(ERROR (identifier))
(statement_block
(expression_statement
(identifier)
(ERROR (identifier)))))
(expression_statement
(identifier)
(ERROR (identifier))))
=======================================================
multiple invalid tokens right after the viable prefix
=======================================================
if (a b c) {
d e f g
}
h i j k
---
(program
(if_statement
(identifier)
(ERROR (identifier) (identifier))
(statement_block
(expression_statement
(identifier)
(ERROR (identifier) (identifier) (identifier)))))
(expression_statement
(identifier)
(ERROR (identifier) (identifier) (identifier))))
===================================================
one invalid subtree right after the viable prefix
===================================================
if ({a: 'b'} {c: 'd'}) {
function(a) { b; } function(c) { d; }
}
---
(program
(expression_statement
(identifier)
(ERROR (identifier) (identifier)))
(expression_statement (function_call (identifier)))
(if_statement (identifier) (statement_block
(ERROR)
(var_declaration (var_assignment (identifier) (identifier))))))
============================================
Invalid if conditions
============================================
if (uh oh)
hmm();
ok();
---
(program
(if_statement (ERROR (identifier)) (identifier)
(expression_statement (function_call (identifier))))
(expression_statement (function_call (identifier))))
============================================
Invalid for loops
============================================
ok1;
for (a b c; d; e)
wat();
ok2;
for (a; b; c d e)
wat();
---
(program
(expression_statement (identifier))
(for_statement
(ERROR (identifier) (identifier))
(identifier)
(identifier)
(identifier)
(expression_statement (function_call (identifier))))
(expression_statement (identifier))
(for_statement
(identifier)
(identifier)
(ERROR (identifier) (identifier))
(identifier)
(expression_statement (function_call (identifier)))))
============================================
Invalid statement blocks
============================================
function() { ^ & * }
---
(program
(expression_statement (function (statement_block (ERROR)))))
============================================
Invalid objects
============================================
x = {
key1: value1,
abc efg,
key2: value2
};
---
(program
(expression_statement (assignment
(identifier)
(object
(pair (identifier) (identifier))
(ERROR (identifier) (identifier))
(pair (identifier) (identifier))))))
============================================
Invalid items in var declarations
============================================
var
a = 1,
-b,
c = 2,
d = = = = =,
e;
---
(program
(var_declaration
(var_assignment (identifier) (number))
(ERROR) (identifier)
(var_assignment (identifier) (number))
(var_assignment (identifier) (ERROR) (identifier))))
============================================
Misplaced expressions in var declarations
============================================
var
a = 1,
b = 2,
[1, 2],
{},
c = 3,
d = 4;
var x;
---
(program
(var_declaration
(var_assignment (identifier) (number))
(var_assignment (identifier) (number))
(ERROR (array (number) (number)) (object))
(var_assignment (identifier) (number))
(var_assignment (identifier) (number)))
(var_declaration (identifier)))
================================================
Mismatched delimiters in var declarations
================================================
var
// keep this
a,
// skip this
[
// keep this
b = 1;
var c;
---
(program
(var_declaration
(comment)
(identifier)
(ERROR (comment) (comment))
(var_assignment (identifier) (number)))
(var_declaration (identifier)))
(if_statement
(object (pair (identifier) (string)))
(ERROR (object (pair (identifier) (string))))
(statement_block
(ERROR (function
(formal_parameters (identifier))
(statement_block (expression_statement (identifier)))))
(expression_statement (function
(formal_parameters (identifier))
(statement_block (expression_statement (identifier))))))))

View file

@ -831,29 +831,24 @@ error:
return false;
}
static bool ts_parser__handle_error(TSParser *self, StackVersion version) {
TSStateId state = ts_stack_top_state(self->stack, version);
typedef enum {
PotentialReductionsFailed,
PotentialReductionsContinue,
PotentialReductionsDone,
} PotentialReductionStatus;
unsigned error_cost = ts_stack_error_cost(self->stack, version);
unsigned error_depth = ts_stack_error_depth(self->stack, version) + 1;
if (ts_parser__better_version_exists(self, version, error_depth, error_cost)) {
ts_stack_halt(self->stack, version);
LOG("bail_on_error");
return true;
}
LOG("handle_error");
size_t previous_version_count = ts_stack_version_count(self->stack);
static PotentialReductionStatus parser__do_potential_reductions(TSParser *self,
StackVersion version) {
bool has_shift_action = false;
TSStateId state = ts_stack_top_state(self->stack, version);
size_t previous_version_count = ts_stack_version_count(self->stack);
array_clear(&self->reduce_actions);
for (TSSymbol symbol = 0; symbol < self->language->symbol_count; symbol++) {
size_t action_count;
const TSParseAction *actions =
ts_language_actions(self->language, state, symbol, &action_count);
for (size_t i = 0; i < action_count; i++) {
TSParseAction action = actions[i];
TableEntry entry;
ts_language_table_entry(self->language, state, symbol, &entry);
for (size_t i = 0; i < entry.action_count; i++) {
TSParseAction action = entry.actions[i];
if (action.extra)
continue;
switch (action.type) {
@ -892,8 +887,48 @@ static bool ts_parser__handle_error(TSParser *self, StackVersion version) {
}
}
if (did_reduce && !has_shift_action)
ts_stack_renumber_version(self->stack, previous_version_count, version);
if (did_reduce) {
if (has_shift_action) {
return PotentialReductionsDone;
} else {
ts_stack_renumber_version(self->stack, previous_version_count, version);
return PotentialReductionsContinue;
}
} else {
return PotentialReductionsDone;
}
error:
return PotentialReductionsFailed;
}
static bool ts_parser__handle_error(TSParser *self, StackVersion version) {
unsigned error_cost = ts_stack_error_cost(self->stack, version);
unsigned error_depth = ts_stack_error_depth(self->stack, version) + 1;
if (ts_parser__better_version_exists(self, version, error_depth, error_cost)) {
ts_stack_halt(self->stack, version);
LOG("bail_on_error");
return true;
}
LOG("handle_error");
size_t previous_version_count = ts_stack_version_count(self->stack);
for (StackVersion v = version; v < ts_stack_version_count(self->stack);) {
switch (parser__do_potential_reductions(self, v)) {
case PotentialReductionsFailed:
goto error;
case PotentialReductionsContinue:
break;
case PotentialReductionsDone:
if (v == version) {
v = previous_version_count;
} else {
v++;
}
break;
}
}
CHECK(ts_stack_push(self->stack, version, NULL, false, TS_STATE_ERROR));
while (ts_stack_version_count(self->stack) > previous_version_count) {