added tuple types, added javadoc for all public attributes

This commit is contained in:
User 2017-07-17 22:46:18 +02:00
parent 11da0a0826
commit a1257c237b
20 changed files with 337 additions and 2022 deletions

View File

@ -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;
/**

View File

@ -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

View File

@ -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)));
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -1,5 +1,8 @@
package pp.s1184725.boppi;
/**
* Generic type interface. All types must have at least these properties.
*/
public interface Type {
/**

View File

@ -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: ',';

View File

@ -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

View File

@ -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); }
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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")));

View File

@ -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));
}
}

View File

@ -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)))