使用ANTLR 4和Java创建条件语句
所以我尝试用瑞典语语法构建自己的编程语言(大部分是为了好玩),我成功地创建了变量,并对它们进行了一些基本的算术运算。继续做一些条件语句,我遇到了一些麻烦。首先,以下是我的(相关)代码: SPL.g4//我的语法文件使用ANTLR 4和Java创建条件语句,java,if-statement,conditional-statements,antlr4,Java,If Statement,Conditional Statements,Antlr4,所以我尝试用瑞典语语法构建自己的编程语言(大部分是为了好玩),我成功地创建了变量,并对它们进行了一些基本的算术运算。继续做一些条件语句,我遇到了一些麻烦。首先,以下是我的(相关)代码: SPL.g4//我的语法文件 语法SPL; 文件 :代码 ; 代码 :语句“;”代码 ; 陈述 :打印 |分配 |十二月 |环路 |状况 ; //声明变量 十二月 :“variabel”ID ; //用表达式指定变量。 分配 :ID“=”expr ; //一般的表达。 expr :“-”expr#unarymen
语法SPL;
文件
:代码
;
代码
:语句“;”代码
;
陈述
:打印
|分配
|十二月
|环路
|状况
;
//声明变量
十二月
:“variabel”ID
;
//用表达式指定变量。
分配
:ID“=”expr
;
//一般的表达。
expr
:“-”expr#unarymensexpr
|'!' expr#notExpr
|expr op=(“/”|“*”)expr#乘法expr
|expr op=(“+”|“-”)expr#additiveExpr
|expr op=('='|''')expr#relationalExpr
|expr op=(“=”|“!=”)expr#equalityExpr
|expr'OCH'expr#and expr
|expr‘ELLER’expr#orExpr
|原子
;
//一个原子表达式,或多或少只是一个变量。
atomExpr
:ID
|INT
|“('expr')”
;
ID:('a'..'z')+;
STR:([a-zA-Z_][a-zA-Z_0-9]*)+;
INT:([0-9]+)+;
WS:[\n\t\r]+->跳过;
//将expr打印到控制台
打印
:“skriv”expr
;
//应该是某种正在进行的循环和条件工作!
条件
:'om'条件代码('annars om'条件代码)*('annars'其他块)?
;
条件码
:expr otherBlock
;
其他块
:“{'file'}”
|代码
;
环
:'när'expr';'
;
翻译
import grammar.SPLBaseListener;
导入grammar.SPLParser;
导入org.antlr.v4.runtime.Token;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Stack;
/**
*解释解析器生成的代码。
*重写TestBaseListener中的方法,以便我们可以决定发生了什么。
*学生于2017年1月27日创建。
*
*/
公共类解释器扩展了SPLBaseListener{
/**
*保存值的类。用于在哈希映射中存储键和值对。
*/
私有静态类变量{
int-val;
公共变量(int-val){
this.val=val;
}
}
private final HashMap vars=new HashMap();//存储键和值。
private Stack exprVal=new Stack();//存储当前值。
私有堆栈条件booleans=new Stack();//存储计算的条件
/**
*从给定变量名称的hashmap中返回一个变量。
*
*@param-tok
*@返回
*/
私有变量getVar(令牌tok){
String name=tok.getText();
变量v=vars.get(名称);
如果(v==null){
错误(tok.getLine(),“未定义”+名称);
返回新变量(0);//避免空指针异常
}否则{
返回v;
}
}
/**
*当输入一个变量的声明时,我们把它和它的名字放在哈希表中
*初始值为0。
*
*@param-ctx
*/
@凌驾
public void enterDecl(SPLParser.DeclContext ctx){
字符串名称=ctx.ID().getText();
变量old=vars.put(名称,新变量(0));
如果(旧!=null){
错误(ctx.ID().getSymbol().getLine(),“重定义”+名称);
}
}
/**
*当我们退出赋值时,变量已经被存储,得到
*堆栈正在保存的值。
*
*@param-ctx
*/
@凌驾
public void exitAssign(SPLParser.AssignContext ctx){
getVar(ctx.ID().getSymbol()).val=exprVal.pop();
}
/**
*如果+在堆栈顶部添加两个数字,则减去它们并将其加回去。
*
*@param-ctx
*/
@重写公共void exitAdditiveExpr(SPLParser.AdditiveExprContext ctx){
字符串op=ctx.op.getText();
if(op.equals(“+”)){
exprVal.push(exprVal.pop()+exprVal.pop());
}else{/'-'
int top=(exprVal.pop());
int second=(exprVal.pop());
exprVal.push(第二个-顶部);
}
}
/**
*如果*乘以堆栈顶部的两个数字,则将它们除以,然后再加回去。
*
*@param-ctx
*/
@重写公共void exitMultiplicationExpr(SPLParser.MultiplicationExprContext ctx){
字符串op=ctx.op.getText();
如果(op.equals(“*”)){
exprVal.push(exprVal.pop()*exprVal.pop());
}else{/'/'
int top=(exprVal.pop());
int second=(exprVal.pop());
外推(第二个/顶部);
}
}
/**
*从堆栈中获取两个顶部元素并进行比较。
*@param-ctx
*/
@重写public void exitRelationalExpr(SPLParser.RelationalExprContext ctx){
System.out.println(“我在这里检查关系!”+exprVal.size());
int top=(exprVal.pop());
int second=(exprVal.pop());
开关(ctx.op.getText()){
案例“=”;
如果(顶部>=秒)
conditionBooleans.push(true);
打破
案例“”);
如果(顶部>第二个)
conditionBooleans.push(true);
打破
违约:
conditionBooleans.push(false);
}
}
/**
*决定要运行的代码块。TODO不起作用!
*@param-ctx
*/
@重写公共void enterCondition(SPLParser.ConditionContext ctx){
System.out.println(“\n输入的条件------------------------------------------------------------------”);
System.out.println(ctx.conditionCode().get(0.getText());
}
/**
*在代码中声明atomexpression时
*如果它不是null,它将被推到堆栈上。
*
*@param-ctx
*/
@凌驾
public void enterAtomExpr(SPLParser.AtomExprContext ctx){
如果(ctx.ID()!=null){
exprVal.push(getVar(ctx.ID().getSymbol()).val);
}else if(ctx.INT()!=null){
exprVal.push(Integer.parseInt(ctx.INT().getText());
}
}
/**
*打印exprValue的值。
*
*@param-ctx
*/
@凌驾
public void exitPrint(SPLParser.PrintContext ctx){
System.out.println(“Utskrift:”);
System.out.println(exprVal.pop());//弹出顶部值并打印它。
}
/**
*将错误消息打印到控制台。
*
*@param行
*@param msg
*/
私有无效错误(整数行,字符串消息){
grammar SPL;
file
:code
;
code
:statement ';' code
;
statement
:print
|assign
|decl
|loop
|condition
;
//Declares variable
decl
:'variabel' ID
;
//Assign variable with an expression.
assign
:ID '=' expr
;
//A general expression.
expr
:'-' expr #unaryMinusExpr
|'!' expr #notExpr
|expr op=('/' | '*') expr #multiplicationExpr
|expr op=('+' | '-') expr #additiveExpr
|expr op=('<=' |'>=' | '<' | '>') expr #relationalExpr
|expr op=('=' | '!=') expr #equalityExpr
|expr 'OCH' expr #andExpr
|expr 'ELLER' expr #orExpr
|atomExpr #atom
;
//An atomic expression, more or less just a variable.
atomExpr
:ID
|INT
|'(' expr ')'
;
ID:('a'..'z')+ ;
STR:([a-zA-Z_] [a-zA-Z_0-9]*)+ ;
INT:([0-9]+)+ ;
WS: [ \n\t\r]+ -> skip ;
//Prints expr to the console
print
: 'skriv' expr
;
//Supposed to be some kind of loop and condition WORK IN PROGRESS!
condition
:'om' conditionCode ('annars om' conditionCode)* ('annars' otherBlock)?
;
conditionCode
: expr otherBlock
;
otherBlock
:'{'file'}'
| code
;
loop
:'när' expr ';'
;
import grammar.SPLBaseListener;
import grammar.SPLParser;
import org.antlr.v4.runtime.Token;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
* Interpretes the code genereated by the parser.
* Overrides methods from the TestBaseListener so we can decide what happends.
* Created by student on 2017-01-27.
*
*/
public class Interpreter extends SPLBaseListener {
/**
* A class that holds a value. Used for storing key & value pairs in a hashmap.
*/
private static class Variable {
int val;
public Variable(int val) {
this.val = val;
}
}
private final HashMap<String, Variable> vars = new HashMap<>(); //Stores keys and values.
private Stack<Integer> exprVal = new Stack<>(); //Stores the current values.
private Stack<Boolean> conditionBooleans = new Stack<>(); //Stores the evaluated conditions
/**
* Returns a variable from the hashmap given the variable's name.
*
* @param tok
* @return
*/
private Variable getVar(Token tok) {
String name = tok.getText();
Variable v = vars.get(name);
if (v == null) {
error(tok.getLine(), "undefined " + name);
return new Variable(0); // avoid null pointer exception
} else {
return v;
}
}
/**
* When entering a declaration of a variable, we put it in the hashtable with it's name
* and a initial value of 0.
*
* @param ctx
*/
@Override
public void enterDecl(SPLParser.DeclContext ctx) {
String name = ctx.ID().getText();
Variable old = vars.put(name, new Variable(0));
if (old != null) {
error(ctx.ID().getSymbol().getLine(), "redefined " + name);
}
}
/**
* When we have exited the assignment, the variable already stored, get's the
* value that the stack is holdning.
*
* @param ctx
*/
@Override
public void exitAssign(SPLParser.AssignContext ctx) {
getVar(ctx.ID().getSymbol()).val = exprVal.pop();
}
/**
* If + add two numbers top of stack else substract them and add them back.
*
* @param ctx
*/
@Override public void exitAdditiveExpr(SPLParser.AdditiveExprContext ctx) {
String op = ctx.op.getText();
if(op.equals("+")){
exprVal.push(exprVal.pop() + exprVal.pop());
}else{ // '-'
int top = (exprVal.pop());
int second = (exprVal.pop());
exprVal.push(second - top);
}
}
/**
* If * multiplty two numbers top of stack else divide them and add them back.
*
* @param ctx
*/
@Override public void exitMultiplicationExpr(SPLParser.MultiplicationExprContext ctx) {
String op = ctx.op.getText();
if(op.equals("*")){
exprVal.push(exprVal.pop() * exprVal.pop());
}else{// '/'
int top = (exprVal.pop());
int second = (exprVal.pop());
exprVal.push(second / top);
}
}
/**
* Takes the two top elements from the stack and compares them.
* @param ctx
*/
@Override public void exitRelationalExpr(SPLParser.RelationalExprContext ctx) {
System.out.println("Im here checking relation! " + exprVal.size());
int top = (exprVal.pop());
int second = (exprVal.pop());
switch (ctx.op.getText()) {
case "<=":
System.out.println("<=");
if(top<=second)
conditionBooleans.push(true);
break;
case ">=":
System.out.println(">=");
if(top>=second)
conditionBooleans.push(true);
break;
case "<":
System.out.println("<");
if(top<second)
conditionBooleans.push(true);
break;
case ">":
System.out.println(">");
if(top>second)
conditionBooleans.push(true);
break;
default:
conditionBooleans.push(false);
}
}
/**
* Decides what codeblock to run. TODO DOES NOT WORK!
* @param ctx
*/
@Override public void enterCondition(SPLParser.ConditionContext ctx) {
System.out.println("\n CONDITION ENTERED------------------------------------------------------------------");
System.out.println(ctx.conditionCode().get(0).getText());
}
/**
* When a atomexpression is declared in code
* and if it's not null it will be pushed onto the stack.
*
* @param ctx
*/
@Override
public void enterAtomExpr(SPLParser.AtomExprContext ctx) {
if (ctx.ID() != null) {
exprVal.push(getVar(ctx.ID().getSymbol()).val);
} else if (ctx.INT() != null) {
exprVal.push(Integer.parseInt(ctx.INT().getText()));
}
}
/**
* Prints the value of exprValue.
*
* @param ctx
*/
@Override
public void exitPrint(SPLParser.PrintContext ctx) {
System.out.println("Utskrift:");
System.out.println(exprVal.pop());//Pop off the top value and print it.
}
/**
* Prints error message to the console.
*
* @param line
* @param msg
*/
private void error(int line, String msg) {
System.err.println(":" + line + ": " + msg);
}
}
variabel a;
variabel b;
a = 10;
b = 20;
a = a + b;
om a < b{
skriv a;
};