我正在使用针对Java的ANTLR 3.x创建解析器。我写了解析器语法(用于创建抽象语法树,AST)和树语法(用于对AST执行操作)。最后,为了测试两个语法文件,我用Java编写了一个测试文件。

看下面的代码,

协议语法

grammar protocol;
options {
      language = Java;
  output = AST;
}

tokens{ //imaginary tokens
PROT;
INITIALP;
PROC;
TRANSITIONS;
}
@header {
import twoprocess.Configuration;
package com.javadude.antlr3.x.tutorial;
}

@lexer::header {
  package com.javadude.antlr3.x.tutorial;
}
/*
parser rules, in lowercase letters
*/
program
    : declaration+
    ;
declaration
    :protocol
    |initialprocess
    |process
    |transitions
    ;

protocol
    :'protocol' ID ';' -> ^(PROT ID)
    ;
initialprocess
    :'pin' '=' INT ';' -> ^(INITIALP INT)
    ;
process
    :'p' '=' INT ';' -> ^(PROC INT)
    ;
transitions
    :'transitions' '=' INT ('(' INT ',' INT ')') + ';' -> ^(TRANSITIONS INT INT INT*)
    ;

/*
lexer rules (tokens), in upper case letters
*/
ID
    : (('a'..'z' | 'A'..'Z'|'_')('a'..'z' | 'A'..'Z'|'0'..'9'|'_'))*;
INT
    : ('0'..'9')+;
WHITESPACE
    : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;};


协议行者

grammar protocolWalker;

options {
  language = Java;
  //Error, eclipse can't access tokenVocab named protocol
  tokenVocab = protocol;    //import tokens from protocol.g i.e, from protocol.tokens file
  ASTLabelType = CommonTree;
  }

@header {
import twoprocess.Configuration;
package com.javadude.antlr3.x.tutorial;
}

program
    : declaration+
    ;

declaration
    :protocol
    |initialprocess
    |process
    |transitions
    ;

protocol
    :^(PROT ID)
    {System.out.println("create protocol " +$ID.text);}
    ;

initialprocess
    :^(INITIALP INT)
    {System.out.println("");}
    ;

process
    :^(PROC INT)
    {System.out.println("");}
    ;

transitions
    :^(TRANSITIONS INT INT INT*)
    {System.out.println("");}
    ;


协议测试


package com.javadude.antlr3.x.tutorial;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
public class Protocoltest {



/**
 * @param args
 */
public static void main(String[] args) throws Exception {
    //create input stream from standard input
    ANTLRInputStream input = new ANTLRInputStream(System.in);
    //create a lexer attached to that input stream
    protocolLexer lexer = new protocolLexer(input);
    //create a stream of tokens pulled from the lexer
    CommonTokenStream tokens = new CommonTokenStream(lexer);

    //create a pareser attached to teh token stream
    protocolParser parser = new protocolParser(tokens);
    //invoke the program rule in get return value
    protocolParser.program_return r =parser.program();
    CommonTree t = (CommonTree)r.getTree();
    //output the extracted tree to the console
    System.out.println(t.toStringTree());

    //walk resulting tree; create treenode stream first
    CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
    //AST nodes have payloads that point into token stream
    nodes.setTokenStream(tokens);


    //create a tree walker attached to the nodes stream
            //Error, can't create TreeGrammar object called walker
    protocolWalker walker = new protocolWalker(nodes);

    //invoke the start symbol, rule program
    walker.program();
    }
}


问题:


在protocolWalker中,我无法访问令牌(protocol.tokens)

//Error, eclipse can't access tokenVocab named protocol
    tokenVocab = protocol; //import tokens from protocol.g i.e, from protocol.tokens file

在ProtocolWalker中,可以在操作列表中创建名为Configuration的java类的对象吗?

protocol
    :^(PROT ID)
       {System.out.println("create protocol " +$ID.text);
        Configuration conf = new Configuration();
       }
    ;

在Protocoltest.java中

//create a tree walker attached to the nodes stream
//Error, can't create TreeGrammar object called walker
    protocolWalker walker = new protocolWalker(nodes);


无法创建protocolWalker的对象。在示例和教程中,我已经看到创建了这样的对象。

最佳答案

在protocolWalker中,我无法访问令牌(protocol.tokens)...


似乎可以很好地访问protocol.tokens:将tokenVocab更改为其他内容会产生错误,但现在不会产生此错误。 protocolWalker.g的问题在于它被定义为令牌解析器(grammar protocolWalker),但它的使用像树解析器一样。将语法定义为tree grammar protocolWalker消除了我看到的有关未定义标记的错误。


  在protocolWalker中,可以在操作列表中创建名为Configuration的java类的对象吗?


是的你可以。常规的Java编程警告适用于导入类等问题,但是它像System.out.println这样的代码可供您使用。


  在Protocoltest.java中...无法创建protocolWalker的对象。


protocolWalker.g(现在是这样)会生成一个名为protocolWalkerParser的令牌解析器。当您将其更改为树语法时,它将生成名为protocolWalker的树解析器。

非常感谢您发布整个语法。这使得回答问题变得容易得多。

09-05 23:07