refactor(tests): migrate remaining grammar.json tests to grammar.js
This commit is contained in:
parent
26fa3a76a5
commit
627617edb4
36 changed files with 560 additions and 1212 deletions
31
test/fixtures/test_grammars/lexical_conflicts_due_to_state_merging/grammar.js
vendored
Normal file
31
test/fixtures/test_grammars/lexical_conflicts_due_to_state_merging/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
module.exports = grammar({
|
||||
name: 'lexical_conflicts_due_to_state_merging',
|
||||
|
||||
rules: {
|
||||
expression: $ => choice(
|
||||
$.conditional,
|
||||
$.quotient,
|
||||
$.regex,
|
||||
$.number,
|
||||
$.parenthesized,
|
||||
),
|
||||
|
||||
conditional: $ => prec.left(1, seq(
|
||||
'if',
|
||||
$.parenthesized,
|
||||
$.expression
|
||||
)),
|
||||
|
||||
quotient: $ => prec.left(seq(
|
||||
$.expression,
|
||||
'/',
|
||||
$.expression
|
||||
)),
|
||||
|
||||
regex: $ => /\/[^/\n]+\//,
|
||||
|
||||
number: $ => /\d+/,
|
||||
|
||||
parenthesized: $ => seq('(', $.expression, ')'),
|
||||
},
|
||||
});
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
"name": "lexical_conflicts_due_to_state_merging",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "conditional"},
|
||||
{"type": "SYMBOL", "name": "regex"},
|
||||
{"type": "SYMBOL", "name": "quotient"},
|
||||
{"type": "SYMBOL", "name": "number"},
|
||||
{"type": "SYMBOL", "name": "parenthesized"}
|
||||
]
|
||||
},
|
||||
|
||||
"conditional": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "if"},
|
||||
{"type": "SYMBOL", "name": "parenthesized"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"quotient": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "/"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"regex": {
|
||||
"type": "PATTERN",
|
||||
"value": "/[^/\n]+/"
|
||||
},
|
||||
|
||||
"number": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\d+"
|
||||
},
|
||||
|
||||
"parenthesized": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "("},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": ")"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
48
test/fixtures/test_grammars/named_precedences/grammar.js
vendored
Normal file
48
test/fixtures/test_grammars/named_precedences/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
module.exports = grammar({
|
||||
name: 'named_precedences',
|
||||
|
||||
conflicts: $ => [
|
||||
[$.expression, $.type],
|
||||
[$.expression, $.nested_type],
|
||||
],
|
||||
|
||||
precedences: $ => [
|
||||
[$.member_expression, "and", "or"],
|
||||
[$.nested_type, "type_intersection", "type_union"],
|
||||
],
|
||||
|
||||
rules: {
|
||||
program: $ => repeat(choice(
|
||||
$.expression_statement,
|
||||
$.declaration_statement,
|
||||
)),
|
||||
|
||||
expression_statement: $ => seq($.expression, ';'),
|
||||
|
||||
declaration_statement: $ => seq($.type, $.expression, ';'),
|
||||
|
||||
expression: $ => choice(
|
||||
$.member_expression,
|
||||
$.binary_expression,
|
||||
$.identifier,
|
||||
),
|
||||
|
||||
member_expression: $ => seq($.expression, '.', $.identifier),
|
||||
|
||||
binary_expression: $ => choice(
|
||||
prec.left('or', seq($.expression, '||', $.expression)),
|
||||
prec.left('and', seq($.expression, '&&', $.expression)),
|
||||
),
|
||||
|
||||
type: $ => choice($.nested_type, $.binary_type, $.identifier),
|
||||
|
||||
nested_type: $ => seq($.identifier, '.', $.identifier),
|
||||
|
||||
binary_type: $ => choice(
|
||||
prec.left('type_union', seq($.type, '||', $.type)),
|
||||
prec.left('type_intersection', seq($.type, '&&', $.type)),
|
||||
),
|
||||
|
||||
identifier: $ => /[a-z]\w+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
{
|
||||
"name": "named_precedences",
|
||||
|
||||
"extras": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "\\s+"
|
||||
}
|
||||
],
|
||||
|
||||
"precedences": [
|
||||
[
|
||||
{"type": "SYMBOL", "name": "member_expression"},
|
||||
{"type": "STRING", "value": "and"},
|
||||
{"type": "STRING", "value": "or"}
|
||||
],
|
||||
[
|
||||
{"type": "SYMBOL", "name": "nested_type"},
|
||||
{"type": "STRING", "value": "type_intersection"},
|
||||
{"type": "STRING", "value": "type_union"}
|
||||
]
|
||||
],
|
||||
|
||||
"conflicts": [
|
||||
["expression", "type"],
|
||||
["expression", "nested_type"]
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"program": {
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression_statement"},
|
||||
{"type": "SYMBOL", "name": "declaration_statement"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"expression_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": ";"}
|
||||
]
|
||||
},
|
||||
|
||||
"declaration_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "type"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": ";"}
|
||||
]
|
||||
},
|
||||
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "member_expression"},
|
||||
{"type": "SYMBOL", "name": "binary_expression"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"member_expression": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "."},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"binary_expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PREC_LEFT",
|
||||
"value": "or",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "||"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "PREC_LEFT",
|
||||
"value": "and",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "&&"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"type": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "nested_type"},
|
||||
{"type": "SYMBOL", "name": "binary_type"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"nested_type": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "STRING", "value": "."},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"binary_type": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PREC_LEFT",
|
||||
"value": "type_union",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "type"},
|
||||
{"type": "STRING", "value": "||"},
|
||||
{"type": "SYMBOL", "name": "type"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "PREC_LEFT",
|
||||
"value": "type_intersection",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "type"},
|
||||
{"type": "STRING", "value": "&&"},
|
||||
{"type": "SYMBOL", "name": "type"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-z]\\w+"
|
||||
}
|
||||
}
|
||||
}
|
||||
15
test/fixtures/test_grammars/named_rule_aliased_as_anonymous/grammar.js
vendored
Normal file
15
test/fixtures/test_grammars/named_rule_aliased_as_anonymous/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
module.exports = grammar({
|
||||
name: 'named_rule_aliased_as_anonymous',
|
||||
|
||||
rules: {
|
||||
a: $ => seq(
|
||||
alias($.b, 'the-alias'),
|
||||
$.c,
|
||||
$.b,
|
||||
),
|
||||
|
||||
b: _ => 'B',
|
||||
|
||||
c: _ => 'C',
|
||||
},
|
||||
});
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"name": "named_rule_aliased_as_anonymous",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"a": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "ALIAS",
|
||||
"value": "the-alias",
|
||||
"named": false,
|
||||
"content": {"type": "SYMBOL", "name": "b"}
|
||||
},
|
||||
{"type": "SYMBOL", "name": "c"},
|
||||
{"type": "SYMBOL", "name": "b"}
|
||||
]
|
||||
},
|
||||
|
||||
"b": {
|
||||
"type": "STRING",
|
||||
"value": "B"
|
||||
},
|
||||
|
||||
"c": {
|
||||
"type": "STRING",
|
||||
"value": "C"
|
||||
}
|
||||
}
|
||||
}
|
||||
22
test/fixtures/test_grammars/nested_inlined_rules/grammar.js
vendored
Normal file
22
test/fixtures/test_grammars/nested_inlined_rules/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
module.exports = grammar({
|
||||
name: 'nested_inlined_rules',
|
||||
|
||||
inline: $ => [
|
||||
$.top_level_item,
|
||||
$.statement,
|
||||
],
|
||||
|
||||
rules: {
|
||||
program: $ => repeat1($.top_level_item),
|
||||
|
||||
top_level_item: $ => choice($.statement, '!'),
|
||||
|
||||
statement: $ => choice($.expression_statement, $.return_statement),
|
||||
|
||||
return_statement: $ => seq('return', $.number, ';'),
|
||||
|
||||
expression_statement: $ => seq($.number, ';'),
|
||||
|
||||
number: _ => /\d+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"name": "nested_inlined_rules",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"inline": [
|
||||
"top_level_item",
|
||||
"statement"
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"program": {
|
||||
"type": "REPEAT1",
|
||||
"content": {"type": "SYMBOL", "name": "top_level_item"}
|
||||
},
|
||||
|
||||
"top_level_item": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "statement"},
|
||||
{"type": "STRING", "value": "!"}
|
||||
]
|
||||
},
|
||||
|
||||
"statement": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression_statement"},
|
||||
{"type": "SYMBOL", "name": "return_statement"}
|
||||
]
|
||||
},
|
||||
|
||||
"return_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "return"},
|
||||
{"type": "SYMBOL", "name": "number"},
|
||||
{"type": "STRING", "value": ";"}
|
||||
]
|
||||
},
|
||||
|
||||
"expression_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "number"},
|
||||
{"type": "STRING", "value": ";"}
|
||||
]
|
||||
},
|
||||
|
||||
"number": {"type": "PATTERN", "value": "\\d+"}
|
||||
}
|
||||
}
|
||||
19
test/fixtures/test_grammars/partially_resolved_conflict/grammar.js
vendored
Normal file
19
test/fixtures/test_grammars/partially_resolved_conflict/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
module.exports = grammar({
|
||||
name: 'partially_resolved_conflict',
|
||||
|
||||
rules: {
|
||||
expression: $ => choice($.binary, $.identifier),
|
||||
|
||||
unary_a: $ => prec(2, seq('!', $.expression)),
|
||||
|
||||
unary_b: $ => prec(2, seq('!', $.expression)),
|
||||
|
||||
binary: $ => seq(
|
||||
choice($.unary_a, $.unary_b, $.expression),
|
||||
'<',
|
||||
$.expression,
|
||||
),
|
||||
|
||||
identifier: _ => /[a-z]+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
{
|
||||
"name": "partially_resolved_conflict",
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "binary"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"unary_a": {
|
||||
"type": "PREC",
|
||||
"value": 2,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "!"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"unary_b": {
|
||||
"type": "PREC",
|
||||
"value": 2,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "!"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"binary": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "unary_a"},
|
||||
{"type": "SYMBOL", "name": "unary_b"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
{"type": "STRING", "value": "<"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-z]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
17
test/fixtures/test_grammars/precedence_on_single_child_missing/grammar.js
vendored
Normal file
17
test/fixtures/test_grammars/precedence_on_single_child_missing/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
module.exports = grammar({
|
||||
name: 'precedence_on_single_child_missing',
|
||||
|
||||
rules: {
|
||||
expression: $ => choice($.function_call, $.identifier),
|
||||
|
||||
function_call: $ => prec.right(choice(
|
||||
seq($.identifier, $.expression),
|
||||
seq($.identifier, $.block),
|
||||
seq($.identifier, $.expression, $.block),
|
||||
)),
|
||||
|
||||
block: $ => seq('{', $.expression, '}'),
|
||||
|
||||
identifier: _ => /[a-zA-Z]+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
{
|
||||
"name": "precedence_on_single_child_missing",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "function_call"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"function_call": {
|
||||
"type": "PREC_RIGHT",
|
||||
"value": 0,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"block": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "{"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "}"}
|
||||
]
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
17
test/fixtures/test_grammars/precedence_on_single_child_negative/grammar.js
vendored
Normal file
17
test/fixtures/test_grammars/precedence_on_single_child_negative/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
module.exports = grammar({
|
||||
name: 'precedence_on_single_child_negative',
|
||||
|
||||
rules: {
|
||||
expression: $ => choice($.function_call, $.identifier),
|
||||
|
||||
function_call: $ => prec.right(-1, choice(
|
||||
seq($.identifier, $.expression),
|
||||
seq($.identifier, $.block),
|
||||
seq($.identifier, $.expression, $.block),
|
||||
)),
|
||||
|
||||
block: $ => seq('{', $.expression, '}'),
|
||||
|
||||
identifier: _ => /[a-zA-Z]+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
{
|
||||
"name": "precedence_on_single_child_negative",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "function_call"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"function_call": {
|
||||
"type": "PREC_RIGHT",
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"block": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "{"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "}"}
|
||||
]
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
17
test/fixtures/test_grammars/precedence_on_single_child_positive/grammar.js
vendored
Normal file
17
test/fixtures/test_grammars/precedence_on_single_child_positive/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
module.exports = grammar({
|
||||
name: 'precedence_on_single_child_positive',
|
||||
|
||||
rules: {
|
||||
expression: $ => choice($.function_call, $.identifier),
|
||||
|
||||
function_call: $ => prec.right(1, choice(
|
||||
seq($.identifier, $.expression),
|
||||
seq($.identifier, $.block),
|
||||
seq($.identifier, $.expression, $.block),
|
||||
)),
|
||||
|
||||
block: $ => seq('{', $.expression, '}'),
|
||||
|
||||
identifier: _ => /[a-zA-X]+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
{
|
||||
"name": "precedence_on_single_child_positive",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "function_call"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"function_call": {
|
||||
"type": "PREC_RIGHT",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "identifier"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "SYMBOL", "name": "block"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"block": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "{"},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "}"}
|
||||
]
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
30
test/fixtures/test_grammars/precedence_on_subsequence/grammar.js
vendored
Normal file
30
test/fixtures/test_grammars/precedence_on_subsequence/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
module.exports = grammar({
|
||||
name: 'precedence_on_subsequence',
|
||||
|
||||
rules: {
|
||||
expression: $ => prec.left(choice(
|
||||
$.function_call,
|
||||
$.identifier,
|
||||
$.scope_resolution,
|
||||
)),
|
||||
|
||||
function_call: $ => choice(
|
||||
seq($.identifier, $.expression),
|
||||
prec(1, seq($.identifier, $.block)),
|
||||
prec(-1, seq($.identifier, $.do_block)),
|
||||
seq($.identifier, prec(1, seq($.expression, $.block))),
|
||||
seq($.identifier, prec(-1, seq($.expression, $.do_block))),
|
||||
),
|
||||
|
||||
scope_resolution: $ => prec.left(1, choice(
|
||||
seq($.expression, '::', $.expression),
|
||||
seq('::', $.expression),
|
||||
)),
|
||||
|
||||
block: _ => '{}',
|
||||
|
||||
do_block: _ => 'do end',
|
||||
|
||||
identifier: _ => /[a-zA-Z]+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
{
|
||||
"name": "precedence_on_subsequence",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"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]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
test/fixtures/test_grammars/precedence_on_token/grammar.js
vendored
Normal file
36
test/fixtures/test_grammars/precedence_on_token/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
module.exports = grammar({
|
||||
name: 'precedence_on_token',
|
||||
|
||||
extras: $ => [
|
||||
/\s/,
|
||||
$.comment,
|
||||
],
|
||||
|
||||
rules: {
|
||||
program: $ => repeat(choice(
|
||||
$.string,
|
||||
$.regex,
|
||||
$.identifier,
|
||||
$.slash,
|
||||
)),
|
||||
|
||||
comment: _ => token(prec(1, /\/\/.*|\/\*[^*]*\*\//)),
|
||||
|
||||
string: $ => seq(
|
||||
'"',
|
||||
repeat(choice(
|
||||
token(prec(2, /[^\"\n\\]+/)),
|
||||
$.escape_sequence,
|
||||
)),
|
||||
'"',
|
||||
),
|
||||
|
||||
escape_sequence: _ => /\\./,
|
||||
|
||||
regex: _ => /\/[^\/\n]+\/[a-z]*/,
|
||||
|
||||
identifier: _ => /[a-z]\w*/,
|
||||
|
||||
slash: _ => '/',
|
||||
},
|
||||
});
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"name": "precedence_on_token",
|
||||
|
||||
"extras": [
|
||||
{"type": "SYMBOL", "name": "comment"},
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"program": {
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "string"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "regex"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "slash"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"comment": {
|
||||
"type": "TOKEN",
|
||||
"content": {
|
||||
"type": "PREC",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "//.*|/\\*[^*]*\\*/"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"string": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "\""},
|
||||
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "TOKEN",
|
||||
"content": {
|
||||
"type": "PREC",
|
||||
"value": 2,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\"\n\\\\]+"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "escape_sequence"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{"type": "STRING", "value": "\""}
|
||||
]
|
||||
},
|
||||
|
||||
"escape_sequence": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\\\."
|
||||
},
|
||||
|
||||
"regex": {
|
||||
"type": "PATTERN",
|
||||
"value": "/[^/\n]+/[a-z]*"
|
||||
},
|
||||
|
||||
"identifier": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-z]\\w*"
|
||||
},
|
||||
|
||||
"slash": {
|
||||
"type": "STRING",
|
||||
"value": "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
test/fixtures/test_grammars/readme_grammar/grammar.js
vendored
Normal file
36
test/fixtures/test_grammars/readme_grammar/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
module.exports = grammar({
|
||||
name: 'readme_grammar',
|
||||
|
||||
// Things that can appear anywhere in the language, like comments
|
||||
// and whitespace, are expressed as 'extras'.
|
||||
extras: $ => [
|
||||
/\s/,
|
||||
$.comment,
|
||||
],
|
||||
|
||||
rules: {
|
||||
// The first rule listed in the grammar becomes the 'start rule'.
|
||||
expression: $ => choice(
|
||||
$.sum,
|
||||
$.product,
|
||||
$.number,
|
||||
$.variable,
|
||||
seq('(', $.expression, ')'),
|
||||
),
|
||||
|
||||
// Tokens like '+' and '*' are described directly within the
|
||||
// grammar's rules, as opposed to in a separate lexer description.
|
||||
sum: $ => prec.left(1, seq($.expression, '+', $.expression)),
|
||||
|
||||
// Ambiguities can be resolved at compile time by assigning precedence
|
||||
// values to rule subtrees.
|
||||
product: $ => prec.left(2, seq($.expression, '*', $.expression)),
|
||||
|
||||
// Tokens can be specified using ECMAScript regexps.
|
||||
number: _ => /\d+/,
|
||||
|
||||
comment: _ => /#.*/,
|
||||
|
||||
variable: _ => /[a-zA-Z]\w*/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
{
|
||||
"name": "readme_grammar",
|
||||
|
||||
// Things that can appear anywhere in the language, like comments
|
||||
// and whitespace, are expressed as 'extras'.
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"},
|
||||
{"type": "SYMBOL", "name": "comment"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
|
||||
// The first rule listed in the grammar becomes the 'start rule'.
|
||||
"expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "sum"},
|
||||
{"type": "SYMBOL", "name": "product"},
|
||||
{"type": "SYMBOL", "name": "number"},
|
||||
{"type": "SYMBOL", "name": "variable"},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "("},
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": ")"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Tokens like '+' and '*' are described directly within the
|
||||
// grammar's rules, as opposed to in a separate lexer description.
|
||||
"sum": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "+"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Ambiguities can be resolved at compile time by assigning precedence
|
||||
// values to rule subtrees.
|
||||
"product": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 2,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "expression"},
|
||||
{"type": "STRING", "value": "*"},
|
||||
{"type": "SYMBOL", "name": "expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Tokens can be specified using ECMAScript regexps.
|
||||
"number": {"type": "PATTERN", "value": "\\d+"},
|
||||
"comment": {"type": "PATTERN", "value": "#.*"},
|
||||
"variable": {"type": "PATTERN", "value": "[a-zA-Z]\\w*"}
|
||||
}
|
||||
}
|
||||
7
test/fixtures/test_grammars/start_rule_is_blank/grammar.js
vendored
Normal file
7
test/fixtures/test_grammars/start_rule_is_blank/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = grammar({
|
||||
name: 'start_rule_is_blank',
|
||||
|
||||
rules: {
|
||||
first_rule: _ => blank(),
|
||||
},
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"name": "start_rule_is_blank",
|
||||
"rules": {
|
||||
"first_rule": {"type": "BLANK"}
|
||||
}
|
||||
}
|
||||
7
test/fixtures/test_grammars/start_rule_is_token/grammar.js
vendored
Normal file
7
test/fixtures/test_grammars/start_rule_is_token/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = grammar({
|
||||
name: 'start_rule_is_token',
|
||||
|
||||
rules: {
|
||||
first_rule: _ => 'the-value',
|
||||
},
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"name": "start_rule_is_token",
|
||||
"rules": {
|
||||
"first_rule": {"type": "STRING", "value": "the-value"}
|
||||
}
|
||||
}
|
||||
20
test/fixtures/test_grammars/unicode_classes/grammar.js
vendored
Normal file
20
test/fixtures/test_grammars/unicode_classes/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
module.exports = grammar({
|
||||
name: 'unicode_classes',
|
||||
|
||||
rules: {
|
||||
program: $ => repeat(choice(
|
||||
$.lower,
|
||||
$.upper,
|
||||
$.math_sym,
|
||||
$.letter_number,
|
||||
)),
|
||||
|
||||
lower: _ => /\p{Ll}\p{L}*/,
|
||||
|
||||
upper: _ => /\p{Lu}\p{L}*/,
|
||||
|
||||
math_sym: _ => /\p{Sm}+/,
|
||||
|
||||
letter_number: _ => /\p{Letter_Number}/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "unicode_classes",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"program": {
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "lower"},
|
||||
{"type": "SYMBOL", "name": "upper"},
|
||||
{"type": "SYMBOL", "name": "math_sym"},
|
||||
{"type": "SYMBOL", "name": "letter_number"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"lower": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\p{Ll}\\p{L}*"
|
||||
},
|
||||
|
||||
"upper": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\p{Lu}\\p{L}*"
|
||||
},
|
||||
|
||||
"math_sym": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\p{Sm}+"
|
||||
},
|
||||
|
||||
"letter_number": {
|
||||
"type": "PATTERN",
|
||||
"value": "\\p{Letter_Number}"
|
||||
}
|
||||
}
|
||||
}
|
||||
27
test/fixtures/test_grammars/unused_rules/grammar.js
vendored
Normal file
27
test/fixtures/test_grammars/unused_rules/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
module.exports = grammar({
|
||||
name: 'unused_rules',
|
||||
|
||||
rules: {
|
||||
a: $ => seq($.d, $.h),
|
||||
|
||||
b: _ => 'B',
|
||||
|
||||
c: _ => 'C',
|
||||
|
||||
d: $ => seq($.e, $.f),
|
||||
|
||||
e: _ => 'E',
|
||||
|
||||
f: _ => 'F',
|
||||
|
||||
g: _ => 'G',
|
||||
|
||||
h: $ => seq($.i, $.j),
|
||||
|
||||
i: _ => 'I',
|
||||
|
||||
j: _ => 'J',
|
||||
|
||||
k: _ => 'K',
|
||||
},
|
||||
});
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
{
|
||||
"name": "unused_rules",
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"a": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "d"},
|
||||
{"type": "SYMBOL", "name": "h"}
|
||||
]
|
||||
},
|
||||
|
||||
"b": {
|
||||
"type": "STRING",
|
||||
"value": "B"
|
||||
},
|
||||
|
||||
"c": {
|
||||
"type": "STRING",
|
||||
"value": "C"
|
||||
},
|
||||
|
||||
"d": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "e"},
|
||||
{"type": "SYMBOL", "name": "f"}
|
||||
]
|
||||
},
|
||||
|
||||
"e": {
|
||||
"type": "STRING",
|
||||
"value": "E"
|
||||
},
|
||||
|
||||
"f": {
|
||||
"type": "STRING",
|
||||
"value": "F"
|
||||
},
|
||||
|
||||
"g": {
|
||||
"type": "STRING",
|
||||
"value": "G"
|
||||
},
|
||||
|
||||
"h": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "i"},
|
||||
{"type": "SYMBOL", "name": "j"}
|
||||
]
|
||||
},
|
||||
|
||||
"i": {
|
||||
"type": "STRING",
|
||||
"value": "I"
|
||||
},
|
||||
|
||||
"j": {
|
||||
"type": "STRING",
|
||||
"value": "J"
|
||||
},
|
||||
|
||||
"k": {
|
||||
"type": "STRING",
|
||||
"value": "K"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
test/fixtures/test_grammars/uses_current_column/grammar.js
vendored
Normal file
36
test/fixtures/test_grammars/uses_current_column/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
module.exports = grammar({
|
||||
name: 'uses_current_column',
|
||||
|
||||
externals: $ => [
|
||||
$._indent,
|
||||
$._dedent,
|
||||
$._newline,
|
||||
],
|
||||
|
||||
rules: {
|
||||
block: $ => repeat1($._statement),
|
||||
|
||||
_statement: $ => seq($._expression, $._newline),
|
||||
|
||||
_expression: $ => choice(
|
||||
$.do_expression,
|
||||
$.binary_expression,
|
||||
$.identifier,
|
||||
),
|
||||
|
||||
do_expression: $ => seq(
|
||||
'do',
|
||||
$._indent,
|
||||
$.block,
|
||||
$._dedent,
|
||||
),
|
||||
|
||||
binary_expression: $ => prec.left(1, seq(
|
||||
$._expression,
|
||||
choice('=', '+', '-'),
|
||||
$._expression,
|
||||
)),
|
||||
|
||||
identifier: _ => /\w+/,
|
||||
},
|
||||
});
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
{
|
||||
"name": "uses_current_column",
|
||||
|
||||
"externals": [
|
||||
{"type": "SYMBOL", "name": "_indent"},
|
||||
{"type": "SYMBOL", "name": "_dedent"},
|
||||
{"type": "SYMBOL", "name": "_newline"}
|
||||
],
|
||||
|
||||
"extras": [
|
||||
{"type": "PATTERN", "value": "\\s"}
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"block": {
|
||||
"type": "REPEAT1",
|
||||
"content": {"type": "SYMBOL", "name": "_statement"}
|
||||
},
|
||||
|
||||
"_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "_expression"},
|
||||
{"type": "SYMBOL", "name": "_newline"}
|
||||
]
|
||||
},
|
||||
|
||||
"_expression": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "do_expression"},
|
||||
{"type": "SYMBOL", "name": "binary_expression"},
|
||||
{"type": "SYMBOL", "name": "identifier"}
|
||||
]
|
||||
},
|
||||
|
||||
"do_expression": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "do"},
|
||||
{"type": "SYMBOL", "name": "_indent"},
|
||||
{"type": "SYMBOL", "name": "block"},
|
||||
{"type": "SYMBOL", "name": "_dedent"}
|
||||
]
|
||||
},
|
||||
|
||||
"binary_expression": {
|
||||
"type": "PREC_LEFT",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{"type": "SYMBOL", "name": "_expression"},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{"type": "STRING", "value": "="},
|
||||
{"type": "STRING", "value": "+"},
|
||||
{"type": "STRING", "value": "-"}
|
||||
]
|
||||
},
|
||||
{"type": "SYMBOL", "name": "_expression"}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"identifier": {"type": "PATTERN", "value": "\\w+"}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue