使用ANTLR 4和Java创建条件语句

使用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.g4//我的语法文件

语法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;
};