有简单的树顶语法的麻烦

时间:2015-02-20 09:07:18

标签: peg treetop

我正在玩树顶游戏而且我只是不能使用简单的语法来生成我想要的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

希望有人可以提供帮助!

由于

1 个答案:

答案 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

如果这无法帮助您解决问题,请发布所有运行示例所需的文件,我们会为您找到错误。