Start work on error recovery
- In runtime, make parse errors part of the parse tree - Add error state to lexers in which they can accept any token
This commit is contained in:
parent
4520d6e1a2
commit
e58a6d8ba7
18 changed files with 622 additions and 528 deletions
|
|
@ -3,18 +3,43 @@
|
|||
#include <string.h>
|
||||
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
|
||||
ts_tree * ts_tree_make(ts_symbol value, size_t child_count, ts_tree **children) {
|
||||
const ts_symbol ts_symbol_error = -1;
|
||||
|
||||
ts_tree * ts_tree_make_leaf(ts_symbol symbol) {
|
||||
ts_tree *result = new ts_tree();
|
||||
result->value = value;
|
||||
result->child_count = child_count;
|
||||
result->children = children;
|
||||
result->ref_count = 0;
|
||||
result->symbol = symbol;
|
||||
result->data.children = {
|
||||
.count = 0,
|
||||
.contents = NULL
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
ts_tree * ts_tree_make_node(ts_symbol symbol, size_t child_count, ts_tree **children) {
|
||||
ts_tree *result = new ts_tree();
|
||||
result->ref_count = 0;
|
||||
result->symbol = symbol;
|
||||
result->data.children = {
|
||||
.count = child_count,
|
||||
.contents = children
|
||||
};
|
||||
for (int i = 0; i < child_count; i++)
|
||||
ts_tree_retain(children[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
ts_tree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const ts_symbol *expected_inputs) {
|
||||
ts_tree *result = new ts_tree();
|
||||
result->data.error = {
|
||||
.lookahead_char = lookahead_char,
|
||||
.expected_input_count = expected_input_count,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_tree_retain(ts_tree *tree) {
|
||||
tree->ref_count++;
|
||||
}
|
||||
|
|
@ -22,28 +47,46 @@ void ts_tree_retain(ts_tree *tree) {
|
|||
void ts_tree_release(ts_tree *tree) {
|
||||
tree->ref_count--;
|
||||
if (tree->ref_count == 0) {
|
||||
for (int i = 0; i < tree->child_count; i++)
|
||||
ts_tree_release(tree->children[i]);
|
||||
ts_tree **children = tree->data.children.contents;
|
||||
for (int i = 0; i < ts_tree_child_count(tree); i++)
|
||||
ts_tree_release(children[i]);
|
||||
// free(children);
|
||||
free(tree);
|
||||
}
|
||||
}
|
||||
|
||||
int ts_tree_equals(const ts_tree *node1, const ts_tree *node2) {
|
||||
if (node1->value != node2->value) return 0;
|
||||
if (node1->child_count != node2->child_count) return 0;
|
||||
for (int i = 0; i < node1->child_count; i++) {
|
||||
ts_tree *child1 = node1->children[i];
|
||||
ts_tree *child2 = node2->children[i];
|
||||
if (!ts_tree_equals(child1, child2)) return 0;
|
||||
if (node1->symbol != node2->symbol) return 0;
|
||||
if (node1->symbol == ts_symbol_error) {
|
||||
// check error equality
|
||||
} else {
|
||||
if (node1->data.children.count != node2->data.children.count)
|
||||
return 0;
|
||||
for (int i = 0; i < node1->data.children.count; i++) {
|
||||
ts_tree *child1 = node1->data.children.contents[i];
|
||||
ts_tree *child2 = node2->data.children.contents[i];
|
||||
if (!ts_tree_equals(child1, child2))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ts_tree ** ts_tree_children(const ts_tree *tree) {
|
||||
if (tree->symbol == ts_symbol_error) return NULL;
|
||||
return tree->data.children.contents;
|
||||
}
|
||||
|
||||
size_t ts_tree_child_count(const ts_tree *tree) {
|
||||
if (tree->symbol == ts_symbol_error) return 0;
|
||||
return tree->data.children.count;
|
||||
}
|
||||
|
||||
static string __tree_to_string(const ts_tree *tree, const char **symbol_names) {
|
||||
if (!tree) return "#<null-tree>";
|
||||
string result = string("(") + symbol_names[tree->value];
|
||||
for (int i = 0; i < tree->child_count; i++)
|
||||
result += " " + __tree_to_string(tree->children[i], symbol_names);
|
||||
string result = string("(") + symbol_names[tree->symbol];
|
||||
for (int i = 0; i < tree->data.children.count; i++)
|
||||
result += " " + __tree_to_string(tree->data.children.contents[i], symbol_names);
|
||||
return result + ")";
|
||||
}
|
||||
|
||||
|
|
@ -53,3 +96,15 @@ char * ts_tree_string(const ts_tree *tree, const char **symbol_names) {
|
|||
strcpy(result, value.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
char * ts_tree_error_string(const ts_tree *tree, const char **symbol_names) {
|
||||
string result = string("Unexpected character '") + tree->data.error.lookahead_char + "'. Expected:";
|
||||
for (int i = 0; i < tree->data.error.expected_input_count; i++) {
|
||||
ts_symbol symbol = tree->data.error.expected_inputs[i];
|
||||
result += string(" ") + symbol_names[symbol];
|
||||
}
|
||||
|
||||
char *stuff = (char *)malloc(result.size() * sizeof(char));
|
||||
strcpy(stuff, result.c_str());
|
||||
return stuff;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue