diff --git a/src/main/java/dk/camelot64/kickc/parser/ExpressionParser.java b/src/main/java/dk/camelot64/kickc/parser/ExpressionParser.java new file mode 100644 index 000000000..a94a09d71 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/parser/ExpressionParser.java @@ -0,0 +1,35 @@ +package dk.camelot64.kickc.parser; + +import dk.camelot64.kickc.model.CompileError; +import org.antlr.v4.runtime.*; + + +/** + * Parser for C-expressions. + *

+ * Used by #if in the preprocessor + */ +public class ExpressionParser { + + /** + * Parse an expression + * + * @param tokenSource The tokens to parse + * @return The parsed expression + */ + public static KickCParser.ExprContext parseExpression(TokenSource tokenSource) { + CParser cParser = new CParser(null); + KickCParser kickCParser = new KickCParser(new CommonTokenStream(tokenSource), cParser); + kickCParser.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + //StatementSource subSource = + // new StatementSource(source.getFileName(), source.getLineNumber() + line, source.getCode(), source.getStartIndex(), source.getStopIndex()); + throw new CompileError("Error parsing expression " + msg); + } + }); + kickCParser.setBuildParseTree(true); + return kickCParser.expr(); + } + +} diff --git a/src/test/java/dk/camelot64/kickc/parsing/TestExpressionParser.java b/src/test/java/dk/camelot64/kickc/parsing/TestExpressionParser.java new file mode 100644 index 000000000..14c6c8409 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/parsing/TestExpressionParser.java @@ -0,0 +1,73 @@ +package dk.camelot64.kickc.parsing; + +import dk.camelot64.kickc.parser.*; +import junit.framework.TestCase; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CodePointCharStream; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; + +public class TestExpressionParser { + + /** + * Test the ExpressionParser + */ + @Test + public void testExpressionParser() { + assertExpression("1", "1"); + assertExpression("1+1", "+(1,1)"); + assertExpression("1+1*-2", "+(1,*(1,-(2)))"); + assertExpression("(1+1)*2", "*([+(1,1)],2)"); + assertExpression("FIELDS*2 exprVisitor = new ExprPrinter(); + final String exprOut = exprVisitor.visit(exprContext); + TestCase.assertEquals("Expression output does not match ", expected, exprOut); + } + + + /** Prints the expression. */ + private static class ExprPrinter extends KickCParserBaseVisitor { + + @Override + public String visitExprBinary(KickCParser.ExprBinaryContext ctx) { + final String left = this.visit(ctx.expr(0)); + String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); + final String right = this.visit(ctx.expr(1)); + return op+"("+left+","+right+")"; + } + + @Override + public String visitExprUnary(KickCParser.ExprUnaryContext ctx) { + String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); + final String right = this.visit(ctx.expr()); + return op+"("+right+")"; + } + + @Override + public String visitExprPar(KickCParser.ExprParContext ctx) { + final String sub = this.visit(ctx.commaExpr()); + return "["+sub+"]"; + } + + @Override + public String visitExprNumber(KickCParser.ExprNumberContext ctx) { + return ctx.NUMBER().getText(); + } + + @Override + public String visitExprId(KickCParser.ExprIdContext ctx) { + return ctx.NAME().getText(); + } + } + +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestKickAssRun.java b/src/test/java/dk/camelot64/kickc/test/TestKickAssRun.java index 237fe0a86..daad4301e 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestKickAssRun.java +++ b/src/test/java/dk/camelot64/kickc/test/TestKickAssRun.java @@ -14,6 +14,9 @@ import java.nio.file.Paths; public class TestKickAssRun { + /** + * Test running KickAsm assembler to compile an ASM file + */ @Test public void testKickAssRun() throws IOException, URISyntaxException { ReferenceHelper asmHelper = new ReferenceHelperFolder("src/test/java/dk/camelot64/kickc/test/");