我为类似Java的DSL编写了一个语法。虽然它仍然存在一些问题(它不能像我希望的那样识别所有输入),但最让我担心的是生成的C代码是不可编译的。
我使用AntlrWorks 1.5和Antlr 3.5(Antlr 4显然不支持C目标)。
问题在于表达规则。我有规则prio14Expression到prio0Expression,它处理运算符优先级。问题是优先级2,它评估前缀和后缀运算符:
...
prio3Expression: prio2Expression (('*' | '/' | '%') prio2Expression)*;
prio2Expression: ('++' | '--' | '!' | '+' | '-')* prio1Expression ('++' | '--')*;
prio1Expression:
prio0Expression (
('.' prio0Expression) |
('(' (expression (',' expression)*)? ')') |
('[' expression (',' expression)* ']')
)*;
prio0Expression:
/*('(') => */('(' expression ')') |
IDENTIFIER |
//collectionLiteral |
coordinateLiteral |
'true' |
'false' |
NUMBER |
STRING
;
...
Expression是prio14Expression的标签。您可以看到完整的语法here。
代码生成本身是成功的(没有任何错误或严重警告)。它生成以下代码:
CONSTRUCTEX();
EXCEPTION->type = ANTLR3_MISMATCHED_SET_EXCEPTION;
EXCEPTION->name = (void *)ANTLR3_MISMATCHED_SET_NAME;
EXCEPTION->expectingSet = &FOLLOW_set_in_prio2Expression962;
RECOVERFROMMISMATCHEDSET(&FOLLOW_set_in_prio2Expression962);
goto ruleprio2ExpressionEx;
不构建错误“Error 5 error C2065: 'FOLLOW_set_in_prio2Expression962' : undeclared identifier
”。
我在语法上做错了吗?没有其他规则会导致此错误,如果我在某种程度上重新制定相关规则,则生成的代码有效(但语法不能达到我想要的效果)。我该怎么做才能解决这个问题?
感谢您的帮助。
答案 0 :(得分:3)
我遇到了同样的问题。
我认为如果解析器规则有一部分简单的OR-ed标记就会发生这样的事情:
problem_case: problematic_rule;
problematic_rule: 'A' | 'B' ;
如果它是词法规则,则不会发生这种情况。
workaround1: As_lexer_rule;
As_lexer_rule: 'A' | 'B' ;
或者,如果它是复杂的规则(不是简单的OR-ed令牌)。
workaround2: make_it_complicated_needlessly;
make_it_complicated_needlessly: 'A' | 'B' | {false}? NeverUsedRule;
NeverUsedRule: /* don't care*/ ;
(我使用语义谓词“{false}?”进行此修改。 我相信它不会改变目标语言的语法。)
答案 1 :(得分:3)
它似乎是一个旧帖子,但是,它可能仍然对某人有用(就像我一样)。
我在antlr 3.5的C运行时遇到了同样的问题。
另一个简单的解决方法,它不会改变语法:
problem_case: problematic_rule;
problematic_rule: a='A' | b='B' ;