遇到简单的树顶语法问题
Having trouble with simple tree top grammar
我正在玩 tree top,但我无法使用简单的语法来生成我期望的 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
希望有人能提供一点帮助!
谢谢
您的解析器适用于这两个示例,我刚刚对其进行了测试。尝试在 irb 中删除 类,然后仅 运行 LineParser.new.parse('some | test'),您将看到解析树。
您的测试程序或语法节点模块中有一些有趣的东西。也许您正在向解析器提供意想不到的字符?对于您显示的第二个示例输出,对命令的递归调用必须失败,因此它返回第二个选项。如果是这样,您还必须将 consume_all_input 选项设置为 false,否则它将失败。
但是因为它是递归的,所以它不会在您的命令 (PipedCommand) 下为您提供命令的平面数组。您将获得一个命令,其中包含第一个命令和另一个命令,其中将包含其他两个命令实例。
如果你不想要嵌套的 AST,你应该使用迭代而不是递归。
这可能看起来像
rule commands
head:command tail:( '|' command )*
{
def ast
[head] + tail.elements.map(&:command)
end
}
end
如果这不能帮助您解决问题,请 post 所有 运行 您的示例所需的文件,我们会找到你的错误。
我正在玩 tree top,但我无法使用简单的语法来生成我期望的 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
希望有人能提供一点帮助!
谢谢
您的解析器适用于这两个示例,我刚刚对其进行了测试。尝试在 irb 中删除 类,然后仅 运行 LineParser.new.parse('some | test'),您将看到解析树。
您的测试程序或语法节点模块中有一些有趣的东西。也许您正在向解析器提供意想不到的字符?对于您显示的第二个示例输出,对命令的递归调用必须失败,因此它返回第二个选项。如果是这样,您还必须将 consume_all_input 选项设置为 false,否则它将失败。
但是因为它是递归的,所以它不会在您的命令 (PipedCommand) 下为您提供命令的平面数组。您将获得一个命令,其中包含第一个命令和另一个命令,其中将包含其他两个命令实例。
如果你不想要嵌套的 AST,你应该使用迭代而不是递归。 这可能看起来像
rule commands
head:command tail:( '|' command )*
{
def ast
[head] + tail.elements.map(&:command)
end
}
end
如果这不能帮助您解决问题,请 post 所有 运行 您的示例所需的文件,我们会找到你的错误。