added tuple types, added javadoc for all public attributes
This commit is contained in:
parent
11da0a0826
commit
a1257c237b
|
@ -27,6 +27,9 @@ public class Annotations {
|
|||
* Maps nodes to their function scope.
|
||||
*/
|
||||
public ParseTreeProperty<Variable<Type>> function;
|
||||
/**
|
||||
* A stack with the current function scope on top.
|
||||
*/
|
||||
public Stack<Variable<Type>> currentFunction;
|
||||
|
||||
/**
|
||||
|
|
|
@ -76,12 +76,12 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
|
||||
if (t instanceof FunctionType) {
|
||||
FunctionType type = (FunctionType) t;
|
||||
if (type.getParameters().size() != ctx.expr().size())
|
||||
log.severe(getError(ctx, "Expected %d arguments but got %d.", type.getParameters().size(),
|
||||
ctx.expr().size()));
|
||||
TupleType parameters = (TupleType) type.getParameter();
|
||||
if (parameters.size() != ctx.expr().size())
|
||||
log.severe(getError(ctx, "Expected %d arguments but got %d.", parameters.size(), ctx.expr().size()));
|
||||
|
||||
for (int i = 0; i < ctx.expr().size() && i < type.getParameters().size(); i++)
|
||||
checkConstraint(visit(ctx.expr(i)), type.getParameters().get(i), ctx.expr(i));
|
||||
for (int i = 0; i < ctx.expr().size() && i < parameters.size(); i++)
|
||||
checkConstraint(visit(ctx.expr(i)), parameters.get(i), ctx.expr(i));
|
||||
|
||||
return type.getReturn();
|
||||
} else {
|
||||
|
@ -109,6 +109,12 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
Variable<Type> var = symbols.put(ctx.IDENTIFIER().getText(), visit(ctx.type()));
|
||||
an.variables.put(ctx, var);
|
||||
|
||||
if (var.getType() instanceof TupleType)
|
||||
log.severe(getError(ctx, "Variable must have a type %s, %s, %s or function.",
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.BOOLTYPE),
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.CHARTYPE),
|
||||
BoppiLexer.VOCABULARY.getLiteralName(BoppiLexer.INTTYPE)));
|
||||
|
||||
if (!(var.getType() instanceof SimpleType))
|
||||
log.warning("Be careful only to pass pure functions outside their scope.");
|
||||
} catch (EmptyStackException e) {
|
||||
|
@ -122,7 +128,8 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
@Override
|
||||
public Type visitFuncDeclare(FuncDeclareContext ctx) {
|
||||
try {
|
||||
List<Type> parameterTypes = ctx.type().stream().skip(1).map(this::visit).collect(Collectors.toList());
|
||||
TupleType parameterTypes = new TupleType(
|
||||
ctx.type().stream().skip(1).map(this::visit).collect(Collectors.toList()));
|
||||
FunctionType type = new FunctionType(visit(ctx.result), parameterTypes);
|
||||
Variable<Type> func = symbols.put(ctx.name.getText(), type);
|
||||
an.variables.put(ctx, func);
|
||||
|
@ -131,8 +138,7 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
type.setLocalDataSize(symbols.withFunctionScope(() -> {
|
||||
for (int i = 1; i < ctx.type().size(); i++)
|
||||
try {
|
||||
Variable<Type> var = symbols.put(ctx.IDENTIFIER(i).getText(), an.types.get(ctx.type(i)));
|
||||
type.getOffsets().add(var.getOffset());
|
||||
symbols.put(ctx.IDENTIFIER(i).getText(), an.types.get(ctx.type(i)));
|
||||
} catch (Exception e) {
|
||||
log.severe(getError(ctx, e.getMessage()));
|
||||
}
|
||||
|
@ -242,7 +248,7 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
|
||||
@Override
|
||||
public Type visitProgram(ProgramContext ctx) {
|
||||
FunctionType main = new FunctionType(SimpleType.VOID, new ArrayList<>());
|
||||
FunctionType main = new FunctionType(TupleType.UNIT, TupleType.UNIT);
|
||||
an.currentFunction.push(new Variable<Type>(main, 0, 0));
|
||||
main.setLocalDataSize(symbols.withFunctionScope(() -> super.visitProgram(ctx)));
|
||||
return null;
|
||||
|
@ -259,11 +265,23 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Type visitType(TypeContext ctx) {
|
||||
if (ctx.variable() != null)
|
||||
return visit(ctx.variable());
|
||||
else
|
||||
return SimpleType.fromToken(ctx.staticType.getType());
|
||||
public Type visitTypeFunction(TypeFunctionContext ctx) {
|
||||
return new FunctionType(visit(ctx.type(1)), visit(ctx.type(0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type visitTypeSimple(TypeSimpleContext ctx) {
|
||||
return SimpleType.fromToken(ctx.staticType.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type visitTypeTuple(TypeTupleContext ctx) {
|
||||
return new TupleType(ctx.children.stream().map(this::visit).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type visitTypeVariable(TypeVariableContext ctx) {
|
||||
return visit(ctx.variable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,6 +14,9 @@ import pp.s1184725.boppi.antlr.BoppiBaseVisitor;
|
|||
import pp.s1184725.boppi.antlr.BoppiLexer;
|
||||
import pp.s1184725.boppi.antlr.BoppiParser.*;
|
||||
|
||||
/**
|
||||
* The generator stage of the Boppi toolchain.
|
||||
*/
|
||||
public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
||||
private static final int ARBASESIZE = 16;
|
||||
private static final Operand ZERO = new Num(0);
|
||||
|
@ -77,6 +80,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
|||
regNum = 0;
|
||||
regFree = new ArrayList<>();
|
||||
regInUse = new ArrayList<>();
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private Reg makeReg(ParserRuleContext ctx) {
|
||||
|
@ -85,7 +89,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
|||
reg = new Reg("__" + (regInUse.size() + 1));
|
||||
regInUse.add(reg);
|
||||
|
||||
if (regInUse.size() > 10)
|
||||
if (regInUse.size() == 11)
|
||||
logger.warning(
|
||||
String.format("Using more than 10 registers at %d:%d. Consider rebalancing your expressions.",
|
||||
ctx.start.getLine(), ctx.start.getCharPositionInLine()));
|
||||
|
@ -237,7 +241,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
|||
public Void visitCall(CallContext ctx) {
|
||||
String base = "call " + ctx.variable().getText() + " - ";
|
||||
Variable<Type> function = an.variables.get(ctx.variable());
|
||||
FunctionType parameters = ((FunctionType) function.getType());
|
||||
TupleType parameters = (TupleType) ((FunctionType) function.getType()).getParameter();
|
||||
visit(ctx.variable());
|
||||
freeReg(ctx.variable());
|
||||
emit(base + "target address", OpCode.loadAI, getVar(ctx.variable()),
|
||||
|
@ -248,7 +252,7 @@ public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
|||
for (int i = 0; i < ctx.expr().size(); i++) {
|
||||
visit(ctx.expr(i));
|
||||
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i)))
|
||||
if (SimpleType.CHAR.equals(parameters.get(i)))
|
||||
emit(base + "param " + i, OpCode.cpush, getReg(ctx.expr(i)));
|
||||
else
|
||||
emit(base + "param " + i, OpCode.push, getReg(ctx.expr(i)));
|
||||
|
@ -260,14 +264,12 @@ public class BoppiGenerator extends BoppiBaseVisitor<Void> {
|
|||
|
||||
makeReg(ctx);
|
||||
for (int i = ctx.expr().size() - 1; i >= 0; i--) {
|
||||
if (SimpleType.CHAR.equals(parameters.getParameters().get(i))) {
|
||||
if (SimpleType.CHAR.equals(parameters.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)));
|
||||
emit(base + "param " + i, OpCode.cstoreAI, getReg(ctx), tempArp, new Num(parameters.getOffset(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 + "param " + i, OpCode.storeAI, getReg(ctx), tempArp, new Num(parameters.getOffset(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,24 +2,21 @@ package pp.s1184725.boppi;
|
|||
|
||||
import java.util.EmptyStackException;
|
||||
|
||||
/**
|
||||
* Same functionality as {@link CachingSymbolTable} except actions on the table
|
||||
* are logged to the console.
|
||||
*
|
||||
* @param <T>
|
||||
* the typing class
|
||||
*/
|
||||
public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable<T> {
|
||||
|
||||
@Override
|
||||
public void openScope() {
|
||||
super.openScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openFunctionScope() {
|
||||
super.openFunctionScope();
|
||||
System.out.println(this.getClass().getName() + ": entering scope depth " + functionDepth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeScope() throws EmptyStackException {
|
||||
super.closeScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeFunctionScope() throws EmptyStackException {
|
||||
System.out.println(this.getClass().getName() + ": leaving scope depth " + functionDepth);
|
||||
|
@ -28,15 +25,11 @@ public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable<
|
|||
|
||||
@Override
|
||||
public Variable<T> put(String id, T type) throws Exception, EmptyStackException {
|
||||
System.out.println(this.getClass().getName() + ": declaring '" + id + "' ("+type.toString()+") at scope " + functionDepth);
|
||||
System.out.println(this.getClass().getName() + ": declaring '" + id + "' (" + type.toString() + ") at scope "
|
||||
+ functionDepth);
|
||||
return super.put(id, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String id) throws EmptyStackException {
|
||||
return super.has(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable<T> get(String id) throws Exception, EmptyStackException {
|
||||
System.out.println(this.getClass().getName() + ": retrieving '" + id + "' (depth "
|
||||
|
@ -44,14 +37,4 @@ public class DebugCachingSymbolTable<T extends Type> extends CachingSymbolTable<
|
|||
return super.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalDataSize() {
|
||||
return super.getLocalDataSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFunctionDepth() {
|
||||
return super.getFunctionDepth();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import pp.iloc.eval.Machine;
|
||||
|
||||
/**
|
||||
* The (->) type. Takes exactly two types as arguments.
|
||||
*/
|
||||
public class FunctionType implements Type {
|
||||
private List<Type> parameters;
|
||||
private List<Integer> offsets;
|
||||
private Type result;
|
||||
private Type argument, result;
|
||||
private int localDataSize;
|
||||
|
||||
public FunctionType(Type returnType, List<Type> parameterTypes) {
|
||||
/**
|
||||
* Creates a new function type from the given parameter and return types.
|
||||
*
|
||||
* @param returnType
|
||||
* the result type when applying an argument to the function
|
||||
* @param parameter
|
||||
* the input type for this function type
|
||||
*/
|
||||
public FunctionType(Type returnType, Type parameter) {
|
||||
result = returnType;
|
||||
parameters = new ArrayList<>(parameterTypes);
|
||||
offsets = new ArrayList<>();
|
||||
argument = parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,13 +33,12 @@ public class FunctionType implements Type {
|
|||
return false;
|
||||
|
||||
FunctionType other = (FunctionType) obj;
|
||||
return result.equals(other.result) && parameters.equals(other.parameters);
|
||||
return result.equals(other.result) && argument.equals(other.argument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parameters.stream().map(Type::toString).collect(Collectors.joining(",", "(", ")")) + "->"
|
||||
+ result.toString();
|
||||
return argument.toString() + "->" + result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,19 +70,11 @@ public class FunctionType implements Type {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the parameter types of this function.
|
||||
* Returns the parameter type of this function.
|
||||
*
|
||||
* @return the parameter types
|
||||
* @return the parameter type
|
||||
*/
|
||||
public List<Type> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(List<Type> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<Integer> getOffsets() {
|
||||
return offsets;
|
||||
public Type getParameter() {
|
||||
return argument;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,23 @@ import pp.s1184725.boppi.antlr.BoppiLexer;
|
|||
* </ul>
|
||||
*/
|
||||
public enum SimpleType implements Type {
|
||||
INT(Machine.INT_SIZE), CHAR(Machine.DEFAULT_CHAR_SIZE), BOOL(Machine.INT_SIZE), VOID(0);
|
||||
|
||||
/**
|
||||
* Integer type
|
||||
*/
|
||||
INT(Machine.INT_SIZE),
|
||||
/**
|
||||
* Character type
|
||||
*/
|
||||
CHAR(Machine.DEFAULT_CHAR_SIZE),
|
||||
/**
|
||||
* Boolean type
|
||||
*/
|
||||
BOOL(Machine.INT_SIZE),
|
||||
/**
|
||||
* Void type (not the same as {@link TupleType#UNIT})
|
||||
*/
|
||||
VOID(0);
|
||||
|
||||
private final int size;
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The n-tuple type. Takes exactly {@link #size()} types. The element indices in
|
||||
* the tuple are 0-based.
|
||||
*/
|
||||
public class TupleType extends AbstractList<Type> implements Type {
|
||||
/**
|
||||
* The empty tuple. Can be used in places where {@link SimpleType#VOID}
|
||||
* cannot.
|
||||
*/
|
||||
public static TupleType UNIT = new TupleType(new ArrayList<>());
|
||||
private List<Type> parameters;
|
||||
|
||||
/**
|
||||
* Creates an n-tuple of the given types.
|
||||
*
|
||||
* @param parameterTypes
|
||||
*/
|
||||
public TupleType(List<Type> parameterTypes) {
|
||||
parameters = new ArrayList<>(parameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset (in bytes) of the type at index {@code n}.
|
||||
*
|
||||
* @param paramIndex
|
||||
* the index of the tuple element
|
||||
* @return the offset in bytes
|
||||
*/
|
||||
public int getOffset(int paramIndex) {
|
||||
return parameters.stream().limit(paramIndex).collect(Collectors.summingInt(Type::getSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return parameters.stream().collect(Collectors.summingInt(Type::getSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof TupleType)
|
||||
return parameters.equals(((TupleType) other).parameters);
|
||||
|
||||
return false;
|
||||
//
|
||||
// switch (parameters.size()) {
|
||||
// case 0:
|
||||
// return SimpleType.VOID.equals(other);
|
||||
// case 1:
|
||||
// return parameters.get(0).equals(other);
|
||||
// default:
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parameters.stream().map(Type::toString).collect(Collectors.joining(",", "(", ")"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type get(int index) {
|
||||
return parameters.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return parameters.size();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package pp.s1184725.boppi;
|
||||
|
||||
/**
|
||||
* Generic type interface. All types must have at least these properties.
|
||||
*/
|
||||
public interface Type {
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,12 @@ singleExpr
|
|||
| (TRUE|FALSE) #bool
|
||||
;
|
||||
|
||||
type: staticType=(INTTYPE | BOOLTYPE | CHARTYPE) | variable;
|
||||
type
|
||||
: type ARROW type #typeFunction
|
||||
| staticType=(INTTYPE | BOOLTYPE | CHARTYPE) #typeSimple
|
||||
| PAROPEN (type (LISTDELIM type )*)? PARCLOSE #typeTuple
|
||||
| variable #typeVariable
|
||||
;
|
||||
variable: IDENTIFIER;
|
||||
|
||||
PAROPEN: '(';
|
||||
|
@ -66,6 +71,7 @@ FUNCTION: 'function';
|
|||
INTTYPE: 'int';
|
||||
BOOLTYPE: 'bool';
|
||||
CHARTYPE: 'char';
|
||||
ARROW: '->';
|
||||
ASSIGN: ':=';
|
||||
COMPOUND: ';';
|
||||
LISTDELIM: ',';
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
PAROPEN=1
|
||||
PARCLOSE=2
|
||||
BRAOPEN=3
|
||||
BRACLOSE=4
|
||||
IN=5
|
||||
OUT=6
|
||||
IFOPEN=7
|
||||
IFTRUE=8
|
||||
IFFALSE=9
|
||||
IFCLOSE=10
|
||||
WHILEOPEN=11
|
||||
WHILETRUE=12
|
||||
WHILECLOSE=13
|
||||
PLUS=14
|
||||
MINUS=15
|
||||
NOT=16
|
||||
MULTIPLY=17
|
||||
DIVIDE=18
|
||||
MODULO=19
|
||||
LEQ=20
|
||||
GTE=21
|
||||
NEQ=22
|
||||
EQ=23
|
||||
LT=24
|
||||
GT=25
|
||||
AND=26
|
||||
OR=27
|
||||
DECLARE=28
|
||||
FUNCTION=29
|
||||
INTTYPE=30
|
||||
BOOLTYPE=31
|
||||
CHARTYPE=32
|
||||
ASSIGN=33
|
||||
COMPOUND=34
|
||||
LISTDELIM=35
|
||||
CHAR=36
|
||||
TRUE=37
|
||||
FALSE=38
|
||||
IDENTIFIER=39
|
||||
LITERAL10=40
|
||||
WHITESPACE=41
|
||||
LINECOMMENT=42
|
||||
BLOCKCOMMENT=43
|
||||
'('=1
|
||||
')'=2
|
||||
'{'=3
|
||||
'}'=4
|
||||
'read'=5
|
||||
'print'=6
|
||||
'if'=7
|
||||
'then'=8
|
||||
'else'=9
|
||||
'fi'=10
|
||||
'while'=11
|
||||
'do'=12
|
||||
'od'=13
|
||||
'+'=14
|
||||
'-'=15
|
||||
'!'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'<='=20
|
||||
'>='=21
|
||||
'<>'=22
|
||||
'=='=23
|
||||
'<'=24
|
||||
'>'=25
|
||||
'&&'=26
|
||||
'||'=27
|
||||
'var'=28
|
||||
'function'=29
|
||||
'int'=30
|
||||
'bool'=31
|
||||
'char'=32
|
||||
':='=33
|
||||
';'=34
|
||||
','=35
|
||||
'true'=37
|
||||
'false'=38
|
|
@ -1,182 +0,0 @@
|
|||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link BoppiVisitor},
|
||||
* which can be extended to create a visitor which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public class BoppiBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements BoppiVisitor<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitProgram(BoppiParser.ProgramContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExpr(BoppiParser.ExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParens(BoppiParser.ParensContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitRead(BoppiParser.ReadContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDeclare(BoppiParser.DeclareContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBool(BoppiParser.BoolContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitVar(BoppiParser.VarContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix2(BoppiParser.Infix2Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix3(BoppiParser.Infix3Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix1(BoppiParser.Infix1Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitWhile(BoppiParser.WhileContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix4(BoppiParser.Infix4Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInfix5(BoppiParser.Infix5Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitCall(BoppiParser.CallContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitNumber(BoppiParser.NumberContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitFuncDeclare(BoppiParser.FuncDeclareContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitChar(BoppiParser.CharContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBlock(BoppiParser.BlockContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitWrite(BoppiParser.WriteContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitIf(BoppiParser.IfContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitPrefix1(BoppiParser.Prefix1Context ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAssign(BoppiParser.AssignContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitType(BoppiParser.TypeContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitVariable(BoppiParser.VariableContext ctx) { return visitChildren(ctx); }
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class BoppiLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
PAROPEN=1, PARCLOSE=2, BRAOPEN=3, BRACLOSE=4, IN=5, OUT=6, IFOPEN=7, IFTRUE=8,
|
||||
IFFALSE=9, IFCLOSE=10, WHILEOPEN=11, WHILETRUE=12, WHILECLOSE=13, PLUS=14,
|
||||
MINUS=15, NOT=16, MULTIPLY=17, DIVIDE=18, MODULO=19, LEQ=20, GTE=21, NEQ=22,
|
||||
EQ=23, LT=24, GT=25, AND=26, OR=27, DECLARE=28, FUNCTION=29, INTTYPE=30,
|
||||
BOOLTYPE=31, CHARTYPE=32, ASSIGN=33, COMPOUND=34, LISTDELIM=35, CHAR=36,
|
||||
TRUE=37, FALSE=38, IDENTIFIER=39, LITERAL10=40, WHITESPACE=41, LINECOMMENT=42,
|
||||
BLOCKCOMMENT=43;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE"
|
||||
};
|
||||
|
||||
public static final String[] ruleNames = {
|
||||
"PAROPEN", "PARCLOSE", "BRAOPEN", "BRACLOSE", "IN", "OUT", "IFOPEN", "IFTRUE",
|
||||
"IFFALSE", "IFCLOSE", "WHILEOPEN", "WHILETRUE", "WHILECLOSE", "PLUS",
|
||||
"MINUS", "NOT", "MULTIPLY", "DIVIDE", "MODULO", "LEQ", "GTE", "NEQ", "EQ",
|
||||
"LT", "GT", "AND", "OR", "DECLARE", "FUNCTION", "INTTYPE", "BOOLTYPE",
|
||||
"CHARTYPE", "ASSIGN", "COMPOUND", "LISTDELIM", "CHAR", "TRUE", "FALSE",
|
||||
"IDENTIFIER", "LITERAL10", "WHITESPACE", "LINECOMMENT", "BLOCKCOMMENT"
|
||||
};
|
||||
|
||||
private static final String[] _LITERAL_NAMES = {
|
||||
null, "'('", "')'", "'{'", "'}'", "'read'", "'print'", "'if'", "'then'",
|
||||
"'else'", "'fi'", "'while'", "'do'", "'od'", "'+'", "'-'", "'!'", "'*'",
|
||||
"'/'", "'%'", "'<='", "'>='", "'<>'", "'=='", "'<'", "'>'", "'&&'", "'||'",
|
||||
"'var'", "'function'", "'int'", "'bool'", "'char'", "':='", "';'", "','",
|
||||
null, "'true'", "'false'"
|
||||
};
|
||||
private static final String[] _SYMBOLIC_NAMES = {
|
||||
null, "PAROPEN", "PARCLOSE", "BRAOPEN", "BRACLOSE", "IN", "OUT", "IFOPEN",
|
||||
"IFTRUE", "IFFALSE", "IFCLOSE", "WHILEOPEN", "WHILETRUE", "WHILECLOSE",
|
||||
"PLUS", "MINUS", "NOT", "MULTIPLY", "DIVIDE", "MODULO", "LEQ", "GTE",
|
||||
"NEQ", "EQ", "LT", "GT", "AND", "OR", "DECLARE", "FUNCTION", "INTTYPE",
|
||||
"BOOLTYPE", "CHARTYPE", "ASSIGN", "COMPOUND", "LISTDELIM", "CHAR", "TRUE",
|
||||
"FALSE", "IDENTIFIER", "LITERAL10", "WHITESPACE", "LINECOMMENT", "BLOCKCOMMENT"
|
||||
};
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
public BoppiLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Boppi.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2-\u0109\b\1\4\2\t"+
|
||||
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
|
||||
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
|
||||
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
|
||||
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
|
||||
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+
|
||||
",\t,\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3"+
|
||||
"\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\13\3"+
|
||||
"\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17"+
|
||||
"\3\20\3\20\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\25\3\26"+
|
||||
"\3\26\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33"+
|
||||
"\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36"+
|
||||
"\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3\""+
|
||||
"\3\"\3\"\3#\3#\3$\3$\3%\3%\3%\3%\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3"+
|
||||
"\'\3(\3(\7(\u00de\n(\f(\16(\u00e1\13(\3)\3)\3)\7)\u00e6\n)\f)\16)\u00e9"+
|
||||
"\13)\5)\u00eb\n)\3*\3*\3*\3*\3+\3+\3+\3+\7+\u00f5\n+\f+\16+\u00f8\13+"+
|
||||
"\3+\3+\3,\3,\3,\3,\7,\u0100\n,\f,\16,\u0103\13,\3,\3,\3,\3,\3,\3\u0101"+
|
||||
"\2-\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35"+
|
||||
"\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36"+
|
||||
";\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-\3\2\b\5\2C\\aac|\6\2\62;C\\aac|\3\2"+
|
||||
"\63;\3\2\62;\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u010d\2\3\3\2\2\2\2\5"+
|
||||
"\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2"+
|
||||
"\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33"+
|
||||
"\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2"+
|
||||
"\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2"+
|
||||
"\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2"+
|
||||
"\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K"+
|
||||
"\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2"+
|
||||
"\2\2\3Y\3\2\2\2\5[\3\2\2\2\7]\3\2\2\2\t_\3\2\2\2\13a\3\2\2\2\rf\3\2\2"+
|
||||
"\2\17l\3\2\2\2\21o\3\2\2\2\23t\3\2\2\2\25y\3\2\2\2\27|\3\2\2\2\31\u0082"+
|
||||
"\3\2\2\2\33\u0085\3\2\2\2\35\u0088\3\2\2\2\37\u008a\3\2\2\2!\u008c\3\2"+
|
||||
"\2\2#\u008e\3\2\2\2%\u0090\3\2\2\2\'\u0092\3\2\2\2)\u0094\3\2\2\2+\u0097"+
|
||||
"\3\2\2\2-\u009a\3\2\2\2/\u009d\3\2\2\2\61\u00a0\3\2\2\2\63\u00a2\3\2\2"+
|
||||
"\2\65\u00a4\3\2\2\2\67\u00a7\3\2\2\29\u00aa\3\2\2\2;\u00ae\3\2\2\2=\u00b7"+
|
||||
"\3\2\2\2?\u00bb\3\2\2\2A\u00c0\3\2\2\2C\u00c5\3\2\2\2E\u00c8\3\2\2\2G"+
|
||||
"\u00ca\3\2\2\2I\u00cc\3\2\2\2K\u00d0\3\2\2\2M\u00d5\3\2\2\2O\u00db\3\2"+
|
||||
"\2\2Q\u00ea\3\2\2\2S\u00ec\3\2\2\2U\u00f0\3\2\2\2W\u00fb\3\2\2\2YZ\7*"+
|
||||
"\2\2Z\4\3\2\2\2[\\\7+\2\2\\\6\3\2\2\2]^\7}\2\2^\b\3\2\2\2_`\7\177\2\2"+
|
||||
"`\n\3\2\2\2ab\7t\2\2bc\7g\2\2cd\7c\2\2de\7f\2\2e\f\3\2\2\2fg\7r\2\2gh"+
|
||||
"\7t\2\2hi\7k\2\2ij\7p\2\2jk\7v\2\2k\16\3\2\2\2lm\7k\2\2mn\7h\2\2n\20\3"+
|
||||
"\2\2\2op\7v\2\2pq\7j\2\2qr\7g\2\2rs\7p\2\2s\22\3\2\2\2tu\7g\2\2uv\7n\2"+
|
||||
"\2vw\7u\2\2wx\7g\2\2x\24\3\2\2\2yz\7h\2\2z{\7k\2\2{\26\3\2\2\2|}\7y\2"+
|
||||
"\2}~\7j\2\2~\177\7k\2\2\177\u0080\7n\2\2\u0080\u0081\7g\2\2\u0081\30\3"+
|
||||
"\2\2\2\u0082\u0083\7f\2\2\u0083\u0084\7q\2\2\u0084\32\3\2\2\2\u0085\u0086"+
|
||||
"\7q\2\2\u0086\u0087\7f\2\2\u0087\34\3\2\2\2\u0088\u0089\7-\2\2\u0089\36"+
|
||||
"\3\2\2\2\u008a\u008b\7/\2\2\u008b \3\2\2\2\u008c\u008d\7#\2\2\u008d\""+
|
||||
"\3\2\2\2\u008e\u008f\7,\2\2\u008f$\3\2\2\2\u0090\u0091\7\61\2\2\u0091"+
|
||||
"&\3\2\2\2\u0092\u0093\7\'\2\2\u0093(\3\2\2\2\u0094\u0095\7>\2\2\u0095"+
|
||||
"\u0096\7?\2\2\u0096*\3\2\2\2\u0097\u0098\7@\2\2\u0098\u0099\7?\2\2\u0099"+
|
||||
",\3\2\2\2\u009a\u009b\7>\2\2\u009b\u009c\7@\2\2\u009c.\3\2\2\2\u009d\u009e"+
|
||||
"\7?\2\2\u009e\u009f\7?\2\2\u009f\60\3\2\2\2\u00a0\u00a1\7>\2\2\u00a1\62"+
|
||||
"\3\2\2\2\u00a2\u00a3\7@\2\2\u00a3\64\3\2\2\2\u00a4\u00a5\7(\2\2\u00a5"+
|
||||
"\u00a6\7(\2\2\u00a6\66\3\2\2\2\u00a7\u00a8\7~\2\2\u00a8\u00a9\7~\2\2\u00a9"+
|
||||
"8\3\2\2\2\u00aa\u00ab\7x\2\2\u00ab\u00ac\7c\2\2\u00ac\u00ad\7t\2\2\u00ad"+
|
||||
":\3\2\2\2\u00ae\u00af\7h\2\2\u00af\u00b0\7w\2\2\u00b0\u00b1\7p\2\2\u00b1"+
|
||||
"\u00b2\7e\2\2\u00b2\u00b3\7v\2\2\u00b3\u00b4\7k\2\2\u00b4\u00b5\7q\2\2"+
|
||||
"\u00b5\u00b6\7p\2\2\u00b6<\3\2\2\2\u00b7\u00b8\7k\2\2\u00b8\u00b9\7p\2"+
|
||||
"\2\u00b9\u00ba\7v\2\2\u00ba>\3\2\2\2\u00bb\u00bc\7d\2\2\u00bc\u00bd\7"+
|
||||
"q\2\2\u00bd\u00be\7q\2\2\u00be\u00bf\7n\2\2\u00bf@\3\2\2\2\u00c0\u00c1"+
|
||||
"\7e\2\2\u00c1\u00c2\7j\2\2\u00c2\u00c3\7c\2\2\u00c3\u00c4\7t\2\2\u00c4"+
|
||||
"B\3\2\2\2\u00c5\u00c6\7<\2\2\u00c6\u00c7\7?\2\2\u00c7D\3\2\2\2\u00c8\u00c9"+
|
||||
"\7=\2\2\u00c9F\3\2\2\2\u00ca\u00cb\7.\2\2\u00cbH\3\2\2\2\u00cc\u00cd\7"+
|
||||
")\2\2\u00cd\u00ce\13\2\2\2\u00ce\u00cf\7)\2\2\u00cfJ\3\2\2\2\u00d0\u00d1"+
|
||||
"\7v\2\2\u00d1\u00d2\7t\2\2\u00d2\u00d3\7w\2\2\u00d3\u00d4\7g\2\2\u00d4"+
|
||||
"L\3\2\2\2\u00d5\u00d6\7h\2\2\u00d6\u00d7\7c\2\2\u00d7\u00d8\7n\2\2\u00d8"+
|
||||
"\u00d9\7u\2\2\u00d9\u00da\7g\2\2\u00daN\3\2\2\2\u00db\u00df\t\2\2\2\u00dc"+
|
||||
"\u00de\t\3\2\2\u00dd\u00dc\3\2\2\2\u00de\u00e1\3\2\2\2\u00df\u00dd\3\2"+
|
||||
"\2\2\u00df\u00e0\3\2\2\2\u00e0P\3\2\2\2\u00e1\u00df\3\2\2\2\u00e2\u00eb"+
|
||||
"\7\62\2\2\u00e3\u00e7\t\4\2\2\u00e4\u00e6\t\5\2\2\u00e5\u00e4\3\2\2\2"+
|
||||
"\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8\u00eb"+
|
||||
"\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00e2\3\2\2\2\u00ea\u00e3\3\2\2\2\u00eb"+
|
||||
"R\3\2\2\2\u00ec\u00ed\t\6\2\2\u00ed\u00ee\3\2\2\2\u00ee\u00ef\b*\2\2\u00ef"+
|
||||
"T\3\2\2\2\u00f0\u00f1\7\61\2\2\u00f1\u00f2\7\61\2\2\u00f2\u00f6\3\2\2"+
|
||||
"\2\u00f3\u00f5\n\7\2\2\u00f4\u00f3\3\2\2\2\u00f5\u00f8\3\2\2\2\u00f6\u00f4"+
|
||||
"\3\2\2\2\u00f6\u00f7\3\2\2\2\u00f7\u00f9\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f9"+
|
||||
"\u00fa\b+\2\2\u00faV\3\2\2\2\u00fb\u00fc\7\61\2\2\u00fc\u00fd\7,\2\2\u00fd"+
|
||||
"\u0101\3\2\2\2\u00fe\u0100\13\2\2\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3"+
|
||||
"\2\2\2\u0101\u0102\3\2\2\2\u0101\u00ff\3\2\2\2\u0102\u0104\3\2\2\2\u0103"+
|
||||
"\u0101\3\2\2\2\u0104\u0105\7,\2\2\u0105\u0106\7\61\2\2\u0106\u0107\3\2"+
|
||||
"\2\2\u0107\u0108\b,\2\2\u0108X\3\2\2\2\b\2\u00df\u00e7\u00ea\u00f6\u0101"+
|
||||
"\3\b\2\2";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
PAROPEN=1
|
||||
PARCLOSE=2
|
||||
BRAOPEN=3
|
||||
BRACLOSE=4
|
||||
IN=5
|
||||
OUT=6
|
||||
IFOPEN=7
|
||||
IFTRUE=8
|
||||
IFFALSE=9
|
||||
IFCLOSE=10
|
||||
WHILEOPEN=11
|
||||
WHILETRUE=12
|
||||
WHILECLOSE=13
|
||||
PLUS=14
|
||||
MINUS=15
|
||||
NOT=16
|
||||
MULTIPLY=17
|
||||
DIVIDE=18
|
||||
MODULO=19
|
||||
LEQ=20
|
||||
GTE=21
|
||||
NEQ=22
|
||||
EQ=23
|
||||
LT=24
|
||||
GT=25
|
||||
AND=26
|
||||
OR=27
|
||||
DECLARE=28
|
||||
FUNCTION=29
|
||||
INTTYPE=30
|
||||
BOOLTYPE=31
|
||||
CHARTYPE=32
|
||||
ASSIGN=33
|
||||
COMPOUND=34
|
||||
LISTDELIM=35
|
||||
CHAR=36
|
||||
TRUE=37
|
||||
FALSE=38
|
||||
IDENTIFIER=39
|
||||
LITERAL10=40
|
||||
WHITESPACE=41
|
||||
LINECOMMENT=42
|
||||
BLOCKCOMMENT=43
|
||||
'('=1
|
||||
')'=2
|
||||
'{'=3
|
||||
'}'=4
|
||||
'read'=5
|
||||
'print'=6
|
||||
'if'=7
|
||||
'then'=8
|
||||
'else'=9
|
||||
'fi'=10
|
||||
'while'=11
|
||||
'do'=12
|
||||
'od'=13
|
||||
'+'=14
|
||||
'-'=15
|
||||
'!'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'<='=20
|
||||
'>='=21
|
||||
'<>'=22
|
||||
'=='=23
|
||||
'<'=24
|
||||
'>'=25
|
||||
'&&'=26
|
||||
'||'=27
|
||||
'var'=28
|
||||
'function'=29
|
||||
'int'=30
|
||||
'bool'=31
|
||||
'char'=32
|
||||
':='=33
|
||||
';'=34
|
||||
','=35
|
||||
'true'=37
|
||||
'false'=38
|
File diff suppressed because it is too large
Load Diff
|
@ -1,177 +0,0 @@
|
|||
// Generated from Boppi.g4 by ANTLR 4.7
|
||||
package pp.s1184725.boppi.antlr;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This interface defines a complete generic visitor for a parse tree produced
|
||||
* by {@link BoppiParser}.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
public interface BoppiVisitor<T> extends ParseTreeVisitor<T> {
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BoppiParser#program}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitProgram(BoppiParser.ProgramContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BoppiParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExpr(BoppiParser.ExprContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code parens}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitParens(BoppiParser.ParensContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code read}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitRead(BoppiParser.ReadContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code declare}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitDeclare(BoppiParser.DeclareContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code bool}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitBool(BoppiParser.BoolContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code var}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitVar(BoppiParser.VarContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix2}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix2(BoppiParser.Infix2Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix3}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix3(BoppiParser.Infix3Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix1}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix1(BoppiParser.Infix1Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code while}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitWhile(BoppiParser.WhileContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix4}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix4(BoppiParser.Infix4Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code infix5}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitInfix5(BoppiParser.Infix5Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code call}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitCall(BoppiParser.CallContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code number}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitNumber(BoppiParser.NumberContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code funcDeclare}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitFuncDeclare(BoppiParser.FuncDeclareContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code char}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitChar(BoppiParser.CharContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code block}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitBlock(BoppiParser.BlockContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code write}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitWrite(BoppiParser.WriteContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code if}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitIf(BoppiParser.IfContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code prefix1}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitPrefix1(BoppiParser.Prefix1Context ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code assign}
|
||||
* labeled alternative in {@link BoppiParser#singleExpr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAssign(BoppiParser.AssignContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BoppiParser#type}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitType(BoppiParser.TypeContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link BoppiParser#variable}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitVariable(BoppiParser.VariableContext ctx);
|
||||
}
|
|
@ -1,14 +1,39 @@
|
|||
package pp.s1184725.boppi.test;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
/**
|
||||
* Test suite for all Boppi compiler stages and language features
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ CheckerTest.class, GeneratorTest.class, ParserTest.class })
|
||||
public class AllTests {
|
||||
static final Path directory = Paths.get("src/pp/s1184725/boppi/test/programs/");
|
||||
/**
|
||||
* The location of test programs
|
||||
*/
|
||||
public static final Path directory = Paths
|
||||
.get("src/" + AllTests.class.getPackage().getName().replaceAll("\\.", "/") + "/programs/");
|
||||
|
||||
/**
|
||||
* The level of error reporting to use for the tests. Can be changed to
|
||||
* include finer tests.
|
||||
*/
|
||||
public static Level logLevel = Level.SEVERE;
|
||||
|
||||
/**
|
||||
* Runs a test with warnings enabled.
|
||||
*
|
||||
* @param test
|
||||
* the test to run
|
||||
*/
|
||||
public static void withWarnings(Runnable test) {
|
||||
logLevel = Level.WARNING;
|
||||
test.run();
|
||||
logLevel = Level.SEVERE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ import org.junit.Test;
|
|||
|
||||
import pp.s1184725.boppi.ToolChain;
|
||||
|
||||
/**
|
||||
* Test cases for the semantic checking stage for all language features.
|
||||
*/
|
||||
public class CheckerTest {
|
||||
private List<LogRecord> log;
|
||||
|
||||
|
@ -25,88 +28,98 @@ public class CheckerTest {
|
|||
private void check(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(AllTests.logLevel);
|
||||
|
||||
ToolChain.getAnnotations(ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program(), logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct basic expressions
|
||||
*/
|
||||
@Test
|
||||
public void correctExpressionTest() {
|
||||
checkFile("simpleExpression.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic expressions with type errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongExpressionTest() {
|
||||
checkString("+true");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("5 || true");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("6 + 'c'");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("4 + print(5, 6)");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("print(print(3, 5))");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct variable use
|
||||
*/
|
||||
@Test
|
||||
public void correctVariableTest() {
|
||||
checkFile("simpleVariable.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Variable use with type errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongVariableTest() {
|
||||
checkString("var bool name; name := 5");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("undefinedName");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("var undefinedType name; 1");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("var bool endsWithDeclaration;");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("var bool var1; var var1 var2; var2 := 'c' ");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct variable scoping
|
||||
*/
|
||||
@Test
|
||||
public void correctScopeTest() {
|
||||
checkFile("simpleScope.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Variable redeclaring and out-of-scope errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongScopeTest() {
|
||||
checkString("var bool var1; var bool var1; 1");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("var bool var1; var char var1; 1");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("{ var int var1; var1 := 4}; var int var2; var1");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct if-else and loop use
|
||||
*/
|
||||
@Test
|
||||
public void correctConditionalTest() {
|
||||
checkFile("if.boppi");
|
||||
|
@ -116,6 +129,9 @@ public class CheckerTest {
|
|||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct function declaration and calls
|
||||
*/
|
||||
@Test
|
||||
public void correctFunctionTest() {
|
||||
checkString("function int id(int a) a; 1");
|
||||
|
@ -124,7 +140,7 @@ public class CheckerTest {
|
|||
checkString("function int id(int a) a; id(1); 1");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
checkString("var int a; function int const(int b) a; 1");
|
||||
checkString("var int a; function int const() a; 1");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
checkString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
|
@ -137,18 +153,18 @@ public class CheckerTest {
|
|||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Function use with type errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongFunctionTest() {
|
||||
checkString("function int add(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("function char add(int a, int b) a+b; print(add(4, 5))");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
checkString("function int add(int a, int b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@ import pp.iloc.Simulator;
|
|||
import pp.iloc.model.Program;
|
||||
import pp.s1184725.boppi.*;
|
||||
|
||||
/**
|
||||
* Test cases for the code generating stage for all language features.
|
||||
*/
|
||||
public class GeneratorTest {
|
||||
private List<LogRecord> log;
|
||||
private String[] out;
|
||||
private Level logLevel = Level.SEVERE;
|
||||
|
||||
private void compileAndRunString(String code, String... input) {
|
||||
compileAndRun(ToolChain.getCharStream(code), String.join("\n", input) + "\n");
|
||||
|
@ -31,7 +33,7 @@ public class GeneratorTest {
|
|||
private void compileAndRun(CharStream stream, String input) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(logLevel);
|
||||
logger.setLevel(AllTests.logLevel);
|
||||
|
||||
ParseTree ast = ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
Annotations annotations = ToolChain.getAnnotations(ast, logger);
|
||||
|
@ -63,15 +65,26 @@ public class GeneratorTest {
|
|||
Simulator.DEBUG = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct basic expressions
|
||||
*/
|
||||
@Test
|
||||
public void correctExpressionTest() {
|
||||
compileAndRunFile("simpleExpression.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
compileAndRunString(StringUtils.repeat("1+(", 8) + "1" + StringUtils.repeat(")", 8));
|
||||
assertThat(log, is(empty()));
|
||||
int n = 12;
|
||||
String expression = StringUtils.repeat("1+(", n) + "1" + StringUtils.repeat(")", n);
|
||||
AllTests.withWarnings(() -> {
|
||||
compileAndRunString("print(" + expression + ")", "" + n);
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.WARNING));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic expression with run-time error
|
||||
*/
|
||||
@Test
|
||||
public void wrongExpressionTest() {
|
||||
compileAndRunString("1/0");
|
||||
|
@ -79,12 +92,18 @@ public class GeneratorTest {
|
|||
assertThat(log.get(0).getMessage(), containsString("zero"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct variable use
|
||||
*/
|
||||
@Test
|
||||
public void correctVariableTest() {
|
||||
compileAndRunFile("simpleVariable.boppi");
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct evaluation of basic programs
|
||||
*/
|
||||
@Test
|
||||
public void basicPrograms() {
|
||||
compileAndRunString("print(5*3)");
|
||||
|
@ -112,6 +131,9 @@ public class GeneratorTest {
|
|||
assertThat(out, is(arrayContaining("13")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct evaluation of basic functions
|
||||
*/
|
||||
@Test
|
||||
public void correctSimpleFunctionTest() {
|
||||
compileAndRunString("function int id(int a) a; 1");
|
||||
|
@ -136,14 +158,16 @@ public class GeneratorTest {
|
|||
assertThat(out, is(arrayContaining("A")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct evaluation of recursive functions, nested functions and function
|
||||
* passing
|
||||
*/
|
||||
@Test
|
||||
public void correctComplexFunctionTest() {
|
||||
compileAndRunString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
compileAndRunString(
|
||||
"function int factorial(int n) {if (n > 1) then factorial(n-1)*n else 1 fi}; var int n; print(factorial(read(n)))",
|
||||
"5");
|
||||
compileAndRunFile("recursiveFactorial.boppi", "5");
|
||||
assertThat(log, is(empty()));
|
||||
assertThat(out, is(arrayContaining("120")));
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.*;
|
||||
import pp.s1184725.boppi.*;
|
||||
|
||||
/**
|
||||
* Test cases for the parsing stage for all language features.
|
||||
*/
|
||||
public class ParserTest {
|
||||
private List<LogRecord> log;
|
||||
|
||||
|
@ -23,69 +26,80 @@ public class ParserTest {
|
|||
private void parse(CharStream stream) {
|
||||
Logger logger = Logger.getAnonymousLogger();
|
||||
log = ToolChain.makeListLog(logger);
|
||||
logger.setLevel(AllTests.logLevel);
|
||||
|
||||
ToolChain.getParser(ToolChain.getLexer(stream, logger), logger).program();
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct basic expressions
|
||||
*/
|
||||
@Test
|
||||
public void correctExpressionTest() {
|
||||
parseFile("simpleExpression.boppi");
|
||||
assertThat(log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic expressions with syntax errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongExpressionTest() {
|
||||
parseString("");
|
||||
assertThat(log, not(empty()));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("~");
|
||||
assertThat(log, not(empty()));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("0A");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("do");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("true true");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct variable use
|
||||
*/
|
||||
@Test
|
||||
public void correctVariableTest() {
|
||||
parseFile("simpleVariable.boppi");
|
||||
assertThat(log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Variable use with syntax errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongVariableTest() {
|
||||
parseString("var");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("var bool 5");
|
||||
assertThat(log, hasSize(1));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("var 'c' varname");
|
||||
assertThat(log, not(empty()));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
|
||||
parseString("var bool; true true;");
|
||||
assertThat(log, hasSize(2));
|
||||
assertThat(log.get(0).getLevel(), is(Level.SEVERE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct variable scoping
|
||||
*/
|
||||
@Test
|
||||
public void correctScopeTest() {
|
||||
parseFile("simpleScope.boppi");
|
||||
assertThat(log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct if-else and loop use
|
||||
*/
|
||||
@Test
|
||||
public void correctConditionalTest() {
|
||||
parseFile("if.boppi");
|
||||
|
@ -95,4 +109,42 @@ public class ParserTest {
|
|||
assertThat(log, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct function declaration and calls
|
||||
*/
|
||||
@Test
|
||||
public void correctFunctionTest() {
|
||||
parseString("function int id(int a) a; 1");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
parseString("function int id(int a) a; id(1)");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
parseString("var int a; a := 1; function int const() a; const()");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
parseString("function int add(int a, int b) a+b; print(add(4, 5)+1)");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
parseString("function char const(char a, char b) a; print(const('A', 'T'))");
|
||||
assertThat(log, is(empty()));
|
||||
|
||||
parseString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}");
|
||||
assertThat(log, is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Function use with syntax errors
|
||||
*/
|
||||
@Test
|
||||
public void wrongFunctionTest() {
|
||||
parseString("function doNothing(int a, char b) a+b; print(add(4, 'T')+1)");
|
||||
assertThat(log, hasSize(1));
|
||||
|
||||
parseString("function char add(int a, int b);");
|
||||
assertThat(log, hasSize(1));
|
||||
|
||||
parseString("function int add(int a, int b) a+b; add(4,)");
|
||||
assertThat(log, hasSize(1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
function int factorial(int n) {
|
||||
if (n > 1) then
|
||||
factorial(n-1)*n
|
||||
else
|
||||
1
|
||||
fi
|
||||
};
|
||||
|
||||
var int n;
|
||||
|
||||
print(factorial(read(n)))
|
Loading…
Reference in New Issue