我已经获得了一个称为静态Java编译器的Java编译器子集的ANTLR语法.我正在尝试扩展语法以包含更多Java的功能,例如,我刚刚为For Loops添加了语法.
使用Eclipse和ANTLR插件,然后我做了"编译ANTLR语法".而不是编译它在第一个代码位上产生了两个错误:
grammar ExtendedStaticJava;
options { backtrack=true; memoize=true; }
@header
{
package sjc.parser.extended;
import java.math.BigInteger;
/**
* Extended StaticJava parser.
* @author <myname>
*/
}
// the rest of the grammar has been excluded.
Run Code Online (Sandbox Code Playgroud)
第一个错误在第1行:'Unexpected Token:grammar'第二个错误在第5行:'意外的char:@'
为什么它不能识别这种基本的ANTLR语法?我的第一个想法是我在类路径中遗漏了一些东西,但是我去了项目的属性,并确保在库下包含以下JAR :
任何想法或建议?
我无法理解为什么这个简单的语法 -
grammar Test;
file : ID;
ID : .*;
Run Code Online (Sandbox Code Playgroud)
导致此错误 -
Test.g:3:6: The following alternatives can never be matched: 1
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
我有以下ANTLR语法:
grammar mygrammar;
ASSIGNMENT
: ID '=' INT
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
INT : '0'..'9'+
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
Run Code Online (Sandbox Code Playgroud)
只有ASSIGNMENT规则实际上是我的,其余的是ANTLRWorks 1.4.3添加的默认值.
当我在解释器中尝试语法时,诸如"a = 5"之类的字符串成功,但是诸如"b [space] = [space] 6"之类的字符串失败:由于空格,我得到MismatchedTokenException:

从阅读ANTLR网站,和
Ignore rules: WS和
{$channel=HIDDEN} 文本/语法规则,似乎应该忽略空格,但事实并非如此.
我究竟做错了什么?
我不明白为什么下面的antlr语法不会为输入"bb b"生成树,但它会为输入"aa a"生成树
statement
|
a a a
Run Code Online (Sandbox Code Playgroud)
你有什么想法吗?谢谢.
grammar Test2;
options {
language = Java;
}
statement: ( a|b )*;
a: 'a';
b: 'b';
WS: ('\n'|' '|'\t'|'r'|'\f')+ {$channel=HIDDEN;};
Run Code Online (Sandbox Code Playgroud)
任何人都可以在ANTLR IDE eclipse插件中尝试这个插件 http://antlrv3ide.sourceforge.net/
在我的Eclipse中,它确实表现得像我上面报道的那样奇怪.
我目前正在教自己ANTLR,在完成"The Definitive ANTLR Reference"一书时,我遇到了一个问题.我正在做第一个例子,并创建了语法文件,得到了我的Lexer和Parser Java文件,创建了以下Java程序来测试它:
import org.antlr.runtime.*;
public class Test
{
public static void main(String[] args) throws Exception
{
ANTLRInputStream input = new ANTLRInputStream(System.in);
TLexer lexer = new TLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TParser parser = new TParser(tokens);
parser.r();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我使用命令行编译哪个工作正常,然后我尝试运行Java类,它失败了,整个命令行如下所示:
C:\Users\Dan\workspace\Test\src>dir
Volume in drive C is Acer
Volume Serial Number is ECB2-5E39
Directory of C:\Users\Dan\workspace\Test\src
17/09/2012 18:15 <DIR> .
17/09/2012 18:15 <DIR> ..
17/09/2012 18:32 723 Test.class
16/09/2012 20:51 353 Test.java
17/09/2012 18:32 3,641 TLexer.class
15/09/2012 21:35 …Run Code Online (Sandbox Code Playgroud) 我无法理解语法中的错误.Bug.g4文件是:
grammar Bug;
text: TEXT;
WORD: ('a'..'z' | 'A'..'Z')+ ;
TEXT: ('a'..'z' | 'A'..'Z')+ ;
NEWLINE: [\n\r] -> skip ;
Run Code Online (Sandbox Code Playgroud)
运行antlr4和javac后,我跑了
grun Bug text -tree
aa
line 1:0 mismatched input 'aa' expecting TEXT
(text aa)
Run Code Online (Sandbox Code Playgroud)
但是如果我改为使用文字:语法中的WORD,那就没关系了.怎么了?
我正在从ANTLRv4书中做Calc/Labeled Expression教程,当我编译时,我得到这个:
EvalVisitor.java:33: error: cannot find symbol
if ( ctx.op.getType() == CalcParser.MUL || ctx.op.getType() == CalcParser.MIDDOT ) {
^
symbol: variable op
location: variable ctx of type MulDivContext
Run Code Online (Sandbox Code Playgroud)
公平地说,我对它进行了一些修改.我的语法看起来像这样:
expr : expr ( STAR | FSLASH | DIVIDE | MIDDOT ) expr # MulDiv
Run Code Online (Sandbox Code Playgroud)
这些是在CommonLexer文件中定义的,如下所示:
lexer grammar CommonLexerRules;
ID : [a-zAZ]+ ;
INT : [0-9]+ ;
STAR : '*';
Run Code Online (Sandbox Code Playgroud)
这对grun工作正常,测试文件正确排列.但是,我认为通过为*定义一些替代方案,我已经改变了它的工作方式.也就是说,我不想*总是意味着乘法,我也想将MIDDOT'·'解析为乘法.
我的问题是,生成的代码中似乎没有任何".op"?
这看起来是这样的:
*
/ \
a b
Run Code Online (Sandbox Code Playgroud)
其中a,b和*为expr.所以我想要的是获取*作为某种令牌,我可以比较angainst CalcParser.MUL和CalcParser.MIDDOT等.
任何帮助,将不胜感激.
/杰森
因此,由于我的任务,我最终想知道下一步可能是什么.
为了澄清事情,我应该使用Java实现DSL语言.该语言应该使"用户"能够指定并根据输入创建问卷表格.
以下输入应提供以下给定的输出:
form taxOfficeExample {
"Did you sell a house in 2010?"
hasSoldHouse: boolean
"Did you buy a house in 2010?"
hasBoughtHouse: boolean
"Did you enter a loan?"
hasMaintLoan: boolean
if (hasSoldHouse) {
"What was the selling price?"
sellingPrice: money
"Private debts for the sold house:"
privateDebt: money
"Value residue:"
valueResidue: money = (sellingPrice - privateDebt)
}
}
Run Code Online (Sandbox Code Playgroud)

我选择的解析器技术是ANTLRv4,它是这个平台的最佳选择.无论如何,我熟悉所有模型,术语等 - 例如解析,词汇,语法等 - 但还有一件事仍然缺乏 - Java和ANTLRv4之间的桥梁.
所以基本上我想根据你的经验知道,ANTLRv4和Java之间的桥梁是什么?例如,一旦我为DSL定义语法,该语法(语言)如何应用?这两个实体之间的桥梁是什么?
我问这个问题只是因为我在这方面很新,因此,任何提示,研究论文指针等都将受到赞赏!
谢谢
我为布尔表达式创建了一个语法,现在我正在尝试实现访问者来评估它.
有人告诉我,不需要使用语义分析来复杂语法词法分析器和解析器规则,因为从访问者那里提供有意义的错误消息要好得多.
所以我试图在访问者中检查类型一致性,日期正确性等.我得到的惊喜是没有办法(至少我没有看到它)报告来自访问者的错误而不是抛出异常.如果我抛出异常,我将无法继续进行表达式验证并立即检测所有错误.另外,我必须以某种方式捕获所有解析异常类型(我应该如何知道它们?).总而言之,异常抛出似乎不是正确的解决方案.
您能否指导我如何计划在访问者遍历期间报告表达式语义中的错误?
在ANTLR4中使用显式令牌定义有什么好处和缺点?我发现单个括号中的文本比创建单独的标记更具描述性且更易于使用,并使用它来代替文本.
例如:
grammar SimpleTest;
top: library | module ;
library: 'library' library_name ';' ;
library_name: IDENTIFIER;
module: MODULE module_name ';' ;
module_name: IDENTIFIER;
MODULE: 'module' ;
IDENTIFIER: [a-zA-Z0-9]+;
Run Code Online (Sandbox Code Playgroud)
生成的令牌是:
T__0=1
T__1=2
MODULE=3
IDENTIFIER=4
'library'=1
';'=2
'module'=3
Run Code Online (Sandbox Code Playgroud)
如果我对'library'"令牌" 不感兴趣,因为规则已经确定了我所匹配的内容,而且无论如何我都会跳过它,用LIBRARY令牌声明替换它是否有意义?(然后令牌的数量会增加.)为什么这是ANTLRWorks中的警告?