fix(tree-sitter): resolve if keyword ambiguity in behavior nodes
Separate if(expr) condition from if(expr) { child } decorator to fix
grammar conflicts. Simplify decorator_params to accept only integer,
range, or duration.
This commit is contained in:
@@ -130,7 +130,7 @@ module.exports = grammar({
|
||||
|
||||
time: $ => /[0-9]{2}:[0-9]{2}(:[0-9]{2})?/,
|
||||
|
||||
duration: $ => /[0-9]+[hms]([0-9]+[hms])*/,
|
||||
duration: $ => /[0-9]+[dhms]([0-9]+[dhms])*/,
|
||||
|
||||
list: $ => seq('[', commaSep($.value), ']'),
|
||||
|
||||
@@ -232,17 +232,83 @@ module.exports = grammar({
|
||||
behavior_node: $ => choice(
|
||||
$.selector_node,
|
||||
$.sequence_node,
|
||||
$.repeat_node,
|
||||
$.condition_node,
|
||||
$.if_decorator_node,
|
||||
$.decorator_node,
|
||||
$.action_node,
|
||||
$.subtree_node
|
||||
),
|
||||
|
||||
selector_node: $ => seq('?', '{', repeat1($.behavior_node), '}'),
|
||||
// Selector node: choose { ... }
|
||||
selector_node: $ => seq(
|
||||
'choose',
|
||||
optional(field('label', $.identifier)),
|
||||
'{',
|
||||
repeat1($.behavior_node),
|
||||
'}'
|
||||
),
|
||||
|
||||
sequence_node: $ => seq('>', '{', repeat1($.behavior_node), '}'),
|
||||
// Sequence node: then { ... }
|
||||
sequence_node: $ => seq(
|
||||
'then',
|
||||
optional(field('label', $.identifier)),
|
||||
'{',
|
||||
repeat1($.behavior_node),
|
||||
'}'
|
||||
),
|
||||
|
||||
repeat_node: $ => seq('*', '{', $.behavior_node, '}'),
|
||||
// Condition node: if(expr) or when(expr) - NO BRACES
|
||||
condition_node: $ => seq(
|
||||
choice('if', 'when'),
|
||||
'(',
|
||||
field('condition', $.expression),
|
||||
')'
|
||||
),
|
||||
|
||||
// If decorator: if(expr) { child } - WITH BRACES
|
||||
if_decorator_node: $ => seq(
|
||||
'if',
|
||||
'(',
|
||||
field('condition', $.expression),
|
||||
')',
|
||||
'{',
|
||||
field('child', $.behavior_node),
|
||||
'}'
|
||||
),
|
||||
|
||||
// Decorator node: repeat/retry/timeout/etc { child }
|
||||
decorator_node: $ => seq(
|
||||
field('decorator', $.decorator_keyword),
|
||||
optional(field('params', $.decorator_params)),
|
||||
'{',
|
||||
field('child', $.behavior_node),
|
||||
'}'
|
||||
),
|
||||
|
||||
decorator_keyword: $ => choice(
|
||||
'repeat',
|
||||
'invert',
|
||||
'retry',
|
||||
'timeout',
|
||||
'cooldown',
|
||||
'succeed_always',
|
||||
'fail_always'
|
||||
),
|
||||
|
||||
decorator_params: $ => seq(
|
||||
'(',
|
||||
choice(
|
||||
// min..max range (for repeat)
|
||||
seq($.integer, '..', $.integer),
|
||||
// N (for repeat, retry)
|
||||
$.integer,
|
||||
// duration (for timeout, cooldown)
|
||||
$.duration
|
||||
),
|
||||
')'
|
||||
),
|
||||
|
||||
// Action node: action_name or action_name(params)
|
||||
action_node: $ => choice(
|
||||
seq($.identifier, '(', commaSep($.action_param), ')'),
|
||||
$.identifier
|
||||
@@ -255,7 +321,8 @@ module.exports = grammar({
|
||||
$.value
|
||||
),
|
||||
|
||||
subtree_node: $ => seq('@', $.path),
|
||||
// Subtree node: include path::to::subtree
|
||||
subtree_node: $ => seq('include', $.path),
|
||||
|
||||
// Institution declaration
|
||||
institution: $ => seq(
|
||||
@@ -275,12 +342,10 @@ module.exports = grammar({
|
||||
),
|
||||
|
||||
participant: $ => choice(
|
||||
// name { fields }
|
||||
seq($.path, $.block),
|
||||
// name as role { fields }
|
||||
// name as role { fields } (role optional)
|
||||
seq($.path, 'as', $.identifier, $.block),
|
||||
// bare name
|
||||
$.path
|
||||
// name { fields } (block required)
|
||||
seq($.path, $.block)
|
||||
),
|
||||
|
||||
// Location declaration
|
||||
|
||||
@@ -581,7 +581,7 @@
|
||||
},
|
||||
"duration": {
|
||||
"type": "PATTERN",
|
||||
"value": "[0-9]+[hms]([0-9]+[hms])*"
|
||||
"value": "[0-9]+[dhms]([0-9]+[dhms])*"
|
||||
},
|
||||
"list": {
|
||||
"type": "SEQ",
|
||||
@@ -1077,7 +1077,15 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "repeat_node"
|
||||
"name": "condition_node"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "if_decorator_node"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "decorator_node"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
@@ -1094,7 +1102,23 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
"value": "choose"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "label",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
@@ -1118,7 +1142,23 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ">"
|
||||
"value": "then"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "label",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
@@ -1137,20 +1177,74 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"repeat_node": {
|
||||
"condition_node": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "if"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "when"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "condition",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ")"
|
||||
}
|
||||
]
|
||||
},
|
||||
"if_decorator_node": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "*"
|
||||
"value": "if"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "condition",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ")"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "behavior_node"
|
||||
"type": "FIELD",
|
||||
"name": "child",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "behavior_node"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
@@ -1158,6 +1252,127 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"decorator_node": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "decorator",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "decorator_keyword"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "params",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "decorator_params"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "child",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "behavior_node"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"decorator_keyword": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "repeat"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "invert"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "retry"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timeout"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "cooldown"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "succeed_always"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "fail_always"
|
||||
}
|
||||
]
|
||||
},
|
||||
"decorator_params": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "integer"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ".."
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "integer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "integer"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "duration"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ")"
|
||||
}
|
||||
]
|
||||
},
|
||||
"action_node": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
@@ -1260,7 +1475,7 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "@"
|
||||
"value": "include"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
@@ -1331,19 +1546,6 @@
|
||||
"participant": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "path"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "block"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
@@ -1366,8 +1568,17 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "path"
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "path"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "block"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -135,7 +135,15 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "repeat_node",
|
||||
"type": "condition_node",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "decorator_node",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "if_decorator_node",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
@@ -261,6 +269,22 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "condition_node",
|
||||
"named": true,
|
||||
"fields": {
|
||||
"condition": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "expression",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "declaration",
|
||||
"named": true,
|
||||
@@ -316,6 +340,66 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator_keyword",
|
||||
"named": true,
|
||||
"fields": {}
|
||||
},
|
||||
{
|
||||
"type": "decorator_node",
|
||||
"named": true,
|
||||
"fields": {
|
||||
"child": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "behavior_node",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"decorator": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "decorator_keyword",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "decorator_params",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator_params",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "duration",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "dotted_path",
|
||||
"named": true,
|
||||
@@ -447,6 +531,32 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "if_decorator_node",
|
||||
"named": true,
|
||||
"fields": {
|
||||
"child": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "behavior_node",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"condition": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "expression",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "include",
|
||||
"named": true,
|
||||
@@ -836,21 +946,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "repeat_node",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "behavior_node",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "schedule",
|
||||
"named": true,
|
||||
@@ -930,7 +1025,18 @@
|
||||
{
|
||||
"type": "selector_node",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"fields": {
|
||||
"label": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
@@ -945,7 +1051,18 @@
|
||||
{
|
||||
"type": "sequence_node",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"fields": {
|
||||
"label": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
@@ -1222,10 +1339,6 @@
|
||||
"type": ">=",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "?",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "@",
|
||||
"named": false
|
||||
@@ -1262,6 +1375,14 @@
|
||||
"type": "character",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "choose",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "cooldown",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "duration",
|
||||
"named": true
|
||||
@@ -1274,6 +1395,10 @@
|
||||
"type": "enum",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "fail_always",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "false",
|
||||
"named": false
|
||||
@@ -1290,6 +1415,10 @@
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "if",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "include",
|
||||
"named": false
|
||||
@@ -1302,6 +1431,10 @@
|
||||
"type": "integer",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "invert",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "is",
|
||||
"named": false
|
||||
@@ -1350,6 +1483,14 @@
|
||||
"type": "remove",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "repeat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "retry",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "schedule",
|
||||
"named": false
|
||||
@@ -1374,14 +1515,26 @@
|
||||
"type": "string",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "succeed_always",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "then",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "time",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "timeout",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "true",
|
||||
"named": false
|
||||
@@ -1390,6 +1543,10 @@
|
||||
"type": "use",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "when",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "{",
|
||||
"named": false
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user