使用Citrus for Parsing Expression Grammar进行堆栈级别太深

时间:2014-09-19 20:24:27

标签: ruby recursion grammar peg treetop

我试图在类似Treetop的Citrus for Ruby中使用语法来处理最终将成为布尔逻辑的内容。我收到了一个递归问题,但我不明白为什么会这样。这是我试图处理的文字(最后应该有一个新行):

COMMANDWORD # MYCOMMENT

这是我的Citrus语法(旨在处理更高级的东西):

grammar Grammar
  rule commandset
    command+
  end

  rule command
    identifier command_detail* comment_to_eol* "\n"
  end

  rule command_detail
    assign_expr | expr
  end

  rule assign_expr
    identifier ":=" expr
  end

  rule expr
    # Stack overflow
    or_expr | gtor_expr
    # No problem!
    # or_expr
  end

  rule or_expr
    # Temporarily match everything except a comment...
    [^#]+
    # What I think will be correct in the future...
    # gtor_expr "OR" expr
  end

  rule gtor_expr
    and_expr | gtand_expr
  end

  rule and_expr
    gtand_expr "AND" gtor_expr
  end

  rule gtand_expr
    not_expr | gtnot_expr
  end

  rule not_expr
    "NOT" gtnot_expr | gtand_expr
  end

  rule gtnot_expr
    parens_expr | identifier
  end

  rule parens_expr
    "(" expr ")"
  end

  rule identifier
    ws* [a-zA-Z0-9]+ ws*
  end

  rule ws
    [ ]
  end

  rule comment_to_eol
    "#" [^\n]*
  end
end

重要的事情在规则expr和规则or_expr中。我已对or_expr进行了更改,因此除了评论之外,它还匹配所有内容。如果我坚持使用当前的expr规则,我会得到堆栈溢出。但是,如果我切换它所以它没有在or_expr和gtor_expr之间做出选择它可以正常工作。

我对"选择的理解"是它会尝试按顺序评估它们。如果第一个选择失败,那么它将尝试第二个。在这种情况下,第一个选择显然能够成功,所以如果我包含一个永远不应该采取的第二个选择,为什么会出现堆栈溢出?

1 个答案:

答案 0 :(得分:1)

可能会导致循环,因为gtand_expr - > not_expr,not_expr - > gtand_expr。

我认为您可以用

替换not_expr的规则
not_expr -> "NOT" not_expr | gtnot_expr

你应该尝试使用regexp运算符更简单的规则:

expr -> orexpr
orexpr -> andexpr ("OR" andexpr)*
andexpr -> notexpr ("AND" notexpr)*
notexpr -> "NOT"? atomicexpr
atomicexpr -> id | "(" expr ")"