Remove generated parsers' dependency on the runtime library
Generated parsers no longer export a parser constructor function. They now export an opaque Language object which can be set on Documents directly. This way, the logic for constructing parsers lives entirely in the runtime. The Languages are just structs which have no load-time dependency on the runtime
This commit is contained in:
parent
048a479b5f
commit
eecbcccee0
21 changed files with 219 additions and 173 deletions
|
|
@ -2,7 +2,7 @@
|
|||
#include "runtime/helpers/spy_reader.h"
|
||||
#include "runtime/tree.h"
|
||||
|
||||
extern "C" TSParser * ts_parser_json();
|
||||
extern "C" const TSLanguage * ts_language_json;
|
||||
|
||||
START_TEST
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ describe("incremental parsing", [&]() {
|
|||
|
||||
before_each([&]() {
|
||||
doc = ts_document_make();
|
||||
ts_document_set_parser(doc, ts_parser_json());
|
||||
ts_document_set_language(doc, ts_language_json);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "runtime/helpers/dummy_parser.h"
|
||||
#include "runtime/helpers/dummy_language.h"
|
||||
#include "tree_sitter/parser.h"
|
||||
|
||||
const TSParseAction parse_table[3][5] = {
|
||||
|
|
@ -30,9 +30,11 @@ const int hidden_symbols[5] = {
|
|||
[dummy_sym3] = 1,
|
||||
};
|
||||
|
||||
TSParserConfig dummy_parser = {
|
||||
static TSLanguage language = {
|
||||
.symbol_count = 5,
|
||||
.parse_table = (const TSParseAction *)parse_table,
|
||||
.lex_states = lex_states,
|
||||
.hidden_symbol_flags = hidden_symbols,
|
||||
};
|
||||
|
||||
TSLanguage *dummy_language = &language;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef HELPERS_DUMMY_PARSER_H_
|
||||
#define HELPERS_DUMMY_PARSER_H_
|
||||
#ifndef HELPERS_DUMMY_LANGUAGE_H_
|
||||
#define HELPERS_DUMMY_LANGUAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -14,10 +14,10 @@ enum {
|
|||
dummy_sym3 = 4,
|
||||
};
|
||||
|
||||
extern TSParserConfig dummy_parser;
|
||||
extern TSLanguage *dummy_language;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HELPERS_DUMMY_PARSER_H_
|
||||
#endif // HELPERS_DUMMY_LANGUAGE_H_
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#include "runtime/runtime_spec_helper.h"
|
||||
#include "runtime/helpers/read_test_entries.h"
|
||||
|
||||
extern "C" TSParser * ts_parser_javascript();
|
||||
extern "C" TSParser * ts_parser_json();
|
||||
extern "C" TSParser * ts_parser_arithmetic();
|
||||
extern "C" TSParser * ts_parser_golang();
|
||||
extern "C" TSLanguage *ts_language_javascript;
|
||||
extern "C" TSLanguage *ts_language_json;
|
||||
extern "C" TSLanguage *ts_language_arithmetic;
|
||||
extern "C" TSLanguage *ts_language_golang;
|
||||
|
||||
START_TEST
|
||||
|
||||
|
|
@ -19,13 +19,13 @@ describe("Languages", [&]() {
|
|||
ts_document_free(doc);
|
||||
});
|
||||
|
||||
auto run_tests_for_language = [&](string language, TSParser * (parser_constructor)()) {
|
||||
describe(language.c_str(), [&]() {
|
||||
auto run_tests_for_language = [&](string language_name, TSLanguage *language) {
|
||||
describe(language_name.c_str(), [&]() {
|
||||
before_each([&]() {
|
||||
ts_document_set_parser(doc, parser_constructor());
|
||||
ts_document_set_language(doc, language);
|
||||
});
|
||||
|
||||
for (auto &entry : test_entries_for_language(language)) {
|
||||
for (auto &entry : test_entries_for_language(language_name)) {
|
||||
it(entry.description.c_str(), [&]() {
|
||||
ts_document_set_input_string(doc, entry.input.c_str());
|
||||
auto doc_string = ts_document_string(doc);
|
||||
|
|
@ -36,10 +36,10 @@ describe("Languages", [&]() {
|
|||
});
|
||||
};
|
||||
|
||||
run_tests_for_language("json", ts_parser_json);
|
||||
run_tests_for_language("arithmetic", ts_parser_arithmetic);
|
||||
run_tests_for_language("javascript", ts_parser_javascript);
|
||||
run_tests_for_language("golang", ts_parser_golang);
|
||||
run_tests_for_language("json", ts_language_json);
|
||||
run_tests_for_language("arithmetic", ts_language_arithmetic);
|
||||
run_tests_for_language("javascript", ts_language_javascript);
|
||||
run_tests_for_language("golang", ts_language_golang);
|
||||
});
|
||||
|
||||
END_TEST
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "runtime/runtime_spec_helper.h"
|
||||
|
||||
extern "C" TSParser * ts_parser_json();
|
||||
extern "C" TSLanguage * ts_language_json;
|
||||
|
||||
START_TEST
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ describe("Node", []() {
|
|||
|
||||
before_each([&]() {
|
||||
document = ts_document_make();
|
||||
ts_document_set_parser(document, ts_parser_json());
|
||||
ts_document_set_language(document, ts_language_json);
|
||||
|
||||
ts_document_set_input_string(document, " [12, 5, 345]");
|
||||
root = ts_document_root_node(document);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
#include "runtime/runtime_spec_helper.h"
|
||||
#include "runtime/helpers/spy_reader.h"
|
||||
#include "runtime/helpers/dummy_parser.h"
|
||||
#include "runtime/helpers/dummy_language.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/parser.h"
|
||||
#include "tree_sitter/parser.h"
|
||||
|
||||
TSTree *lex_fn_node_to_return;
|
||||
TSStateId lex_fn_state_received;
|
||||
TSParser *lex_fn_parser_received;
|
||||
TSLexer *lex_fn_lexer_received;
|
||||
|
||||
TSTree * fake_lex(TSParser *parser, TSStateId state_id) {
|
||||
lex_fn_parser_received = parser;
|
||||
TSTree * fake_lex(TSLexer *lexer, TSStateId state_id) {
|
||||
lex_fn_lexer_received = lexer;
|
||||
lex_fn_state_received = state_id;
|
||||
return lex_fn_node_to_return;
|
||||
}
|
||||
|
|
@ -17,31 +18,29 @@ TSTree * fake_lex(TSParser *parser, TSStateId state_id) {
|
|||
START_TEST
|
||||
|
||||
describe("LR Parsers", [&]() {
|
||||
TSParser *parser;
|
||||
TSParser parser;
|
||||
SpyReader *reader;
|
||||
|
||||
before_each([&]() {
|
||||
TSParserConfig config = dummy_parser;
|
||||
config.lex_fn = fake_lex;
|
||||
|
||||
parser = ts_parser_make(config);
|
||||
dummy_language->lex_fn = fake_lex;
|
||||
parser = ts_parser_make(dummy_language);
|
||||
|
||||
reader = new SpyReader("some structured text", 5);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_parser_free(parser);
|
||||
ts_parser_destroy(&parser);
|
||||
delete reader;
|
||||
});
|
||||
|
||||
describe("when starting at the beginning of the input (edit is NULL)", [&]() {
|
||||
before_each([&]() {
|
||||
ts_parser_start(parser, reader->input, nullptr);
|
||||
ts_parser_start(&parser, reader->input, nullptr);
|
||||
});
|
||||
|
||||
it("runs the lexer with the lex state corresponding to the initial state", [&]() {
|
||||
lex_fn_node_to_return = ts_tree_make_leaf(dummy_sym2, 5, 1, 0);
|
||||
ts_parser_step(parser);
|
||||
ts_parser_step(&parser);
|
||||
AssertThat(lex_fn_state_received, Equals(100));
|
||||
});
|
||||
|
||||
|
|
@ -51,12 +50,12 @@ describe("LR Parsers", [&]() {
|
|||
});
|
||||
|
||||
it("advances to the state specified in the action", [&]() {
|
||||
ts_parser_step(parser);
|
||||
AssertThat(ts_stack_top_state(&parser->stack), Equals(12));
|
||||
ts_parser_step(&parser);
|
||||
AssertThat(ts_stack_top_state(&parser.stack), Equals(12));
|
||||
});
|
||||
|
||||
it("continues parsing (returns NULL)", [&]() {
|
||||
auto result = ts_parser_step(parser);
|
||||
auto result = ts_parser_step(&parser);
|
||||
AssertThat(result, Equals((TSTree *)nullptr));
|
||||
});
|
||||
});
|
||||
|
|
@ -67,7 +66,7 @@ describe("LR Parsers", [&]() {
|
|||
});
|
||||
|
||||
it("ends the parse, returning an error tree", [&]() {
|
||||
auto result = ts_parser_step(parser);
|
||||
auto result = ts_parser_step(&parser);
|
||||
AssertThat(result->symbol, Equals(ts_builtin_sym_error));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "runtime/runtime_spec_helper.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "tree_sitter/parser.h"
|
||||
#include "runtime/stack.h"
|
||||
|
||||
START_TEST
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue