【发布时间】:2010-02-24 04:19:37
【问题描述】:
我正在尝试在使用 C 作为输出语言的 C++ 项目中使用由 ANTLR v3.2 生成的解析器。理论上,生成的解析器可以编译为 C++,但我在处理解析器操作中的 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’ requestedno 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++ 后端?
【问题讨论】:
-
准备回答的朋友可以先查看antlr.org/pipermail/antlr-interest/2010-February/037764.html,看看是不是还没向克里斯提议。
-
我确定我不知道为什么在另一个论坛上提问会引起反对票。我很乐意在这里投票/接受任何有用的答案。
-
如果是我的话,我会这么说。虽然我考虑过投反对票,但我没有考虑,因为您的问题是一个非常好的问题:详细程度高、问题明确等。但我确实理解投反对票:在多个论坛中提问在其中任何一个中都没有提及这一点是 IMO 的错误做法。我的意思是,为什么不在这里发布一个链接到您在 ANTLR 邮件列表上的帖子?这样,其他人就可以看到已经回答的内容,而不必花时间在这里复制已经在其他地方提出的(详细的)答案。
-
如果我在任一论坛上收到任何实质性答复,我想我会更清楚地看到您的观点。事实上,我要以第二种方式打破礼仪并自我回答。
标签: c++ c parsing antlr antlr3