Merge pull request #53 from tree-sitter/precedence-fix
Avoid incorrect application of precedence
This commit is contained in:
commit
269ee1c120
2 changed files with 155 additions and 1 deletions
|
|
@ -243,6 +243,160 @@ describe("compile_grammar", []() {
|
|||
"(block (expression (identifier)))))))");
|
||||
});
|
||||
|
||||
it("handles precedence applied to specific rule subsequences (regression)", [&]() {
|
||||
TSCompileResult result = ts_compile_grammar(R"JSON({
|
||||
"name": "precedence_on_subsequence",
|
||||
|
||||
"extras": [
|
||||
{"type": "STRING", "value": " "}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "function_call"},
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "scope_resolution"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"function_call": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"type": "PREC",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "PREC",
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "do_block"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{
|
||||
"type": "PREC",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{
|
||||
"type": "PREC",
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "SYMBOL", "name": "do_block"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"scope_resolution": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "::"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "::"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"block": {
|
||||
"type": "STRING",
|
||||
"value": "{}"
|
||||
},
|
||||
|
||||
"do_block": {
|
||||
"type": "STRING",
|
||||
"value": "do end"
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z]+"
|
||||
}
|
||||
}
|
||||
})JSON");
|
||||
|
||||
auto language = load_compile_result("precedence_on_subsequence", result);
|
||||
ts_document_set_language(document, language);
|
||||
|
||||
ts_document_set_input_string(document, "a b {}");
|
||||
ts_document_parse(document);
|
||||
assert_root_node("(expression (function_call "
|
||||
"(identifier) "
|
||||
"(expression (function_call (identifier) (block)))))");
|
||||
|
||||
ts_document_set_input_string(document, "a b do end");
|
||||
ts_document_parse(document);
|
||||
assert_root_node("(expression (function_call "
|
||||
"(identifier) "
|
||||
"(expression (identifier)) "
|
||||
"(do_block)))");
|
||||
});
|
||||
|
||||
it("does not allow conflicting precedences", [&]() {
|
||||
string grammar_template = R"JSON({
|
||||
"name": "conflicting_precedence_example",
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ class ParseTableBuilder {
|
|||
LookaheadSet first_set = item_set_builder.get_first_set(item.next_symbol());
|
||||
if (first_set.contains(lookahead)) {
|
||||
shift_items.insert(item);
|
||||
shift_precedence.add(item.precedence());
|
||||
shift_precedence.add(item.production->at(item.step_index - 1).precedence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue