代码之家  ›  专栏  ›  技术社区  ›  peter.murray.rust

ANTLR:“规则作用域上缺少属性访问”问题

  •  6
  • peter.murray.rust  · 技术社区  · 15 年前

    我正在尝试构建一个分析标记语句的antlr语法,例如:

    DT The NP cat VB ate DT a NP rat
    

    还有语法:

    fragment TOKEN  :   (('A'..'Z') | ('a'..'z'))+;
    fragment WS :   (' ' | '\t')+;
    WSX :   WS;
    DTTOK   :   ('DT' WS TOKEN);
    NPTOK   :   ('NP' WS TOKEN);
    nounPhrase:  (DTTOK WSX NPTOK);
    chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase+")");};
    

    语法生成器生成“ missing attribute access on rule scope: nounPhrase “在最后一行。

    [我对Antlr还是个新手,虽然有些语法有用,但它仍然是试验和错误。我还经常在运行像这样小的语法时出现“内存不足”错误-欢迎任何帮助。]

    我正在使用ANTLRWorks1.3生成代码,并在Java 1.6下运行。

    4 回复  |  直到 10 年前
        1
  •  9
  •   Brad Mace Mike King    13 年前

    “缺少属性访问”意味着您引用了一个作用域( $nounPhrase )而不是 属性 范围(例如 $nounPhrase.text )

    一般来说,解决属性问题的一个好方法是查看为相关规则生成的解析器方法。

    例如,当我有点生疏时,我最初尝试创建一个新规则:

    multiple_names returns [List<Name> names]
    @init {
        names = new ArrayList<Name>(4);
    }
     : a=fullname ' AND ' b=fullname { names.add($a.value); names.add($b.value); };
    

    导致“ 规则全名的未知属性 “。所以我尝试

    multiple_names returns [List<Name> names]
    @init {
        names = new ArrayList<Name>(4);
    }
     : a=fullname ' AND ' b=fullname { names.add($a); names.add($b); };
    

    结果是” 缺少属性访问 “。查看生成的解析器方法可以清楚地了解我需要做什么。虽然有一些神秘的部分,但与范围(变量)相关的部分很容易理解:

    public final List<Name> multiple_names() throws RecognitionException {
        List<Name> names = null;        // based on "returns" clause of rule definition
        Name a = null;                  // based on scopes declared in rule definition
        Name b = null;                  // based on scopes declared in rule definition
        names = new ArrayList<Name>(4); // snippet inserted from `@init` block
    
        try {
            pushFollow(FOLLOW_fullname_in_multiple_names42);
            a=fullname();
            state._fsp--;
            match(input,189,FOLLOW_189_in_multiple_names44); 
            pushFollow(FOLLOW_fullname_in_multiple_names48);
            b=fullname();
            state._fsp--;
            names.add($a); names.add($b);// code inserted from {...} block
        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
            // do for sure before leaving
        }
        return names;                    // based on "returns" clause of rule definition
    }
    

    在查看生成的代码之后,很容易看到 fullname 规则正在返回 Name 在这个例子中,我需要的只是:

    multiple_names returns [List<Name> names]
    @init {
        names = new ArrayList<Name>(4);
    }
     : a=fullname ' AND ' b=fullname { names.add(a); names.add(b); };
    

    在您的情况下,您需要的版本可能是不同的,但是您通常可以通过查看生成的代码很容易地找到它。

        2
  •  3
  •   Brad Mace Mike King    13 年前

    在最初的语法中,为什么不包括它要求的属性,最有可能是:

    chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase.text+")");};
    

    你的每一条规则( chunker 作为一个我可以迅速发现)有属性(额外的信息)与它们相关。您可以在中找到不同类型规则的不同属性的快速列表。 http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes 如果将这些属性的描述放在网页上(比如解析器规则的start和stop属性,请参考lexer中的标记-这将允许您返回行号和位置)。

    我觉得你的春格规则应该稍微改一下,而不是 $nounPhrase 你应该使用 $nounPhrase.text . text 是您的属性 nounPhrase 规则。

    您可能还需要进行一些其他格式化,通常解析器规则(以小写字母开始)出现在lexer规则之前(以大写字母开始)。

    另外,当我在框中键入时,chunker规则是从新行开始的,但在我原来的答案中,它不是从新行开始的。

        3
  •  1
  •   Dylan Knowles    10 年前

    如果你不小心做了傻事 $thing.$attribute 你指的是哪里 $thing.attribute ,您还将看到 missing attribute access on rule scope 错误信息。(我知道这个问题很久以前就被回答了,但是这一点小技巧可能会帮助其他看到错误消息的人!)

        4
  •  0
  •   peter.murray.rust    15 年前

    找到更好的方法后回答问题…

    WS  :    (' '|'\t')+;
    TOKEN   :   (('A'..'Z') | ('a'..'z'))+;
    dttok   :   'DT' WS TOKEN;
    nntok   :   'NN' WS TOKEN; 
    nounPhrase :    (dttok WS nntok);
    chunker :  nounPhrase ;
    

    问题是我在lexer和解析器之间变得混乱(这显然很常见)。大写的项目是词汇的,在解析器中是小写的。现在看来这是可行的。(注意,我把np改为nn)。