作为编程社区的很多人,我也在尝试用Java为学校项目构建自己的编程语言。我正在将antlr4与Intelellij一起使用,因为它在编写测试代码的同时有助于生成树。我创建了一个访问者类来为我的代码添加功能,到目前为止,我能够制作一个 if/else 语句和一个 while 语句。所以我还想创建一个 switch 语句并将其实现到 visitor 类。我的开关语句语法如下:
switch_rule: SWITCH LPAREN any_var RPAREN LBRACKET case_rule* RBRACKET;
case_rule: CASE any_var PRES statement;
statement:
expression
| rule_ifset
| rule_for
| method_call
| rule_whiledo
| rule_dowhile
| switch_rule
| assign
|var_declaration;
any_var :INT # NumericConst
| DOUBLE # NumericConst
| IDENTIFIER # NumericVariable
|boolean_var # BooleanConst;
所以我假设我像这样启动方法:
@Override
public InputValue visitSwitch_rule(AdamantParser.Switch_ruleContext ctx) {
InputValue value = this.visit(ctx.any_var().getChild(0));
if(!value.isInteger()){throw new RuntimeException("switch value is not an integer");}
else{
//code to write here
}
return InputValue.VOIDval;
}
我想在switch方法中编写case语句,但我不知道如何从这里开始,也没有找到任何简单的例子......任何人都可以指出正确的方向,或者提供一些简单的代码吗?提前谢谢。
编辑:我想要的语法的简单示例如下:
switch(aNumber){
case 1: print("return 1");
case 2: print("return 2");
}
从您的评论中,听起来您正在编写一个解释器,该解释器直接在访问者中执行代码,而无需通过任何 IR 或类似的东西(如果我误解了,请纠正我(。
所以你的问题是,如果你甚至不知道有多少条case
语句,你就不能只在你的代码中写一个switch
语句——毕竟你不能把case
放在一个循环中。即使这不是问题,另一个问题是case
语句需要编译时常量,但您需要将它们与从解析树中提取的值一起使用。
如果您正在生成代码,那么这些都不是问题,因为您可以使用给定的值生成适当数量的案例,一切都会很好。但你不是,所以一切都是动态的,你不能使用switch
.
但这不是问题,因为没有人说你必须使用switch
来实现switch
。您可能知道,开关只是编写一系列if
语句的一种更方便(通常性能更高(的方式。在您的示例中(假设您的语言具有隐式break
(,这将是:
if (aNumber == 1) {
print("return 1");
} else if (aNumber == 2) {
print("return 2");
}
这对您的解释器意味着您可以评估您正在打开的表达式,然后遍历所有情况,并针对每种情况将评估的数字与带有if
的case
值进行比较。一旦其中一个条件匹配,您就会执行关联的代码并脱离循环。
如果你没有隐式break
s,你应该只在遇到break
时脱离循环,否则使用标志来记住你是否已经遇到过一个真正的条件,然后执行每个后续代码块,直到你遇到break
或到达switch
的末尾。