antlr - if 语句的 ANTLR 正确语法
问题描述
我为我决定称之为 SWL 的语言创建了一个简单的语法:
grammar swl;
program : 'begin' statement+ 'end';
statement : assign | add | sub | mul | div | print | whilecond | ifcond ;
condition : expr ;
expr : '(' expr ')' | expr 'and' expr | expr 'or' expr | 'not' expr | expr '=' expr | expr '>=' expr | expr '<=' expr | expr '>' expr | expr '<' expr | ID | NUMBER;
assign : 'let' ID 'be' (NUMBER | ID) ;
print : 'print' (NUMBER | ID) ;
add : 'add' (NUMBER | ID) 'to' ID ;
sub : 'sub' (NUMBER | ID) 'to' ID ;
mul : 'mul' (NUMBER | ID) 'to' ID ;
div : 'div' (NUMBER | ID) 'to' ID ;
whilecond : 'while (' condition ') do' statement+ 'stop' ;
ifcond : 'if (' condition ') then' statement+ 'stop' | 'if (' condition ') then' statement+ 'else' statement+ 'stop' ;
ID : [a-z]+ ;
NUMBER : [0-9]+ ;
WS : [ \n\t]+ -> skip;
ErrorChar : . ;
我有点麻烦ifcond
。鉴于此 SWL 程序:
begin
if (not(a > 1) or (c <= b)) then
mul 5 to k
stop
end
我能够得到这个 C++ 输出:
#include <iostream>
using namespace std;
int main() {
if ( !(a>1) || (c<=b)) {
k *= 5;
}
}
这很棒!顺便说一下,输入以下内容:
begin
if (not(a > 1) or (c <= b)) then
mul 5 to k
else
mul 15 to k
stop
end
我有这个输出:
#include <iostream>
using namespace std;
int main() {
if ( !(a>1) || (c<=b)) {
k *= 5;
k *= 15;
}
}
如您所见,第二个示例缺少 elsestatement
部分。怎么了?我是否必须更改ifcond
语法并添加另一个规则/变量?这是MyListner.cpp
文件。
void fixString(string& cond) {
size_t pos = cond.find("and", 0);
if (pos != string::npos) { cond.replace(pos, 3, " && "); }
pos = cond.find("or", 0);
if (pos != string::npos) { cond.replace(pos, 2, " || "); }
pos = cond.find("not", 0);
if (pos != string::npos) { cond.replace(pos, 3, " !"); }
}
void MyListener::enterIfcond(swlParser::IfcondContext *ctx) {
string cond = ctx->condition()->getText();
fixString(cond);
cout << string(indent, ' ') << "if (" << cond << ") {" << endl;
}
void MyListener::exitIfcond(swlParser::IfcondContext *ctx) {
cout << string(indent, ' ') << "}" << endl;
}
我怀疑语法不够好,我需要另一个变量来调用 else 部分。我不知道如何解决这个问题,知道吗?
解决方案
很好,ifcond
但是如果您在 else 之前添加另一个变量,这样您就可以使用exit
侦听器的方法会更容易。用这个:
ifelsecond: ifcond | statement ;
ifcond : 'if (' condition ') then' statement+ 'stop' | 'if (' condition ') then' ifelsecond+ 'else' statement+ 'stop' ;
现在您可以像这样轻松编辑MyListner.cpp
:
void MyListener::enterIfcond(swlParser::IfcondContext *ctx) {
string cond = ctx->condition()->getText();
fixString(cond);
cout << "\n" << string(indent, ' ') << "if (" << cond << ") {" << endl;
}
void MyListener::exitIfcond(swlParser::IfcondContext *ctx) {
cout << string(indent, ' ') << "}\n" << endl;
}
void MyListener::exitIfelsecond(swlParser::IfelsecondContext *ctx) {
cout << string(indent, ' ') << "} else {" << endl;
}
您的语法很好,但是您使用的不是真正需要的产品,这使侦听器代码更难编写。由于您使用的是,所以stop
您没有悬空的 else问题。
我给出的解决方案可能不是最好的,但它之所以有效,是因为语法并不模棱两可,因为包含在某些东西中的“范围”语句(在你的情况下是then
and stop
)。
推荐阅读
- ios - 是否可以将 swift 与任何其他语言内联?
- c++ - 更改包含 QButtons 的 Qlayout 的背景颜色
- python - 无法通过 python 发送电子邮件(gmail)
- ansible - 如何在一个地方为所有后续主机设置变量而无需冗余代码?
- typescript - 如何递归使用 Typescript 泛型?
- javascript - ES6 解构和扩展运算符无法正常工作
- node.js - NodeJS Promise 然后没有执行
- javascript - 当模块存在时,Webpack 别名被忽略
- java - 多集群环境中的 Oracle 数据库连续查询通知
- google-cloud-platform - 当我在 GCP 中有微服务架构时使用哪些负载均衡器