我正在學習 Antlr。在這一點上,我正在撰寫一種基于堆疊的小語言,作為我學習程序的一部分 —— 想想 PostScript 或 Forth。RPN 語言。例如:
10 20 毫升
這會將 10 和 20 壓入堆疊,然后執行乘法,這會彈出兩個值,將它們相乘,然后壓入 200。我正在使用訪問者模式。我發現自己在寫一些有點瘋狂的代碼。一定有更好的方法。
這是我的 WaveParser.g4 檔案的一部分:
any_operator:
value_operator |
stack_operator |
logic_operator |
math_operator |
flow_control_operator;
value_operator:
BIND | DEF
;
stack_operator:
DUP |
EXCH |
POP |
COPY |
ROLL |
INDEX |
CLEAR |
COUNT
;
BIND 只是bind關鍵字等。所以我的訪問者有這個方法:
antlrcpp::Any WaveVisitor::visitAny_operator(Parser::Any_operatorContext *ctx);
現在這里是我正在撰寫的非常丑陋的代碼的地方,這導致了這個問題。
Value::Operator op = Value::Operator::NO_OP;
WaveParser::Value_operatorContext * valueOp = ctx->value_operator();
WaveParser::Stack_operatorContext * stackOp = ctx->stack_operator();
WaveParser::Logic_operatorContext * logicOp = ctx->logic_operator();
WaveParser::Math_operatorContext * mathOp = ctx->math_operator();
WaveParser::Flow_control_operatorContext * flowOp = ctx->flow_control_operator();
if (valueOp) {
if (valueOp->BIND()) {
op = Value::Operator::BIND;
}
else if (valueOp->DEF()) {
op = Value::Operator::DEF;
}
}
else if (stackOp) {
if (stackOp->DUP()) {
op = Value::Operator::DUP;
}
...
}
...
我支持大約 50 個運算子,而且我將使用這一系列 if 陳述句來確定這是哪個運算子,這太瘋狂了。必須有更好的方法來做到這一點。我在背景關系中找不到映射到我可以在哈希映射表中使用的內容的欄位。
我不知道我是否應該讓我的每個操作員都有一個單獨的規則,并在我的訪問者中使用相應的方法,或者我還缺少什么。
有沒有更好的辦法?
uj5u.com熱心網友回復:
使用 ANTLR,標記規則的組件以及高級替代方案通常非常有幫助。
如果決議器規則的一部分只能是單一型別的一件事,通常默認訪問器就可以了。但是,如果您有多個替代方案,它們本質上是“同一事物”的替代方案,或者您可能不止一次在決議器規則中擁有相同的子規則參考并想要區分它們,那么給它們命名非常方便。(一旦你開始這樣做并看到對 Context 類的影響,它們提供價值的地方就會變得非常明顯。)
此外,當規則有多個頂級替代方案時,給每個規則都一個標簽會非常方便。這將導致 ANTLR 為每個備選方案生成一個單獨的 Context 類,而不是將每個備選方案的所有內容都轉儲到單個類中。
(制作一些東西只是為了獲得有效的編譯)
grammar WaveParser
;
any_operator
: value_operator # val_op
| stack_operator # stack_op
| logic_operator # logic_op
| math_operator # math_op
| flow_control_operator # flow_op
;
value_operator: op = ( BIND | DEF);
stack_operator
: op = (
DUP
| EXCH
| POP
| COPY
| ROLL
| INDEX
| CLEAR
| COUNT
)
;
logic_operator: op = (AND | OR);
math_operator: op = (ADD | SUB);
flow_control_operator: op = (FLOW1 | FLOW2);
AND: 'and';
OR: 'or';
ADD: ' ';
SUB: '-';
FLOW1: '>>';
FLOW2: '<<';
BIND: 'bind';
DEF: 'def';
DUP: 'dup';
EXCH: 'exch';
POP: 'pop';
COPY: 'copy';
ROLL: 'roll';
INDEX: 'index';
CLEAR: 'clear';
COUNT: 'count';
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/321251.html
上一篇:如何創建多執行緒清潔器?
下一篇:呼叫從另一個類傳遞過來的回呼
