Unify debugging API for parsing and lexing
This commit is contained in:
parent
7498725d7f
commit
8cf800ef5d
8 changed files with 58 additions and 80 deletions
|
|
@ -5,7 +5,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "tree_sitter/runtime.h"
|
||||
|
|
|
|||
|
|
@ -20,9 +20,14 @@ typedef struct {
|
|||
void (*release_fn)(void *data);
|
||||
} TSInput;
|
||||
|
||||
typedef enum {
|
||||
TSDebugTypeParse,
|
||||
TSDebugTypeLex
|
||||
} TSDebugType;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
void (*debug_fn)(void *data, const char *);
|
||||
void (*debug_fn)(void *data, TSDebugType, const char *);
|
||||
void (*release_fn)(void *data);
|
||||
} TSDebugger;
|
||||
|
||||
|
|
@ -59,8 +64,8 @@ void ts_document_set_language(TSDocument *, const TSLanguage *);
|
|||
void ts_document_set_input(TSDocument *, TSInput);
|
||||
void ts_document_set_input_string(TSDocument *, const char *);
|
||||
void ts_document_edit(TSDocument *, TSInputEdit);
|
||||
void ts_document_debug_parse(TSDocument *, TSDebugger);
|
||||
void ts_document_debug_lex(TSDocument *, TSDebugger);
|
||||
TSDebugger ts_document_get_debugger(const TSDocument *);
|
||||
void ts_document_set_debugger(TSDocument *, TSDebugger);
|
||||
TSNode *ts_document_root_node(const TSDocument *);
|
||||
|
||||
#define ts_builtin_sym_error 0
|
||||
|
|
|
|||
|
|
@ -63,69 +63,47 @@ describe("Document", [&]() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("debugging", [&]() {
|
||||
describe("set_debugger(TSDebugger)", [&]() {
|
||||
SpyDebugger *debugger;
|
||||
|
||||
before_each([&]() {
|
||||
ts_document_set_language(doc, ts_language_json());
|
||||
debugger = new SpyDebugger();
|
||||
ts_document_set_language(doc, ts_language_json());
|
||||
ts_document_set_debugger(doc, debugger->debugger());
|
||||
});
|
||||
|
||||
describe("debug_lex(TSDebugger)", [&]() {
|
||||
before_each([&]() {
|
||||
ts_document_debug_lex(doc, debugger->debugger());
|
||||
});
|
||||
it("calls the debugger with a message for each lex action", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
|
||||
it("calls the debugger with a message for each lex action", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
|
||||
AssertThat(debugger->messages, Contains("lookahead char:'1'"));
|
||||
AssertThat(debugger->messages, Contains("accept_token sym:number"));
|
||||
AssertThat(debugger->messages, Contains("advance state:1"));
|
||||
});
|
||||
|
||||
describe("disabling debugging", [&]() {
|
||||
before_each([&]() {
|
||||
ts_document_debug_lex(doc, {});
|
||||
});
|
||||
|
||||
it("does not call the debugger any more", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
AssertThat(debugger->messages, IsEmpty());
|
||||
});
|
||||
|
||||
it("releases the old debugger", [&]() {
|
||||
AssertThat(debugger->release_call_count, Equals<size_t>(1));
|
||||
});
|
||||
});
|
||||
AssertThat(debugger->messages, Contains("lookahead char:'1'"));
|
||||
AssertThat(debugger->messages, Contains("advance state:1"));
|
||||
AssertThat(debugger->messages, Contains("accept_token sym:number"));
|
||||
});
|
||||
|
||||
describe("debug_parse(TSDebugger)", [&]() {
|
||||
it("calls the debugger with a message for each parse action", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
|
||||
AssertThat(debugger->messages, Contains("shift state:1"));
|
||||
AssertThat(debugger->messages, Contains("reduce sym:value count:1"));
|
||||
AssertThat(debugger->messages, Contains("accept"));
|
||||
});
|
||||
|
||||
it("allows the debugger to be retrieved later", [&]() {
|
||||
AssertThat(ts_document_get_debugger(doc).data, Equals(debugger));
|
||||
});
|
||||
|
||||
describe("disabling debugging", [&]() {
|
||||
before_each([&]() {
|
||||
ts_document_debug_parse(doc, debugger->debugger());
|
||||
ts_document_set_debugger(doc, {});
|
||||
});
|
||||
|
||||
it("calls the debugger with a message for each parse action", [&]() {
|
||||
it("does not call the debugger any more", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
|
||||
AssertThat(debugger->messages, Contains("lex sym:number"));
|
||||
AssertThat(debugger->messages, Contains("shift state:1"));
|
||||
AssertThat(debugger->messages, Contains("reduce sym:value count:1"));
|
||||
AssertThat(debugger->messages, IsEmpty());
|
||||
});
|
||||
|
||||
describe("disabling debugging", [&]() {
|
||||
before_each([&]() {
|
||||
ts_document_debug_parse(doc, ts_debugger_null());
|
||||
});
|
||||
|
||||
it("does not call the debugger any more", [&]() {
|
||||
ts_document_set_input_string(doc, "[1, 2]");
|
||||
AssertThat(debugger->messages, IsEmpty());
|
||||
});
|
||||
|
||||
it("releases the old debugger", [&]() {
|
||||
AssertThat(debugger->release_call_count, Equals<size_t>(1));
|
||||
});
|
||||
it("releases the old debugger", [&]() {
|
||||
AssertThat(debugger->release_call_count, Equals<size_t>(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
static void spy_debug(void *data, const char *msg) {
|
||||
static void spy_debug(void *data, TSDebugType type, const char *msg) {
|
||||
SpyDebugger *debugger = static_cast<SpyDebugger *>(data);
|
||||
debugger->messages.push_back(msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ void ts_document_set_language(TSDocument *document, const TSLanguage *language)
|
|||
reparse(document, NULL);
|
||||
}
|
||||
|
||||
void ts_document_debug_parse(TSDocument *document, TSDebugger debugger) {
|
||||
ts_parser_debug_parse(&document->parser, debugger);
|
||||
TSDebugger ts_document_get_debugger(const TSDocument *document) {
|
||||
return ts_parser_get_debugger(&document->parser);
|
||||
}
|
||||
|
||||
void ts_document_debug_lex(TSDocument *document, TSDebugger debugger) {
|
||||
ts_parser_debug_lex(&document->parser, debugger);
|
||||
void ts_document_set_debugger(TSDocument *document, TSDebugger debugger) {
|
||||
ts_parser_set_debugger(&document->parser, debugger);
|
||||
}
|
||||
|
||||
void ts_document_set_input(TSDocument *document, TSInput input) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdio.h>
|
||||
#include "runtime/lexer.h"
|
||||
#include "tree_sitter/parser.h"
|
||||
#include "runtime/tree.h"
|
||||
|
|
@ -5,10 +6,11 @@
|
|||
#include "runtime/debugger.h"
|
||||
#include "utf8proc.h"
|
||||
|
||||
#define DEBUG(...) \
|
||||
if (lexer->debugger.debug_fn) { \
|
||||
snprintf(lexer->debug_buffer, TS_DEBUG_BUFFER_SIZE, __VA_ARGS__); \
|
||||
lexer->debugger.debug_fn(lexer->debugger.data, lexer->debug_buffer); \
|
||||
#define DEBUG(...) \
|
||||
if (lexer->debugger.debug_fn) { \
|
||||
snprintf(lexer->debug_buffer, TS_DEBUG_BUFFER_SIZE, __VA_ARGS__); \
|
||||
lexer->debugger.debug_fn(lexer->debugger.data, TSDebugTypeLex, \
|
||||
lexer->debug_buffer); \
|
||||
}
|
||||
|
||||
static const char *empty_chunk = "";
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@
|
|||
* Debugging
|
||||
*/
|
||||
|
||||
#define DEBUG(...) \
|
||||
if (parser->debugger.debug_fn) { \
|
||||
#define DEBUG(...) \
|
||||
if (parser->lexer.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); \
|
||||
parser->lexer.debugger.debug_fn(parser->lexer.debugger.data, \
|
||||
TSDebugTypeParse, \
|
||||
parser->lexer.debug_buffer); \
|
||||
}
|
||||
|
||||
#define SYM_NAME(sym) parser->language->symbol_names[sym]
|
||||
|
|
@ -283,8 +284,7 @@ static TSTree *finish(TSParser *parser) {
|
|||
TSParser ts_parser_make() {
|
||||
return (TSParser) { .lexer = ts_lexer_make(),
|
||||
.stack = ts_stack_make(),
|
||||
.right_stack = ts_stack_make(),
|
||||
.debugger = ts_debugger_null() };
|
||||
.right_stack = ts_stack_make() };
|
||||
}
|
||||
|
||||
void ts_parser_destroy(TSParser *parser) {
|
||||
|
|
@ -296,20 +296,15 @@ void ts_parser_destroy(TSParser *parser) {
|
|||
if (parser->next_lookahead)
|
||||
ts_tree_release(parser->next_lookahead);
|
||||
|
||||
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;
|
||||
TSDebugger ts_parser_get_debugger(const TSParser *parser) {
|
||||
return parser->lexer.debugger;
|
||||
}
|
||||
|
||||
void ts_parser_debug_lex(TSParser *parser, TSDebugger debugger) {
|
||||
void ts_parser_set_debugger(TSParser *parser, TSDebugger debugger) {
|
||||
TSDebugger old_debugger = parser->lexer.debugger;
|
||||
if (old_debugger.release_fn)
|
||||
old_debugger.release_fn(old_debugger.data);
|
||||
|
|
@ -324,7 +319,7 @@ const TSTree *ts_parser_parse(TSParser *parser, TSInput input,
|
|||
TSLength position;
|
||||
if (edit) {
|
||||
DEBUG("edit pos:%lu inserted:%lu deleted:%lu", edit->position,
|
||||
edit->chars_inserted, edit->chars_removed);
|
||||
edit->chars_inserted, edit->chars_removed);
|
||||
position = break_down_left_stack(parser, *edit);
|
||||
} else {
|
||||
DEBUG("new_parse");
|
||||
|
|
@ -362,7 +357,7 @@ const TSTree *ts_parser_parse(TSParser *parser, TSInput input,
|
|||
|
||||
case TSParseActionTypeReduce:
|
||||
DEBUG("reduce sym:%s count:%u", SYM_NAME(action.data.symbol),
|
||||
action.data.child_count);
|
||||
action.data.child_count);
|
||||
reduce(parser, action.data.symbol, action.data.child_count);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,12 @@ typedef struct {
|
|||
TSTree *lookahead;
|
||||
TSTree *next_lookahead;
|
||||
const TSLanguage *language;
|
||||
TSDebugger debugger;
|
||||
} TSParser;
|
||||
|
||||
TSParser ts_parser_make();
|
||||
void ts_parser_destroy(TSParser *);
|
||||
void ts_parser_debug_parse(TSParser *, TSDebugger);
|
||||
void ts_parser_debug_lex(TSParser *, TSDebugger);
|
||||
TSDebugger ts_parser_get_debugger(const TSParser *);
|
||||
void ts_parser_set_debugger(TSParser *, TSDebugger);
|
||||
const TSTree *ts_parser_parse(TSParser *, TSInput, TSInputEdit *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue