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 {
|
||||
|
||||
/**
|
||||
* 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/");
|
||||
|
Loading…
Reference in New Issue
Block a user