【问题标题】:ANTLR java test file can't create object of tree grammarANTLR java测试文件无法创建树语法对象
【发布时间】:2012-10-22 13:21:46
【问题描述】:

我正在使用针对 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;};

protocolWalker

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("");}
    ;

Protocoltest.java

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();
    }
}

问题:

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

    //Error, eclipse can't access tokenVocab named protocol  
        tokenVocab = protocol; //import tokens from protocol.g i.e, from protocol.tokens file
    
  2. 在protocolWalker中,我可以在action list中创建java类的对象,叫做Configuration吗?

    protocol
        :^(PROT ID)
           {System.out.println("create protocol " +$ID.text);
            Configuration conf = new Configuration();
           }
        ;
    
  3. 在 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 的对象无法创建。我在示例和教程中看到创建了这样的对象。

【问题讨论】:

  • 我已经阅读了权威的 antlr 参考书,构建了特定领域的语言,并且还学习了一些在线教程。

标签: java parsing antlr dsl antlrworks


【解决方案1】:

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

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

在protocolWalker中,我可以在action list中创建java类的对象,叫做Configuration吗?

是的,你可以。正常的 Java 编程注意事项适用于导入类等,但它与 System.out.println 之类的代码一样可供您使用。

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

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

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

【讨论】:

  • 我在下面的答案中回答了你,而不是评论
【解决方案2】:

感谢您的回复,这是一个愚蠢的错误。 令牌问题和创建protocolWalker 对象现在已解决,但无论何时,无论是protocol.g 还是protocolWalker.g,我都必须在protocolParser.java 和protocolWalker.java 中再次(每次)写入包名。我之前在使用 lexer 文件时也遇到过同样的问题,但是下面的声明解决了这个问题。

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

但我不知道如何解决这个问题?

另外,我使用 SWING 在 Java 中开发了一个 GUI,其中我有一个 textarea。在那个文本区域, 用户将编写输入,就像我的语法用户将编写一样,

protocol test;
pin = 5;
p = 3;
transitions = 2(5,0) (5,1);

如何在 Java Swing GUI 中处理此输入并在那里生成输出?

此外,如果我将 protocolWalker.g 的以下部分提供给

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

initialprocess
    :^(INITIALP INT)
    {System.out.println("create initial process (with state) ");}
    ;

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

并使用以下输入运行测试文件,

protocol test;
pin = 5;
p = 3;
transitions = 2(5,0) (5,1);

我得到以下输出

(PROT test) (INITIALP 5) (PROC 3) (TRANSITIONS 2 5 0 5 1)
create protocol test

为什么protocolWalker.g中的第二个和第三个println没有显示在输出中?

有什么想法/帮助吗?

再次感谢您。

【讨论】:

  • 解决了解析器包问题,使用以下链接Why doesn't my header show up in the lexer as well as the parser?@tenterhook
  • Swing:听起来您只需要一个简单的 Swing 应用程序即可。看看那里的一些教程,如果您遇到困难,请发布一个新问题(我不是 Swing 人,所以我不会提供太多帮助)。 输出:我在更新和重新生成 protocolWalker.g 后运行了你的 main,我得到了正确的输出。如果重新生成代码不能解决您的问题,请考虑为其编写一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
相关资源
最近更新 更多