如何解决相似结构的保姆匹配
我正在尝试为 minecraft 函数语法创建一个 tree-sitter。
语言的结构如下所示:
command @e[key=value] other args
我在上面的例子中遇到了第二个参数(目标选择器)中的值的问题。这个值可以是很多东西,比如字符串、数字、布尔值和两个相似的对象结构(NBT 和记分板对象)。
以下是每个示例:
NBT
{key:value}
记分板对象
{key=number} // where number is: N,..N,N..,or N..N
// unrelated code removed
module.exports = grammar({
name: "mcfunction",rules: {
root: $ => repeat(
choice(
$.command
)
),command: $ => prec.right(seq(
field("command_name",$.identifier),repeat(
choice(
$.selector
)
),"\n"
)),identifier: $ => /[A-Za-z][\w-]+/,number: $ => prec(1,/-?\d+(\.\d+)?/),boolean: $ => choice(
"true","false"
),string: $ => seq(
"\"",repeat(
choice(
$._escape_sequence,/[^"]/
)
),"\""
),_escape_sequence: $ => seq("\\","\""),selector: $ => seq(
token(
seq(
"@",choice(
"p","a","e","s","r"
)
)
),optional(
seq(
token.immediate("["),optional(
repeat(
seq(
$.selector_option,optional(",")
)
)
),"]"
)
),),selector_option: $ => seq(
$.selector_key,"=",$.selector_value
),selector_key: $ => /[a-z_-]+/,selector_value: $ => choice(
$.item,$.path,$.selector_key,$.selector_number,$.number,$.boolean,$.selector_object
),selector_number: $ => prec.right(1,choice(
seq(
"..",$.number
),seq(
$.number,"..",".."
),$.number
)),selector_object: $ => choice(
seq(
"{",repeat(
seq(
$.selector_score,")
)
),"}"
),seq(
"{",repeat(
seq(
$.selector_nbt,"}"
)
),selector_nbt: $ => seq(
$.nbt_object_key,":",$.nbt_object_value
),selector_score: $ => seq(
field("selector_score_key",$.selector_key),field("selector_score_value",$.selector_number)
),_namespace: $ => /[a-z_-]+:/,item: $ => seq(
$._namespace,$.selector_key
),path: $ => seq(
choice($.item,/[a-z_]+/),repeat1(
token("/",/[a-z_]/)
)
),nbt: $ => choice(
$.nbt_array,$.nbt_object
),nbt_object: $ => seq(
"{",repeat(
seq(
$.nbt_object_key,$.nbt_object_value,")
)
),"}"
),nbt_array: $ => seq(
"[",repeat(
seq(
$.nbt_object_value,"]"
),nbt_object_key: $ => choice(
$.string,$.identifier
),nbt_object_value: $ => choice(
$.string,$.nbt_number,$.nbt
),nbt_number: $ => seq(
$.number,field("nbt_number_suffix",optional(choice("l","d","f","b")))
)
}
});
但是,如果我编译并解析 test @e[scores={example=1..}]
,我会得到:
(root [0,0] - [6,0]
(command [0,0] - [1,0]
command_name: (identifier [0,0] - [0,4])
(selector [0,5] - [0,29]
(selector_option [0,8] - [0,28]
(selector_key [0,14])
(selector_value [0,15] - [0,28]
(selector_object [0,28]
(ERROR [0,16] - [0,27]
(nbt_object_key [0,23]
(identifier [0,23]))))))))
tests/test.mcfunction 0 ms (ERROR [0,27])
预期:应该是ERROR
而不是selector_score
,并且应该有score_key
和score_value
。
如果我从 selector_nbt
中删除 selector_object
序列,则不会发生这种情况。但是,如果在使用 nbt 数据的命令上运行解析(使用两个序列或仅使用 selector_nbt
),则不会出现错误。
我做错了什么?
解决方法
我通过使用两个冲突键的 choice
解决了这个问题,如下所示:
choice(
alias($.key_1,$.key_2),$.key_2
)
GitHub 上的 ahlinc 回答:
您可以通过为 selector_key
终端而不是 identifier
终端分配词法分析器优先级来修复上述语法的错误,例如:
selector_key: $ => token(prec(1,/[a-z_-]+/)),
但你需要注意的是,你使用了冲突的正则表达式:
identifier: $ => /[A-Za-z][\w-]+/,selector_key: $ => token(prec(1,
如果无法重写上述正则表达式以使其不存在冲突,那么您可能需要此处描述的解决方法:#1287 (reply in thread)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。