遇到简单的树顶语法问题

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 所有 运行 您的示例所需的文件,我们会找到你的错误。