1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Added support for void parameter lists. Closes #161

This commit is contained in:
jespergravgaard 2019-04-08 23:27:05 +02:00
parent 9a9e4f456e
commit c3849c78b0
10 changed files with 714 additions and 593 deletions

View File

@ -39,7 +39,9 @@ parameterListDecl
: parameterDecl (',' parameterDecl)* ; : parameterDecl (',' parameterDecl)* ;
parameterDecl parameterDecl
: directive* typeDecl directive* NAME ; : directive* typeDecl directive* NAME #parameterDeclType
| SIMPLETYPE #parameterDeclVoid
;
directive directive
: 'const' #directiveConst : 'const' #directiveConst

View File

@ -124,13 +124,25 @@ public class KickCBaseListener implements KickCListener {
* *
* <p>The default implementation does nothing.</p> * <p>The default implementation does nothing.</p>
*/ */
@Override public void enterParameterDecl(KickCParser.ParameterDeclContext ctx) { } @Override public void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* <p>The default implementation does nothing.</p> * <p>The default implementation does nothing.</p>
*/ */
@Override public void exitParameterDecl(KickCParser.ParameterDeclContext ctx) { } @Override public void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@ -80,7 +80,14 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* <p>The default implementation returns the result of calling * <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p> * {@link #visitChildren} on {@code ctx}.</p>
*/ */
@Override public T visitParameterDecl(KickCParser.ParameterDeclContext ctx) { return visitChildren(ctx); } @Override public T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { return visitChildren(ctx); }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@ -98,15 +98,29 @@ public interface KickCListener extends ParseTreeListener {
*/ */
void exitParameterListDecl(KickCParser.ParameterListDeclContext ctx); void exitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
/** /**
* Enter a parse tree produced by {@link KickCParser#parameterDecl}. * Enter a parse tree produced by the {@code parameterDeclType}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree * @param ctx the parse tree
*/ */
void enterParameterDecl(KickCParser.ParameterDeclContext ctx); void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
/** /**
* Exit a parse tree produced by {@link KickCParser#parameterDecl}. * Exit a parse tree produced by the {@code parameterDeclType}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree * @param ctx the parse tree
*/ */
void exitParameterDecl(KickCParser.ParameterDeclContext ctx); void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
/**
* Enter a parse tree produced by the {@code parameterDeclVoid}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
/**
* Exit a parse tree produced by the {@code parameterDeclVoid}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
/** /**
* Enter a parse tree produced by the {@code directiveConst} * Enter a parse tree produced by the {@code directiveConst}
* labeled alternative in {@link KickCParser#directive}. * labeled alternative in {@link KickCParser#directive}.

File diff suppressed because it is too large Load Diff

View File

@ -65,11 +65,19 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
*/ */
T visitParameterListDecl(KickCParser.ParameterListDeclContext ctx); T visitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
/** /**
* Visit a parse tree produced by {@link KickCParser#parameterDecl}. * Visit a parse tree produced by the {@code parameterDeclType}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree * @param ctx the parse tree
* @return the visitor result * @return the visitor result
*/ */
T visitParameterDecl(KickCParser.ParameterDeclContext ctx); T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
/**
* Visit a parse tree produced by the {@code parameterDeclVoid}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
/** /**
* Visit a parse tree produced by the {@code directiveConst} * Visit a parse tree produced by the {@code directiveConst}
* labeled alternative in {@link KickCParser#directive}. * labeled alternative in {@link KickCParser#directive}.

View File

@ -150,14 +150,25 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) { public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) {
ArrayList<Variable> parameterDecls = new ArrayList<>(); ArrayList<Variable> parameterDecls = new ArrayList<>();
for(KickCParser.ParameterDeclContext parameterDeclCtx : ctx.parameterDecl()) { for(KickCParser.ParameterDeclContext parameterDeclCtx : ctx.parameterDecl()) {
Variable parameterDecl = (Variable) this.visit(parameterDeclCtx); Object parameterDecl = this.visit(parameterDeclCtx);
parameterDecls.add(parameterDecl); if(parameterDecl.equals(SymbolType.VOID)) {
if(ctx.parameterDecl().size() == 1) {
// A single void parameter decl - equals zero parameters
return new ArrayList<>();
} else {
throw new CompileError("Illegal void parameter." , new StatementSource(ctx));
}
} else if(parameterDecl instanceof Variable) {
parameterDecls.add((Variable) parameterDecl);
} else {
throw new CompileError("Unknown parameter " + ctx.getText(), new StatementSource(ctx));
}
} }
return parameterDecls; return parameterDecls;
} }
@Override @Override
public Variable visitParameterDecl(KickCParser.ParameterDeclContext ctx) { public Object visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) {
SymbolType type = (SymbolType) this.visit(ctx.typeDecl()); SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentScope(), type); VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentScope(), type);
// Add directives // Add directives
@ -165,6 +176,14 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
return param; return param;
} }
@Override
public Object visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) {
if(!SymbolType.VOID.getTypeName().equals(ctx.SIMPLETYPE().getText())) {
throw new CompileError("Illegal unnamed parameter " + ctx.SIMPLETYPE().getText(), new StatementSource(ctx));
}
return SymbolType.VOID;
}
@Override @Override
public Object visitDeclKasm(KickCParser.DeclKasmContext ctx) { public Object visitDeclKasm(KickCParser.DeclKasmContext ctx) {
String kasm = ctx.KICKASM().getText(); String kasm = ctx.KICKASM().getText();

View File

@ -32,6 +32,16 @@ public class TestPrograms {
public TestPrograms() { public TestPrograms() {
} }
@Test
public void testIllegalVoidParameter() throws IOException, URISyntaxException {
assertError("illegal-void-parameter", "Illegal void parameter");
}
@Test
public void testIllegalUnnamedParameter() throws IOException, URISyntaxException {
assertError("illegal-unnamed-parameter", "Illegal unnamed parameter");
}
@Test @Test
public void testFire() throws IOException, URISyntaxException { public void testFire() throws IOException, URISyntaxException {
compileAndCompare("examples/fire/fire"); compileAndCompare("examples/fire/fire");

View File

@ -0,0 +1,4 @@
// Tests that the compiler complains if a non-void parameter has no name
void main(char) {
}

View File

@ -0,0 +1,4 @@
// Tests that the compiler complains if a non-void parameter has no name
void main(char c, void) {
}