我正在玩树顶游戏而且我只是不能使用简单的语法来生成我想要的AST。
我的规则是
1:LINE可以由一个或多个PIPED COMMAND组成; 2:PIPED COMMAND是由|分隔的一个或多个COMMAND 3:COMMAND是由空格分隔的一个或多个IDENTIFIERS
我希望像这样的树
hello | abc | def ; abc | test ; cats ;
生成这样的树
Line
PipedCommand
Command
Identifier hello
Command
Identifier abc
Command
Identifier def
PipedCommand
Command
Identifier abc
Command
Identifier test
PipedCommand
Command
Identifier cats
然而,即使只是正确地返回管道命令,我也无法得到它,如果我指定的数量超过2,结果就搞砸了
> test | abc
[Command+Command0 offset=0, "test " (identifier):
Identifier+Identifier0 offset=0, "test",
Command+Command0 offset=6, " abc" (identifier):
Identifier+Identifier0 offset=7, "abc"]
> test | abc | def
[Command+Command0 offset=0, "test " (identifier):
Identifier+Identifier0 offset=0, "test"]
>
语法目前看起来像:
grammar Line
rule commands
(command space? '|' commands space?) <Commands> / command
end
rule command
space? identifier space? <Command>
end
rule identifier
[a-zA-Z] [a-zA-Z0-9_]* <Identifier>
end
rule space
[\s]+
end
end
希望有人可以提供帮助!
由于
答案 0 :(得分:1)
你的解析器适用于这两个例子,我刚测试过它。尝试删除类,然后在irb中运行LineParser.new.parse(&#39; some | test&#39;),您将看到解析树。
您的测试程序或语法节点模块中有一些有趣的东西。也许你会在解析器中输入一个意外的角色?使用您显示的第二个示例输出,对命令的递归调用必须失败,因此它返回第二个选项。如果是这样,您还必须将consume_all_input选项设置为false,否则它将失败。
但是因为它是递归的,所以它不会在你的命令(PipedCommand)下给你一个平面的Command数组。您将获得第一个命令和另一个命令的命令,其中包含命令的其他两个实例。
如果您不想要嵌套AST,则应使用迭代而不是递归。 这可能看起来像
rule commands
head:command tail:( '|' command )*
{
def ast
[head] + tail.elements.map(&:command)
end
}
end
如果这无法帮助您解决问题,请发布所有运行示例所需的文件,我们会为您找到错误。