我想在使用C作为输出语言的C++项目中使用ANTLR v3.2生成的分析器。理论上,生成的解析器可以编译为C++,但是在处理解析器操作中的C++类型时遇到问题。下面是一个C++头文件中定义了几个类型的,我想在解析器使用方法:在ANTLR生成的C语法分析器中使用C++类型
/* expr.h */
enum Kind {
PLUS,
MINUS
};
class Expr { // stub
};
class ExprFactory {
public:
Expr mkExpr(Kind kind, Expr op1, Expr op2);
Expr mkInt(std::string n);
};
而且这里有一个简单的分析器定义:
/* Expr.g */
grammar Expr;
options {
language = 'C';
}
@parser::includes {
#include "expr.h"
}
@members {
ExprFactory *exprFactory;
}
start returns [Expr expr]
: e = expression EOF { $expr = e; }
;
expression returns [Expr e]
: TOK_LPAREN k=builtinOp op1=expression op2=expression TOK_RPAREN
{ e = exprFactory->mkExpr(k,op1,op2); }
| INTEGER { e = exprFactory->mkInt((char*)$INTEGER.text->chars); }
;
builtinOp returns [Kind kind]
: TOK_PLUS { kind = PLUS; }
| TOK_MINUS { kind = MINUS; }
;
TOK_PLUS : '+';
TOK_MINUS : '-';
TOK_LPAREN : '(';
TOK_RPAREN : ')';
INTEGER : ('0'..'9')+;
语法通过ANTLR运行良好。当我尝试编译ExprParser.c,我得到这样的错误
conversion from ‘long int’ to non-scalar type ‘Expr’ requested
no match for ‘operator=’ in ‘e = 0l’
invalid conversion from ‘long int’ to ‘Kind’
在每种情况下,语句为Expr
或Kind
值来初始化NULL
。
我可以通过将所有内容更改为Expr*
来解决Expr
的问题。这是可行的,虽然很不理想。但是传递一个简单枚举类似Kind
的指针似乎很荒谬。我发现的一个丑陋的解决方法是创建第二个返回值,该值将Kind
值推入结构中,并将初始化设置为NULL
。即,builtinOp
成为
builtinOp returns [Kind kind, bool dummy]
: TOK_PLUS { $kind = PLUS; }
| TOK_MINUS { $kind = MINUS; }
;
和第一expression
替代成为
TOK_LPAREN k=builtinOp op1=expression op2=expression TOK_RPAREN
{ e = exprFactory->mkExpr(k.kind,*op1,*op2); }
必须有一个更好的方式来做事?我错过了C语言后端的配置选项吗?有没有另一种方法来安排我的语法来避免这种尴尬?是否有我可以使用的纯C++后端?
对于那些正在计划回答的人,您可以首先查看http://www.antlr.org/pipermail/antlr-interest/2010-February/037764.html,看它是否已经提交给Chris。 – 2010-02-24 21:42:50
我相信我不知道为什么在另一个论坛上要求得到一个赞誉。我很乐意在此提出/接受任何有用的答案。 – 2010-02-24 23:50:19
我会这样说,如果它是我的。虽然我曾经考虑过低调,但我没有提出你的问题,因为你的问题是非常好的:细节层次高,问题明确等。但是,我*明白downvote:在多个论坛中提问**而不提这个在其中任何一个**是国际海事组织不好的做法。我的意思是,为什么不直接在这里发布一个链接到ANTLR邮件列表上的帖子?这样,其他人就可以看到已经回答了什么,并且不用花时间复制在这里已经在其他地方建议的(精心制作的)答案。 – 2010-02-25 06:51:23