我正在使用针对java的ANTLR 3.x创建一个解析器。我编写了解析器语法(用于创建抽象语法树,AST)和Tree Grammar(用于在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();
}
}
问题:
在protocolWalker中,我无法访问令牌(protocol.tokens)
//Error, eclipse can't access tokenVocab named protocol
tokenVocab = protocol; //import tokens from protocol.g i.e, from protocol.tokens file
在in 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对象。我在示例和教程中已经看到创建了这样的对象。
答案 0 :(得分:1)
在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
的树解析器。
非常感谢发布整个语法。这使得回答问题变得更加容易。
答案 1 :(得分:0)
感谢您的回复,这是一个愚蠢的错误。 现在已经解决了令牌问题和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没有显示在输出中?
有任何想法/帮助吗?
再次感谢你。