树顶语法无限循环

时间:2011-05-24 00:52:34

标签: ruby abstract-syntax-tree treetop

我对于一种新的编程语言有了一些想法,所以我想我会尝试实现它。一位朋友建议我尝试使用Treetop(Ruby gem)来创建一个解析器。 Treetop的文档稀少,我以前从未做过这样的事情。

我的解析器就像它有一个无限循环,但没有堆栈跟踪;事实证明难以追查。有人能指出我的入门级解析/ AST指南的方向吗?我真的需要一些列出规则,常用用法等东西来使用像Treetop这样的工具。我的解析器语法在GitHub,以防有人希望帮助我改进它。

class {
  initialize = lambda (name) {
    receiver.name = name
  }

  greet = lambda {
    IO.puts("Hello, #{receiver.name}!")
  }
}.new(:World).greet()

2 个答案:

答案 0 :(得分:7)

我让treetop将您的语言编译成.rb文件。这让我有所了解:

$ tt -o /tmp/rip.rb /tmp/rip.treetop

然后我用这个小存根来重新创建循环:

require 'treetop'
load '/tmp/rip.rb'
RipParser.new.parse('')

这就挂了。现在,不是那么有趣!空字符串可以再现您的问题中的十几行示例。

为了找出它挂起的位置,我使用Emacs键盘宏来编辑rip.rb,在每个方法的条目中添加一个调试语句。例如:

def _nt_root
  p [__LINE__, '_nt_root'] #DEBUG
  start_index = index

现在我们可以看到循环的范围:

[16, "root"]
[21, "_nt_root"]
[57, "_nt_statement"]
...
[3293, "_nt_eol"]
[3335, "_nt_semicolon"]
[3204, "_nt_comment"]
[57, "_nt_statement"]
[57, "_nt_statement"]
[57, "_nt_statement"]
...

从那里进一步调试显示允许整数为空字符串:

rule integer
   digit*
end

这间接允许语句为空字符串,顶级规则statement*永远使用空语句。将*更改为+会修复循环,但会显示另一个问题:

/tmp/rip.rb:777:in `_nt_object': stack level too deep (SystemStackError)
        from /tmp/rip.rb:757:in `_nt_compound_object'
        from /tmp/rip.rb:1726:in `_nt_range'
        from /tmp/rip.rb:1671:in `_nt_special_literals'
        from /tmp/rip.rb:825:in `_nt_literal_object'
        from /tmp/rip.rb:787:in `_nt_object'
        from /tmp/rip.rb:757:in `_nt_compound_object'
        from /tmp/rip.rb:1726:in `_nt_range'
        from /tmp/rip.rb:1671:in `_nt_special_literals'
         ... 3283 levels...

Range通过special_literals,literal_object,object和compound_object间接地进行左递归。树梢,当面对左递归时,吃掉堆叠直到它呕吐。我没有快速解决这个问题,但至少从现在开始你已经有了一个堆栈跟踪。

此外,这不是您的直接问题,但digit的定义很奇怪:它可以是一位数,也可以是多位数。这会导致digit*digit+允许(可能)非法整数1________2

答案 1 :(得分:1)

我非常喜欢Language Implementation Patterns by Parr;因为Parr创建了ANTLR解析器生成器,所以它是他在整本书中使用的工具,但它应该足够简单,可以从中学到它。

我真正喜欢它的是每个例子在前一个例子上的成长方式;他没有开始使用具有巨大AST功能的解析器,而是慢慢地引入需要越来越多“后端智能”来完成工作的问题,因此本书与需要解析的语言一起很好地扩展。

我希望它更深入地涵盖了人们可以编写的语言类型,并在设计语言时提供 Do's Do Not Do's 的建议。我已经看到一些语言非常难以解析,我希望更多地了解可能以不同方式做出的设计决策。