ruby – 树顶语法无限循环

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

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

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

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

解决方法

我让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"]
...

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

rule integer
   digit*
end

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

/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...

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

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

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...