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; | package pp.s1184725.boppi; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.*; | ||||||
| import java.util.EmptyStackException; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.logging.Logger; | import java.util.logging.Logger; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
| import org.antlr.v4.runtime.ParserRuleContext; | import org.antlr.v4.runtime.ParserRuleContext; | ||||||
| import org.antlr.v4.runtime.tree.ParseTree; | 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 |  * This class performs type checking and variable assignment on a bare parse | ||||||
|  * tree. |  * tree. | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| public class BoppiBasicChecker extends BasicBaseVisitor<Type> { | public class BoppiChecker extends BoppiBaseVisitor<Type> { | ||||||
| 	private CachingSymbolTable<Type> symbols; | 	private CachingSymbolTable<Type> symbols; | ||||||
| 	private Annotations an; | 	private Annotations an; | ||||||
| 	private Logger log; | 	private Logger log; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new checker with a logger and an object to link types and | 	 * Checks and annotates a program. Problems are reported to the given | ||||||
| 	 * variables to parse tree nodes. | 	 * logger. | ||||||
| 	 *  | 	 *  | ||||||
|  | 	 * @param ast | ||||||
|  | 	 *            the program's AST | ||||||
| 	 * @param logger | 	 * @param logger | ||||||
| 	 *            the logger object to write warnings and errors to | 	 *            the logger object to write warnings and errors to | ||||||
| 	 * @param annotations | 	 * @return the generated annotations | ||||||
| 	 *            the annotations object |  | ||||||
| 	 */ | 	 */ | ||||||
| 	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<>(); | 		symbols = new CachingSymbolTable<>(); | ||||||
| 		an = annotations; | 		an = new Annotations(); | ||||||
| 		log = logger; | 		log = logger; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -116,7 +123,7 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> { | ||||||
| 	public Type visitFuncDeclare(FuncDeclareContext ctx) { | 	public Type visitFuncDeclare(FuncDeclareContext ctx) { | ||||||
| 		try { | 		try { | ||||||
| 			List<Type> parameterTypes = ctx.type().stream().skip(1).map(this::visit).collect(Collectors.toList()); | 			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); | 			Variable<Type> func = symbols.put(ctx.name.getText(), type); | ||||||
| 			an.variables.put(ctx, func); | 			an.variables.put(ctx, func); | ||||||
| 			an.currentFunction.push(func); | 			an.currentFunction.push(func); | ||||||
|  | @ -179,10 +186,10 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> { | ||||||
| 		checkConstraint(lht, rht, ctx); | 		checkConstraint(lht, rht, ctx); | ||||||
| 
 | 
 | ||||||
| 		switch (ctx.op.getType()) { | 		switch (ctx.op.getType()) { | ||||||
| 		case BasicLexer.LT: | 		case BoppiLexer.LT: | ||||||
| 		case BasicLexer.LEQ: | 		case BoppiLexer.LEQ: | ||||||
| 		case BasicLexer.GTE: | 		case BoppiLexer.GTE: | ||||||
| 		case BasicLexer.GT: | 		case BoppiLexer.GT: | ||||||
| 			checkConstraint(lht, SimpleType.INT, ctx); | 			checkConstraint(lht, SimpleType.INT, ctx); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -220,12 +227,12 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> { | ||||||
| 		Type type = visit(ctx.singleExpr()); | 		Type type = visit(ctx.singleExpr()); | ||||||
| 
 | 
 | ||||||
| 		switch (ctx.op.getType()) { | 		switch (ctx.op.getType()) { | ||||||
| 		case BasicLexer.NOT: | 		case BoppiLexer.NOT: | ||||||
| 			checkConstraint(type, SimpleType.BOOL, ctx.singleExpr()); | 			checkConstraint(type, SimpleType.BOOL, ctx.singleExpr()); | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		case BasicLexer.PLUS: | 		case BoppiLexer.PLUS: | ||||||
| 		case BasicLexer.MINUS: | 		case BoppiLexer.MINUS: | ||||||
| 			checkConstraint(type, SimpleType.INT, ctx.singleExpr()); | 			checkConstraint(type, SimpleType.INT, ctx.singleExpr()); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | @ -235,7 +242,7 @@ public class BoppiBasicChecker extends BasicBaseVisitor<Type> { | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public Type visitProgram(ProgramContext ctx) { | 	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)); | 		an.currentFunction.push(new Variable<Type>(main, 0, 0)); | ||||||
| 		main.setLocalDataSize(symbols.withFunctionScope(() -> super.visitProgram(ctx))); | 		main.setLocalDataSize(symbols.withFunctionScope(() -> super.visitProgram(ctx))); | ||||||
| 		return null; | 		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 | 	@Override | ||||||
| 	public void openFunctionScope() { | 	public void openFunctionScope() { | ||||||
| 		System.out.println(this.getClass().getName() + ": entering scope depth " + functionDepth); |  | ||||||
| 		super.openFunctionScope(); | 		super.openFunctionScope(); | ||||||
|  | 		System.out.println(this.getClass().getName() + ": entering scope depth " + functionDepth); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  | @ -28,7 +28,7 @@ public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable< | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public Variable<T> put(String id, T type) throws Exception, EmptyStackException { | 	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); | 		return super.put(id, type); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,13 +10,11 @@ public class FunctionType implements Type { | ||||||
| 	private List<Integer> offsets; | 	private List<Integer> offsets; | ||||||
| 	private Type result; | 	private Type result; | ||||||
| 	private int localDataSize; | 	private int localDataSize; | ||||||
| 	private int depth; |  | ||||||
| 
 | 
 | ||||||
| 	public FunctionType(Type returnType, List<Type> parameterTypes, int depth) { | 	public FunctionType(Type returnType, List<Type> parameterTypes) { | ||||||
| 		result = returnType; | 		result = returnType; | ||||||
| 		parameters = new ArrayList<>(parameterTypes); | 		parameters = new ArrayList<>(parameterTypes); | ||||||
| 		offsets = new ArrayList<>(); | 		offsets = new ArrayList<>(); | ||||||
| 		this.depth = depth; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  | @ -83,12 +81,4 @@ public class FunctionType implements Type { | ||||||
| 	public List<Integer> getOffsets() { | 	public List<Integer> getOffsets() { | ||||||
| 		return offsets; | 		return offsets; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	public int getDepth() { |  | ||||||
| 		return depth; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public void setDepth(int newDepth) { |  | ||||||
| 		depth = newDepth; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| package pp.s1184725.boppi; | package pp.s1184725.boppi; | ||||||
| 
 | 
 | ||||||
| import static pp.s1184725.boppi.BasicLexer.*; | import static pp.s1184725.boppi.antlr.BoppiLexer.*; | ||||||
| 
 | 
 | ||||||
| import pp.iloc.eval.Machine; | import pp.iloc.eval.Machine; | ||||||
|  | import pp.s1184725.boppi.antlr.BoppiLexer; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This class provides 4 basic data types: |  * 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 | 	 * @param token | ||||||
| 	 *            the token to parse | 	 *            the token to parse | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ import org.apache.commons.lang3.tuple.Pair; | ||||||
| 
 | 
 | ||||||
| import pp.iloc.Simulator; | import pp.iloc.Simulator; | ||||||
| import pp.iloc.model.Program; | 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. |  * This class provides methods for all steps in the Boppi tool chain. | ||||||
|  | @ -56,8 +58,8 @@ public class ToolChain { | ||||||
| 	 *            the logger to attach | 	 *            the logger to attach | ||||||
| 	 * @return the initialised lexer | 	 * @return the initialised lexer | ||||||
| 	 */ | 	 */ | ||||||
| 	public static BasicLexer getLexer(CharStream stream, Logger logger) { | 	public static BoppiLexer getLexer(CharStream stream, Logger logger) { | ||||||
| 		BasicLexer lexer = new BasicLexer(stream); | 		BoppiLexer lexer = new BoppiLexer(stream); | ||||||
| 		lexer.removeErrorListeners(); | 		lexer.removeErrorListeners(); | ||||||
| 		lexer.addErrorListener(new BaseErrorListener() { | 		lexer.addErrorListener(new BaseErrorListener() { | ||||||
| 			@Override | 			@Override | ||||||
|  | @ -79,8 +81,8 @@ public class ToolChain { | ||||||
| 	 *            the logger to attach | 	 *            the logger to attach | ||||||
| 	 * @return the initialised parser | 	 * @return the initialised parser | ||||||
| 	 */ | 	 */ | ||||||
| 	public static BasicParser getParser(BasicLexer lexer, Logger logger) { | 	public static BoppiParser getParser(BoppiLexer lexer, Logger logger) { | ||||||
| 		BasicParser parser = new BasicParser(new CommonTokenStream(lexer)); | 		BoppiParser parser = new BoppiParser(new CommonTokenStream(lexer)); | ||||||
| 		parser.removeErrorListeners(); | 		parser.removeErrorListeners(); | ||||||
| 		parser.addErrorListener(new BaseErrorListener() { | 		parser.addErrorListener(new BaseErrorListener() { | ||||||
| 			@Override | 			@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. | 	 * annotations. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param program | 	 * @param program | ||||||
|  | @ -103,9 +105,7 @@ public class ToolChain { | ||||||
| 	 * @return the annotations made by the checker | 	 * @return the annotations made by the checker | ||||||
| 	 */ | 	 */ | ||||||
| 	public static Annotations getAnnotations(ParseTree program, Logger logger) { | 	public static Annotations getAnnotations(ParseTree program, Logger logger) { | ||||||
| 		Annotations annotations = new Annotations(); | 		return BoppiChecker.checkProgram(program, logger); | ||||||
| 		new BoppiBasicChecker(logger, annotations).visit(program); |  | ||||||
| 		return annotations; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -115,12 +115,12 @@ public class ToolChain { | ||||||
| 	 *            the parse tree to convert to ILOC | 	 *            the parse tree to convert to ILOC | ||||||
| 	 * @param annotations | 	 * @param annotations | ||||||
| 	 *            the annotations object provided by the checking phase | 	 *            the annotations object provided by the checking phase | ||||||
|  | 	 * @param logger | ||||||
|  | 	 *            the logger to write checker messages to | ||||||
| 	 * @return an ILOC program | 	 * @return an ILOC program | ||||||
| 	 */ | 	 */ | ||||||
| 	public static Program getILOC(ParseTree program, Annotations annotations) { | 	public static Program getILOC(ParseTree program, Logger logger, Annotations annotations) { | ||||||
| 		BoppiBasicGenerator generator = new BoppiBasicGenerator(annotations); | 		return BoppiGenerator.generateProgram(program, annotations, logger); | ||||||
| 		generator.visit(program); |  | ||||||
| 		return generator.prog; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -170,7 +170,7 @@ public class ToolChain { | ||||||
| 		List<LogRecord> logs = makeListLog(logger); | 		List<LogRecord> logs = makeListLog(logger); | ||||||
| 
 | 
 | ||||||
| 		ParseTree ast = getParser(getLexer(stream, logger), logger).program(); | 		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) { | 	public static Program compile(CharStream stream, Logger logger) { | ||||||
| 		ParseTree ast = getParser(getLexer(stream, logger), logger).program(); | 		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 | 	 * @param type | ||||||
| 	 *            the type of the variable | 	 *            the type of the variable | ||||||
|  | 	 * @param depth | ||||||
|  | 	 *            the lexical depth of this variable | ||||||
| 	 * @param offset | 	 * @param offset | ||||||
| 	 *            the memory offset for this variable | 	 *            the memory offset for this variable | ||||||
| 	 */ | 	 */ | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| grammar Basic; | grammar Boppi; | ||||||
| 
 | 
 | ||||||
| program: expr EOF; | program: expr EOF; | ||||||
| 
 | 
 | ||||||
|  | @ -11,7 +11,7 @@ singleExpr | ||||||
|     | BRAOPEN expr BRACLOSE #block |     | BRAOPEN expr BRACLOSE #block | ||||||
|     | IN PAROPEN variable (LISTDELIM variable)* PARCLOSE #read |     | IN PAROPEN variable (LISTDELIM variable)* PARCLOSE #read | ||||||
|     | OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write |     | 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 |     | IFOPEN cond=expr IFTRUE onTrue=expr (IFFALSE onFalse=expr)? IFCLOSE #if | ||||||
|     | WHILEOPEN cond=expr WHILETRUE onTrue=expr WHILECLOSE #while |     | WHILEOPEN cond=expr WHILETRUE onTrue=expr WHILECLOSE #while | ||||||
|     | op=(PLUS|MINUS|NOT) singleExpr #prefix1 |     | op=(PLUS|MINUS|NOT) singleExpr #prefix1 | ||||||
|  | @ -21,7 +21,7 @@ singleExpr | ||||||
|     | lhs=singleExpr AND rhs=singleExpr #infix4 |     | lhs=singleExpr AND rhs=singleExpr #infix4 | ||||||
|     | lhs=singleExpr OR rhs=singleExpr #infix5 |     | lhs=singleExpr OR rhs=singleExpr #infix5 | ||||||
|     | DECLARE type IDENTIFIER #declare |     | 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 |     | <assoc=right> variable ASSIGN singleExpr #assign | ||||||
|     | variable #var |     | variable #var | ||||||
|     | LITERAL10 #number |     | LITERAL10 #number | ||||||
|  | @ -1,182 +1,182 @@ | ||||||
| // Generated from Basic.g4 by ANTLR 4.7 | // Generated from Boppi.g4 by ANTLR 4.7 | ||||||
| package pp.s1184725.boppi; | package pp.s1184725.boppi.antlr; | ||||||
| import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; | 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 |  * which can be extended to create a visitor which only needs to handle a subset | ||||||
|  * of the available methods. |  * of the available methods. | ||||||
|  * |  * | ||||||
|  * @param <T> The return type of the visit operation. Use {@link Void} for |  * @param <T> The return type of the visit operation. Use {@link Void} for | ||||||
|  * operations with no return type. |  * 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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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} | 	 * {@inheritDoc} | ||||||
| 	 * | 	 * | ||||||
| 	 * <p>The default implementation returns the result of calling | 	 * <p>The default implementation returns the result of calling | ||||||
| 	 * {@link #visitChildren} on {@code ctx}.</p> | 	 * {@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 | // Generated from Boppi.g4 by ANTLR 4.7 | ||||||
| package pp.s1184725.boppi; | package pp.s1184725.boppi.antlr; | ||||||
| import org.antlr.v4.runtime.Lexer; | import org.antlr.v4.runtime.Lexer; | ||||||
| import org.antlr.v4.runtime.CharStream; | import org.antlr.v4.runtime.CharStream; | ||||||
| import org.antlr.v4.runtime.Token; | import org.antlr.v4.runtime.Token; | ||||||
|  | @ -10,7 +10,7 @@ import org.antlr.v4.runtime.dfa.DFA; | ||||||
| import org.antlr.v4.runtime.misc.*; | import org.antlr.v4.runtime.misc.*; | ||||||
| 
 | 
 | ||||||
| @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) | ||||||
| public class BasicLexer extends Lexer { | public class BoppiLexer extends Lexer { | ||||||
| 	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } | 	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } | ||||||
| 
 | 
 | ||||||
| 	protected static final DFA[] _decisionToDFA; | 	protected static final DFA[] _decisionToDFA; | ||||||
|  | @ -90,13 +90,13 @@ public class BasicLexer extends Lexer { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	public BasicLexer(CharStream input) { | 	public BoppiLexer(CharStream input) { | ||||||
| 		super(input); | 		super(input); | ||||||
| 		_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); | 		_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String getGrammarFileName() { return "Basic.g4"; } | 	public String getGrammarFileName() { return "Boppi.g4"; } | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String[] getRuleNames() { return ruleNames; } | 	public String[] getRuleNames() { return ruleNames; } | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| // Generated from Basic.g4 by ANTLR 4.7 | // Generated from Boppi.g4 by ANTLR 4.7 | ||||||
| package pp.s1184725.boppi; | package pp.s1184725.boppi.antlr; | ||||||
| import org.antlr.v4.runtime.atn.*; | import org.antlr.v4.runtime.atn.*; | ||||||
| import org.antlr.v4.runtime.dfa.DFA; | import org.antlr.v4.runtime.dfa.DFA; | ||||||
| import org.antlr.v4.runtime.*; | import org.antlr.v4.runtime.*; | ||||||
|  | @ -10,7 +10,7 @@ import java.util.Iterator; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| 
 | 
 | ||||||
| @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) | ||||||
| public class BasicParser extends Parser { | public class BoppiParser extends Parser { | ||||||
| 	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } | 	static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } | ||||||
| 
 | 
 | ||||||
| 	protected static final DFA[] _decisionToDFA; | 	protected static final DFA[] _decisionToDFA; | ||||||
|  | @ -79,7 +79,7 @@ public class BasicParser extends Parser { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String getGrammarFileName() { return "Basic.g4"; } | 	public String getGrammarFileName() { return "Boppi.g4"; } | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public String[] getRuleNames() { return ruleNames; } | 	public String[] getRuleNames() { return ruleNames; } | ||||||
|  | @ -90,7 +90,7 @@ public class BasicParser extends Parser { | ||||||
| 	@Override | 	@Override | ||||||
| 	public ATN getATN() { return _ATN; } | 	public ATN getATN() { return _ATN; } | ||||||
| 
 | 
 | ||||||
| 	public BasicParser(TokenStream input) { | 	public BoppiParser(TokenStream input) { | ||||||
| 		super(input); | 		super(input); | ||||||
| 		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); | 		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); | ||||||
| 	} | 	} | ||||||
|  | @ -98,14 +98,14 @@ public class BasicParser extends Parser { | ||||||
| 		public ExprContext expr() { | 		public ExprContext expr() { | ||||||
| 			return getRuleContext(ExprContext.class,0); | 			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) { | 		public ProgramContext(ParserRuleContext parent, int invokingState) { | ||||||
| 			super(parent, invokingState); | 			super(parent, invokingState); | ||||||
| 		} | 		} | ||||||
| 		@Override public int getRuleIndex() { return RULE_program; } | 		@Override public int getRuleIndex() { return RULE_program; } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -140,9 +140,9 @@ public class BasicParser extends Parser { | ||||||
| 		public SingleExprContext singleExpr(int i) { | 		public SingleExprContext singleExpr(int i) { | ||||||
| 			return getRuleContext(SingleExprContext.class,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) { | 		public TerminalNode COMPOUND(int i) { | ||||||
| 			return getToken(BasicParser.COMPOUND, i); | 			return getToken(BoppiParser.COMPOUND, i); | ||||||
| 		} | 		} | ||||||
| 		public ExprContext(ParserRuleContext parent, int invokingState) { | 		public ExprContext(ParserRuleContext parent, int invokingState) { | ||||||
| 			super(parent, invokingState); | 			super(parent, invokingState); | ||||||
|  | @ -150,7 +150,7 @@ public class BasicParser extends Parser { | ||||||
| 		@Override public int getRuleIndex() { return RULE_expr; } | 		@Override public int getRuleIndex() { return RULE_expr; } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -213,59 +213,59 @@ public class BasicParser extends Parser { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class ParensContext extends SingleExprContext { | 	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() { | 		public ExprContext expr() { | ||||||
| 			return getRuleContext(ExprContext.class,0); | 			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); } | 		public ParensContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class ReadContext extends SingleExprContext { | 	public static class ReadContext extends SingleExprContext { | ||||||
| 		public TerminalNode IN() { return getToken(BasicParser.IN, 0); } | 		public TerminalNode IN() { return getToken(BoppiParser.IN, 0); } | ||||||
| 		public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); } | 		public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); } | ||||||
| 		public List<VariableContext> variable() { | 		public List<VariableContext> variable() { | ||||||
| 			return getRuleContexts(VariableContext.class); | 			return getRuleContexts(VariableContext.class); | ||||||
| 		} | 		} | ||||||
| 		public VariableContext variable(int i) { | 		public VariableContext variable(int i) { | ||||||
| 			return getRuleContext(VariableContext.class,i); | 			return getRuleContext(VariableContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); } | 		public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); } | ||||||
| 		public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); } | 		public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); } | ||||||
| 		public TerminalNode LISTDELIM(int i) { | 		public TerminalNode LISTDELIM(int i) { | ||||||
| 			return getToken(BasicParser.LISTDELIM, i); | 			return getToken(BoppiParser.LISTDELIM, i); | ||||||
| 		} | 		} | ||||||
| 		public ReadContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public ReadContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class DeclareContext extends SingleExprContext { | 	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() { | 		public TypeContext type() { | ||||||
| 			return getRuleContext(TypeContext.class,0); | 			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); } | 		public DeclareContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class BoolContext extends SingleExprContext { | 	public static class BoolContext extends SingleExprContext { | ||||||
| 		public TerminalNode TRUE() { return getToken(BasicParser.TRUE, 0); } | 		public TerminalNode TRUE() { return getToken(BoppiParser.TRUE, 0); } | ||||||
| 		public TerminalNode FALSE() { return getToken(BasicParser.FALSE, 0); } | 		public TerminalNode FALSE() { return getToken(BoppiParser.FALSE, 0); } | ||||||
| 		public BoolContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public BoolContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -276,7 +276,7 @@ public class BasicParser extends Parser { | ||||||
| 		public VarContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public VarContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -290,12 +290,12 @@ public class BasicParser extends Parser { | ||||||
| 		public SingleExprContext singleExpr(int i) { | 		public SingleExprContext singleExpr(int i) { | ||||||
| 			return getRuleContext(SingleExprContext.class,i); | 			return getRuleContext(SingleExprContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode PLUS() { return getToken(BasicParser.PLUS, 0); } | 		public TerminalNode PLUS() { return getToken(BoppiParser.PLUS, 0); } | ||||||
| 		public TerminalNode MINUS() { return getToken(BasicParser.MINUS, 0); } | 		public TerminalNode MINUS() { return getToken(BoppiParser.MINUS, 0); } | ||||||
| 		public Infix2Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Infix2Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -309,16 +309,16 @@ public class BasicParser extends Parser { | ||||||
| 		public SingleExprContext singleExpr(int i) { | 		public SingleExprContext singleExpr(int i) { | ||||||
| 			return getRuleContext(SingleExprContext.class,i); | 			return getRuleContext(SingleExprContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode LT() { return getToken(BasicParser.LT, 0); } | 		public TerminalNode LT() { return getToken(BoppiParser.LT, 0); } | ||||||
| 		public TerminalNode LEQ() { return getToken(BasicParser.LEQ, 0); } | 		public TerminalNode LEQ() { return getToken(BoppiParser.LEQ, 0); } | ||||||
| 		public TerminalNode GTE() { return getToken(BasicParser.GTE, 0); } | 		public TerminalNode GTE() { return getToken(BoppiParser.GTE, 0); } | ||||||
| 		public TerminalNode GT() { return getToken(BasicParser.GT, 0); } | 		public TerminalNode GT() { return getToken(BoppiParser.GT, 0); } | ||||||
| 		public TerminalNode EQ() { return getToken(BasicParser.EQ, 0); } | 		public TerminalNode EQ() { return getToken(BoppiParser.EQ, 0); } | ||||||
| 		public TerminalNode NEQ() { return getToken(BasicParser.NEQ, 0); } | 		public TerminalNode NEQ() { return getToken(BoppiParser.NEQ, 0); } | ||||||
| 		public Infix3Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Infix3Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -332,22 +332,22 @@ public class BasicParser extends Parser { | ||||||
| 		public SingleExprContext singleExpr(int i) { | 		public SingleExprContext singleExpr(int i) { | ||||||
| 			return getRuleContext(SingleExprContext.class,i); | 			return getRuleContext(SingleExprContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode MULTIPLY() { return getToken(BasicParser.MULTIPLY, 0); } | 		public TerminalNode MULTIPLY() { return getToken(BoppiParser.MULTIPLY, 0); } | ||||||
| 		public TerminalNode DIVIDE() { return getToken(BasicParser.DIVIDE, 0); } | 		public TerminalNode DIVIDE() { return getToken(BoppiParser.DIVIDE, 0); } | ||||||
| 		public TerminalNode MODULO() { return getToken(BasicParser.MODULO, 0); } | 		public TerminalNode MODULO() { return getToken(BoppiParser.MODULO, 0); } | ||||||
| 		public Infix1Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Infix1Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class WhileContext extends SingleExprContext { | 	public static class WhileContext extends SingleExprContext { | ||||||
| 		public ExprContext cond; | 		public ExprContext cond; | ||||||
| 		public ExprContext onTrue; | 		public ExprContext onTrue; | ||||||
| 		public TerminalNode WHILEOPEN() { return getToken(BasicParser.WHILEOPEN, 0); } | 		public TerminalNode WHILEOPEN() { return getToken(BoppiParser.WHILEOPEN, 0); } | ||||||
| 		public TerminalNode WHILETRUE() { return getToken(BasicParser.WHILETRUE, 0); } | 		public TerminalNode WHILETRUE() { return getToken(BoppiParser.WHILETRUE, 0); } | ||||||
| 		public TerminalNode WHILECLOSE() { return getToken(BasicParser.WHILECLOSE, 0); } | 		public TerminalNode WHILECLOSE() { return getToken(BoppiParser.WHILECLOSE, 0); } | ||||||
| 		public List<ExprContext> expr() { | 		public List<ExprContext> expr() { | ||||||
| 			return getRuleContexts(ExprContext.class); | 			return getRuleContexts(ExprContext.class); | ||||||
| 		} | 		} | ||||||
|  | @ -357,14 +357,14 @@ public class BasicParser extends Parser { | ||||||
| 		public WhileContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public WhileContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class Infix4Context extends SingleExprContext { | 	public static class Infix4Context extends SingleExprContext { | ||||||
| 		public SingleExprContext lhs; | 		public SingleExprContext lhs; | ||||||
| 		public SingleExprContext rhs; | 		public SingleExprContext rhs; | ||||||
| 		public TerminalNode AND() { return getToken(BasicParser.AND, 0); } | 		public TerminalNode AND() { return getToken(BoppiParser.AND, 0); } | ||||||
| 		public List<SingleExprContext> singleExpr() { | 		public List<SingleExprContext> singleExpr() { | ||||||
| 			return getRuleContexts(SingleExprContext.class); | 			return getRuleContexts(SingleExprContext.class); | ||||||
| 		} | 		} | ||||||
|  | @ -374,14 +374,14 @@ public class BasicParser extends Parser { | ||||||
| 		public Infix4Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Infix4Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class Infix5Context extends SingleExprContext { | 	public static class Infix5Context extends SingleExprContext { | ||||||
| 		public SingleExprContext lhs; | 		public SingleExprContext lhs; | ||||||
| 		public SingleExprContext rhs; | 		public SingleExprContext rhs; | ||||||
| 		public TerminalNode OR() { return getToken(BasicParser.OR, 0); } | 		public TerminalNode OR() { return getToken(BoppiParser.OR, 0); } | ||||||
| 		public List<SingleExprContext> singleExpr() { | 		public List<SingleExprContext> singleExpr() { | ||||||
| 			return getRuleContexts(SingleExprContext.class); | 			return getRuleContexts(SingleExprContext.class); | ||||||
| 		} | 		} | ||||||
|  | @ -391,7 +391,7 @@ public class BasicParser extends Parser { | ||||||
| 		public Infix5Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Infix5Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -399,31 +399,31 @@ public class BasicParser extends Parser { | ||||||
| 		public VariableContext variable() { | 		public VariableContext variable() { | ||||||
| 			return getRuleContext(VariableContext.class,0); | 			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() { | 		public List<ExprContext> expr() { | ||||||
| 			return getRuleContexts(ExprContext.class); | 			return getRuleContexts(ExprContext.class); | ||||||
| 		} | 		} | ||||||
| 		public ExprContext expr(int i) { | 		public ExprContext expr(int i) { | ||||||
| 			return getRuleContext(ExprContext.class,i); | 			return getRuleContext(ExprContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); } | 		public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); } | ||||||
| 		public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); } |  | ||||||
| 		public TerminalNode LISTDELIM(int i) { | 		public TerminalNode LISTDELIM(int i) { | ||||||
| 			return getToken(BasicParser.LISTDELIM, i); | 			return getToken(BoppiParser.LISTDELIM, i); | ||||||
| 		} | 		} | ||||||
| 		public CallContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public CallContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class NumberContext extends SingleExprContext { | 	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); } | 		public NumberContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -431,73 +431,73 @@ public class BasicParser extends Parser { | ||||||
| 		public TypeContext result; | 		public TypeContext result; | ||||||
| 		public Token name; | 		public Token name; | ||||||
| 		public SingleExprContext body; | 		public SingleExprContext body; | ||||||
| 		public TerminalNode FUNCTION() { return getToken(BasicParser.FUNCTION, 0); } | 		public TerminalNode FUNCTION() { return getToken(BoppiParser.FUNCTION, 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<TypeContext> type() { | 		public List<TypeContext> type() { | ||||||
| 			return getRuleContexts(TypeContext.class); | 			return getRuleContexts(TypeContext.class); | ||||||
| 		} | 		} | ||||||
| 		public TypeContext type(int i) { | 		public TypeContext type(int i) { | ||||||
| 			return getRuleContext(TypeContext.class,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) { | 		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() { | 		public SingleExprContext singleExpr() { | ||||||
| 			return getRuleContext(SingleExprContext.class,0); | 			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) { | 		public TerminalNode LISTDELIM(int i) { | ||||||
| 			return getToken(BasicParser.LISTDELIM, i); | 			return getToken(BoppiParser.LISTDELIM, i); | ||||||
| 		} | 		} | ||||||
| 		public FuncDeclareContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public FuncDeclareContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class CharContext extends SingleExprContext { | 	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); } | 		public CharContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class BlockContext extends SingleExprContext { | 	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() { | 		public ExprContext expr() { | ||||||
| 			return getRuleContext(ExprContext.class,0); | 			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); } | 		public BlockContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	public static class WriteContext extends SingleExprContext { | 	public static class WriteContext extends SingleExprContext { | ||||||
| 		public TerminalNode OUT() { return getToken(BasicParser.OUT, 0); } | 		public TerminalNode OUT() { return getToken(BoppiParser.OUT, 0); } | ||||||
| 		public TerminalNode PAROPEN() { return getToken(BasicParser.PAROPEN, 0); } | 		public TerminalNode PAROPEN() { return getToken(BoppiParser.PAROPEN, 0); } | ||||||
| 		public List<ExprContext> expr() { | 		public List<ExprContext> expr() { | ||||||
| 			return getRuleContexts(ExprContext.class); | 			return getRuleContexts(ExprContext.class); | ||||||
| 		} | 		} | ||||||
| 		public ExprContext expr(int i) { | 		public ExprContext expr(int i) { | ||||||
| 			return getRuleContext(ExprContext.class,i); | 			return getRuleContext(ExprContext.class,i); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode PARCLOSE() { return getToken(BasicParser.PARCLOSE, 0); } | 		public TerminalNode PARCLOSE() { return getToken(BoppiParser.PARCLOSE, 0); } | ||||||
| 		public List<TerminalNode> LISTDELIM() { return getTokens(BasicParser.LISTDELIM); } | 		public List<TerminalNode> LISTDELIM() { return getTokens(BoppiParser.LISTDELIM); } | ||||||
| 		public TerminalNode LISTDELIM(int i) { | 		public TerminalNode LISTDELIM(int i) { | ||||||
| 			return getToken(BasicParser.LISTDELIM, i); | 			return getToken(BoppiParser.LISTDELIM, i); | ||||||
| 		} | 		} | ||||||
| 		public WriteContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public WriteContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -505,20 +505,20 @@ public class BasicParser extends Parser { | ||||||
| 		public ExprContext cond; | 		public ExprContext cond; | ||||||
| 		public ExprContext onTrue; | 		public ExprContext onTrue; | ||||||
| 		public ExprContext onFalse; | 		public ExprContext onFalse; | ||||||
| 		public TerminalNode IFOPEN() { return getToken(BasicParser.IFOPEN, 0); } | 		public TerminalNode IFOPEN() { return getToken(BoppiParser.IFOPEN, 0); } | ||||||
| 		public TerminalNode IFTRUE() { return getToken(BasicParser.IFTRUE, 0); } | 		public TerminalNode IFTRUE() { return getToken(BoppiParser.IFTRUE, 0); } | ||||||
| 		public TerminalNode IFCLOSE() { return getToken(BasicParser.IFCLOSE, 0); } | 		public TerminalNode IFCLOSE() { return getToken(BoppiParser.IFCLOSE, 0); } | ||||||
| 		public List<ExprContext> expr() { | 		public List<ExprContext> expr() { | ||||||
| 			return getRuleContexts(ExprContext.class); | 			return getRuleContexts(ExprContext.class); | ||||||
| 		} | 		} | ||||||
| 		public ExprContext expr(int i) { | 		public ExprContext expr(int i) { | ||||||
| 			return getRuleContext(ExprContext.class,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); } | 		public IfContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -527,13 +527,13 @@ public class BasicParser extends Parser { | ||||||
| 		public SingleExprContext singleExpr() { | 		public SingleExprContext singleExpr() { | ||||||
| 			return getRuleContext(SingleExprContext.class,0); | 			return getRuleContext(SingleExprContext.class,0); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode PLUS() { return getToken(BasicParser.PLUS, 0); } | 		public TerminalNode PLUS() { return getToken(BoppiParser.PLUS, 0); } | ||||||
| 		public TerminalNode MINUS() { return getToken(BasicParser.MINUS, 0); } | 		public TerminalNode MINUS() { return getToken(BoppiParser.MINUS, 0); } | ||||||
| 		public TerminalNode NOT() { return getToken(BasicParser.NOT, 0); } | 		public TerminalNode NOT() { return getToken(BoppiParser.NOT, 0); } | ||||||
| 		public Prefix1Context(SingleExprContext ctx) { copyFrom(ctx); } | 		public Prefix1Context(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -541,14 +541,14 @@ public class BasicParser extends Parser { | ||||||
| 		public VariableContext variable() { | 		public VariableContext variable() { | ||||||
| 			return getRuleContext(VariableContext.class,0); | 			return getRuleContext(VariableContext.class,0); | ||||||
| 		} | 		} | ||||||
| 		public TerminalNode ASSIGN() { return getToken(BasicParser.ASSIGN, 0); } | 		public TerminalNode ASSIGN() { return getToken(BoppiParser.ASSIGN, 0); } | ||||||
| 		public SingleExprContext singleExpr() { | 		public SingleExprContext singleExpr() { | ||||||
| 			return getRuleContext(SingleExprContext.class,0); | 			return getRuleContext(SingleExprContext.class,0); | ||||||
| 		} | 		} | ||||||
| 		public AssignContext(SingleExprContext ctx) { copyFrom(ctx); } | 		public AssignContext(SingleExprContext ctx) { copyFrom(ctx); } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -569,9 +569,9 @@ public class BasicParser extends Parser { | ||||||
| 			int _alt; | 			int _alt; | ||||||
| 			enterOuterAlt(_localctx, 1); | 			enterOuterAlt(_localctx, 1); | ||||||
| 			{ | 			{ | ||||||
| 			setState(116); | 			setState(120); | ||||||
| 			_errHandler.sync(this); | 			_errHandler.sync(this); | ||||||
| 			switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { | 			switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) { | ||||||
| 			case 1: | 			case 1: | ||||||
| 				{ | 				{ | ||||||
| 				_localctx = new ParensContext(_localctx); | 				_localctx = new ParensContext(_localctx); | ||||||
|  | @ -670,25 +670,33 @@ public class BasicParser extends Parser { | ||||||
| 				variable(); | 				variable(); | ||||||
| 				setState(57); | 				setState(57); | ||||||
| 				match(PAROPEN); | 				match(PAROPEN); | ||||||
| 				setState(58); | 				setState(66); | ||||||
| 				expr(); |  | ||||||
| 				setState(63); |  | ||||||
| 				_errHandler.sync(this); | 				_errHandler.sync(this); | ||||||
| 				_la = _input.LA(1); | 				_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(58); | ||||||
| 					setState(59); |  | ||||||
| 					match(LISTDELIM); |  | ||||||
| 					setState(60); |  | ||||||
| 					expr(); | 					expr(); | ||||||
| 					} | 					setState(63); | ||||||
| 					} |  | ||||||
| 					setState(65); |  | ||||||
| 					_errHandler.sync(this); | 					_errHandler.sync(this); | ||||||
| 					_la = _input.LA(1); | 					_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); | 				match(PARCLOSE); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -697,27 +705,27 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new IfContext(_localctx); | 				_localctx = new IfContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(68); |  | ||||||
| 				match(IFOPEN); |  | ||||||
| 				setState(69); |  | ||||||
| 				((IfContext)_localctx).cond = expr(); |  | ||||||
| 				setState(70); | 				setState(70); | ||||||
| 				match(IFTRUE); | 				match(IFOPEN); | ||||||
| 				setState(71); | 				setState(71); | ||||||
|  | 				((IfContext)_localctx).cond = expr(); | ||||||
|  | 				setState(72); | ||||||
|  | 				match(IFTRUE); | ||||||
|  | 				setState(73); | ||||||
| 				((IfContext)_localctx).onTrue = expr(); | 				((IfContext)_localctx).onTrue = expr(); | ||||||
| 				setState(74); | 				setState(76); | ||||||
| 				_errHandler.sync(this); | 				_errHandler.sync(this); | ||||||
| 				_la = _input.LA(1); | 				_la = _input.LA(1); | ||||||
| 				if (_la==IFFALSE) { | 				if (_la==IFFALSE) { | ||||||
| 					{ | 					{ | ||||||
| 					setState(72); | 					setState(74); | ||||||
| 					match(IFFALSE); | 					match(IFFALSE); | ||||||
| 					setState(73); | 					setState(75); | ||||||
| 					((IfContext)_localctx).onFalse = expr(); | 					((IfContext)_localctx).onFalse = expr(); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				setState(76); | 				setState(78); | ||||||
| 				match(IFCLOSE); | 				match(IFCLOSE); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -726,15 +734,15 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new WhileContext(_localctx); | 				_localctx = new WhileContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(78); |  | ||||||
| 				match(WHILEOPEN); |  | ||||||
| 				setState(79); |  | ||||||
| 				((WhileContext)_localctx).cond = expr(); |  | ||||||
| 				setState(80); | 				setState(80); | ||||||
| 				match(WHILETRUE); | 				match(WHILEOPEN); | ||||||
| 				setState(81); | 				setState(81); | ||||||
| 				((WhileContext)_localctx).onTrue = expr(); | 				((WhileContext)_localctx).cond = expr(); | ||||||
| 				setState(82); | 				setState(82); | ||||||
|  | 				match(WHILETRUE); | ||||||
|  | 				setState(83); | ||||||
|  | 				((WhileContext)_localctx).onTrue = expr(); | ||||||
|  | 				setState(84); | ||||||
| 				match(WHILECLOSE); | 				match(WHILECLOSE); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -743,7 +751,7 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new Prefix1Context(_localctx); | 				_localctx = new Prefix1Context(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(84); | 				setState(86); | ||||||
| 				((Prefix1Context)_localctx).op = _input.LT(1); | 				((Prefix1Context)_localctx).op = _input.LT(1); | ||||||
| 				_la = _input.LA(1); | 				_la = _input.LA(1); | ||||||
| 				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << PLUS) | (1L << MINUS) | (1L << NOT))) != 0)) ) { | 				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); | 					_errHandler.reportMatch(this); | ||||||
| 					consume(); | 					consume(); | ||||||
| 				} | 				} | ||||||
| 				setState(85); | 				setState(87); | ||||||
| 				singleExpr(13); | 				singleExpr(13); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -763,11 +771,11 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new DeclareContext(_localctx); | 				_localctx = new DeclareContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(86); |  | ||||||
| 				match(DECLARE); |  | ||||||
| 				setState(87); |  | ||||||
| 				type(); |  | ||||||
| 				setState(88); | 				setState(88); | ||||||
|  | 				match(DECLARE); | ||||||
|  | 				setState(89); | ||||||
|  | 				type(); | ||||||
|  | 				setState(90); | ||||||
| 				match(IDENTIFIER); | 				match(IDENTIFIER); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -776,39 +784,47 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new FuncDeclareContext(_localctx); | 				_localctx = new FuncDeclareContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(90); |  | ||||||
| 				match(FUNCTION); |  | ||||||
| 				setState(91); |  | ||||||
| 				((FuncDeclareContext)_localctx).result = type(); |  | ||||||
| 				setState(92); | 				setState(92); | ||||||
| 				((FuncDeclareContext)_localctx).name = match(IDENTIFIER); | 				match(FUNCTION); | ||||||
| 				setState(93); | 				setState(93); | ||||||
| 				match(PAROPEN); | 				((FuncDeclareContext)_localctx).result = type(); | ||||||
| 				setState(94); | 				setState(94); | ||||||
| 				type(); | 				((FuncDeclareContext)_localctx).name = match(IDENTIFIER); | ||||||
| 				setState(95); | 				setState(95); | ||||||
| 				match(IDENTIFIER); | 				match(PAROPEN); | ||||||
| 				setState(102); | 				setState(107); | ||||||
| 				_errHandler.sync(this); | 				_errHandler.sync(this); | ||||||
| 				_la = _input.LA(1); | 				_la = _input.LA(1); | ||||||
| 				while (_la==LISTDELIM) { | 				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INTTYPE) | (1L << BOOLTYPE) | (1L << CHARTYPE) | (1L << IDENTIFIER))) != 0)) { | ||||||
| 					{ |  | ||||||
| 					{ | 					{ | ||||||
| 					setState(96); | 					setState(96); | ||||||
| 					match(LISTDELIM); |  | ||||||
| 					setState(97); |  | ||||||
| 					type(); | 					type(); | ||||||
| 					setState(98); | 					setState(97); | ||||||
| 					match(IDENTIFIER); | 					match(IDENTIFIER); | ||||||
| 					} |  | ||||||
| 					} |  | ||||||
| 					setState(104); | 					setState(104); | ||||||
| 					_errHandler.sync(this); | 					_errHandler.sync(this); | ||||||
| 					_la = _input.LA(1); | 					_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); | 				match(PARCLOSE); | ||||||
| 				setState(106); | 				setState(110); | ||||||
| 				((FuncDeclareContext)_localctx).body = singleExpr(6); | 				((FuncDeclareContext)_localctx).body = singleExpr(6); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -817,11 +833,11 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new AssignContext(_localctx); | 				_localctx = new AssignContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(108); | 				setState(112); | ||||||
| 				variable(); | 				variable(); | ||||||
| 				setState(109); | 				setState(113); | ||||||
| 				match(ASSIGN); | 				match(ASSIGN); | ||||||
| 				setState(110); | 				setState(114); | ||||||
| 				singleExpr(5); | 				singleExpr(5); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -830,7 +846,7 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new VarContext(_localctx); | 				_localctx = new VarContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(112); | 				setState(116); | ||||||
| 				variable(); | 				variable(); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -839,7 +855,7 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new NumberContext(_localctx); | 				_localctx = new NumberContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(113); | 				setState(117); | ||||||
| 				match(LITERAL10); | 				match(LITERAL10); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -848,7 +864,7 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new CharContext(_localctx); | 				_localctx = new CharContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(114); | 				setState(118); | ||||||
| 				match(CHAR); | 				match(CHAR); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -857,7 +873,7 @@ public class BasicParser extends Parser { | ||||||
| 				_localctx = new BoolContext(_localctx); | 				_localctx = new BoolContext(_localctx); | ||||||
| 				_ctx = _localctx; | 				_ctx = _localctx; | ||||||
| 				_prevctx = _localctx; | 				_prevctx = _localctx; | ||||||
| 				setState(115); | 				setState(119); | ||||||
| 				_la = _input.LA(1); | 				_la = _input.LA(1); | ||||||
| 				if ( !(_la==TRUE || _la==FALSE) ) { | 				if ( !(_la==TRUE || _la==FALSE) ) { | ||||||
| 				_errHandler.recoverInline(this); | 				_errHandler.recoverInline(this); | ||||||
|  | @ -871,25 +887,25 @@ public class BasicParser extends Parser { | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			_ctx.stop = _input.LT(-1); | 			_ctx.stop = _input.LT(-1); | ||||||
| 			setState(135); | 			setState(139); | ||||||
| 			_errHandler.sync(this); | 			_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 ) { | 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { | ||||||
| 				if ( _alt==1 ) { | 				if ( _alt==1 ) { | ||||||
| 					if ( _parseListeners!=null ) triggerExitRuleEvent(); | 					if ( _parseListeners!=null ) triggerExitRuleEvent(); | ||||||
| 					_prevctx = _localctx; | 					_prevctx = _localctx; | ||||||
| 					{ | 					{ | ||||||
| 					setState(133); | 					setState(137); | ||||||
| 					_errHandler.sync(this); | 					_errHandler.sync(this); | ||||||
| 					switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { | 					switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { | ||||||
| 					case 1: | 					case 1: | ||||||
| 						{ | 						{ | ||||||
| 						_localctx = new Infix1Context(new SingleExprContext(_parentctx, _parentState)); | 						_localctx = new Infix1Context(new SingleExprContext(_parentctx, _parentState)); | ||||||
| 						((Infix1Context)_localctx).lhs = _prevctx; | 						((Infix1Context)_localctx).lhs = _prevctx; | ||||||
| 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | ||||||
| 						setState(118); | 						setState(122); | ||||||
| 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); | 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); | ||||||
| 						setState(119); | 						setState(123); | ||||||
| 						((Infix1Context)_localctx).op = _input.LT(1); | 						((Infix1Context)_localctx).op = _input.LT(1); | ||||||
| 						_la = _input.LA(1); | 						_la = _input.LA(1); | ||||||
| 						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MULTIPLY) | (1L << DIVIDE) | (1L << MODULO))) != 0)) ) { | 						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); | 							_errHandler.reportMatch(this); | ||||||
| 							consume(); | 							consume(); | ||||||
| 						} | 						} | ||||||
| 						setState(120); | 						setState(124); | ||||||
| 						((Infix1Context)_localctx).rhs = singleExpr(13); | 						((Infix1Context)_localctx).rhs = singleExpr(13); | ||||||
| 						} | 						} | ||||||
| 						break; | 						break; | ||||||
|  | @ -909,9 +925,9 @@ public class BasicParser extends Parser { | ||||||
| 						_localctx = new Infix2Context(new SingleExprContext(_parentctx, _parentState)); | 						_localctx = new Infix2Context(new SingleExprContext(_parentctx, _parentState)); | ||||||
| 						((Infix2Context)_localctx).lhs = _prevctx; | 						((Infix2Context)_localctx).lhs = _prevctx; | ||||||
| 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | ||||||
| 						setState(121); | 						setState(125); | ||||||
| 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); | 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); | ||||||
| 						setState(122); | 						setState(126); | ||||||
| 						((Infix2Context)_localctx).op = _input.LT(1); | 						((Infix2Context)_localctx).op = _input.LT(1); | ||||||
| 						_la = _input.LA(1); | 						_la = _input.LA(1); | ||||||
| 						if ( !(_la==PLUS || _la==MINUS) ) { | 						if ( !(_la==PLUS || _la==MINUS) ) { | ||||||
|  | @ -922,7 +938,7 @@ public class BasicParser extends Parser { | ||||||
| 							_errHandler.reportMatch(this); | 							_errHandler.reportMatch(this); | ||||||
| 							consume(); | 							consume(); | ||||||
| 						} | 						} | ||||||
| 						setState(123); | 						setState(127); | ||||||
| 						((Infix2Context)_localctx).rhs = singleExpr(12); | 						((Infix2Context)_localctx).rhs = singleExpr(12); | ||||||
| 						} | 						} | ||||||
| 						break; | 						break; | ||||||
|  | @ -931,9 +947,9 @@ public class BasicParser extends Parser { | ||||||
| 						_localctx = new Infix3Context(new SingleExprContext(_parentctx, _parentState)); | 						_localctx = new Infix3Context(new SingleExprContext(_parentctx, _parentState)); | ||||||
| 						((Infix3Context)_localctx).lhs = _prevctx; | 						((Infix3Context)_localctx).lhs = _prevctx; | ||||||
| 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | ||||||
| 						setState(124); | 						setState(128); | ||||||
| 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); | 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); | ||||||
| 						setState(125); | 						setState(129); | ||||||
| 						((Infix3Context)_localctx).op = _input.LT(1); | 						((Infix3Context)_localctx).op = _input.LT(1); | ||||||
| 						_la = _input.LA(1); | 						_la = _input.LA(1); | ||||||
| 						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LEQ) | (1L << GTE) | (1L << NEQ) | (1L << EQ) | (1L << LT) | (1L << GT))) != 0)) ) { | 						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); | 							_errHandler.reportMatch(this); | ||||||
| 							consume(); | 							consume(); | ||||||
| 						} | 						} | ||||||
| 						setState(126); | 						setState(130); | ||||||
| 						((Infix3Context)_localctx).rhs = singleExpr(11); | 						((Infix3Context)_localctx).rhs = singleExpr(11); | ||||||
| 						} | 						} | ||||||
| 						break; | 						break; | ||||||
|  | @ -953,11 +969,11 @@ public class BasicParser extends Parser { | ||||||
| 						_localctx = new Infix4Context(new SingleExprContext(_parentctx, _parentState)); | 						_localctx = new Infix4Context(new SingleExprContext(_parentctx, _parentState)); | ||||||
| 						((Infix4Context)_localctx).lhs = _prevctx; | 						((Infix4Context)_localctx).lhs = _prevctx; | ||||||
| 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | ||||||
| 						setState(127); | 						setState(131); | ||||||
| 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); | 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); | ||||||
| 						setState(128); | 						setState(132); | ||||||
| 						match(AND); | 						match(AND); | ||||||
| 						setState(129); | 						setState(133); | ||||||
| 						((Infix4Context)_localctx).rhs = singleExpr(10); | 						((Infix4Context)_localctx).rhs = singleExpr(10); | ||||||
| 						} | 						} | ||||||
| 						break; | 						break; | ||||||
|  | @ -966,20 +982,20 @@ public class BasicParser extends Parser { | ||||||
| 						_localctx = new Infix5Context(new SingleExprContext(_parentctx, _parentState)); | 						_localctx = new Infix5Context(new SingleExprContext(_parentctx, _parentState)); | ||||||
| 						((Infix5Context)_localctx).lhs = _prevctx; | 						((Infix5Context)_localctx).lhs = _prevctx; | ||||||
| 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | 						pushNewRecursionContext(_localctx, _startState, RULE_singleExpr); | ||||||
| 						setState(130); | 						setState(134); | ||||||
| 						if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); | 						if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); | ||||||
| 						setState(131); | 						setState(135); | ||||||
| 						match(OR); | 						match(OR); | ||||||
| 						setState(132); | 						setState(136); | ||||||
| 						((Infix5Context)_localctx).rhs = singleExpr(9); | 						((Infix5Context)_localctx).rhs = singleExpr(9); | ||||||
| 						} | 						} | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
| 					}  | 					}  | ||||||
| 				} | 				} | ||||||
| 				setState(137); | 				setState(141); | ||||||
| 				_errHandler.sync(this); | 				_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 static class TypeContext extends ParserRuleContext { | ||||||
| 		public Token staticType; | 		public Token staticType; | ||||||
| 		public TerminalNode INTTYPE() { return getToken(BasicParser.INTTYPE, 0); } | 		public TerminalNode INTTYPE() { return getToken(BoppiParser.INTTYPE, 0); } | ||||||
| 		public TerminalNode BOOLTYPE() { return getToken(BasicParser.BOOLTYPE, 0); } | 		public TerminalNode BOOLTYPE() { return getToken(BoppiParser.BOOLTYPE, 0); } | ||||||
| 		public TerminalNode CHARTYPE() { return getToken(BasicParser.CHARTYPE, 0); } | 		public TerminalNode CHARTYPE() { return getToken(BoppiParser.CHARTYPE, 0); } | ||||||
| 		public VariableContext variable() { | 		public VariableContext variable() { | ||||||
| 			return getRuleContext(VariableContext.class,0); | 			return getRuleContext(VariableContext.class,0); | ||||||
| 		} | 		} | ||||||
|  | @ -1008,7 +1024,7 @@ public class BasicParser extends Parser { | ||||||
| 		@Override public int getRuleIndex() { return RULE_type; } | 		@Override public int getRuleIndex() { return RULE_type; } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1018,7 +1034,7 @@ public class BasicParser extends Parser { | ||||||
| 		enterRule(_localctx, 6, RULE_type); | 		enterRule(_localctx, 6, RULE_type); | ||||||
| 		int _la; | 		int _la; | ||||||
| 		try { | 		try { | ||||||
| 			setState(140); | 			setState(144); | ||||||
| 			_errHandler.sync(this); | 			_errHandler.sync(this); | ||||||
| 			switch (_input.LA(1)) { | 			switch (_input.LA(1)) { | ||||||
| 			case INTTYPE: | 			case INTTYPE: | ||||||
|  | @ -1026,7 +1042,7 @@ public class BasicParser extends Parser { | ||||||
| 			case CHARTYPE: | 			case CHARTYPE: | ||||||
| 				enterOuterAlt(_localctx, 1); | 				enterOuterAlt(_localctx, 1); | ||||||
| 				{ | 				{ | ||||||
| 				setState(138); | 				setState(142); | ||||||
| 				((TypeContext)_localctx).staticType = _input.LT(1); | 				((TypeContext)_localctx).staticType = _input.LT(1); | ||||||
| 				_la = _input.LA(1); | 				_la = _input.LA(1); | ||||||
| 				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INTTYPE) | (1L << BOOLTYPE) | (1L << CHARTYPE))) != 0)) ) { | 				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << INTTYPE) | (1L << BOOLTYPE) | (1L << CHARTYPE))) != 0)) ) { | ||||||
|  | @ -1042,7 +1058,7 @@ public class BasicParser extends Parser { | ||||||
| 			case IDENTIFIER: | 			case IDENTIFIER: | ||||||
| 				enterOuterAlt(_localctx, 2); | 				enterOuterAlt(_localctx, 2); | ||||||
| 				{ | 				{ | ||||||
| 				setState(139); | 				setState(143); | ||||||
| 				variable(); | 				variable(); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  | @ -1062,14 +1078,14 @@ public class BasicParser extends Parser { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static class VariableContext extends ParserRuleContext { | 	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) { | 		public VariableContext(ParserRuleContext parent, int invokingState) { | ||||||
| 			super(parent, invokingState); | 			super(parent, invokingState); | ||||||
| 		} | 		} | ||||||
| 		@Override public int getRuleIndex() { return RULE_variable; } | 		@Override public int getRuleIndex() { return RULE_variable; } | ||||||
| 		@Override | 		@Override | ||||||
| 		public <T> T accept(ParseTreeVisitor<? extends T> visitor) { | 		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); | 			else return visitor.visitChildren(this); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1080,7 +1096,7 @@ public class BasicParser extends Parser { | ||||||
| 		try { | 		try { | ||||||
| 			enterOuterAlt(_localctx, 1); | 			enterOuterAlt(_localctx, 1); | ||||||
| 			{ | 			{ | ||||||
| 			setState(142); | 			setState(146); | ||||||
| 			match(IDENTIFIER); | 			match(IDENTIFIER); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1119,47 +1135,49 @@ public class BasicParser extends Parser { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static final String _serializedATN = | 	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"+ | 		"\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"+ | 		"\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"+ | 		"\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"+ | 		"\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"+ | 		"\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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		" \"\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"+ | 		"\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\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$"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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\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\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\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\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"$)\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"+ | 		"\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)\'"+ | ||||||
| 		"\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"+ | 		"\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/"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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:"+ | 		"\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"+ | ||||||
| 		";\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"+ | 		"\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"+ | ||||||
| 		"?\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"+ | 		"\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"+ | ||||||
| 		"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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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\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["+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"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"+ | ||||||
| 		"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_`\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"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"+ | 		"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"+ | ||||||
| 		"\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"+ | 		"\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"+ | ||||||
| 		"\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\2\2zx\3\2\2\2zy\3\2\2\2{\u008d\3\2\2\2|}\f\16\2\2}~\t\4\2\2~\u008c"+ | ||||||
| 		"\2\u0080\u0088\5\6\4\r\u0081\u0082\f\13\2\2\u0082\u0083\7\34\2\2\u0083"+ | 		"\5\6\4\17\177\u0080\f\r\2\2\u0080\u0081\t\5\2\2\u0081\u008c\5\6\4\16\u0082"+ | ||||||
| 		"\u0088\5\6\4\f\u0084\u0085\f\n\2\2\u0085\u0086\7\35\2\2\u0086\u0088\5"+ | 		"\u0083\f\f\2\2\u0083\u0084\t\6\2\2\u0084\u008c\5\6\4\r\u0085\u0086\f\13"+ | ||||||
| 		"\6\4\13\u0087x\3\2\2\2\u0087{\3\2\2\2\u0087~\3\2\2\2\u0087\u0081\3\2\2"+ | 		"\2\2\u0086\u0087\7\34\2\2\u0087\u008c\5\6\4\f\u0088\u0089\f\n\2\2\u0089"+ | ||||||
| 		"\2\u0087\u0084\3\2\2\2\u0088\u008b\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a"+ | 		"\u008a\7\35\2\2\u008a\u008c\5\6\4\13\u008b|\3\2\2\2\u008b\177\3\2\2\2"+ | ||||||
| 		"\3\2\2\2\u008a\7\3\2\2\2\u008b\u0089\3\2\2\2\u008c\u008f\t\7\2\2\u008d"+ | 		"\u008b\u0082\3\2\2\2\u008b\u0085\3\2\2\2\u008b\u0088\3\2\2\2\u008c\u008f"+ | ||||||
| 		"\u008f\5\n\6\2\u008e\u008c\3\2\2\2\u008e\u008d\3\2\2\2\u008f\t\3\2\2\2"+ | 		"\3\2\2\2\u008d\u008b\3\2\2\2\u008d\u008e\3\2\2\2\u008e\7\3\2\2\2\u008f"+ | ||||||
| 		"\u0090\u0091\7)\2\2\u0091\13\3\2\2\2\r\22\26)\65ALhv\u0087\u0089\u008e"; | 		"\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 = | 	public static final ATN _ATN = | ||||||
| 		new ATNDeserializer().deserialize(_serializedATN.toCharArray()); | 		new ATNDeserializer().deserialize(_serializedATN.toCharArray()); | ||||||
| 	static { | 	static { | ||||||
|  | @ -1,177 +1,177 @@ | ||||||
| // Generated from Basic.g4 by ANTLR 4.7 | // Generated from Boppi.g4 by ANTLR 4.7 | ||||||
| package pp.s1184725.boppi; | package pp.s1184725.boppi.antlr; | ||||||
| import org.antlr.v4.runtime.tree.ParseTreeVisitor; | import org.antlr.v4.runtime.tree.ParseTreeVisitor; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This interface defines a complete generic visitor for a parse tree produced |  * 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 |  * @param <T> The return type of the visit operation. Use {@link Void} for | ||||||
|  * operations with no return type. |  * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitExpr(BasicParser.ExprContext ctx); | 	T visitExpr(BoppiParser.ExprContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code parens} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitParens(BasicParser.ParensContext ctx); | 	T visitParens(BoppiParser.ParensContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code read} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitRead(BasicParser.ReadContext ctx); | 	T visitRead(BoppiParser.ReadContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code declare} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitDeclare(BasicParser.DeclareContext ctx); | 	T visitDeclare(BoppiParser.DeclareContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code bool} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitBool(BasicParser.BoolContext ctx); | 	T visitBool(BoppiParser.BoolContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code var} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitVar(BasicParser.VarContext ctx); | 	T visitVar(BoppiParser.VarContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code infix2} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitInfix2(BasicParser.Infix2Context ctx); | 	T visitInfix2(BoppiParser.Infix2Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code infix3} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitInfix3(BasicParser.Infix3Context ctx); | 	T visitInfix3(BoppiParser.Infix3Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code infix1} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitInfix1(BasicParser.Infix1Context ctx); | 	T visitInfix1(BoppiParser.Infix1Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code while} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitWhile(BasicParser.WhileContext ctx); | 	T visitWhile(BoppiParser.WhileContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code infix4} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitInfix4(BasicParser.Infix4Context ctx); | 	T visitInfix4(BoppiParser.Infix4Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code infix5} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitInfix5(BasicParser.Infix5Context ctx); | 	T visitInfix5(BoppiParser.Infix5Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code call} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitCall(BasicParser.CallContext ctx); | 	T visitCall(BoppiParser.CallContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code number} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitNumber(BasicParser.NumberContext ctx); | 	T visitNumber(BoppiParser.NumberContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code funcDeclare} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitFuncDeclare(BasicParser.FuncDeclareContext ctx); | 	T visitFuncDeclare(BoppiParser.FuncDeclareContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code char} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitChar(BasicParser.CharContext ctx); | 	T visitChar(BoppiParser.CharContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code block} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitBlock(BasicParser.BlockContext ctx); | 	T visitBlock(BoppiParser.BlockContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code write} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitWrite(BasicParser.WriteContext ctx); | 	T visitWrite(BoppiParser.WriteContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code if} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitIf(BasicParser.IfContext ctx); | 	T visitIf(BoppiParser.IfContext ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code prefix1} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @return the visitor result | ||||||
| 	 */ | 	 */ | ||||||
| 	T visitPrefix1(BasicParser.Prefix1Context ctx); | 	T visitPrefix1(BoppiParser.Prefix1Context ctx); | ||||||
| 	/** | 	/** | ||||||
| 	 * Visit a parse tree produced by the {@code assign} | 	 * 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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @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 | 	 * @param ctx the parse tree | ||||||
| 	 * @return the visitor result | 	 * @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) | @RunWith(Suite.class) | ||||||
| @SuiteClasses({ CheckerTest.class, GeneratorTest.class, ParserTest.class }) | @SuiteClasses({ CheckerTest.class, GeneratorTest.class, ParserTest.class }) | ||||||
| public class AllTests { | 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.CharStream; | ||||||
| import org.antlr.v4.runtime.tree.ParseTree; | import org.antlr.v4.runtime.tree.ParseTree; | ||||||
|  | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.junit.Test; | import org.junit.Test; | ||||||
| 
 | 
 | ||||||
| import pp.iloc.Simulator; | import pp.iloc.Simulator; | ||||||
|  | @ -17,6 +18,7 @@ import pp.s1184725.boppi.*; | ||||||
| public class GeneratorTest { | public class GeneratorTest { | ||||||
| 	private List<LogRecord> log; | 	private List<LogRecord> log; | ||||||
| 	private String[] out; | 	private String[] out; | ||||||
|  | 	private Level logLevel = Level.SEVERE; | ||||||
| 
 | 
 | ||||||
| 	private void compileAndRunString(String code, String... input) { | 	private void compileAndRunString(String code, String... input) { | ||||||
| 		compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n"); | 		compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n"); | ||||||
|  | @ -29,10 +31,11 @@ public class GeneratorTest { | ||||||
| 	private void compileAndRun(CharStream stream, String input) { | 	private void compileAndRun(CharStream stream, String input) { | ||||||
| 		Logger logger = Logger.getAnonymousLogger(); | 		Logger logger = Logger.getAnonymousLogger(); | ||||||
| 		log = ToolChain.makeListLog(logger); | 		log = ToolChain.makeListLog(logger); | ||||||
|  | 		logger.setLevel(logLevel); | ||||||
| 
 | 
 | ||||||
| 		ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program(); | 		ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program(); | ||||||
| 		Annotations annotations = ToolChain.getAnnotations(ast, logger); | 		Annotations annotations = ToolChain.getAnnotations(ast, logger); | ||||||
| 		Program program = ToolChain.getILOC(ast, annotations); | 		Program program = ToolChain.getILOC(ast, logger, annotations); | ||||||
| 
 | 
 | ||||||
| 		if (Simulator.DEBUG) | 		if (Simulator.DEBUG) | ||||||
| 			System.out.println(program.prettyPrint()); | 			System.out.println(program.prettyPrint()); | ||||||
|  | @ -40,10 +43,33 @@ public class GeneratorTest { | ||||||
| 		out = ToolChain.execute(program, logger, input).split("\n"); | 		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 | 	@Test | ||||||
| 	public void correctExpressionTest() { | 	public void correctExpressionTest() { | ||||||
| 		compileAndRunFile("simpleExpression.boppi"); | 		compileAndRunFile("simpleExpression.boppi"); | ||||||
| 		assertThat(log, is(empty())); | 		assertThat(log, is(empty())); | ||||||
|  | 
 | ||||||
|  | 		compileAndRunString(StringUtils.repeat("1+(", 8) + "1" + StringUtils.repeat(")", 8)); | ||||||
|  | 		assertThat(log, is(empty())); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | @ -87,7 +113,7 @@ public class GeneratorTest { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	public void correctFunctionTest() { | 	public void correctSimpleFunctionTest() { | ||||||
| 		compileAndRunString("function int id(int a) a; 1"); | 		compileAndRunString("function int id(int a) a; 1"); | ||||||
| 		assertThat(log, is(empty())); | 		assertThat(log, is(empty())); | ||||||
| 
 | 
 | ||||||
|  | @ -108,7 +134,10 @@ public class GeneratorTest { | ||||||
| 		compileAndRunString("function char const(char a, char b) a; print(const('A', 'T'))"); | 		compileAndRunString("function char const(char a, char b) a; print(const('A', 'T'))"); | ||||||
| 		assertThat(log, is(empty())); | 		assertThat(log, is(empty())); | ||||||
| 		assertThat(out, is(arrayContaining("A"))); | 		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}"); | 		compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}"); | ||||||
| 		assertThat(log, is(empty())); | 		assertThat(log, is(empty())); | ||||||
| 
 | 
 | ||||||
|  | @ -117,6 +146,9 @@ public class GeneratorTest { | ||||||
| 				"5"); | 				"5"); | ||||||
| 		assertThat(log, is(empty())); | 		assertThat(log, is(empty())); | ||||||
| 		assertThat(out, is(arrayContaining("120"))); | 		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
	
	 User
						User