improved nested call correctness, register allocations, renamed project files
This commit is contained in:
parent
85e5f569b4
commit
11da0a0826
|
@ -1,397 +0,0 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.RuleContext;
|
||||
import org.antlr.v4.runtime.tree.*;
|
||||
|
||||
import pp.iloc.model.*;
|
||||
import pp.s1184725.boppi.BasicParser.*;
|
||||
|
||||
public class BoppiBasicGenerator extends BasicBaseVisitor<Void> {
|
||||
private static final int ARBASESIZE = 8;
|
||||
public Program prog;
|
||||
private Annotations an;
|
||||
private int regNum;
|
||||
private final Reg tempArp = new Reg("ART"), arp = new Reg("ARP"), resultReg = new Reg("RES");
|
||||
|
||||
/**
|
||||
* Maps operator tokens to ILOC opcodes.
|
||||
*/
|
||||
private static Map<Integer, OpCode> ops = new HashMap<Integer, OpCode>() {
|
||||
private static final long serialVersionUID = 8979722313842633807L;
|
||||
|
||||
{
|
||||
put(BasicLexer.AND, OpCode.and);
|
||||
put(BasicLexer.DIVIDE, OpCode.div);
|
||||
put(BasicLexer.EQ, OpCode.cmp_EQ);
|
||||
put(BasicLexer.GT, OpCode.cmp_GT);
|
||||
put(BasicLexer.GTE, OpCode.cmp_GE);
|
||||
put(BasicLexer.LEQ, OpCode.cmp_LE);
|
||||
put(BasicLexer.LT, OpCode.cmp_LT);
|
||||
put(BasicLexer.MINUS, OpCode.sub);
|
||||
put(BasicLexer.MULTIPLY, OpCode.mult);
|
||||
put(BasicLexer.NEQ, OpCode.cmp_NE);
|
||||
put(BasicLexer.PLUS, OpCode.add);
|
||||
put(BasicLexer.OR, OpCode.or);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new generator with the given variable annotations.
|
||||
*
|
||||
* @param annotations
|
||||
* the annotation object to use during generation
|
||||
*/
|
||||
public BoppiBasicGenerator(Annotations annotations) {
|
||||
an = annotations;
|
||||
prog = new Program();
|
||||
regNum = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a register for a given tree node.
|
||||
*
|
||||
* @param parseTree
|
||||
* the tree node
|
||||
* @return a register for the tree node
|
||||
*/
|
||||
private Reg getReg(ParseTree parseTree) {
|
||||
Reg reg = an.registers.get(parseTree);
|
||||
if (reg == null) {
|
||||
reg = new Reg("r_" + (regNum++));
|
||||
an.registers.put(parseTree, reg);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the register used in the {@code source} tree node to the
|
||||
* {@link destination} node.
|
||||
*
|
||||
* @param source
|
||||
* the node to retrieve the register from
|
||||
* @param destination
|
||||
* the node to copy the register to
|
||||
* @return the register that was copied
|
||||
*/
|
||||
private Reg copyReg(ParseTree source, ParseTree destination) {
|
||||
Reg reg = an.registers.get(source);
|
||||
an.registers.put(destination, reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
private <T> Reg getVar(ParserRuleContext node, Variable<T> var) {
|
||||
int difference = an.function.get(node).getDepth() + 1 - var.getDepth();
|
||||
if (difference > 0) {
|
||||
emit(node, OpCode.i2i, arp, tempArp);
|
||||
while (difference-- > 0)
|
||||
emit(node, OpCode.loadAI, tempArp, new Num(-4), tempArp);
|
||||
|
||||
return tempArp;
|
||||
} else
|
||||
return arp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an operation from the parameters and adds it to the program
|
||||
* under construction.
|
||||
*/
|
||||
private Op emit(ParserRuleContext ctx, Label label, OpCode opCode, Operand... args) {
|
||||
Op result = new Op(label, opCode, args);
|
||||
result.setComment(ctx.getText());
|
||||
this.prog.addInstr(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an operation from the parameters and adds it to the program
|
||||
* under construction.
|
||||
*/
|
||||
private Op emit(ParserRuleContext ctx, OpCode opCode, Operand... args) {
|
||||
return emit(ctx, (Label) null, opCode, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitChildren(RuleNode tree) {
|
||||
super.visitChildren(tree);
|
||||
if (an.registers.get(tree) == null)
|
||||
for (int i = tree.getChildCount() - 1; i >= 0; i--)
|
||||
if (tree.getChild(i) instanceof RuleContext) {
|
||||
copyReg(tree.getChild(i), tree);
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProgram(ProgramContext ctx) {
|
||||
emit(ctx, OpCode.loadI, new Num(0), tempArp);
|
||||
emit(ctx, OpCode.loadI, new Num(0), arp);
|
||||
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAssign(AssignContext ctx) {
|
||||
visit(ctx.singleExpr());
|
||||
copyReg(ctx.singleExpr(), ctx);
|
||||
|
||||
if (SimpleType.CHAR.equals(an.types.get(ctx)))
|
||||
emit(ctx, OpCode.cstoreAI, getReg(ctx), getVar(ctx.variable(), an.variables.get(ctx.variable())),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()));
|
||||
else
|
||||
emit(ctx, OpCode.storeAI, getReg(ctx), getVar(ctx.variable(), an.variables.get(ctx.variable())),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(CallContext ctx) {
|
||||
Variable<Type> function = an.variables.get(ctx.variable());
|
||||
FunctionType parameters = ((FunctionType) function.getType());
|
||||
Reg temp = new Reg("r__");
|
||||
visit(ctx.variable());
|
||||
emit(ctx.variable(), OpCode.loadAI, getVar(ctx.variable(), an.variables.get(ctx.variable())),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), temp);
|
||||
emit(ctx.variable(), OpCode.push, temp);
|
||||
|
||||
for (int i = 0; i < ctx.expr().size(); i++) {
|
||||
visit(ctx.expr(i));
|
||||
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i)))
|
||||
emit(ctx.expr(i), OpCode.cpush, getReg(ctx.expr(i)));
|
||||
else
|
||||
emit(ctx.expr(i), OpCode.push, getReg(ctx.expr(i)));
|
||||
}
|
||||
emit(ctx.variable(), OpCode.addI, arp,
|
||||
new Num(((FunctionType) an.function.get(ctx).getType()).getLocalDataSize() + ARBASESIZE), tempArp);
|
||||
for (int i = ctx.expr().size() - 1; i >= 0; i--) {
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i))) {
|
||||
emit(ctx.expr(i), OpCode.cpop, temp);
|
||||
emit(ctx.expr(i), OpCode.cstoreAI, temp, tempArp, new Num(parameters.getOffsets().get(i)));
|
||||
} else {
|
||||
emit(ctx.expr(i), OpCode.pop, temp);
|
||||
emit(ctx.expr(i), OpCode.storeAI, temp, tempArp, new Num(parameters.getOffsets().get(i)));
|
||||
}
|
||||
}
|
||||
emit(ctx.variable(), OpCode.storeAI, arp, tempArp, new Num(-4));
|
||||
Label label = new Label("ret" + ctx.hashCode());
|
||||
emit(ctx.variable(), OpCode.loadI, new Num(label), temp);
|
||||
emit(ctx.variable(), OpCode.storeAI, temp, tempArp, new Num(-8));
|
||||
emit(ctx, OpCode.i2i, tempArp, arp);
|
||||
emit(ctx.variable(), OpCode.pop, temp);
|
||||
emit(ctx, OpCode.jump, temp);
|
||||
emit(ctx, label, OpCode.loadAI, arp, new Num(-4), arp);
|
||||
|
||||
an.registers.put(ctx, resultReg);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFuncDeclare(FuncDeclareContext ctx) {
|
||||
Reg temp = new Reg("r__");
|
||||
Label skip = new Label("s" + ctx.hashCode());
|
||||
emit(ctx, OpCode.jumpI, skip);
|
||||
int targetAddress = emit(ctx, OpCode.nop).getLine();
|
||||
visit(ctx.body);
|
||||
copyReg(ctx.body, ctx);
|
||||
if (SimpleType.CHAR.equals(an.types.get(ctx.body)))
|
||||
emit(ctx, OpCode.c2c, getReg(ctx), resultReg);
|
||||
else
|
||||
emit(ctx, OpCode.i2i, getReg(ctx), resultReg);
|
||||
emit(ctx, OpCode.loadAI, arp, new Num(-8), temp);
|
||||
emit(ctx, OpCode.jump, temp);
|
||||
emit(ctx, skip, OpCode.loadI, new Num(targetAddress), temp);
|
||||
emit(ctx, OpCode.storeAI, temp, getVar(ctx, an.variables.get(ctx)), new Num(an.variables.get(ctx).getOffset()));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBool(BoolContext ctx) {
|
||||
emit(ctx, OpCode.loadI, new Num(ctx.TRUE() != null ? 1 : 0), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNumber(NumberContext ctx) {
|
||||
emit(ctx, OpCode.loadI, new Num(Integer.parseInt(ctx.LITERAL10().getText())), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix1(Infix1Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx, ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix2(Infix2Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx, ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix3(Infix3Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx, ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix4(Infix4Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx, OpCode.and, getReg(ctx.lhs), getReg(ctx.rhs), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix5(Infix5Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx, OpCode.or, getReg(ctx.lhs), getReg(ctx.rhs), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPrefix1(Prefix1Context ctx) {
|
||||
visitChildren(ctx);
|
||||
|
||||
switch (ctx.op.getType()) {
|
||||
case BasicLexer.MINUS:
|
||||
emit(ctx, OpCode.rsubI, getReg(ctx.singleExpr()), new Num(0), getReg(ctx));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitVar(VarContext ctx) {
|
||||
if (SimpleType.CHAR.equals(an.types.get(ctx)))
|
||||
emit(ctx, OpCode.cloadAI, getVar(ctx.variable(), an.variables.get(ctx.variable())),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), getReg(ctx));
|
||||
else
|
||||
emit(ctx, OpCode.loadAI, getVar(ctx.variable(), an.variables.get(ctx.variable())),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), getReg(ctx));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitChar(CharContext ctx) {
|
||||
emit(ctx, OpCode.loadI, new Num(ctx.CHAR().getText().codePointAt(1)), getReg(ctx));
|
||||
emit(ctx, OpCode.i2c, getReg(ctx), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitRead(ReadContext ctx) {
|
||||
for (VariableContext expr : ctx.variable()) {
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit(ctx, OpCode.in, new Str(""), getReg(ctx));
|
||||
emit(ctx, OpCode.storeAI, getReg(ctx), getVar(expr, an.variables.get(expr)),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
// Get input until at least 1 character
|
||||
Label getTarget = new Label("lcin_l" + ctx.hashCode());
|
||||
Label continueTarget = new Label("lcin_e" + ctx.hashCode());
|
||||
Reg countReg = new Reg("tempReg");
|
||||
emit(ctx, getTarget, OpCode.cin, new Str(""));
|
||||
emit(ctx, OpCode.pop, countReg);
|
||||
emit(ctx, OpCode.cbr, countReg, continueTarget, getTarget);
|
||||
|
||||
// Get character
|
||||
emit(ctx, continueTarget, OpCode.cpop, getReg(ctx));
|
||||
emit(ctx, OpCode.cstoreAI, getReg(ctx), getVar(expr, an.variables.get(expr)),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
|
||||
// Pop all remaining characters
|
||||
Label loopTarget = new Label("lcpop_l" + ctx.hashCode());
|
||||
Label iterTarget = new Label("lcpop_c" + ctx.hashCode());
|
||||
Label stopTarget = new Label("lcpop_e" + ctx.hashCode());
|
||||
Reg tempReg2 = new Reg("tempReg2");
|
||||
emit(ctx, loopTarget, OpCode.subI, countReg, new Num(1), countReg);
|
||||
emit(ctx, OpCode.cbr, countReg, iterTarget, stopTarget);
|
||||
emit(ctx, iterTarget, OpCode.cpop, tempReg2);
|
||||
emit(ctx, OpCode.jumpI, loopTarget);
|
||||
emit(ctx, stopTarget, OpCode.nop);
|
||||
} else {
|
||||
emit(ctx, OpCode.out, new Str("Unknown type: "), an.registers.get(expr));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIf(IfContext ctx) {
|
||||
Label toTrue = new Label("if_t" + ctx.hashCode());
|
||||
Label toFalse = new Label("if_f" + ctx.hashCode());
|
||||
Label toEnd = new Label("if_e" + ctx.hashCode());
|
||||
|
||||
visit(ctx.cond);
|
||||
if (ctx.onFalse == null) {
|
||||
emit(ctx, OpCode.cbr, getReg(ctx.cond), toTrue, toEnd);
|
||||
|
||||
emit(ctx, toTrue, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
} else {
|
||||
emit(ctx, OpCode.cbr, getReg(ctx.cond), toTrue, toFalse);
|
||||
|
||||
emit(ctx, toTrue, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
if (an.types.get(ctx) != SimpleType.VOID)
|
||||
emit(ctx, OpCode.i2i, getReg(ctx.onTrue), getReg(ctx));
|
||||
emit(ctx, OpCode.jumpI, toEnd);
|
||||
|
||||
emit(ctx, toFalse, OpCode.nop);
|
||||
visit(ctx.onFalse);
|
||||
if (an.types.get(ctx) != SimpleType.VOID)
|
||||
emit(ctx, OpCode.i2i, getReg(ctx.onFalse), getReg(ctx));
|
||||
|
||||
}
|
||||
emit(ctx, toEnd, OpCode.nop);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhile(WhileContext ctx) {
|
||||
Label toLoop = new Label("while_t" + ctx.hashCode());
|
||||
Label toCond = new Label("while_f" + ctx.hashCode());
|
||||
Label toEnd = new Label("while_e" + ctx.hashCode());
|
||||
|
||||
emit(ctx, OpCode.jumpI, toCond);
|
||||
emit(ctx, toLoop, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
emit(ctx, toCond, OpCode.nop);
|
||||
visit(ctx.cond);
|
||||
emit(ctx, OpCode.cbr, getReg(ctx.cond), toLoop, toEnd);
|
||||
emit(ctx, toEnd, OpCode.nop);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWrite(WriteContext ctx) {
|
||||
for (ExprContext expr : ctx.expr()) {
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit(ctx, OpCode.out, new Str(""), getReg(expr));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
Reg tempReg = new Reg("tempReg");
|
||||
emit(ctx, OpCode.cpush, getReg(expr));
|
||||
emit(ctx, OpCode.loadI, new Num(1), tempReg);
|
||||
emit(ctx, OpCode.push, tempReg);
|
||||
emit(ctx, OpCode.cout, new Str(""));
|
||||
} else {
|
||||
emit(ctx, OpCode.out, new Str("Unknown type: "), getReg(expr));
|
||||
}
|
||||
}
|
||||
copyReg(ctx.expr(0), ctx);
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,38 +1,45 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import pp.s1184725.boppi.BasicParser.*;
|
||||
import pp.s1184725.boppi.antlr.BoppiBaseVisitor;
|
||||
import pp.s1184725.boppi.antlr.BoppiLexer;
|
||||
import pp.s1184725.boppi.antlr.BoppiParser.*;
|
||||
|
||||
/**
|
||||
* This class performs type checking and variable assignment on a bare parse
|
||||
* tree.
|
||||
*
|
||||
*/
|
||||
public class BoppiBasicChecker extends BasicBaseVisitor<Type> {
|
||||
public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
||||
private CachingSymbolTable<Type> symbols;
|
||||
private Annotations an;
|
||||
private Logger log;
|
||||
|
||||
/**
|
||||
* Creates a new checker with a logger and an object to link types and
|
||||
* variables to parse tree nodes.
|
||||
* Checks and annotates a program. Problems are reported to the given
|
||||
* logger.
|
||||
*
|
||||
* @param ast
|
||||
* the program's AST
|
||||
* @param logger
|
||||
* the logger object to write warnings and errors to
|
||||
* @param annotations
|
||||
* the annotations object
|
||||
* @return the generated annotations
|
||||
*/
|
||||
public BoppiBasicChecker(Logger logger, Annotations annotations) {
|
||||
public static Annotations checkProgram(ParseTree ast, Logger logger) {
|
||||
BoppiChecker checker = new BoppiChecker(logger);
|
||||
checker.visit(ast);
|
||||
return checker.an;
|
||||
}
|
||||
|
||||
protected BoppiChecker(Logger logger) {
|
||||
symbols = new CachingSymbolTable<>();
|
||||
an = annotations;
|
||||
an = new Annotations();
|
||||
log = logger;
|
||||
}
|
||||
|
||||
|
@ -116,7 +123,7 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> {
|
|||
public Type visitFuncDeclare(FuncDeclareContext ctx) {
|
||||
try {
|
||||
List<Type> parameterTypes = ctx.type().stream().skip(1).map(this::visit).collect(Collectors.toList());
|
||||
FunctionType type = new FunctionType(visit(ctx.result), parameterTypes, symbols.functionDepth);
|
||||
FunctionType type = new FunctionType(visit(ctx.result), parameterTypes);
|
||||
Variable<Type> func = symbols.put(ctx.name.getText(), type);
|
||||
an.variables.put(ctx, func);
|
||||
an.currentFunction.push(func);
|
||||
|
@ -179,10 +186,10 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> {
|
|||
checkConstraint(lht, rht, ctx);
|
||||
|
||||
switch (ctx.op.getType()) {
|
||||
case BasicLexer.LT:
|
||||
case BasicLexer.LEQ:
|
||||
case BasicLexer.GTE:
|
||||
case BasicLexer.GT:
|
||||
case BoppiLexer.LT:
|
||||
case BoppiLexer.LEQ:
|
||||
case BoppiLexer.GTE:
|
||||
case BoppiLexer.GT:
|
||||
checkConstraint(lht, SimpleType.INT, ctx);
|
||||
}
|
||||
|
||||
|
@ -220,12 +227,12 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> {
|
|||
Type type = visit(ctx.singleExpr());
|
||||
|
||||
switch (ctx.op.getType()) {
|
||||
case BasicLexer.NOT:
|
||||
case BoppiLexer.NOT:
|
||||
checkConstraint(type, SimpleType.BOOL, ctx.singleExpr());
|
||||
break;
|
||||
|
||||
case BasicLexer.PLUS:
|
||||
case BasicLexer.MINUS:
|
||||
case BoppiLexer.PLUS:
|
||||
case BoppiLexer.MINUS:
|
||||
checkConstraint(type, SimpleType.INT, ctx.singleExpr());
|
||||
break;
|
||||
}
|
||||
|
@ -235,7 +242,7 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> {
|
|||
|
||||
@Override
|
||||
public Type visitProgram(ProgramContext ctx) {
|
||||
FunctionType main = new FunctionType(SimpleType.VOID, new ArrayList<>(), symbols.functionDepth);
|
||||
FunctionType main = new FunctionType(SimpleType.VOID, new ArrayList<>());
|
||||
an.currentFunction.push(new Variable<Type>(main, 0, 0));
|
||||
main.setLocalDataSize(symbols.withFunctionScope(() -> super.visitProgram(ctx)));
|
||||
return null;
|
|
@ -0,0 +1,605 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import pp.iloc.eval.Machine;
|
||||
import pp.iloc.model.*;
|
||||
import pp.s1184725.boppi.antlr.BoppiBaseVisitor;
|
||||
import pp.s1184725.boppi.antlr.BoppiLexer;
|
||||
import pp.s1184725.boppi.antlr.BoppiParser.*;
|
||||
|
||||
public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
||||
private static final int ARBASESIZE = 16;
|
||||
private static final Operand ZERO = new Num(0);
|
||||
private static final Operand OFFSET_ARP = new Num(-4), OFFSET_RETURN_ADDR = new Num(-8),
|
||||
OFFSET_RETURN_VAL = new Num(-12), OFFSET_AL = new Num(-16);
|
||||
|
||||
/**
|
||||
* Recommended number of registers to use before throwing a warning.
|
||||
*/
|
||||
public static int RECOMMENDED_REGISTER_COUNT = 10;
|
||||
private Program prog;
|
||||
private Annotations an;
|
||||
private int regNum;
|
||||
private final Reg tempArp = new Reg("ART"), arp = Machine.ARP_REG;
|
||||
private List<Reg> regFree, regInUse;
|
||||
private Logger logger;
|
||||
|
||||
/**
|
||||
* Maps operator tokens to ILOC opcodes.
|
||||
*/
|
||||
private static Map<Integer, OpCode> ops = new HashMap<Integer, OpCode>() {
|
||||
private static final long serialVersionUID = 8979722313842633807L;
|
||||
|
||||
{
|
||||
put(BoppiLexer.AND, OpCode.and);
|
||||
put(BoppiLexer.DIVIDE, OpCode.div);
|
||||
put(BoppiLexer.EQ, OpCode.cmp_EQ);
|
||||
put(BoppiLexer.GT, OpCode.cmp_GT);
|
||||
put(BoppiLexer.GTE, OpCode.cmp_GE);
|
||||
put(BoppiLexer.LEQ, OpCode.cmp_LE);
|
||||
put(BoppiLexer.LT, OpCode.cmp_LT);
|
||||
put(BoppiLexer.MINUS, OpCode.sub);
|
||||
put(BoppiLexer.MULTIPLY, OpCode.mult);
|
||||
put(BoppiLexer.NEQ, OpCode.cmp_NE);
|
||||
put(BoppiLexer.PLUS, OpCode.add);
|
||||
put(BoppiLexer.OR, OpCode.or);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new generator with the given variable annotations and attaches
|
||||
* the given logger.
|
||||
*
|
||||
* @param ast
|
||||
* the program's AST
|
||||
* @param annotations
|
||||
* the annotation object to use during generation
|
||||
* @param logger
|
||||
* the logger to report errors to
|
||||
* @return an ILOC program generated from the AST
|
||||
*/
|
||||
public static Program generateProgram(ParseTree ast, Annotations annotations, Logger logger) {
|
||||
BoppiGenerator generator = new BoppiGenerator(annotations, logger);
|
||||
generator.visit(ast);
|
||||
return generator.prog;
|
||||
}
|
||||
|
||||
protected BoppiGenerator(Annotations annotations, Logger logger) {
|
||||
an = annotations;
|
||||
prog = new Program();
|
||||
regNum = 0;
|
||||
regFree = new ArrayList<>();
|
||||
regInUse = new ArrayList<>();
|
||||
}
|
||||
|
||||
private Reg makeReg(ParserRuleContext ctx) {
|
||||
Reg reg;
|
||||
if (regFree.isEmpty()) {
|
||||
reg = new Reg("__" + (regInUse.size() + 1));
|
||||
regInUse.add(reg);
|
||||
|
||||
if (regInUse.size() > 10)
|
||||
logger.warning(
|
||||
String.format("Using more than 10 registers at %d:%d. Consider rebalancing your expressions.",
|
||||
ctx.start.getLine(), ctx.start.getCharPositionInLine()));
|
||||
} else {
|
||||
if (regFree.remove(an.registers.get(ctx)))
|
||||
reg = an.registers.get(ctx);
|
||||
else
|
||||
reg = regFree.remove(0);
|
||||
regInUse.add(reg);
|
||||
}
|
||||
an.registers.put(ctx, reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
private void freeReg(ParserRuleContext ctx) {
|
||||
Reg reg = an.registers.get(ctx);
|
||||
if (reg == null)
|
||||
return;
|
||||
if (!regInUse.contains(reg)) {
|
||||
logger.severe(getError(ctx, "INTERNAL: cannot free register %s since it is not in use.", reg.getName()));
|
||||
} else {
|
||||
regInUse.remove(reg);
|
||||
regFree.add(reg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a register for a given tree node.
|
||||
*
|
||||
* @param parseTree
|
||||
* the tree node
|
||||
* @return a register for the tree node
|
||||
*/
|
||||
private Reg getReg(ParseTree parseTree) {
|
||||
Reg reg = an.registers.get(parseTree);
|
||||
if (reg == null) {
|
||||
if (Math.max(3, 4) > 2)
|
||||
throw new RuntimeException("???" + parseTree.getText());
|
||||
reg = new Reg("r_" + (regNum++));
|
||||
an.registers.put(parseTree, reg);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the register used in the {@code source} tree node to the
|
||||
* {@link destination} node.
|
||||
*
|
||||
* @param source
|
||||
* the node to retrieve the register from
|
||||
* @param destination
|
||||
* the node to copy the register to
|
||||
* @return the register that was copied
|
||||
*/
|
||||
private Reg copyReg(ParseTree source, ParseTree destination) {
|
||||
Reg reg = an.registers.get(source);
|
||||
an.registers.put(destination, reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
private Reg getVar(ParserRuleContext node) {
|
||||
Variable<Type> var = an.variables.get(node);
|
||||
|
||||
if (var.getDepth() <= an.function.get(node).getDepth()) {
|
||||
emit("travelling ALs", OpCode.i2i, arp, tempArp);
|
||||
for (int i = var.getDepth(); i <= an.function.get(node).getDepth(); i++)
|
||||
emit(StringUtils.repeat(' ', i) + "\\", OpCode.loadAI, tempArp, OFFSET_AL, tempArp);
|
||||
|
||||
return tempArp;
|
||||
} else
|
||||
return arp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an operation from the parameters and adds it to the program
|
||||
* under construction.
|
||||
*/
|
||||
private Op emit(String comment, Label label, OpCode opCode, Operand... args) {
|
||||
Op result = new Op(label, opCode, args);
|
||||
result.setComment(String.format("%-40s | %20s : %s", comment,
|
||||
regInUse.stream().map((reg) -> reg.getName().substring(2)).collect(Collectors.joining(" ")),
|
||||
regFree.stream().map((reg) -> reg.getName().substring(2)).collect(Collectors.joining(" "))));
|
||||
this.prog.addInstr(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an operation from the parameters and adds it to the program
|
||||
* under construction.
|
||||
*/
|
||||
private Op emit(String comment, OpCode opCode, Operand... args) {
|
||||
return emit(comment, (Label) null, opCode, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBlock(BlockContext ctx) {
|
||||
super.visitBlock(ctx);
|
||||
copyReg(ctx.expr(), ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDeclare(DeclareContext ctx) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitParens(ParensContext ctx) {
|
||||
super.visitParens(ctx);
|
||||
copyReg(ctx.expr(), ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProgram(ProgramContext ctx) {
|
||||
emit("initialise temp ARP", OpCode.loadI, ZERO, tempArp);
|
||||
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitExpr(ExprContext ctx) {
|
||||
for (int i = 0; i < ctx.singleExpr().size() - 1; i++) {
|
||||
visit(ctx.singleExpr(i));
|
||||
freeReg(ctx.singleExpr(i));
|
||||
}
|
||||
ParserRuleContext last = ctx.singleExpr(ctx.singleExpr().size() - 1);
|
||||
visit(last);
|
||||
copyReg(last, ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAssign(AssignContext ctx) {
|
||||
visit(ctx.singleExpr());
|
||||
copyReg(ctx.singleExpr(), ctx);
|
||||
|
||||
if (SimpleType.CHAR.equals(an.types.get(ctx)))
|
||||
emit("to " + ctx.variable().getText(), OpCode.cstoreAI, getReg(ctx), getVar(ctx.variable()),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()));
|
||||
else
|
||||
emit("to " + ctx.variable().getText(), OpCode.storeAI, getReg(ctx), getVar(ctx.variable()),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(CallContext ctx) {
|
||||
String base = "call " + ctx.variable().getText() + " - ";
|
||||
Variable<Type> function = an.variables.get(ctx.variable());
|
||||
FunctionType parameters = ((FunctionType) function.getType());
|
||||
visit(ctx.variable());
|
||||
freeReg(ctx.variable());
|
||||
emit(base + "target address", OpCode.loadAI, getVar(ctx.variable()),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), makeReg(ctx));
|
||||
emit(base + "target address", OpCode.push, getReg(ctx));
|
||||
freeReg(ctx);
|
||||
|
||||
for (int i = 0; i < ctx.expr().size(); i++) {
|
||||
visit(ctx.expr(i));
|
||||
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i)))
|
||||
emit(base + "param " + i, OpCode.cpush, getReg(ctx.expr(i)));
|
||||
else
|
||||
emit(base + "param " + i, OpCode.push, getReg(ctx.expr(i)));
|
||||
freeReg(ctx.expr(i));
|
||||
}
|
||||
|
||||
emit(base + "set new ARP", OpCode.addI, arp,
|
||||
new Num(((FunctionType) an.function.get(ctx).getType()).getLocalDataSize() + ARBASESIZE), tempArp);
|
||||
|
||||
makeReg(ctx);
|
||||
for (int i = ctx.expr().size() - 1; i >= 0; i--) {
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i))) {
|
||||
emit(base + "param " + i, OpCode.cpop, getReg(ctx));
|
||||
emit(base + "param " + i, OpCode.cstoreAI, getReg(ctx), tempArp,
|
||||
new Num(parameters.getOffsets().get(i)));
|
||||
} else {
|
||||
emit(base + "param " + i, OpCode.pop, getReg(ctx));
|
||||
emit(base + "param " + i, OpCode.storeAI, getReg(ctx), tempArp,
|
||||
new Num(parameters.getOffsets().get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
emit(base + "link caller ARP", OpCode.storeAI, arp, tempArp, OFFSET_ARP);
|
||||
|
||||
emit(base + "travelling ALs", OpCode.i2i, arp, getReg(ctx));
|
||||
for (int i = an.variables.get(ctx.variable()).getDepth(); i <= an.function.get(ctx).getDepth(); i++)
|
||||
emit(base + StringUtils.repeat(' ', i) + "\\", OpCode.loadAI, getReg(ctx), OFFSET_AL, getReg(ctx));
|
||||
emit(base + "link caller AL", OpCode.storeAI, getReg(ctx), tempArp, OFFSET_AL);
|
||||
|
||||
Label label = new Label("ret" + ctx.hashCode());
|
||||
emit(base + "load return address", OpCode.loadI, new Num(label), getReg(ctx));
|
||||
emit(base + "set return address", OpCode.storeAI, getReg(ctx), tempArp, OFFSET_RETURN_ADDR);
|
||||
emit(base + "move ARP", OpCode.i2i, tempArp, arp);
|
||||
emit(base + "target address", OpCode.pop, getReg(ctx));
|
||||
freeReg(ctx);
|
||||
|
||||
Stack<Reg> inUse = new Stack<>();
|
||||
for (Reg reg : regInUse) {
|
||||
inUse.push(reg);
|
||||
emit(base + "register save " + reg.getName(), OpCode.push, reg);
|
||||
}
|
||||
|
||||
emit(base + "execute", OpCode.jump, getReg(ctx));
|
||||
|
||||
emit(base + "load result", label, OpCode.loadAI, arp, OFFSET_RETURN_VAL, makeReg(ctx));
|
||||
while (!inUse.isEmpty()) {
|
||||
Reg reg = inUse.pop();
|
||||
emit(base + "restoring register save " + reg.getName(), OpCode.pop, reg);
|
||||
}
|
||||
emit(base + "reset ARP", OpCode.loadAI, arp, OFFSET_ARP, arp);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFuncDeclare(FuncDeclareContext ctx) {
|
||||
String base = "define " + ctx.IDENTIFIER(0).getText() + " - ";
|
||||
Label skip = new Label("s" + ctx.hashCode());
|
||||
emit(base + "jump over body", OpCode.jumpI, skip);
|
||||
int targetAddress = emit(base + "entry point", OpCode.nop).getLine();
|
||||
visit(ctx.body);
|
||||
emit(base + "move result", OpCode.storeAI, getReg(ctx.body), arp, OFFSET_RETURN_VAL);
|
||||
freeReg(ctx.body);
|
||||
emit(base + "load return address", OpCode.loadAI, arp, OFFSET_RETURN_ADDR, makeReg(ctx));
|
||||
emit(base + "go to return address", OpCode.jump, getReg(ctx));
|
||||
emit(base + "load target address", skip, OpCode.loadI, new Num(targetAddress), getReg(ctx));
|
||||
emit(base + "set target address", OpCode.storeAI, getReg(ctx), getVar(ctx),
|
||||
new Num(an.variables.get(ctx).getOffset()));
|
||||
freeReg(ctx);
|
||||
an.registers.removeFrom(ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBool(BoolContext ctx) {
|
||||
emit(ctx.getText(), OpCode.loadI, new Num(ctx.TRUE() != null ? 1 : 0), makeReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNumber(NumberContext ctx) {
|
||||
emit(ctx.getText(), OpCode.loadI, new Num(Integer.parseInt(ctx.LITERAL10().getText())), makeReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix1(Infix1Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx.getChild(1).getText(), ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs),
|
||||
copyReg(ctx.lhs, ctx));
|
||||
freeReg(ctx.rhs);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix2(Infix2Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx.getChild(1).getText(), ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs),
|
||||
copyReg(ctx.lhs, ctx));
|
||||
freeReg(ctx.rhs);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix3(Infix3Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx.getChild(1).getText(), ops.get(ctx.op.getType()), getReg(ctx.lhs), getReg(ctx.rhs),
|
||||
copyReg(ctx.lhs, ctx));
|
||||
freeReg(ctx.rhs);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix4(Infix4Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx.getChild(1).getText(), ops.get(ctx.AND().getSymbol().getType()), getReg(ctx.lhs), getReg(ctx.rhs),
|
||||
copyReg(ctx.lhs, ctx));
|
||||
freeReg(ctx.rhs);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInfix5(Infix5Context ctx) {
|
||||
visitChildren(ctx);
|
||||
emit(ctx.getChild(1).getText(), ops.get(ctx.OR().getSymbol().getType()), getReg(ctx.lhs), getReg(ctx.rhs),
|
||||
copyReg(ctx.lhs, ctx));
|
||||
freeReg(ctx.rhs);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPrefix1(Prefix1Context ctx) {
|
||||
visitChildren(ctx);
|
||||
copyReg(ctx.singleExpr(), ctx);
|
||||
|
||||
switch (ctx.op.getType()) {
|
||||
case BoppiLexer.MINUS:
|
||||
emit("unary -", OpCode.rsubI, getReg(ctx), ZERO, getReg(ctx));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitVar(VarContext ctx) {
|
||||
if (SimpleType.CHAR.equals(an.types.get(ctx)))
|
||||
emit("var " + ctx.variable().getText(), OpCode.cloadAI, getVar(ctx.variable()),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), makeReg(ctx));
|
||||
else
|
||||
emit("var " + ctx.variable().getText(), OpCode.loadAI, getVar(ctx.variable()),
|
||||
new Num(an.variables.get(ctx.variable()).getOffset()), makeReg(ctx));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitChar(CharContext ctx) {
|
||||
emit(ctx.getText(), OpCode.loadI, new Num(ctx.CHAR().getText().codePointAt(1)), makeReg(ctx));
|
||||
emit(ctx.getText(), OpCode.i2c, getReg(ctx), getReg(ctx));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitRead(ReadContext ctx) {
|
||||
if (ctx.variable().size() > 1) {
|
||||
for (VariableContext expr : ctx.variable()) {
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit("", OpCode.in, new Str(""), makeReg(ctx));
|
||||
emit("var " + expr.getText(), OpCode.storeAI, getReg(ctx), getVar(expr),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
// Get input until at least 1 character
|
||||
Label getTarget = new Label("lcin_l" + ctx.hashCode());
|
||||
Label continueTarget = new Label("lcin_e" + ctx.hashCode());
|
||||
|
||||
Reg countReg = makeReg(ctx);
|
||||
makeReg(ctx);
|
||||
|
||||
emit("", getTarget, OpCode.cin, new Str(""));
|
||||
emit("str length", OpCode.pop, countReg);
|
||||
emit("repeat if 0 length", OpCode.cbr, countReg, continueTarget, getTarget);
|
||||
|
||||
// Get character
|
||||
emit("pop whole string", continueTarget, OpCode.cpop, getReg(ctx));
|
||||
emit("var " + expr.getText(), OpCode.cstoreAI, getReg(ctx), getVar(expr),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
|
||||
// Pop all remaining characters
|
||||
Label loopTarget = new Label("lcpop_l" + ctx.hashCode());
|
||||
Label iterTarget = new Label("lcpop_c" + ctx.hashCode());
|
||||
Label stopTarget = new Label("lcpop_e" + ctx.hashCode());
|
||||
emit("pop remaining", loopTarget, OpCode.subI, countReg, new Num(1), countReg);
|
||||
emit("pop remaining", OpCode.cbr, countReg, iterTarget, stopTarget);
|
||||
emit("pop remaining", iterTarget, OpCode.cpop, getReg(ctx));
|
||||
emit("pop remaining", OpCode.jumpI, loopTarget);
|
||||
emit("pop remaining", stopTarget, OpCode.nop);
|
||||
} else {
|
||||
emit("????????", OpCode.out, new Str("Unknown type: "), copyReg(expr, ctx));
|
||||
}
|
||||
freeReg(ctx);
|
||||
}
|
||||
} else {
|
||||
VariableContext expr = ctx.variable(0);
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit("", OpCode.in, new Str(""), makeReg(ctx));
|
||||
emit("var " + expr.getText(), OpCode.storeAI, getReg(ctx), getVar(expr),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
// Get input until at least 1 character
|
||||
Label getTarget = new Label("lcin_l" + ctx.hashCode());
|
||||
Label continueTarget = new Label("lcin_e" + ctx.hashCode());
|
||||
|
||||
Reg countReg = makeReg(ctx);
|
||||
makeReg(ctx);
|
||||
|
||||
emit("", getTarget, OpCode.cin, new Str(""));
|
||||
emit("str length", OpCode.pop, countReg);
|
||||
emit("repeat if 0 length", OpCode.cbr, countReg, continueTarget, getTarget);
|
||||
|
||||
// Get character
|
||||
emit("pop whole string", continueTarget, OpCode.cpop, getReg(ctx));
|
||||
emit("var " + expr.getText(), OpCode.cstoreAI, getReg(ctx), getVar(expr),
|
||||
new Num(an.variables.get(expr).getOffset()));
|
||||
|
||||
// Pop all remaining characters
|
||||
Label loopTarget = new Label("lcpop_l" + ctx.hashCode());
|
||||
Label iterTarget = new Label("lcpop_c" + ctx.hashCode());
|
||||
Label stopTarget = new Label("lcpop_e" + ctx.hashCode());
|
||||
emit("pop remaining", loopTarget, OpCode.subI, countReg, new Num(1), countReg);
|
||||
emit("pop remaining", OpCode.cbr, countReg, iterTarget, stopTarget);
|
||||
emit("pop remaining", iterTarget, OpCode.cpop, getReg(ctx));
|
||||
emit("pop remaining", OpCode.jumpI, loopTarget);
|
||||
emit("pop remaining", stopTarget, OpCode.nop);
|
||||
// Reload value
|
||||
emit("var " + expr.getText(), OpCode.cloadAI, getVar(expr), new Num(an.variables.get(expr).getOffset()),
|
||||
getReg(ctx));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIf(IfContext ctx) {
|
||||
Label toTrue = new Label("if_t" + ctx.hashCode());
|
||||
Label toFalse = new Label("if_f" + ctx.hashCode());
|
||||
Label toEnd = new Label("if_e" + ctx.hashCode());
|
||||
|
||||
visit(ctx.cond);
|
||||
if (ctx.onFalse == null) {
|
||||
emit("", OpCode.cbr, getReg(ctx.cond), toTrue, toEnd);
|
||||
freeReg(ctx.cond);
|
||||
|
||||
emit("", toTrue, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
freeReg(ctx.onTrue);
|
||||
} else {
|
||||
emit("", OpCode.cbr, getReg(ctx.cond), toTrue, toFalse);
|
||||
freeReg(ctx.cond);
|
||||
|
||||
emit("", toTrue, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
freeReg(ctx.onTrue);
|
||||
if (an.types.get(ctx) != SimpleType.VOID)
|
||||
emit("result", OpCode.i2i, getReg(ctx.onTrue), makeReg(ctx));
|
||||
emit("", OpCode.jumpI, toEnd);
|
||||
freeReg(ctx);
|
||||
|
||||
emit("", toFalse, OpCode.nop);
|
||||
visit(ctx.onFalse);
|
||||
freeReg(ctx.onFalse);
|
||||
if (an.types.get(ctx) != SimpleType.VOID)
|
||||
emit("result", OpCode.i2i, getReg(ctx.onFalse), makeReg(ctx));
|
||||
|
||||
}
|
||||
emit("end target", toEnd, OpCode.nop);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWhile(WhileContext ctx) {
|
||||
Label toLoop = new Label("while_t" + ctx.hashCode());
|
||||
Label toCond = new Label("while_f" + ctx.hashCode());
|
||||
Label toEnd = new Label("while_e" + ctx.hashCode());
|
||||
|
||||
emit("to condition", OpCode.jumpI, toCond);
|
||||
emit("loop target", toLoop, OpCode.nop);
|
||||
visit(ctx.onTrue);
|
||||
freeReg(ctx.onTrue);
|
||||
emit("condition target", toCond, OpCode.nop);
|
||||
visit(ctx.cond);
|
||||
freeReg(ctx.cond);
|
||||
emit("", OpCode.cbr, getReg(ctx.cond), toLoop, toEnd);
|
||||
emit("end target", toEnd, OpCode.nop);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitWrite(WriteContext ctx) {
|
||||
if (ctx.expr().size() > 1) {
|
||||
for (ExprContext expr : ctx.expr()) {
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit("", OpCode.out, new Str(""), getReg(expr));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
makeReg(ctx);
|
||||
emit("push character", OpCode.cpush, getReg(expr));
|
||||
emit("load 1", OpCode.loadI, new Num(1), getReg(ctx));
|
||||
emit("push 1", OpCode.push, getReg(ctx));
|
||||
emit("print character", OpCode.cout, new Str(""));
|
||||
freeReg(ctx);
|
||||
} else {
|
||||
emit("??????????????", OpCode.out, new Str("Unknown type: "), getReg(expr));
|
||||
}
|
||||
freeReg(expr);
|
||||
}
|
||||
an.registers.removeFrom(ctx);
|
||||
} else {
|
||||
ExprContext expr = ctx.expr(0);
|
||||
visit(expr);
|
||||
if (SimpleType.BOOL.equals(an.types.get(expr)) || SimpleType.INT.equals(an.types.get(expr))) {
|
||||
emit("", OpCode.out, new Str(""), getReg(expr));
|
||||
} else if (SimpleType.CHAR.equals(an.types.get(expr))) {
|
||||
makeReg(ctx);
|
||||
emit("push character", OpCode.cpush, getReg(expr));
|
||||
emit("load 1", OpCode.loadI, new Num(1), getReg(ctx));
|
||||
emit("push 1", OpCode.push, getReg(ctx));
|
||||
emit("print character", OpCode.cout, new Str(""));
|
||||
freeReg(ctx);
|
||||
}
|
||||
|
||||
copyReg(expr, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an error message for a given parse tree node.
|
||||
*
|
||||
* @param ctx
|
||||
* the parse tree node at which the error occurred
|
||||
* @param message
|
||||
* the error message
|
||||
* @param args
|
||||
* arguments for the message, see {@link String#format}
|
||||
*/
|
||||
private String getError(ParserRuleContext node, String message, Object... args) {
|
||||
int line = node.getStart().getLine();
|
||||
int column = node.getStart().getCharPositionInLine();
|
||||
return String.format("Line %d:%d - %s", line, column, String.format(message, args));
|
||||
}
|
||||
}
|
|
@ -11,8 +11,8 @@ public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable<
|
|||
|
||||
@Override
|
||||
public void openFunctionScope() {
|
||||
System.out.println(this.getClass().getName() + ": entering scope depth " + functionDepth);
|
||||
super.openFunctionScope();
|
||||
System.out.println(this.getClass().getName() + ": entering scope depth " + functionDepth);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,7 +28,7 @@ public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable<
|
|||
|
||||
@Override
|
||||
public Variable<T> put(String id, T type) throws Exception, EmptyStackException {
|
||||
System.out.println(this.getClass().getName() + ": declaring '" + id + "' at scope " + functionDepth);
|
||||
System.out.println(this.getClass().getName() + ": declaring '" + id + "' ("+type.toString()+") at scope " + functionDepth);
|
||||
return super.put(id, type);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,11 @@ public class FunctionType implements Type {
|
|||
private List<Integer> offsets;
|
||||
private Type result;
|
||||
private int localDataSize;
|
||||
private int depth;
|
||||
|
||||
public FunctionType(Type returnType, List<Type> parameterTypes, int depth) {
|
||||
public FunctionType(Type returnType, List<Type> parameterTypes) {
|
||||
result = returnType;
|
||||
parameters = new ArrayList<>(parameterTypes);
|
||||
offsets = new ArrayList<>();
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,12 +81,4 @@ public class FunctionType implements Type {
|
|||
public List<Integer> getOffsets() {
|
||||
return offsets;
|
||||
}
|
||||
|
||||
public int getDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public void setDepth(int newDepth) {
|
||||
depth = newDepth;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import static pp.s1184725.boppi.BasicLexer.*;
|
||||
import static pp.s1184725.boppi.antlr.BoppiLexer.*;
|
||||
|
||||
import pp.iloc.eval.Machine;
|
||||
import pp.s1184725.boppi.antlr.BoppiLexer;
|
||||
|
||||
/**
|
||||
* This class provides 4 basic data types:
|
||||
|
@ -28,7 +29,7 @@ public enum SimpleType implements Type {
|
|||
}
|
||||
|
||||
/**
|
||||
* Maps a token lexed by {@link BasicLexer} to a data type.
|
||||
* Maps a token lexed by {@link BoppiLexer} to a data type.
|
||||
*
|
||||
* @param token
|
||||
* the token to parse
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
|
||||
import pp.iloc.Simulator;
|
||||
import pp.iloc.model.Program;
|
||||
import pp.s1184725.boppi.antlr.BoppiLexer;
|
||||
import pp.s1184725.boppi.antlr.BoppiParser;
|
||||
|
||||
/**
|
||||
* This class provides methods for all steps in the Boppi tool chain.
|
||||
|
@ -56,8 +58,8 @@ public class ToolChain {
|
|||
* the logger to attach
|
||||
* @return the initialised lexer
|
||||
*/
|
||||
public static BasicLexer getLexer(CharStream stream, Logger logger) {
|
||||
BasicLexer lexer = new BasicLexer(stream);
|
||||
public static BoppiLexer getLexer(CharStream stream, Logger logger) {
|
||||
BoppiLexer lexer = new BoppiLexer(stream);
|
||||
lexer.removeErrorListeners();
|
||||
lexer.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
|
@ -79,8 +81,8 @@ public class ToolChain {
|
|||
* the logger to attach
|
||||
* @return the initialised parser
|
||||
*/
|
||||
public static BasicParser getParser(BasicLexer lexer, Logger logger) {
|
||||
BasicParser parser = new BasicParser(new CommonTokenStream(lexer));
|
||||
public static BoppiParser getParser(BoppiLexer lexer, Logger logger) {
|
||||
BoppiParser parser = new BoppiParser(new CommonTokenStream(lexer));
|
||||
parser.removeErrorListeners();
|
||||
parser.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
|
@ -93,7 +95,7 @@ public class ToolChain {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks a (sub)program with the {@link BoppiBasicChecker} and returns the
|
||||
* Checks a (sub)program with the {@link BoppiChecker} and returns the
|
||||
* annotations.
|
||||
*
|
||||
* @param program
|
||||
|
@ -103,9 +105,7 @@ public class ToolChain {
|
|||
* @return the annotations made by the checker
|
||||
*/
|
||||
public static Annotations getAnnotations(ParseTree program, Logger logger) {
|
||||
Annotations annotations = new Annotations();
|
||||
new BoppiBasicChecker(logger, annotations).visit(program);
|
||||
return annotations;
|
||||
return BoppiChecker.checkProgram(program, logger);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,12 +115,12 @@ public class ToolChain {
|
|||
* the parse tree to convert to ILOC
|
||||
* @param annotations
|
||||
* the annotations object provided by the checking phase
|
||||
* @param logger
|
||||
* the logger to write checker messages to
|
||||
* @return an ILOC program
|
||||
*/
|
||||
public static Program getILOC(ParseTree program, Annotations annotations) {
|
||||
BoppiBasicGenerator generator = new BoppiBasicGenerator(annotations);
|
||||
generator.visit(program);
|
||||
return generator.prog;
|
||||
public static Program getILOC(ParseTree program, Logger logger, Annotations annotations) {
|
||||
return BoppiGenerator.generateProgram(program, annotations, logger);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,7 +170,7 @@ public class ToolChain {
|
|||
List<LogRecord> logs = makeListLog(logger);
|
||||
|
||||
ParseTree ast = getParser(getLexer(stream, logger), logger).program();
|
||||
return Pair.of(getILOC(ast, getAnnotations(ast, logger)), logs);
|
||||
return Pair.of(getILOC(ast, logger, getAnnotations(ast, logger)), logs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,7 +185,7 @@ public class ToolChain {
|
|||
*/
|
||||
public static Program compile(CharStream stream, Logger logger) {
|
||||
ParseTree ast = getParser(getLexer(stream, logger), logger).program();
|
||||
return getILOC(ast, getAnnotations(ast, logger));
|
||||
return getILOC(ast, logger, getAnnotations(ast, logger));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,8 @@ public class Variable<T> {
|
|||
*
|
||||
* @param type
|
||||
* the type of the variable
|
||||
* @param depth
|
||||
* the lexical depth of this variable
|
||||
* @param offset
|
||||
* the memory offset for this variable
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
grammar Basic;
|
||||
grammar Boppi;
|
||||
|
||||
program: expr EOF;
|
||||
|
||||
|
@ -11,7 +11,7 @@ singleExpr
|
|||
| BRAOPEN expr BRACLOSE #block
|
||||
| IN PAROPEN variable (LISTDELIM variable)* PARCLOSE #read
|
||||
| OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write
|
||||
| variable PAROPEN expr (LISTDELIM expr)* PARCLOSE #call
|
||||
| variable PAROPEN (expr (LISTDELIM expr)*)? PARCLOSE #call
|
||||
| IFOPEN cond=expr IFTRUE onTrue=expr (IFFALSE onFalse=expr)? IFCLOSE #if
|
||||
| WHILEOPEN cond=expr WHILETRUE onTrue=expr WHILECLOSE #while
|
||||
| op=(PLUS|MINUS|NOT) singleExpr #prefix1
|
||||
|
@ -21,7 +21,7 @@ singleExpr
|
|||
| lhs=singleExpr AND rhs=singleExpr #infix4
|
||||
| lhs=singleExpr OR rhs=singleExpr #infix5
|
||||
| DECLARE type IDENTIFIER #declare
|
||||
| FUNCTION result=type name=IDENTIFIER PAROPEN type IDENTIFIER (LISTDELIM type IDENTIFIER)* PARCLOSE body=singleExpr #funcDeclare
|
||||
| FUNCTION result=type name=IDENTIFIER PAROPEN (type IDENTIFIER (LISTDELIM type IDENTIFIER)*)? PARCLOSE body=singleExpr #funcDeclare
|
||||
| <assoc=right> variable ASSIGN singleExpr #assign
|
||||
| variable #var
|
||||
| LITERAL10 #number
|
|
@ -1,182 +1,182 @@
|
|||
// Generated from Basic.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi;
|
||||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link BasicVisitor},
|
||||
* This class provides an empty implementation of {@link BoppiVisitor},
|
||||
* which can be extended to create a visitor which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public class BasicBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements BasicVisitor<T> {
|
||||
public class BoppiBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements BoppiVisitor<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitProgram(BasicParser.ProgramContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitProgram(BoppiParser.ProgramContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExpr(BasicParser.ExprContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitExpr(BoppiParser.ExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParens(BasicParser.ParensContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitParens(BoppiParser.ParensContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitRead(BasicParser.ReadContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitRead(BoppiParser.ReadContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDeclare(BasicParser.DeclareContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitDeclare(BoppiParser.DeclareContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBool(BasicParser.BoolContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitBool(BoppiParser.BoolContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitVar(BasicParser.VarContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitVar(BoppiParser.VarContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix2(BasicParser.Infix2Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitInfix2(BoppiParser.Infix2Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix3(BasicParser.Infix3Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitInfix3(BoppiParser.Infix3Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix1(BasicParser.Infix1Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitInfix1(BoppiParser.Infix1Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitWhile(BasicParser.WhileContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitWhile(BoppiParser.WhileContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix4(BasicParser.Infix4Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitInfix4(BoppiParser.Infix4Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix5(BasicParser.Infix5Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitInfix5(BoppiParser.Infix5Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitCall(BasicParser.CallContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitCall(BoppiParser.CallContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitNumber(BasicParser.NumberContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitNumber(BoppiParser.NumberContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitFuncDeclare(BasicParser.FuncDeclareContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitFuncDeclare(BoppiParser.FuncDeclareContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitChar(BasicParser.CharContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitChar(BoppiParser.CharContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBlock(BasicParser.BlockContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitBlock(BoppiParser.BlockContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitWrite(BasicParser.WriteContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitWrite(BoppiParser.WriteContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitIf(BasicParser.IfContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitIf(BoppiParser.IfContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitPrefix1(BasicParser.Prefix1Context ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitPrefix1(BoppiParser.Prefix1Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAssign(BasicParser.AssignContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitAssign(BoppiParser.AssignContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitType(BasicParser.TypeContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitType(BoppiParser.TypeContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitVariable(BasicParser.VariableContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitVariable(BoppiParser.VariableContext ctx) { return visitChildren(ctx); }
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Generated from Basic.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi;
|
||||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
@ -10,7 +10,7 @@ import org.antlr.v4.runtime.dfa.DFA;
|
|||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class BasicLexer extends Lexer {
|
||||
public class BoppiLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
|
@ -90,13 +90,13 @@ public class BasicLexer extends Lexer {
|
|||
}
|
||||
|
||||
|
||||
public BasicLexer(CharStream input) {
|
||||
public BoppiLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Basic.g4"; }
|
||||
public String getGrammarFileName() { return "Boppi.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
|
@ -1,5 +1,5 @@
|
|||
// Generated from Basic.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi;
|
||||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
@ -10,7 +10,7 @@ import java.util.Iterator;
|
|||
import java.util.ArrayList;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class BasicParser extends Parser {
|
||||
public class BoppiParser extends Parser {
|
||||
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
|
@ -79,7 +79,7 @@ public class BasicParser extends Parser {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Basic.g4"; }
|
||||
public String getGrammarFileName() { return "Boppi.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
@ -90,7 +90,7 @@ public class BasicParser extends Parser {
|
|||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public BasicParser(TokenStream input) {
|
||||
public BoppiParser(TokenStream input) {
|
||||
super(input);
|
||||
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
@ -98,14 +98,14 @@ public class BasicParser extends Parser {
|
|||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public TerminalNode EOF() { return getToken(BasicParser.EOF, 0); }
|
||||
public TerminalNode EOF() { return getToken(BoppiParser.EOF, 0); }
|
||||
public ProgramContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
@Override public int getRuleIndex() { return RULE_program; }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitProgram(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitProgram(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -140,9 +140,9 @@ public class BasicParser extends Parser {
|
|||
public SingleExprContext singleExpr(int i) {
|
||||
return getRuleContext(SingleExprContext.class,i);
|
||||
}
|
||||
public List<TerminalNode> COMPOUND() { return getTokens(BasicParser.COMPOUND); }
|
||||
public List<TerminalNode> COMPOUND() { return getTokens(BoppiParser.COMPOUND); }
|
||||
public TerminalNode COMPOUND(int i) {
|
||||
return getToken(BasicParser.COMPOUND, i);
|
||||
return getToken(BoppiParser.COMPOUND, i);
|
||||
}
|
||||
public ExprContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
|
@ -150,7 +150,7 @@ public class BasicParser extends Parser {
|
|||
@Override public int getRuleIndex() { return RULE_expr; }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitExpr(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitExpr(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -213,59 +213,59 @@ public class BasicParser extends Parser {
|
|||
}
|
||||
}
|
||||
public static class ParensContext extends SingleExprContext {
|
||||
public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); }
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); }
|
||||
public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); }
|
||||
public ParensContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitParens(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitParens(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class ReadContext extends SingleExprContext {
|
||||
public TerminalNode IN() { return getToken(BasicParser.IN, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); }
|
||||
public TerminalNode IN() { return getToken(BoppiParser.IN, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); }
|
||||
public List<VariableContext> variable() {
|
||||
return getRuleContexts(VariableContext.class);
|
||||
}
|
||||
public VariableContext variable(int i) {
|
||||
return getRuleContext(VariableContext.class,i);
|
||||
}
|
||||
public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); }
|
||||
public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); }
|
||||
public TerminalNode LISTDELIM(int i) {
|
||||
return getToken(BasicParser.LISTDELIM, i);
|
||||
return getToken(BoppiParser.LISTDELIM, i);
|
||||
}
|
||||
public ReadContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitRead(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitRead(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class DeclareContext extends SingleExprContext {
|
||||
public TerminalNode DECLARE() { return getToken(BasicParser.DECLARE, 0); }
|
||||
public TerminalNode DECLARE() { return getToken(BoppiParser.DECLARE, 0); }
|
||||
public TypeContext type() {
|
||||
return getRuleContext(TypeContext.class,0);
|
||||
}
|
||||
public TerminalNode IDENTIFIER() { return getToken(BasicParser.IDENTIFIER, 0); }
|
||||
public TerminalNode IDENTIFIER() { return getToken(BoppiParser.IDENTIFIER, 0); }
|
||||
public DeclareContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitDeclare(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitDeclare(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class BoolContext extends SingleExprContext {
|
||||
public TerminalNode TRUE() { return getToken(BasicParser.TRUE, 0); }
|
||||
public TerminalNode FALSE() { return getToken(BasicParser.FALSE, 0); }
|
||||
public TerminalNode TRUE() { return getToken(BoppiParser.TRUE, 0); }
|
||||
public TerminalNode FALSE() { return getToken(BoppiParser.FALSE, 0); }
|
||||
public BoolContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitBool(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitBool(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ public class BasicParser extends Parser {
|
|||
public VarContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitVar(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitVar(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -290,12 +290,12 @@ public class BasicParser extends Parser {
|
|||
public SingleExprContext singleExpr(int i) {
|
||||
return getRuleContext(SingleExprContext.class,i);
|
||||
}
|
||||
public TerminalNode PLUS() { return getToken(BasicParser.PLUS, 0); }
|
||||
public TerminalNode MINUS() { return getToken(BasicParser.MINUS, 0); }
|
||||
public TerminalNode PLUS() { return getToken(BoppiParser.PLUS, 0); }
|
||||
public TerminalNode MINUS() { return getToken(BoppiParser.MINUS, 0); }
|
||||
public Infix2Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitInfix2(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitInfix2(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -309,16 +309,16 @@ public class BasicParser extends Parser {
|
|||
public SingleExprContext singleExpr(int i) {
|
||||
return getRuleContext(SingleExprContext.class,i);
|
||||
}
|
||||
public TerminalNode LT() { return getToken(BasicParser.LT, 0); }
|
||||
public TerminalNode LEQ() { return getToken(BasicParser.LEQ, 0); }
|
||||
public TerminalNode GTE() { return getToken(BasicParser.GTE, 0); }
|
||||
public TerminalNode GT() { return getToken(BasicParser.GT, 0); }
|
||||
public TerminalNode EQ() { return getToken(BasicParser.EQ, 0); }
|
||||
public TerminalNode NEQ() { return getToken(BasicParser.NEQ, 0); }
|
||||
public TerminalNode LT() { return getToken(BoppiParser.LT, 0); }
|
||||
public TerminalNode LEQ() { return getToken(BoppiParser.LEQ, 0); }
|
||||
public TerminalNode GTE() { return getToken(BoppiParser.GTE, 0); }
|
||||
public TerminalNode GT() { return getToken(BoppiParser.GT, 0); }
|
||||
public TerminalNode EQ() { return getToken(BoppiParser.EQ, 0); }
|
||||
public TerminalNode NEQ() { return getToken(BoppiParser.NEQ, 0); }
|
||||
public Infix3Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitInfix3(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitInfix3(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -332,22 +332,22 @@ public class BasicParser extends Parser {
|
|||
public SingleExprContext singleExpr(int i) {
|
||||
return getRuleContext(SingleExprContext.class,i);
|
||||
}
|
||||
public TerminalNode MULTIPLY() { return getToken(BasicParser.MULTIPLY, 0); }
|
||||
public TerminalNode DIVIDE() { return getToken(BasicParser.DIVIDE, 0); }
|
||||
public TerminalNode MODULO() { return getToken(BasicParser.MODULO, 0); }
|
||||
public TerminalNode MULTIPLY() { return getToken(BoppiParser.MULTIPLY, 0); }
|
||||
public TerminalNode DIVIDE() { return getToken(BoppiParser.DIVIDE, 0); }
|
||||
public TerminalNode MODULO() { return getToken(BoppiParser.MODULO, 0); }
|
||||
public Infix1Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitInfix1(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitInfix1(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class WhileContext extends SingleExprContext {
|
||||
public ExprContext cond;
|
||||
public ExprContext onTrue;
|
||||
public TerminalNode WHILEOPEN() { return getToken(BasicParser.WHILEOPEN, 0); }
|
||||
public TerminalNode WHILETRUE() { return getToken(BasicParser.WHILETRUE, 0); }
|
||||
public TerminalNode WHILECLOSE() { return getToken(BasicParser.WHILECLOSE, 0); }
|
||||
public TerminalNode WHILEOPEN() { return getToken(BoppiParser.WHILEOPEN, 0); }
|
||||
public TerminalNode WHILETRUE() { return getToken(BoppiParser.WHILETRUE, 0); }
|
||||
public TerminalNode WHILECLOSE() { return getToken(BoppiParser.WHILECLOSE, 0); }
|
||||
public List<ExprContext> expr() {
|
||||
return getRuleContexts(ExprContext.class);
|
||||
}
|
||||
|
@ -357,14 +357,14 @@ public class BasicParser extends Parser {
|
|||
public WhileContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitWhile(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitWhile(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class Infix4Context extends SingleExprContext {
|
||||
public SingleExprContext lhs;
|
||||
public SingleExprContext rhs;
|
||||
public TerminalNode AND() { return getToken(BasicParser.AND, 0); }
|
||||
public TerminalNode AND() { return getToken(BoppiParser.AND, 0); }
|
||||
public List<SingleExprContext> singleExpr() {
|
||||
return getRuleContexts(SingleExprContext.class);
|
||||
}
|
||||
|
@ -374,14 +374,14 @@ public class BasicParser extends Parser {
|
|||
public Infix4Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitInfix4(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitInfix4(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class Infix5Context extends SingleExprContext {
|
||||
public SingleExprContext lhs;
|
||||
public SingleExprContext rhs;
|
||||
public TerminalNode OR() { return getToken(BasicParser.OR, 0); }
|
||||
public TerminalNode OR() { return getToken(BoppiParser.OR, 0); }
|
||||
public List<SingleExprContext> singleExpr() {
|
||||
return getRuleContexts(SingleExprContext.class);
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ public class BasicParser extends Parser {
|
|||
public Infix5Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitInfix5(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitInfix5(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -399,31 +399,31 @@ public class BasicParser extends Parser {
|
|||
public VariableContext variable() {
|
||||
return getRuleContext(VariableContext.class,0);
|
||||
}
|
||||
public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); }
|
||||
public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); }
|
||||
public List<ExprContext> expr() {
|
||||
return getRuleContexts(ExprContext.class);
|
||||
}
|
||||
public ExprContext expr(int i) {
|
||||
return getRuleContext(ExprContext.class,i);
|
||||
}
|
||||
public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); }
|
||||
public TerminalNode LISTDELIM(int i) {
|
||||
return getToken(BasicParser.LISTDELIM, i);
|
||||
return getToken(BoppiParser.LISTDELIM, i);
|
||||
}
|
||||
public CallContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitCall(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitCall(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class NumberContext extends SingleExprContext {
|
||||
public TerminalNode LITERAL10() { return getToken(BasicParser.LITERAL10, 0); }
|
||||
public TerminalNode LITERAL10() { return getToken(BoppiParser.LITERAL10, 0); }
|
||||
public NumberContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitNumber(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitNumber(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -431,73 +431,73 @@ public class BasicParser extends Parser {
|
|||
public TypeContext result;
|
||||
public Token name;
|
||||
public SingleExprContext body;
|
||||
public TerminalNode FUNCTION() { return getToken(BasicParser.FUNCTION, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); }
|
||||
public TerminalNode FUNCTION() { return getToken(BoppiParser.FUNCTION, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); }
|
||||
public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); }
|
||||
public List<TypeContext> type() {
|
||||
return getRuleContexts(TypeContext.class);
|
||||
}
|
||||
public TypeContext type(int i) {
|
||||
return getRuleContext(TypeContext.class,i);
|
||||
}
|
||||
public List<TerminalNode> IDENTIFIER() { return getTokens(BasicParser.IDENTIFIER); }
|
||||
public List<TerminalNode> IDENTIFIER() { return getTokens(BoppiParser.IDENTIFIER); }
|
||||
public TerminalNode IDENTIFIER(int i) {
|
||||
return getToken(BasicParser.IDENTIFIER, i);
|
||||
return getToken(BoppiParser.IDENTIFIER, i);
|
||||
}
|
||||
public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); }
|
||||
public SingleExprContext singleExpr() {
|
||||
return getRuleContext(SingleExprContext.class,0);
|
||||
}
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); }
|
||||
public TerminalNode LISTDELIM(int i) {
|
||||
return getToken(BasicParser.LISTDELIM, i);
|
||||
return getToken(BoppiParser.LISTDELIM, i);
|
||||
}
|
||||
public FuncDeclareContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitFuncDeclare(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitFuncDeclare(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class CharContext extends SingleExprContext {
|
||||
public TerminalNode CHAR() { return getToken(BasicParser.CHAR, 0); }
|
||||
public TerminalNode CHAR() { return getToken(BoppiParser.CHAR, 0); }
|
||||
public CharContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitChar(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitChar(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class BlockContext extends SingleExprContext {
|
||||
public TerminalNode BRAOPEN() { return getToken(BasicParser.BRAOPEN, 0); }
|
||||
public TerminalNode BRAOPEN() { return getToken(BoppiParser.BRAOPEN, 0); }
|
||||
public ExprContext expr() {
|
||||
return getRuleContext(ExprContext.class,0);
|
||||
}
|
||||
public TerminalNode BRACLOSE() { return getToken(BasicParser.BRACLOSE, 0); }
|
||||
public TerminalNode BRACLOSE() { return getToken(BoppiParser.BRACLOSE, 0); }
|
||||
public BlockContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitBlock(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitBlock(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class WriteContext extends SingleExprContext {
|
||||
public TerminalNode OUT() { return getToken(BasicParser.OUT, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); }
|
||||
public TerminalNode OUT() { return getToken(BoppiParser.OUT, 0); }
|
||||
public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); }
|
||||
public List<ExprContext> expr() {
|
||||
return getRuleContexts(ExprContext.class);
|
||||
}
|
||||
public ExprContext expr(int i) {
|
||||
return getRuleContext(ExprContext.class,i);
|
||||
}
|
||||
public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); }
|
||||
public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); }
|
||||
public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); }
|
||||
public TerminalNode LISTDELIM(int i) {
|
||||
return getToken(BasicParser.LISTDELIM, i);
|
||||
return getToken(BoppiParser.LISTDELIM, i);
|
||||
}
|
||||
public WriteContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitWrite(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitWrite(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -505,20 +505,20 @@ public class BasicParser extends Parser {
|
|||
public ExprContext cond;
|
||||
public ExprContext onTrue;
|
||||
public ExprContext onFalse;
|
||||
public TerminalNode IFOPEN() { return getToken(BasicParser.IFOPEN, 0); }
|
||||
public TerminalNode IFTRUE() { return getToken(BasicParser.IFTRUE, 0); }
|
||||
public TerminalNode IFCLOSE() { return getToken(BasicParser.IFCLOSE, 0); }
|
||||
public TerminalNode IFOPEN() { return getToken(BoppiParser.IFOPEN, 0); }
|
||||
public TerminalNode IFTRUE() { return getToken(BoppiParser.IFTRUE, 0); }
|
||||
public TerminalNode IFCLOSE() { return getToken(BoppiParser.IFCLOSE, 0); }
|
||||
public List<ExprContext> expr() {
|
||||
return getRuleContexts(ExprContext.class);
|
||||
}
|
||||
public ExprContext expr(int i) {
|
||||
return getRuleContext(ExprContext.class,i);
|
||||
}
|
||||
public TerminalNode IFFALSE() { return getToken(BasicParser.IFFALSE, 0); }
|
||||
public TerminalNode IFFALSE() { return getToken(BoppiParser.IFFALSE, 0); }
|
||||
public IfContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitIf(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitIf(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -527,13 +527,13 @@ public class BasicParser extends Parser {
|
|||
public SingleExprContext singleExpr() {
|
||||
return getRuleContext(SingleExprContext.class,0);
|
||||
}
|
||||
public TerminalNode PLUS() { return getToken(BasicParser.PLUS, 0); }
|
||||
public TerminalNode MINUS() { return getToken(BasicParser.MINUS, 0); }
|
||||
public TerminalNode NOT() { return getToken(BasicParser.NOT, 0); }
|
||||
public TerminalNode PLUS() { return getToken(BoppiParser.PLUS, 0); }
|
||||
public TerminalNode MINUS() { return getToken(BoppiParser.MINUS, 0); }
|
||||
public TerminalNode NOT() { return getToken(BoppiParser.NOT, 0); }
|
||||
public Prefix1Context(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitPrefix1(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitPrefix1(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -541,14 +541,14 @@ public class BasicParser extends Parser {
|
|||
public VariableContext variable() {
|
||||
return getRuleContext(VariableContext.class,0);
|
||||
}
|
||||
public TerminalNode ASSIGN() { return getToken(BasicParser.ASSIGN, 0); }
|
||||
public TerminalNode ASSIGN() { return getToken(BoppiParser.ASSIGN, 0); }
|
||||
public SingleExprContext singleExpr() {
|
||||
return getRuleContext(SingleExprContext.class,0);
|
||||
}
|
||||
public AssignContext(SingleExprContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitAssign(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitAssign(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -569,9 +569,9 @@ public class BasicParser extends Parser {
|
|||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(116);
|
||||
setState(120);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ParensContext(_localctx);
|
||||
|
@ -670,25 +670,33 @@ public class BasicParser extends Parser {
|
|||
variable();
|
||||
setState(57);
|
||||
match(PAROPEN);
|
||||
setState(58);
|
||||
expr();
|
||||
setState(63);
|
||||
setState(66);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==LISTDELIM) {
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << PAROPEN) | (1L << BRAOPEN) | (1L << IN) | (1L << OUT) | (1L << IFOPEN) | (1L << WHILEOPEN) | (1L << PLUS) | (1L << MINUS) | (1L << NOT) | (1L << DECLARE) | (1L << FUNCTION) | (1L << CHAR) | (1L << TRUE) | (1L << FALSE) | (1L << IDENTIFIER) | (1L << LITERAL10))) != 0)) {
|
||||
{
|
||||
{
|
||||
setState(59);
|
||||
match(LISTDELIM);
|
||||
setState(60);
|
||||
setState(58);
|
||||
expr();
|
||||
}
|
||||
}
|
||||
setState(65);
|
||||
setState(63);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==LISTDELIM) {
|
||||
{
|
||||
{
|
||||
setState(59);
|
||||
match(LISTDELIM);
|
||||
setState(60);
|
||||
expr();
|
||||
}
|
||||
}
|
||||
setState(65);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(66);
|
||||
|
||||
setState(68);
|
||||
match(PARCLOSE);
|
||||
}
|
||||
break;
|
||||
|
@ -697,27 +705,27 @@ public class BasicParser extends Parser {
|
|||
_localctx = new IfContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(68);
|
||||
match(IFOPEN);
|
||||
setState(69);
|
||||
((IfContext)_localctx).cond = expr();
|
||||
setState(70);
|
||||
match(IFTRUE);
|
||||
match(IFOPEN);
|
||||
setState(71);
|
||||
((IfContext)_localctx).cond = expr();
|
||||
setState(72);
|
||||
match(IFTRUE);
|
||||
setState(73);
|
||||
((IfContext)_localctx).onTrue = expr();
|
||||
setState(74);
|
||||
setState(76);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if (_la==IFFALSE) {
|
||||
{
|
||||
setState(72);
|
||||
setState(74);
|
||||
match(IFFALSE);
|
||||
setState(73);
|
||||
setState(75);
|
||||
((IfContext)_localctx).onFalse = expr();
|
||||
}
|
||||
}
|
||||
|
||||
setState(76);
|
||||
setState(78);
|
||||
match(IFCLOSE);
|
||||
}
|
||||
break;
|
||||
|
@ -726,15 +734,15 @@ public class BasicParser extends Parser {
|
|||
_localctx = new WhileContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(78);
|
||||
match(WHILEOPEN);
|
||||
setState(79);
|
||||
((WhileContext)_localctx).cond = expr();
|
||||
setState(80);
|
||||
match(WHILETRUE);
|
||||
match(WHILEOPEN);
|
||||
setState(81);
|
||||
((WhileContext)_localctx).onTrue = expr();
|
||||
((WhileContext)_localctx).cond = expr();
|
||||
setState(82);
|
||||
match(WHILETRUE);
|
||||
setState(83);
|
||||
((WhileContext)_localctx).onTrue = expr();
|
||||
setState(84);
|
||||
match(WHILECLOSE);
|
||||
}
|
||||
break;
|
||||
|
@ -743,7 +751,7 @@ public class BasicParser extends Parser {
|
|||
_localctx = new Prefix1Context(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(84);
|
||||
setState(86);
|
||||
((Prefix1Context)_localctx).op = _input.LT(1);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << PLUS) | (1L << MINUS) | (1L << NOT))) != 0)) ) {
|
||||
|
@ -754,7 +762,7 @@ public class BasicParser extends Parser {
|
|||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(85);
|
||||
setState(87);
|
||||
singleExpr(13);
|
||||
}
|
||||
break;
|
||||
|
@ -763,11 +771,11 @@ public class BasicParser extends Parser {
|
|||
_localctx = new DeclareContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(86);
|
||||
match(DECLARE);
|
||||
setState(87);
|
||||
type();
|
||||
setState(88);
|
||||
match(DECLARE);
|
||||
setState(89);
|
||||
type();
|
||||
setState(90);
|
||||
match(IDENTIFIER);
|
||||
}
|
||||
break;
|
||||
|
@ -776,39 +784,47 @@ public class BasicParser extends Parser {
|
|||
_localctx = new FuncDeclareContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(90);
|
||||
match(FUNCTION);
|
||||
setState(91);
|
||||
((FuncDeclareContext)_localctx).result = type();
|
||||
setState(92);
|
||||
((FuncDeclareContext)_localctx).name = match(IDENTIFIER);
|
||||
match(FUNCTION);
|
||||
setState(93);
|
||||
match(PAROPEN);
|
||||
((FuncDeclareContext)_localctx).result = type();
|
||||
setState(94);
|
||||
type();
|
||||
((FuncDeclareContext)_localctx).name = match(IDENTIFIER);
|
||||
setState(95);
|
||||
match(IDENTIFIER);
|
||||
setState(102);
|
||||
match(PAROPEN);
|
||||
setState(107);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==LISTDELIM) {
|
||||
{
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INTTYPE) | (1L << BOOLTYPE) | (1L << CHARTYPE) | (1L << IDENTIFIER))) != 0)) {
|
||||
{
|
||||
setState(96);
|
||||
match(LISTDELIM);
|
||||
setState(97);
|
||||
type();
|
||||
setState(98);
|
||||
setState(97);
|
||||
match(IDENTIFIER);
|
||||
}
|
||||
}
|
||||
setState(104);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==LISTDELIM) {
|
||||
{
|
||||
{
|
||||
setState(98);
|
||||
match(LISTDELIM);
|
||||
setState(99);
|
||||
type();
|
||||
setState(100);
|
||||
match(IDENTIFIER);
|
||||
}
|
||||
}
|
||||
setState(106);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(105);
|
||||
|
||||
setState(109);
|
||||
match(PARCLOSE);
|
||||
setState(106);
|
||||
setState(110);
|
||||
((FuncDeclareContext)_localctx).body = singleExpr(6);
|
||||
}
|
||||
break;
|
||||
|
@ -817,11 +833,11 @@ public class BasicParser extends Parser {
|
|||
_localctx = new AssignContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(108);
|
||||
setState(112);
|
||||
variable();
|
||||
setState(109);
|
||||
setState(113);
|
||||
match(ASSIGN);
|
||||
setState(110);
|
||||
setState(114);
|
||||
singleExpr(5);
|
||||
}
|
||||
break;
|
||||
|
@ -830,7 +846,7 @@ public class BasicParser extends Parser {
|
|||
_localctx = new VarContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(112);
|
||||
setState(116);
|
||||
variable();
|
||||
}
|
||||
break;
|
||||
|
@ -839,7 +855,7 @@ public class BasicParser extends Parser {
|
|||
_localctx = new NumberContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(113);
|
||||
setState(117);
|
||||
match(LITERAL10);
|
||||
}
|
||||
break;
|
||||
|
@ -848,7 +864,7 @@ public class BasicParser extends Parser {
|
|||
_localctx = new CharContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(114);
|
||||
setState(118);
|
||||
match(CHAR);
|
||||
}
|
||||
break;
|
||||
|
@ -857,7 +873,7 @@ public class BasicParser extends Parser {
|
|||
_localctx = new BoolContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(115);
|
||||
setState(119);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==TRUE || _la==FALSE) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
|
@ -871,25 +887,25 @@ public class BasicParser extends Parser {
|
|||
break;
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(135);
|
||||
setState(139);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
if ( _alt==1 ) {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
_prevctx = _localctx;
|
||||
{
|
||||
setState(133);
|
||||
setState(137);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new Infix1Context(new SingleExprContext(_parentctx, _parentState));
|
||||
((Infix1Context)_localctx).lhs = _prevctx;
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_singleExpr);
|
||||
setState(118);
|
||||
setState(122);
|
||||
if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
|
||||
setState(119);
|
||||
setState(123);
|
||||
((Infix1Context)_localctx).op = _input.LT(1);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MULTIPLY) | (1L << DIVIDE) | (1L << MODULO))) != 0)) ) {
|
||||
|
@ -900,7 +916,7 @@ public class BasicParser extends Parser {
|
|||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(120);
|
||||
setState(124);
|
||||
((Infix1Context)_localctx).rhs = singleExpr(13);
|
||||
}
|
||||
break;
|
||||
|
@ -909,9 +925,9 @@ public class BasicParser extends Parser {
|
|||
_localctx = new Infix2Context(new SingleExprContext(_parentctx, _parentState));
|
||||
((Infix2Context)_localctx).lhs = _prevctx;
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_singleExpr);
|
||||
setState(121);
|
||||
setState(125);
|
||||
if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
|
||||
setState(122);
|
||||
setState(126);
|
||||
((Infix2Context)_localctx).op = _input.LT(1);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==PLUS || _la==MINUS) ) {
|
||||
|
@ -922,7 +938,7 @@ public class BasicParser extends Parser {
|
|||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(123);
|
||||
setState(127);
|
||||
((Infix2Context)_localctx).rhs = singleExpr(12);
|
||||
}
|
||||
break;
|
||||
|
@ -931,9 +947,9 @@ public class BasicParser extends Parser {
|
|||
_localctx = new Infix3Context(new SingleExprContext(_parentctx, _parentState));
|
||||
((Infix3Context)_localctx).lhs = _prevctx;
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_singleExpr);
|
||||
setState(124);
|
||||
setState(128);
|
||||
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
|
||||
setState(125);
|
||||
setState(129);
|
||||
((Infix3Context)_localctx).op = _input.LT(1);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LEQ) | (1L << GTE) | (1L << NEQ) | (1L << EQ) | (1L << LT) | (1L << GT))) != 0)) ) {
|
||||
|
@ -944,7 +960,7 @@ public class BasicParser extends Parser {
|
|||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(126);
|
||||
setState(130);
|
||||
((Infix3Context)_localctx).rhs = singleExpr(11);
|
||||
}
|
||||
break;
|
||||
|
@ -953,11 +969,11 @@ public class BasicParser extends Parser {
|
|||
_localctx = new Infix4Context(new SingleExprContext(_parentctx, _parentState));
|
||||
((Infix4Context)_localctx).lhs = _prevctx;
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_singleExpr);
|
||||
setState(127);
|
||||
setState(131);
|
||||
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
|
||||
setState(128);
|
||||
setState(132);
|
||||
match(AND);
|
||||
setState(129);
|
||||
setState(133);
|
||||
((Infix4Context)_localctx).rhs = singleExpr(10);
|
||||
}
|
||||
break;
|
||||
|
@ -966,20 +982,20 @@ public class BasicParser extends Parser {
|
|||
_localctx = new Infix5Context(new SingleExprContext(_parentctx, _parentState));
|
||||
((Infix5Context)_localctx).lhs = _prevctx;
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_singleExpr);
|
||||
setState(130);
|
||||
setState(134);
|
||||
if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
|
||||
setState(131);
|
||||
setState(135);
|
||||
match(OR);
|
||||
setState(132);
|
||||
setState(136);
|
||||
((Infix5Context)_localctx).rhs = singleExpr(9);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(137);
|
||||
setState(141);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -996,9 +1012,9 @@ public class BasicParser extends Parser {
|
|||
|
||||
public static class TypeContext extends ParserRuleContext {
|
||||
public Token staticType;
|
||||
public TerminalNode INTTYPE() { return getToken(BasicParser.INTTYPE, 0); }
|
||||
public TerminalNode BOOLTYPE() { return getToken(BasicParser.BOOLTYPE, 0); }
|
||||
public TerminalNode CHARTYPE() { return getToken(BasicParser.CHARTYPE, 0); }
|
||||
public TerminalNode INTTYPE() { return getToken(BoppiParser.INTTYPE, 0); }
|
||||
public TerminalNode BOOLTYPE() { return getToken(BoppiParser.BOOLTYPE, 0); }
|
||||
public TerminalNode CHARTYPE() { return getToken(BoppiParser.CHARTYPE, 0); }
|
||||
public VariableContext variable() {
|
||||
return getRuleContext(VariableContext.class,0);
|
||||
}
|
||||
|
@ -1008,7 +1024,7 @@ public class BasicParser extends Parser {
|
|||
@Override public int getRuleIndex() { return RULE_type; }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitType(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitType(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -1018,7 +1034,7 @@ public class BasicParser extends Parser {
|
|||
enterRule(_localctx, 6, RULE_type);
|
||||
int _la;
|
||||
try {
|
||||
setState(140);
|
||||
setState(144);
|
||||
_errHandler.sync(this);
|
||||
switch (_input.LA(1)) {
|
||||
case INTTYPE:
|
||||
|
@ -1026,7 +1042,7 @@ public class BasicParser extends Parser {
|
|||
case CHARTYPE:
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(138);
|
||||
setState(142);
|
||||
((TypeContext)_localctx).staticType = _input.LT(1);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INTTYPE) | (1L << BOOLTYPE) | (1L << CHARTYPE))) != 0)) ) {
|
||||
|
@ -1042,7 +1058,7 @@ public class BasicParser extends Parser {
|
|||
case IDENTIFIER:
|
||||
enterOuterAlt(_localctx, 2);
|
||||
{
|
||||
setState(139);
|
||||
setState(143);
|
||||
variable();
|
||||
}
|
||||
break;
|
||||
|
@ -1062,14 +1078,14 @@ public class BasicParser extends Parser {
|
|||
}
|
||||
|
||||
public static class VariableContext extends ParserRuleContext {
|
||||
public TerminalNode IDENTIFIER() { return getToken(BasicParser.IDENTIFIER, 0); }
|
||||
public TerminalNode IDENTIFIER() { return getToken(BoppiParser.IDENTIFIER, 0); }
|
||||
public VariableContext(ParserRuleContext parent, int invokingState) {
|
||||
super(parent, invokingState);
|
||||
}
|
||||
@Override public int getRuleIndex() { return RULE_variable; }
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof BasicVisitor ) return ((BasicVisitor<? extends T>)visitor).visitVariable(this);
|
||||
if ( visitor instanceof BoppiVisitor ) return ((BoppiVisitor<? extends T>)visitor).visitVariable(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
|
@ -1080,7 +1096,7 @@ public class BasicParser extends Parser {
|
|||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(142);
|
||||
setState(146);
|
||||
match(IDENTIFIER);
|
||||
}
|
||||
}
|
||||
|
@ -1119,47 +1135,49 @@ public class BasicParser extends Parser {
|
|||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3-\u0093\4\2\t\2\4"+
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3-\u0097\4\2\t\2\4"+
|
||||
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\3\2\3\2\3\2\3\3\3\3\3\3\5\3\23\n\3\7\3"+
|
||||
"\25\n\3\f\3\16\3\30\13\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+
|
||||
"\4\3\4\3\4\7\4(\n\4\f\4\16\4+\13\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4\64"+
|
||||
"\n\4\f\4\16\4\67\13\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4@\n\4\f\4\16\4C\13"+
|
||||
"\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4M\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+
|
||||
"\4\5\4E\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4O\n\4\3\4\3\4\3\4\3\4\3"+
|
||||
"\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+
|
||||
"\7\4g\n\4\f\4\16\4j\13\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5"+
|
||||
"\4w\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7"+
|
||||
"\4\u0088\n\4\f\4\16\4\u008b\13\4\3\5\3\5\5\5\u008f\n\5\3\6\3\6\3\6\2\3"+
|
||||
"\6\7\2\4\6\b\n\2\b\3\2\20\22\3\2\'(\3\2\23\25\3\2\20\21\3\2\26\33\3\2"+
|
||||
" \"\2\u00a8\2\f\3\2\2\2\4\17\3\2\2\2\6v\3\2\2\2\b\u008e\3\2\2\2\n\u0090"+
|
||||
"\3\2\2\2\f\r\5\4\3\2\r\16\7\2\2\3\16\3\3\2\2\2\17\26\5\6\4\2\20\22\7$"+
|
||||
"\2\2\21\23\5\6\4\2\22\21\3\2\2\2\22\23\3\2\2\2\23\25\3\2\2\2\24\20\3\2"+
|
||||
"\2\2\25\30\3\2\2\2\26\24\3\2\2\2\26\27\3\2\2\2\27\5\3\2\2\2\30\26\3\2"+
|
||||
"\2\2\31\32\b\4\1\2\32\33\7\3\2\2\33\34\5\4\3\2\34\35\7\4\2\2\35w\3\2\2"+
|
||||
"\2\36\37\7\5\2\2\37 \5\4\3\2 !\7\6\2\2!w\3\2\2\2\"#\7\7\2\2#$\7\3\2\2"+
|
||||
"$)\5\n\6\2%&\7%\2\2&(\5\n\6\2\'%\3\2\2\2(+\3\2\2\2)\'\3\2\2\2)*\3\2\2"+
|
||||
"\2*,\3\2\2\2+)\3\2\2\2,-\7\4\2\2-w\3\2\2\2./\7\b\2\2/\60\7\3\2\2\60\65"+
|
||||
"\5\4\3\2\61\62\7%\2\2\62\64\5\4\3\2\63\61\3\2\2\2\64\67\3\2\2\2\65\63"+
|
||||
"\3\2\2\2\65\66\3\2\2\2\668\3\2\2\2\67\65\3\2\2\289\7\4\2\29w\3\2\2\2:"+
|
||||
";\5\n\6\2;<\7\3\2\2<A\5\4\3\2=>\7%\2\2>@\5\4\3\2?=\3\2\2\2@C\3\2\2\2A"+
|
||||
"?\3\2\2\2AB\3\2\2\2BD\3\2\2\2CA\3\2\2\2DE\7\4\2\2Ew\3\2\2\2FG\7\t\2\2"+
|
||||
"GH\5\4\3\2HI\7\n\2\2IL\5\4\3\2JK\7\13\2\2KM\5\4\3\2LJ\3\2\2\2LM\3\2\2"+
|
||||
"\2MN\3\2\2\2NO\7\f\2\2Ow\3\2\2\2PQ\7\r\2\2QR\5\4\3\2RS\7\16\2\2ST\5\4"+
|
||||
"\3\2TU\7\17\2\2Uw\3\2\2\2VW\t\2\2\2Ww\5\6\4\17XY\7\36\2\2YZ\5\b\5\2Z["+
|
||||
"\7)\2\2[w\3\2\2\2\\]\7\37\2\2]^\5\b\5\2^_\7)\2\2_`\7\3\2\2`a\5\b\5\2a"+
|
||||
"h\7)\2\2bc\7%\2\2cd\5\b\5\2de\7)\2\2eg\3\2\2\2fb\3\2\2\2gj\3\2\2\2hf\3"+
|
||||
"\2\2\2hi\3\2\2\2ik\3\2\2\2jh\3\2\2\2kl\7\4\2\2lm\5\6\4\bmw\3\2\2\2no\5"+
|
||||
"\n\6\2op\7#\2\2pq\5\6\4\7qw\3\2\2\2rw\5\n\6\2sw\7*\2\2tw\7&\2\2uw\t\3"+
|
||||
"\2\2v\31\3\2\2\2v\36\3\2\2\2v\"\3\2\2\2v.\3\2\2\2v:\3\2\2\2vF\3\2\2\2"+
|
||||
"vP\3\2\2\2vV\3\2\2\2vX\3\2\2\2v\\\3\2\2\2vn\3\2\2\2vr\3\2\2\2vs\3\2\2"+
|
||||
"\2vt\3\2\2\2vu\3\2\2\2w\u0089\3\2\2\2xy\f\16\2\2yz\t\4\2\2z\u0088\5\6"+
|
||||
"\4\17{|\f\r\2\2|}\t\5\2\2}\u0088\5\6\4\16~\177\f\f\2\2\177\u0080\t\6\2"+
|
||||
"\2\u0080\u0088\5\6\4\r\u0081\u0082\f\13\2\2\u0082\u0083\7\34\2\2\u0083"+
|
||||
"\u0088\5\6\4\f\u0084\u0085\f\n\2\2\u0085\u0086\7\35\2\2\u0086\u0088\5"+
|
||||
"\6\4\13\u0087x\3\2\2\2\u0087{\3\2\2\2\u0087~\3\2\2\2\u0087\u0081\3\2\2"+
|
||||
"\2\u0087\u0084\3\2\2\2\u0088\u008b\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a"+
|
||||
"\3\2\2\2\u008a\7\3\2\2\2\u008b\u0089\3\2\2\2\u008c\u008f\t\7\2\2\u008d"+
|
||||
"\u008f\5\n\6\2\u008e\u008c\3\2\2\2\u008e\u008d\3\2\2\2\u008f\t\3\2\2\2"+
|
||||
"\u0090\u0091\7)\2\2\u0091\13\3\2\2\2\r\22\26)\65ALhv\u0087\u0089\u008e";
|
||||
"\3\4\3\4\7\4i\n\4\f\4\16\4l\13\4\5\4n\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\3\4\5\4{\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\3\4\7\4\u008c\n\4\f\4\16\4\u008f\13\4\3\5\3\5\5\5\u0093\n"+
|
||||
"\5\3\6\3\6\3\6\2\3\6\7\2\4\6\b\n\2\b\3\2\20\22\3\2\'(\3\2\23\25\3\2\20"+
|
||||
"\21\3\2\26\33\3\2 \"\2\u00ae\2\f\3\2\2\2\4\17\3\2\2\2\6z\3\2\2\2\b\u0092"+
|
||||
"\3\2\2\2\n\u0094\3\2\2\2\f\r\5\4\3\2\r\16\7\2\2\3\16\3\3\2\2\2\17\26\5"+
|
||||
"\6\4\2\20\22\7$\2\2\21\23\5\6\4\2\22\21\3\2\2\2\22\23\3\2\2\2\23\25\3"+
|
||||
"\2\2\2\24\20\3\2\2\2\25\30\3\2\2\2\26\24\3\2\2\2\26\27\3\2\2\2\27\5\3"+
|
||||
"\2\2\2\30\26\3\2\2\2\31\32\b\4\1\2\32\33\7\3\2\2\33\34\5\4\3\2\34\35\7"+
|
||||
"\4\2\2\35{\3\2\2\2\36\37\7\5\2\2\37 \5\4\3\2 !\7\6\2\2!{\3\2\2\2\"#\7"+
|
||||
"\7\2\2#$\7\3\2\2$)\5\n\6\2%&\7%\2\2&(\5\n\6\2\'%\3\2\2\2(+\3\2\2\2)\'"+
|
||||
"\3\2\2\2)*\3\2\2\2*,\3\2\2\2+)\3\2\2\2,-\7\4\2\2-{\3\2\2\2./\7\b\2\2/"+
|
||||
"\60\7\3\2\2\60\65\5\4\3\2\61\62\7%\2\2\62\64\5\4\3\2\63\61\3\2\2\2\64"+
|
||||
"\67\3\2\2\2\65\63\3\2\2\2\65\66\3\2\2\2\668\3\2\2\2\67\65\3\2\2\289\7"+
|
||||
"\4\2\29{\3\2\2\2:;\5\n\6\2;D\7\3\2\2<A\5\4\3\2=>\7%\2\2>@\5\4\3\2?=\3"+
|
||||
"\2\2\2@C\3\2\2\2A?\3\2\2\2AB\3\2\2\2BE\3\2\2\2CA\3\2\2\2D<\3\2\2\2DE\3"+
|
||||
"\2\2\2EF\3\2\2\2FG\7\4\2\2G{\3\2\2\2HI\7\t\2\2IJ\5\4\3\2JK\7\n\2\2KN\5"+
|
||||
"\4\3\2LM\7\13\2\2MO\5\4\3\2NL\3\2\2\2NO\3\2\2\2OP\3\2\2\2PQ\7\f\2\2Q{"+
|
||||
"\3\2\2\2RS\7\r\2\2ST\5\4\3\2TU\7\16\2\2UV\5\4\3\2VW\7\17\2\2W{\3\2\2\2"+
|
||||
"XY\t\2\2\2Y{\5\6\4\17Z[\7\36\2\2[\\\5\b\5\2\\]\7)\2\2]{\3\2\2\2^_\7\37"+
|
||||
"\2\2_`\5\b\5\2`a\7)\2\2am\7\3\2\2bc\5\b\5\2cj\7)\2\2de\7%\2\2ef\5\b\5"+
|
||||
"\2fg\7)\2\2gi\3\2\2\2hd\3\2\2\2il\3\2\2\2jh\3\2\2\2jk\3\2\2\2kn\3\2\2"+
|
||||
"\2lj\3\2\2\2mb\3\2\2\2mn\3\2\2\2no\3\2\2\2op\7\4\2\2pq\5\6\4\bq{\3\2\2"+
|
||||
"\2rs\5\n\6\2st\7#\2\2tu\5\6\4\7u{\3\2\2\2v{\5\n\6\2w{\7*\2\2x{\7&\2\2"+
|
||||
"y{\t\3\2\2z\31\3\2\2\2z\36\3\2\2\2z\"\3\2\2\2z.\3\2\2\2z:\3\2\2\2zH\3"+
|
||||
"\2\2\2zR\3\2\2\2zX\3\2\2\2zZ\3\2\2\2z^\3\2\2\2zr\3\2\2\2zv\3\2\2\2zw\3"+
|
||||
"\2\2\2zx\3\2\2\2zy\3\2\2\2{\u008d\3\2\2\2|}\f\16\2\2}~\t\4\2\2~\u008c"+
|
||||
"\5\6\4\17\177\u0080\f\r\2\2\u0080\u0081\t\5\2\2\u0081\u008c\5\6\4\16\u0082"+
|
||||
"\u0083\f\f\2\2\u0083\u0084\t\6\2\2\u0084\u008c\5\6\4\r\u0085\u0086\f\13"+
|
||||
"\2\2\u0086\u0087\7\34\2\2\u0087\u008c\5\6\4\f\u0088\u0089\f\n\2\2\u0089"+
|
||||
"\u008a\7\35\2\2\u008a\u008c\5\6\4\13\u008b|\3\2\2\2\u008b\177\3\2\2\2"+
|
||||
"\u008b\u0082\3\2\2\2\u008b\u0085\3\2\2\2\u008b\u0088\3\2\2\2\u008c\u008f"+
|
||||
"\3\2\2\2\u008d\u008b\3\2\2\2\u008d\u008e\3\2\2\2\u008e\7\3\2\2\2\u008f"+
|
||||
"\u008d\3\2\2\2\u0090\u0093\t\7\2\2\u0091\u0093\5\n\6\2\u0092\u0090\3\2"+
|
||||
"\2\2\u0092\u0091\3\2\2\2\u0093\t\3\2\2\2\u0094\u0095\7)\2\2\u0095\13\3"+
|
||||
"\2\2\2\17\22\26)\65ADNjmz\u008b\u008d\u0092";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
|
@ -1,177 +1,177 @@
|
|||
// Generated from Basic.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi;
|
||||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This interface defines a complete generic visitor for a parse tree produced
|
||||
* by {@link BasicParser}.
|
||||
* by {@link BoppiParser}.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public interface BasicVisitor<T> extends ParseTreeVisitor<T> {
|
||||
public interface BoppiVisitor<T> extends ParseTreeVisitor<T> {
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BasicParser#program}.
|
||||
* Visit a parse tree produced by {@link BoppiParser#program}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitProgram(BasicParser.ProgramContext ctx);
|
||||
T visitProgram(BoppiParser.ProgramContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BasicParser#expr}.
|
||||
* Visit a parse tree produced by {@link BoppiParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExpr(BasicParser.ExprContext ctx);
|
||||
T visitExpr(BoppiParser.ExprContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code parens}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitParens(BasicParser.ParensContext ctx);
|
||||
T visitParens(BoppiParser.ParensContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code read}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitRead(BasicParser.ReadContext ctx);
|
||||
T visitRead(BoppiParser.ReadContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code declare}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitDeclare(BasicParser.DeclareContext ctx);
|
||||
T visitDeclare(BoppiParser.DeclareContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code bool}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitBool(BasicParser.BoolContext ctx);
|
||||
T visitBool(BoppiParser.BoolContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code var}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitVar(BasicParser.VarContext ctx);
|
||||
T visitVar(BoppiParser.VarContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix2}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix2(BasicParser.Infix2Context ctx);
|
||||
T visitInfix2(BoppiParser.Infix2Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix3}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix3(BasicParser.Infix3Context ctx);
|
||||
T visitInfix3(BoppiParser.Infix3Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix1}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix1(BasicParser.Infix1Context ctx);
|
||||
T visitInfix1(BoppiParser.Infix1Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code while}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitWhile(BasicParser.WhileContext ctx);
|
||||
T visitWhile(BoppiParser.WhileContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix4}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix4(BasicParser.Infix4Context ctx);
|
||||
T visitInfix4(BoppiParser.Infix4Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix5}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix5(BasicParser.Infix5Context ctx);
|
||||
T visitInfix5(BoppiParser.Infix5Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code call}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitCall(BasicParser.CallContext ctx);
|
||||
T visitCall(BoppiParser.CallContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code number}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitNumber(BasicParser.NumberContext ctx);
|
||||
T visitNumber(BoppiParser.NumberContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code funcDeclare}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitFuncDeclare(BasicParser.FuncDeclareContext ctx);
|
||||
T visitFuncDeclare(BoppiParser.FuncDeclareContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code char}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitChar(BasicParser.CharContext ctx);
|
||||
T visitChar(BoppiParser.CharContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code block}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitBlock(BasicParser.BlockContext ctx);
|
||||
T visitBlock(BoppiParser.BlockContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code write}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitWrite(BasicParser.WriteContext ctx);
|
||||
T visitWrite(BoppiParser.WriteContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code if}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitIf(BasicParser.IfContext ctx);
|
||||
T visitIf(BoppiParser.IfContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code prefix1}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitPrefix1(BasicParser.Prefix1Context ctx);
|
||||
T visitPrefix1(BoppiParser.Prefix1Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code assign}
|
||||
* labeled alternative in {@link BasicParser#singleExpr}.
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAssign(BasicParser.AssignContext ctx);
|
||||
T visitAssign(BoppiParser.AssignContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BasicParser#type}.
|
||||
* Visit a parse tree produced by {@link BoppiParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitType(BasicParser.TypeContext ctx);
|
||||
T visitType(BoppiParser.TypeContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BasicParser#variable}.
|
||||
* Visit a parse tree produced by {@link BoppiParser#variable}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitVariable(BasicParser.VariableContext ctx);
|
||||
T visitVariable(BoppiParser.VariableContext ctx);
|
||||
}
|
|
@ -9,6 +9,6 @@ import org.junit.runners.Suite.SuiteClasses;
|
|||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ CheckerTest.class, GeneratorTest.class, ParserTest.class })
|
||||
public class AllTests {
|
||||
static final Path directory = Paths.get("src/pp/s1184725/boppi/test/parsing/");
|
||||
static final Path directory = Paths.get("src/pp/s1184725/boppi/test/programs/");
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.logging.*;
|
|||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import pp.iloc.Simulator;
|
||||
|
@ -17,6 +18,7 @@ import pp.s1184725.boppi.*;
|
|||
public class GeneratorTest {
|
||||
private List<LogRecord> log;
|
||||
private String[] out;
|
||||
private Level logLevel = Level.SEVERE;
|
||||
|
||||
private void compileAndRunString(String code, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n");
|
||||
|
@ -29,10 +31,11 @@ public class GeneratorTest {
|
|||
private void compileAndRun(CharStream stream, String input) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, annotations);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
if (Simulator.DEBUG)
|
||||
System.out.println(program.prettyPrint());
|
||||
|
@ -40,10 +43,33 @@ public class GeneratorTest {
|
|||
out = ToolChain.execute(program, logger, input).split("\n");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void debugRun(CharStream stream, String... input) {
|
||||
Simulator.DEBUG = true;
|
||||
String in = String.join("\n", input) + "\n";
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(Level.FINEST);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
Program program = ToolChain.getILOC(ast, logger, annotations);
|
||||
|
||||
System.out.println(program.prettyPrint());
|
||||
|
||||
out = ToolChain.execute(program, logger, in).split("\n");
|
||||
|
||||
log.forEach((entry) -> System.out.println(entry.getMessage()));
|
||||
Simulator.DEBUG = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctExpressionTest() {
|
||||
compileAndRunFile("simpleExpression.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
compileAndRunString(StringUtils.repeat("1+(", 8) + "1" + StringUtils.repeat(")", 8));
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -87,7 +113,7 @@ public class GeneratorTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void correctFunctionTest() {
|
||||
public void correctSimpleFunctionTest() {
|
||||
compileAndRunString("function int id(int a) a; 1");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
|
@ -108,7 +134,10 @@ public class GeneratorTest {
|
|||
compileAndRunString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(log, is(empty()));
|
||||
assertThat(out, is(arrayContaining("A")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctComplexFunctionTest() {
|
||||
compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
|
@ -117,6 +146,9 @@ public class GeneratorTest {
|
|||
"5");
|
||||
assertThat(log, is(empty()));
|
||||
assertThat(out, is(arrayContaining("120")));
|
||||
}
|
||||
|
||||
compileAndRunFile("simpleFunctionPassing.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
assertThat(out, is(arrayContaining("40", "104", "1", "2", "8")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
var int undefined;
|
||||
function int intDiadic(int a, int b) undefined;
|
||||
|
||||
function intDiadic getMultiply() {
|
||||
function int multiply(int a, int b)
|
||||
a*b;
|
||||
multiply
|
||||
};
|
||||
|
||||
function int biasedMultiply(int a, int b) a*b+4;
|
||||
|
||||
var intDiadic myMultiply;
|
||||
myMultiply := getMultiply();
|
||||
print(myMultiply(5, 8));
|
||||
|
||||
myMultiply := biasedMultiply;
|
||||
print(myMultiply(10, 10));
|
||||
|
||||
function int fibonacci(int n) {
|
||||
var int start0; start0 := 1;
|
||||
var int start1; start1 := 1;
|
||||
|
||||
function int doFibonacci(int n)
|
||||
if n == 0 then
|
||||
start0
|
||||
else
|
||||
if n == 1 then
|
||||
start1
|
||||
else
|
||||
doFibonacci(n-1)+doFibonacci(n-2)
|
||||
fi
|
||||
fi
|
||||
;
|
||||
|
||||
doFibonacci(n)
|
||||
};
|
||||
|
||||
print(fibonacci(1), fibonacci(2), fibonacci(5));
|
Loading…
Reference in New Issue