Simplify error recovery; eliminate recovery states
The previous approach to error recovery relied on special error-recovery states in the parse table. For each token T, there was an error recovery state in which the parser looked for *any* token that could follow T. Unfortunately, sometimes the set of tokens that could follow T contained conflicts. For example, in JS, the token '}' can be followed by the open-ended 'template_chars' token, but also by ordinary tokens like 'identifier'. So with the old algorithm, when recovering from an unexpected '}' token, the lexer had no way to distinguish identifiers from template_chars. This commit drops the error recovery states. Instead, when we encounter an unexpected token T, we recover from the error by finding a previous state S in the stack in which T would be valid, popping all of the nodes after S, and wrapping them in an error. This way, the lexer is always invoked in a normal parse state, in which it is looking for a non-conflicting set of tokens. Eliminating the error recovery states also shrinks the lex state machine significantly. Signed-off-by: Rick Winfrey <rewinfrey@github.com>
This commit is contained in:
parent
8b3941764f
commit
99d048e016
15 changed files with 327 additions and 639 deletions
|
|
@ -23,7 +23,6 @@ typedef struct {
|
|||
typedef Array(StackSlice) StackSliceArray;
|
||||
|
||||
typedef struct {
|
||||
bool stopped_at_error;
|
||||
StackSliceArray slices;
|
||||
} StackPopResult;
|
||||
|
||||
|
|
@ -34,6 +33,13 @@ enum {
|
|||
StackIteratePop = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned depth;
|
||||
TSStateId state;
|
||||
} StackSummaryEntry;
|
||||
|
||||
typedef Array(StackSummaryEntry) StackSummary;
|
||||
|
||||
typedef StackIterateAction (*StackIterateCallback)(void *, TSStateId state,
|
||||
const TreeArray *trees,
|
||||
uint32_t tree_count);
|
||||
|
|
@ -89,10 +95,18 @@ StackPopResult ts_stack_pop_count(Stack *, StackVersion, uint32_t count);
|
|||
|
||||
StackPopResult ts_stack_iterate(Stack *, StackVersion, StackIterateCallback, void *);
|
||||
|
||||
StackPopResult ts_stack_pop_error(Stack *, StackVersion);
|
||||
|
||||
StackPopResult ts_stack_pop_pending(Stack *, StackVersion);
|
||||
|
||||
StackPopResult ts_stack_pop_all(Stack *, StackVersion);
|
||||
|
||||
unsigned ts_stack_depth_since_error(Stack *, StackVersion);
|
||||
|
||||
void ts_stack_record_summary(Stack *, StackVersion);
|
||||
|
||||
StackSummary *ts_stack_get_summary(Stack *, StackVersion);
|
||||
|
||||
ErrorStatus ts_stack_error_status(const Stack *, StackVersion);
|
||||
|
||||
bool ts_stack_merge(Stack *, StackVersion, StackVersion);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue