ANTLR v.3-使用语法谓词进行前瞻

时间:2013-02-13 21:15:35

标签: antlr abstract-syntax-tree

还在学习如何正确使用ANTLR ......这是我的问题。

假设您有一个(子集)UML语法和一个ANTLR Lexer / Parser,其中包含以下规则:

    // Parser Rules

    model
    :   'MODEL' IDENTIFIER list_dec
    ;

    list_dec
    :   declaration*
    ;

    declaration
    :   class_dec ';' 
    |   association ';' 
    |   generalization ';'
    |   aggregation ';'
    ; 

    class_dec
    :   'CLASS' IDENTIFIER class_content
    ;

    ...

    association
    :   'RELATION' IDENTIFIER 'ROLES' two_roles
    ;

    two_roles
    :   role ',' role
    ;

    role
    :   'CLASS' IDENTIFIER multiplicity
    ;

    ...

我希望'role'规则只允许IDENTIFIER标记与现有的类IDENTIFIER匹配。换句话说,如果给你一个输入文件并在其上运行词法分析器/解析器,那么所有引用的类(例如关联规则中的IDENTIFIER)都应该存在。问题是类(可能)在运行时可能不存在(它可以在文件中的任何位置声明)。最好的办法是什么?

提前致谢...

1 个答案:

答案 0 :(得分:1)

这可能是在解析之后完成的。解析器为您创建某种树,然后您遍历树并收集有关已声明类的信息,并再次遍历它以验证role树/规则。

当然,有些事情可以通过一些自定义代码完成:

grammar G;

options {
  ...
}

@parser::members {
  java.util.Set<String> declaredClasses = new java.util.HashSet<String>();
}

model
:   'MODEL' IDENTIFIER list_dec
;

...

class_dec
:   'CLASS' id=IDENTIFIER class_content 
    {
      declaredClasses.add($id.text);
    }
;

...

role
:   'CLASS' id=IDENTIFIER multiplicity
    {
      if(!declaredClasses.contains($id.text)) {
        // warning or exception in here
      }
    }
;

...

修改

或使用自定义方法:

@parser::members {
  java.util.Set<String> declaredClasses = new java.util.HashSet<String>();

  void addClass(String id) {
    boolean added = declaredClasses.add(id);
    if(!added) {
      // 'id' was already present, do something, perhaps?
    }
  }

  void checkClass(String id) {
    if(!declaredClasses.contains(id)) {
      // exception, error or warning?
    }
  }
}

...

class_dec
:   'CLASS' id=IDENTIFIER class_content {addClass($id.text);}
;

role
:   'CLASS' id=IDENTIFIER multiplicity {checkClass($id.text);}
;