我想在使用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