【问题标题】:How to generate a list from a * rule in ANTLR3?如何从 ANTLR3 中的 * 规则生成列表?
【发布时间】:2014-12-05 23:22:15
【问题描述】:

我的语法如下:

grammar Test;

options {
  lang = Python;
}

declaration returns [value]
    :     'enum' ID { statement* }
                 { $value = {'id': $ID.text,
                             'fields': $statement.value}
                 }
    ;

statement returns [value]
    :     ID ':' INT ';' { $value = {'id': $ID.text, 'value': int($INT.text)} }
    ;

解析类型的语法:

enum Test {
  Foo: 3;
  Bar: 5;
}

但是,我正在努力将 statement* 规则放入语句列表中。我希望我的最终解析对象看起来像:

declaration = {
  'id': 'Test',
  'fields': [
    {'id': 'Foo', 'value': 3},
    {'id': 'Bar', 'value': 5},
}

我可以正确解析每个statement 结果,因此每个$statement.value 都是正确的。 但是,鉴于规则declarationstatement* 上的星号,有没有办法可以轻松地将其压缩为字段列表?我希望有某种语法可以让我免费获得这个选项。

现在这只是最后一条语句,所以它返回:

declaration = {
  'id': 'Test',
  'fields': [
    {'id': 'Bar', 'value': 5},
}

我想要一个通用的解决方案,因为我的语法有很多形式的规则:

some_declaration
      :     keyword ID '{' declaration_statement* '}'
      ;

注意:我是用 Python 编写的。 我尝试将其编码为解析器,然后是树语法,但即使这样,最后一个元素也是我得到的唯一元素,其余元素都被丢弃了。

【问题讨论】:

    标签: python parsing antlr grammar antlr3


    【解决方案1】:

    你可以这样做:

    declaration returns [value]
        :     'enum' ID 
                     { $value = {'id': $ID.text,
                                 'fields': []}
                     }
               '{' (r=statement
                     { $value['fields'].append($r.value) }
                 )*
               '}'
        ;
    

    或者您也可以将您的字段列表作为参数传递给语句规则,并在那里附加新值。像这样的:

    declaration returns [value]
        :     'enum' ID 
                     { $value = {'id': $ID.text,
                                 'fields': []}
                     }
                     { list = $value['fields']
                     }
                '{' statement[list]* '}'
        ;
    
    statement[list]
        :     ID ':' INT ';' { $list.append({'id': $ID.text, 'value': int($INT.text)}) }
        ;
    

    取决于你想要什么,但可能第一个选项更好一点。

    您可以在此处找到更多关于将值从一条规则返回到另一条规则的示例: Two basic ANTLR questions

    【讨论】:

    • 谢谢。我最终使用了您提到的第一个构造。另外,+= 操作符有什么用呢?
    • 您的意思是使用+= 而不是append(例如$value['fields']+=$r.value$value['fields'].append($r.value))?略有不同,请查看this post
    • 啊,不,我的意思是 antlr3 += 运算符。我在表单中看到了它的一些用法:c=ID ('.' c+=ID)+
    • 啊哈! += 对于拥有匹配标记列表或收集 AST 很有用,但我认为您不能简单地将其与语法规则一起使用。所以你不能只说l+=statement(你可能需要在这里)。也许,您可以在声明中说(ids+=ID ':' ints+=INT)*,而不是statement*,并处理idsints 列表。但这不是一个好的解决方案;) 查看The Definitive ANTLR Reference 的第 4.3 节,或者尝试将 statement 中的 ID 替换为 ids+=ID 并查看生成的 Python 代码会发生什么在那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    相关资源
    最近更新 更多