Allow callbacks to be specified for debug output

This commit is contained in:
Max Brunsfeld 2014-10-13 01:02:12 -07:00
parent 71cc7a2dc2
commit c594208ab8
9 changed files with 226 additions and 69 deletions

View file

@ -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: