Allow callbacks to be specified for debug output
This commit is contained in:
parent
71cc7a2dc2
commit
c594208ab8
9 changed files with 226 additions and 69 deletions
|
|
@ -12,10 +12,11 @@
|
|||
* Private
|
||||
*/
|
||||
|
||||
#define DEBUG_PARSE(...) \
|
||||
if (parser->debug) { \
|
||||
fprintf(stderr, "PARSE " __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
#define DEBUG_PARSE(...) \
|
||||
if (parser->debugger.debug_fn) { \
|
||||
snprintf(parser->lexer.debug_buffer, TS_DEBUG_BUFFER_SIZE, __VA_ARGS__); \
|
||||
parser->debugger.debug_fn(parser->debugger.data, \
|
||||
parser->lexer.debug_buffer); \
|
||||
}
|
||||
|
||||
static TSParseAction action_for(const TSLanguage *lang, TSStateId state,
|
||||
|
|
@ -45,7 +46,7 @@ static size_t breakdown_right_stack(TSParser *parser, TSLength cur_position,
|
|||
size_t child_count;
|
||||
TSTree **children = ts_tree_children(node, &child_count);
|
||||
|
||||
DEBUG_PARSE("POP RIGHT %s", parser->language->symbol_names[node->symbol]);
|
||||
DEBUG_PARSE("pop_right %s", parser->language->symbol_names[node->symbol]);
|
||||
stack->size--;
|
||||
right_subtree_start += ts_tree_total_size(node).chars;
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ static size_t breakdown_right_stack(TSParser *parser, TSLength cur_position,
|
|||
TSTree *child = children[i];
|
||||
|
||||
if (right_subtree_start > cur_position.chars) {
|
||||
DEBUG_PARSE("PUSH RIGHT %s",
|
||||
DEBUG_PARSE("push_right %s",
|
||||
parser->language->symbol_names[child->symbol]);
|
||||
ts_stack_push(stack, 0, child);
|
||||
right_subtree_start -= ts_tree_total_size(child).chars;
|
||||
|
|
@ -92,7 +93,8 @@ static TSLength breakdown_stack(TSParser *parser, TSInputEdit *edit) {
|
|||
if (left_subtree_end.chars < edit->position && !children)
|
||||
break;
|
||||
|
||||
DEBUG_PARSE("POP LEFT %s", parser->language->symbol_names[node->symbol]);
|
||||
DEBUG_PARSE("pop_left sym: %s",
|
||||
parser->language->symbol_names[node->symbol]);
|
||||
parser->stack.size--;
|
||||
left_subtree_end = ts_length_sub(left_subtree_end, ts_tree_total_size(node));
|
||||
|
||||
|
|
@ -104,7 +106,8 @@ static TSLength breakdown_stack(TSParser *parser, TSInputEdit *edit) {
|
|||
TSStateId next_state =
|
||||
action.type == TSParseActionTypeShift ? action.data.to_state : state;
|
||||
|
||||
DEBUG_PARSE("PUSH LEFT %s", parser->language->symbol_names[child->symbol]);
|
||||
DEBUG_PARSE("push_left sym: %s",
|
||||
parser->language->symbol_names[child->symbol]);
|
||||
ts_stack_push(&parser->stack, next_state, child);
|
||||
left_subtree_end =
|
||||
ts_length_add(left_subtree_end, ts_tree_total_size(child));
|
||||
|
|
@ -116,7 +119,7 @@ static TSLength breakdown_stack(TSParser *parser, TSInputEdit *edit) {
|
|||
if (right_subtree_start < edit->position + edit->chars_inserted)
|
||||
break;
|
||||
|
||||
DEBUG_PARSE("PUSH RIGHT %s",
|
||||
DEBUG_PARSE("push_right sym: %s",
|
||||
parser->language->symbol_names[child->symbol]);
|
||||
ts_stack_push(&parser->right_stack, 0, child);
|
||||
}
|
||||
|
|
@ -124,7 +127,7 @@ static TSLength breakdown_stack(TSParser *parser, TSInputEdit *edit) {
|
|||
ts_tree_release(node);
|
||||
}
|
||||
|
||||
DEBUG_PARSE("RESUME LEFT %lu", left_subtree_end.chars);
|
||||
DEBUG_PARSE("reuse_left chars:%lu", left_subtree_end.chars);
|
||||
return left_subtree_end;
|
||||
}
|
||||
|
||||
|
|
@ -141,10 +144,11 @@ static void lex(TSParser *parser, TSStateId lex_state) {
|
|||
parser->lookahead = node;
|
||||
parser->lexer.current_position =
|
||||
ts_length_add(parser->lexer.current_position, ts_tree_total_size(node));
|
||||
DEBUG_PARSE("REUSE %s", parser->language->symbol_names[node->symbol]);
|
||||
DEBUG_PARSE("reuse_right sym:%s",
|
||||
parser->language->symbol_names[node->symbol]);
|
||||
} else {
|
||||
parser->lookahead = parser->language->lex_fn(&parser->lexer, lex_state);
|
||||
DEBUG_PARSE("TOKEN %s",
|
||||
DEBUG_PARSE("lex sym:%s",
|
||||
parser->language->symbol_names[parser->lookahead->symbol]);
|
||||
}
|
||||
}
|
||||
|
|
@ -156,20 +160,32 @@ static void resize_error(TSParser *parser, TSTree *error) {
|
|||
error->padding);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse Actions
|
||||
*/
|
||||
|
||||
static void shift(TSParser *parser, TSStateId parse_state) {
|
||||
DEBUG_PARSE("shift state:%d", parse_state);
|
||||
|
||||
if (ts_tree_is_extra(parser->lookahead))
|
||||
parse_state = ts_stack_top_state(&parser->stack);
|
||||
|
||||
ts_stack_push(&parser->stack, parse_state, parser->lookahead);
|
||||
parser->lookahead = parser->next_lookahead;
|
||||
parser->next_lookahead = NULL;
|
||||
}
|
||||
|
||||
static void shift_extra(TSParser *parser) {
|
||||
DEBUG_PARSE("shift_extra");
|
||||
|
||||
ts_tree_set_extra(parser->lookahead);
|
||||
shift(parser, 0);
|
||||
}
|
||||
|
||||
static void reduce(TSParser *parser, TSSymbol symbol, size_t child_count) {
|
||||
DEBUG_PARSE("reduce sym:%s count:%lu", parser->language->symbol_names[symbol],
|
||||
child_count);
|
||||
|
||||
TSStack *stack = &parser->stack;
|
||||
parser->next_lookahead = parser->lookahead;
|
||||
|
||||
|
|
@ -197,6 +213,7 @@ static void reduce(TSParser *parser, TSSymbol symbol, size_t child_count) {
|
|||
}
|
||||
|
||||
static void reduce_extra(TSParser *parser, TSSymbol symbol) {
|
||||
DEBUG_PARSE("reduce_extra");
|
||||
reduce(parser, symbol, 1);
|
||||
ts_tree_set_extra(parser->lookahead);
|
||||
}
|
||||
|
|
@ -222,7 +239,7 @@ static int handle_error(TSParser *parser) {
|
|||
parser->language, state_after_error, parser->lookahead->symbol);
|
||||
|
||||
if (action_after_error.type != TSParseActionTypeError) {
|
||||
DEBUG_PARSE("RECOVER %u", state_after_error);
|
||||
DEBUG_PARSE("recover state:%u", state_after_error);
|
||||
|
||||
ts_stack_shrink(&parser->stack, entry - parser->stack.entries + 1);
|
||||
parser->lookahead->padding = ts_length_zero();
|
||||
|
|
@ -240,7 +257,7 @@ static int handle_error(TSParser *parser) {
|
|||
* current lookahead token, advance to the next token. If no characters
|
||||
* were consumed, advance the lexer to the next character.
|
||||
*/
|
||||
DEBUG_PARSE("LEX AGAIN");
|
||||
DEBUG_PARSE("lex_again");
|
||||
TSLength prev_position = parser->lexer.current_position;
|
||||
if (parser->lookahead)
|
||||
ts_tree_release(parser->lookahead);
|
||||
|
|
@ -252,7 +269,7 @@ static int handle_error(TSParser *parser) {
|
|||
*/
|
||||
if (ts_length_eq(parser->lexer.current_position, prev_position))
|
||||
if (!ts_lexer_advance(&parser->lexer)) {
|
||||
DEBUG_PARSE("FAIL TO RECOVER");
|
||||
DEBUG_PARSE("fail_to_recover");
|
||||
|
||||
resize_error(parser, error);
|
||||
ts_stack_push(&parser->stack, 0, error);
|
||||
|
|
@ -262,7 +279,9 @@ static int handle_error(TSParser *parser) {
|
|||
}
|
||||
}
|
||||
|
||||
static TSTree *get_root(TSParser *parser) {
|
||||
static TSTree *finish(TSParser *parser) {
|
||||
DEBUG_PARSE("finish");
|
||||
|
||||
if (parser->stack.size == 0)
|
||||
ts_stack_push(&parser->stack, 0,
|
||||
ts_tree_make_error(ts_length_zero(), ts_length_zero(), 0));
|
||||
|
|
@ -277,20 +296,40 @@ static TSTree *get_root(TSParser *parser) {
|
|||
* Public
|
||||
*/
|
||||
|
||||
TSParser ts_parser_make(const TSLanguage *language) {
|
||||
TSParser ts_parser_make() {
|
||||
return (TSParser) { .lexer = ts_lexer_make(),
|
||||
.stack = ts_stack_make(),
|
||||
.right_stack = ts_stack_make(),
|
||||
.debug = 0,
|
||||
.language = language, };
|
||||
.debugger = (TSDebugger) {} };
|
||||
}
|
||||
|
||||
void ts_parser_destroy(TSParser *parser) {
|
||||
ts_stack_delete(&parser->stack);
|
||||
ts_stack_delete(&parser->right_stack);
|
||||
|
||||
if (parser->lookahead)
|
||||
ts_tree_release(parser->lookahead);
|
||||
if (parser->next_lookahead)
|
||||
ts_tree_release(parser->next_lookahead);
|
||||
ts_stack_delete(&parser->stack);
|
||||
|
||||
if (parser->debugger.release_fn)
|
||||
parser->debugger.release_fn(parser->debugger.data);
|
||||
if (parser->lexer.debugger.release_fn)
|
||||
parser->lexer.debugger.release_fn(parser->lexer.debugger.data);
|
||||
}
|
||||
|
||||
void ts_parser_debug_parse(TSParser *parser, TSDebugger debugger) {
|
||||
TSDebugger old_debugger = parser->debugger;
|
||||
if (old_debugger.release_fn)
|
||||
old_debugger.release_fn(old_debugger.data);
|
||||
parser->debugger = debugger;
|
||||
}
|
||||
|
||||
void ts_parser_debug_lex(TSParser *parser, TSDebugger debugger) {
|
||||
TSDebugger old_debugger = parser->lexer.debugger;
|
||||
if (old_debugger.release_fn)
|
||||
old_debugger.release_fn(old_debugger.data);
|
||||
parser->lexer.debugger = debugger;
|
||||
}
|
||||
|
||||
const TSTree *ts_parser_parse(TSParser *parser, TSInput input,
|
||||
|
|
@ -313,38 +352,30 @@ const TSTree *ts_parser_parse(TSParser *parser, TSInput input,
|
|||
case TSParseActionTypeShift:
|
||||
if (parser->lookahead->symbol == ts_builtin_sym_error) {
|
||||
if (!handle_error(parser))
|
||||
return get_root(parser);
|
||||
return finish(parser);
|
||||
} else {
|
||||
DEBUG_PARSE("SHIFT %d", action.data.to_state);
|
||||
shift(parser, action.data.to_state);
|
||||
}
|
||||
break;
|
||||
|
||||
case TSParseActionTypeShiftExtra:
|
||||
DEBUG_PARSE("SHIFT EXTRA");
|
||||
shift_extra(parser);
|
||||
break;
|
||||
|
||||
case TSParseActionTypeReduce:
|
||||
DEBUG_PARSE("REDUCE %s %d",
|
||||
parser->language->symbol_names[action.data.symbol],
|
||||
action.data.child_count);
|
||||
reduce(parser, action.data.symbol, action.data.child_count);
|
||||
break;
|
||||
|
||||
case TSParseActionTypeReduceExtra:
|
||||
DEBUG_PARSE("REDUCE EXTRA");
|
||||
reduce_extra(parser, action.data.symbol);
|
||||
break;
|
||||
|
||||
case TSParseActionTypeAccept:
|
||||
DEBUG_PARSE("ACCEPT");
|
||||
return get_root(parser);
|
||||
return finish(parser);
|
||||
|
||||
case TSParseActionTypeError:
|
||||
DEBUG_PARSE("ERROR");
|
||||
if (!handle_error(parser))
|
||||
return get_root(parser);
|
||||
return finish(parser);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue