mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-10-21 02:24:34 +00:00
Added an expression parser to use for #if. #169
This commit is contained in:
parent
88b2cd86c2
commit
263987f059
@ -0,0 +1,35 @@
|
|||||||
|
package dk.camelot64.kickc.parser;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for C-expressions.
|
||||||
|
* <p>
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<MAX", "<(*(FIELDS,2),MAX)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertExpression(String expr, String expected) {
|
||||||
|
CodePointCharStream fragmentCharStream = CharStreams.fromString(expr);
|
||||||
|
CParser cParser = new CParser(null);
|
||||||
|
KickCLexer kickCLexer = new KickCLexer(fragmentCharStream, cParser);
|
||||||
|
KickCParser.ExprContext exprContext = ExpressionParser.parseExpression(kickCLexer);
|
||||||
|
final KickCParserBaseVisitor<String> 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<String> {
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,9 @@ import java.nio.file.Paths;
|
|||||||
|
|
||||||
public class TestKickAssRun {
|
public class TestKickAssRun {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test running KickAsm assembler to compile an ASM file
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testKickAssRun() throws IOException, URISyntaxException {
|
public void testKickAssRun() throws IOException, URISyntaxException {
|
||||||
ReferenceHelper asmHelper = new ReferenceHelperFolder("src/test/java/dk/camelot64/kickc/test/");
|
ReferenceHelper asmHelper = new ReferenceHelperFolder("src/test/java/dk/camelot64/kickc/test/");
|
||||||
|
Loading…
Reference in New Issue
Block a user