From a908e4f1cadef0b0fa4cee8303cba38a425a0981 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard Date: Fri, 14 Jul 2017 12:13:16 +0200 Subject: [PATCH] Proper implementation of pre-modifiers (++/--) --- .../kickc/asm/fragment/aby=aby_plus_zpby1.asm | 2 + .../kickc/asm/fragment/zpby1=_inc_zpby1.asm | 1 + .../icl/Pass1GenerateStatementSequence.java | 82 +++++-- .../kickc/icl/Pass3RegisterAllocation.java | 16 +- src/dk/camelot64/kickc/parser/KickC.g4 | 1 + .../kickc/parser/KickCBaseListener.java | 12 + .../kickc/parser/KickCBaseVisitor.java | 7 + .../camelot64/kickc/parser/KickCListener.java | 12 + .../camelot64/kickc/parser/KickCParser.java | 220 +++++++++++------- .../camelot64/kickc/parser/KickCVisitor.java | 7 + src/dk/camelot64/kickc/test/flipper-rex2.kc | 18 +- src/dk/camelot64/kickc/test/postinc.kc | 2 +- 12 files changed, 252 insertions(+), 128 deletions(-) create mode 100644 src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_zpby1.asm create mode 100644 src/dk/camelot64/kickc/asm/fragment/zpby1=_inc_zpby1.asm diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_zpby1.asm new file mode 100644 index 000000000..b4d3dbf05 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_zpby1.asm @@ -0,0 +1,2 @@ +clc +adc {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=_inc_zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=_inc_zpby1.asm new file mode 100644 index 000000000..d28af0f96 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=_inc_zpby1.asm @@ -0,0 +1 @@ +inc {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index 466550956..1920f64af 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -70,15 +70,17 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtExpr(KickCParser.StmtExprContext ctx) { + PrePostModifierHandler.addPreModifiers(this, ctx.expr()); this.visit(ctx.expr()); - PostModifierHandler.addPostModifiers(this, ctx.expr()); + PrePostModifierHandler.addPostModifiers(this, ctx.expr()); return null; } @Override public Void visitStmtIfElse(KickCParser.StmtIfElseContext ctx) { + PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); - PostModifierHandler.addPostModifiers(this, ctx.expr()); + PrePostModifierHandler.addPostModifiers(this, ctx.expr()); Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate(); Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel); @@ -112,8 +114,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel); sequence.addStatement(beginJumpTarget); + PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); - PostModifierHandler.addPostModifiers(this, ctx.expr()); + PrePostModifierHandler.addPostModifiers(this, ctx.expr()); Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel); sequence.addStatement(doJmpStmt); Statement endJmpStmt = new StatementJump(endJumpLabel); @@ -136,8 +139,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { if (ctx.stmt() != null) { this.visit(ctx.stmt()); } + PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); - PostModifierHandler.addPostModifiers(this, ctx.expr()); + PrePostModifierHandler.addPostModifiers(this, ctx.expr()); Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel); sequence.addStatement(doJmpStmt); return null; @@ -196,10 +200,11 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { KickCParser.ExprContext exprCtx = ctx.expr(); RValue rValue = null; if (exprCtx != null) { + PrePostModifierHandler.addPreModifiers(this, exprCtx); rValue = (RValue) this.visit(exprCtx); Variable returnVar = procedure.getVariable("return"); sequence.addStatement(new StatementAssignment(returnVar, rValue)); - PostModifierHandler.addPostModifiers(this, exprCtx); + PrePostModifierHandler.addPostModifiers(this, exprCtx); } Label returnLabel = procedure.getLabel("@return"); sequence.addStatement(new StatementJump(returnLabel)); @@ -214,21 +219,23 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { SymbolType type = (SymbolType) visit(ctx.typeDecl()); VariableUnversioned lValue = getCurrentSymbols().addVariable(ctx.NAME().getText(), type); if (ctx.initializer() != null) { + PrePostModifierHandler.addPreModifiers(this, ctx.initializer()); RValue rValue = (RValue) visit(ctx.initializer()); Statement stmt = new StatementAssignment(lValue, rValue); sequence.addStatement(stmt); - PostModifierHandler.addPostModifiers(this, ctx.initializer()); + PrePostModifierHandler.addPostModifiers(this, ctx.initializer()); } return null; } @Override public Void visitStmtAssignment(KickCParser.StmtAssignmentContext ctx) { + PrePostModifierHandler.addPreModifiers(this, ctx); LValue lValue = (LValue) visit(ctx.lvalue()); RValue rValue = (RValue) this.visit(ctx.expr()); Statement stmt = new StatementAssignment(lValue, rValue); sequence.addStatement(stmt); - PostModifierHandler.addPostModifiers(this, ctx); + PrePostModifierHandler.addPostModifiers(this, ctx); return null; } @@ -376,6 +383,12 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { return tmpVar; } + @Override + public Object visitExprPreMod(KickCParser.ExprPreModContext ctx) { + RValue child = (RValue) this.visit(ctx.expr()); + return child; + } + @Override public Object visitExprPostMod(KickCParser.ExprPostModContext ctx) { RValue child = (RValue) this.visit(ctx.expr()); @@ -396,28 +409,47 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { return sequence; } - private static class PostModifierHandler extends KickCBaseVisitor { + private static class PrePostModifierHandler extends KickCBaseVisitor { - private List postMods; + private List postMods; + private List preMods; private Pass1GenerateStatementSequence mainParser; - public PostModifierHandler(Pass1GenerateStatementSequence mainParser) { + public PrePostModifierHandler(Pass1GenerateStatementSequence mainParser) { this.mainParser = mainParser; + preMods = new ArrayList<>(); postMods = new ArrayList<>(); } - public List getPostMods() { + public List getPreMods() { + return preMods; + } + + public List getPostMods() { return postMods; } public static void addPostModifiers(Pass1GenerateStatementSequence parser, ParserRuleContext ctx) { - PostModifierHandler postModifierHandler = new PostModifierHandler(parser); - postModifierHandler.visit(ctx); - List postMods = postModifierHandler.getPostMods(); - for (PostMod mod : postMods) { + PrePostModifierHandler prePostModifierHandler = new PrePostModifierHandler(parser); + prePostModifierHandler.visit(ctx); + List modifiers = prePostModifierHandler.getPostMods(); + addModifierStatements(parser, modifiers); + } + + public static void addPreModifiers(Pass1GenerateStatementSequence parser, ParserRuleContext ctx) { + PrePostModifierHandler modifierHandler = new PrePostModifierHandler(parser); + modifierHandler.visit(ctx); + List modifiers = modifierHandler.getPreMods(); + addModifierStatements(parser, modifiers); + } + + private static void addModifierStatements( + Pass1GenerateStatementSequence parser, + List modifiers) { + for (PrePostModifier mod : modifiers) { Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child); parser.sequence.addStatement(stmt); - System.out.println("Adding postmod "+stmt); + System.out.println("Adding pre/post-modifier "+stmt); } } @@ -426,16 +458,26 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { RValue child = (RValue) mainParser.visit(ctx.expr()); String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); Operator operator = new Operator(op); - PostMod postMod = new PostMod(child, operator); - postMods.add(postMod); + PrePostModifier modifier = new PrePostModifier(child, operator); + postMods.add(modifier); return null; } - private static class PostMod { + @Override + public Void visitExprPreMod(KickCParser.ExprPreModContext ctx) { + RValue child = (RValue) mainParser.visit(ctx.expr()); + String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); + Operator operator = new Operator(op); + PrePostModifier modifier = new PrePostModifier(child, operator); + preMods.add(modifier); + return null; + } + + private static class PrePostModifier { public RValue child; public Operator operator; - public PostMod(RValue child, Operator operator) { + public PrePostModifier(RValue child, Operator operator) { this.child = child; this.operator = operator; } diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index a16755138..e93eaef6f 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -74,14 +74,21 @@ public class Pass3RegisterAllocation { // Registers for postinc.kc /* - allocation.allocate(symbols.getVariable("c#0"), new RegisterAllocation.RegisterZpByte(101)); - allocation.allocate(symbols.getVariable("c#1"), new RegisterAllocation.RegisterZpByte(101)); - allocation.allocate(symbols.getVariable("c#2"), new RegisterAllocation.RegisterZpByte(101)); + allocation.allocate(symbols.getVariable("c#0"), RegisterAllocation.getRegisterA()); + allocation.allocate(symbols.getVariable("c#1"), RegisterAllocation.getRegisterA()); + allocation.allocate(symbols.getVariable("c#2"), RegisterAllocation.getRegisterA()); + allocation.allocate(symbols.getVariable("b#0"), new RegisterAllocation.RegisterZpByte(102)); + allocation.allocate(symbols.getVariable("b#1"), new RegisterAllocation.RegisterZpByte(102)); + allocation.allocate(symbols.getVariable("b#2"), new RegisterAllocation.RegisterZpByte(102)); allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterZpByte(101)); + allocation.allocate(symbols.getVariable("a#0"), new RegisterAllocation.RegisterZpByte(103)); + allocation.allocate(symbols.getVariable("a#1"), new RegisterAllocation.RegisterZpByte(103)); + allocation.allocate(symbols.getVariable("a#2"), new RegisterAllocation.RegisterZpByte(103)); + allocation.allocate(symbols.getVariable("$0"), RegisterAllocation.getRegisterA()); allocation.allocate(symbols.getVariable("i#0"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("i#2"), RegisterAllocation.getRegisterX()); - */ + */ // Optimal Registers for flipper-rex2.kc allocation.allocate(symbols.getVariable("plot::i#0"), RegisterAllocation.getRegisterX()); @@ -139,7 +146,6 @@ public class Pass3RegisterAllocation { allocation.allocate(symbols.getVariable("c#2"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("c#3"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("c#4"), RegisterAllocation.getRegisterX()); - symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/parser/KickC.g4 b/src/dk/camelot64/kickc/parser/KickC.g4 index 79a0eafaf..c4933ed3a 100644 --- a/src/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/dk/camelot64/kickc/parser/KickC.g4 @@ -50,6 +50,7 @@ expr | NAME '(' parameterList? ')' #exprCall | '(' typeDecl ')' expr #exprCast | expr '[' expr ']' #exprArray + | ('--' | '++' ) expr #exprPreMod | expr ('--' | '++' )#exprPostMod | ('+' | '-' | 'not' | '!' | '&' | '*') expr #exprUnary | expr ('>>' | '<<' ) expr #exprBinary diff --git a/src/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/dk/camelot64/kickc/parser/KickCBaseListener.java index 0fee04348..7d571eb8b 100644 --- a/src/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -299,6 +299,18 @@ public class KickCBaseListener implements KickCListener { *

The default implementation does nothing.

*/ @Override public void exitExprCall(KickCParser.ExprCallContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterExprPreMod(KickCParser.ExprPreModContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitExprPreMod(KickCParser.ExprPreModContext ctx) { } /** * {@inheritDoc} * diff --git a/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java index 4ee2523ae..378f966b1 100644 --- a/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -179,6 +179,13 @@ public class KickCBaseVisitor extends AbstractParseTreeVisitor implements * {@link #visitChildren} on {@code ctx}.

*/ @Override public T visitExprCall(KickCParser.ExprCallContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExprPreMod(KickCParser.ExprPreModContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/src/dk/camelot64/kickc/parser/KickCListener.java b/src/dk/camelot64/kickc/parser/KickCListener.java index f13cd0805..2c8b1a9e7 100644 --- a/src/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/dk/camelot64/kickc/parser/KickCListener.java @@ -287,6 +287,18 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitExprCall(KickCParser.ExprCallContext ctx); + /** + * Enter a parse tree produced by the {@code exprPreMod} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void enterExprPreMod(KickCParser.ExprPreModContext ctx); + /** + * Exit a parse tree produced by the {@code exprPreMod} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + */ + void exitExprPreMod(KickCParser.ExprPreModContext ctx); /** * Enter a parse tree produced by the {@code exprBinary} * labeled alternative in {@link KickCParser#expr}. diff --git a/src/dk/camelot64/kickc/parser/KickCParser.java b/src/dk/camelot64/kickc/parser/KickCParser.java index e1d4c738a..1b3b1bfcf 100644 --- a/src/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/dk/camelot64/kickc/parser/KickCParser.java @@ -191,7 +191,7 @@ public class KickCParser extends Parser { setState(26); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0) ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0) ); } } catch (RecognitionException re) { @@ -431,7 +431,7 @@ public class KickCParser extends Parser { setState(30); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { setState(29); stmtSeq(); @@ -469,7 +469,7 @@ public class KickCParser extends Parser { setState(42); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << T__4) | (1L << T__7) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << SIMPLETYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { setState(41); stmtSeq(); @@ -609,7 +609,7 @@ public class KickCParser extends Parser { setState(89); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { setState(88); expr(0); @@ -871,7 +871,7 @@ public class KickCParser extends Parser { setState(113); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { setState(112); expr(0); @@ -965,6 +965,8 @@ public class KickCParser extends Parser { switch (_input.LA(1)) { case T__2: case T__13: + case T__16: + case T__17: case T__18: case T__19: case T__20: @@ -1261,6 +1263,25 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class ExprPreModContext extends ExprContext { + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public ExprPreModContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprPreMod(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprPreMod(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor)visitor).visitExprPreMod(this); + else return visitor.visitChildren(this); + } + } public static class ExprBinaryContext extends ExprContext { public List expr() { return getRuleContexts(ExprContext.class); @@ -1447,7 +1468,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(177); + setState(179); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: @@ -1476,7 +1497,7 @@ public class KickCParser extends Parser { setState(163); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { setState(162); parameterList(); @@ -1499,16 +1520,35 @@ public class KickCParser extends Parser { setState(168); match(T__3); setState(169); - expr(14); + expr(15); } break; case 4: { - _localctx = new ExprUnaryContext(_localctx); + _localctx = new ExprPreModContext(_localctx); _ctx = _localctx; _prevctx = _localctx; setState(171); _la = _input.LA(1); + if ( !(_la==T__16 || _la==T__17) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(172); + expr(13); + } + break; + case 5: + { + _localctx = new ExprUnaryContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(173); + _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) ) { _errHandler.recoverInline(this); } @@ -1517,49 +1557,49 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(172); + setState(174); expr(11); } break; - case 5: - { - _localctx = new ExprIdContext(_localctx); - _ctx = _localctx; - _prevctx = _localctx; - setState(173); - match(NAME); - } - break; case 6: { - _localctx = new ExprNumberContext(_localctx); + _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(174); - match(NUMBER); + setState(175); + match(NAME); } break; case 7: { - _localctx = new ExprStringContext(_localctx); + _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(175); - match(STRING); + setState(176); + match(NUMBER); } break; case 8: + { + _localctx = new ExprStringContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(177); + match(STRING); + } + break; + case 9: { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(176); + setState(178); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(206); + setState(208); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -1567,16 +1607,16 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(204); + setState(206); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(179); + setState(181); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); - setState(180); + setState(182); _la = _input.LA(1); if ( !(_la==T__23 || _la==T__24) ) { _errHandler.recoverInline(this); @@ -1586,7 +1626,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(181); + setState(183); expr(11); } break; @@ -1594,9 +1634,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(182); + setState(184); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(183); + setState(185); _la = _input.LA(1); if ( !(_la==T__13 || _la==T__25) ) { _errHandler.recoverInline(this); @@ -1606,7 +1646,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(184); + setState(186); expr(10); } break; @@ -1614,9 +1654,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(185); + setState(187); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(186); + setState(188); _la = _input.LA(1); if ( !(_la==T__18 || _la==T__19) ) { _errHandler.recoverInline(this); @@ -1626,7 +1666,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(187); + setState(189); expr(9); } break; @@ -1634,9 +1674,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(188); + setState(190); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(189); + setState(191); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__26) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33) | (1L << T__34))) != 0)) ) { _errHandler.recoverInline(this); @@ -1646,7 +1686,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(190); + setState(192); expr(8); } break; @@ -1654,9 +1694,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(191); + setState(193); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(192); + setState(194); _la = _input.LA(1); if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); @@ -1666,7 +1706,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(193); + setState(195); expr(7); } break; @@ -1674,9 +1714,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(194); + setState(196); if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); - setState(195); + setState(197); _la = _input.LA(1); if ( !(_la==T__37 || _la==T__38) ) { _errHandler.recoverInline(this); @@ -1686,7 +1726,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(196); + setState(198); expr(6); } break; @@ -1694,13 +1734,13 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(197); - if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); - setState(198); - match(T__14); setState(199); - expr(0); + if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); setState(200); + match(T__14); + setState(201); + expr(0); + setState(202); match(T__15); } break; @@ -1708,9 +1748,9 @@ public class KickCParser extends Parser { { _localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(202); + setState(204); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); - setState(203); + setState(205); _la = _input.LA(1); if ( !(_la==T__16 || _la==T__17) ) { _errHandler.recoverInline(this); @@ -1725,7 +1765,7 @@ public class KickCParser extends Parser { } } } - setState(208); + setState(210); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,20,_ctx); } @@ -1775,21 +1815,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(209); + setState(211); expr(0); - setState(214); + setState(216); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(210); + setState(212); match(T__12); - setState(211); + setState(213); expr(0); } } - setState(216); + setState(218); _errHandler.sync(this); _la = _input.LA(1); } @@ -1848,7 +1888,7 @@ public class KickCParser extends Parser { case 8: return precpred(_ctx, 5); case 9: - return precpred(_ctx, 13); + return precpred(_ctx, 14); case 10: return precpred(_ctx, 12); } @@ -1856,7 +1896,7 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\39\u00dc\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\39\u00de\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\3\2\3\2\3\2\3\3\6\3\33\n\3\r\3\16\3\34\3\4\3\4\5\4!\n\4\3\4\3\4\3"+ "\4\3\4\3\4\5\4(\n\4\3\4\3\4\3\4\5\4-\n\4\3\4\3\4\3\4\5\4\62\n\4\3\4\3"+ @@ -1868,13 +1908,13 @@ public class KickCParser extends Parser { "\13\b\3\b\3\b\5\b\u0088\n\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u0092"+ "\n\t\3\t\3\t\3\t\3\t\3\t\7\t\u0099\n\t\f\t\16\t\u009c\13\t\3\n\3\n\3\n"+ "\3\n\3\n\3\n\3\n\3\n\5\n\u00a6\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\5\n\u00b4\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00cf\n\n"+ - "\f\n\16\n\u00d2\13\n\3\13\3\13\3\13\7\13\u00d7\n\13\f\13\16\13\u00da\13"+ - "\13\3\13\2\5\f\20\22\f\2\4\6\b\n\f\16\20\22\24\2\n\4\2\20\20\25\31\3\2"+ - "\32\33\4\2\20\20\34\34\3\2\25\26\3\2\35%\3\2&\'\3\2()\3\2\23\24\2\u00fb"+ + "\3\n\3\n\3\n\3\n\3\n\5\n\u00b6\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00d1"+ + "\n\n\f\n\16\n\u00d4\13\n\3\13\3\13\3\13\7\13\u00d9\n\13\f\13\16\13\u00dc"+ + "\13\13\3\13\2\5\f\20\22\f\2\4\6\b\n\f\16\20\22\24\2\n\3\2\23\24\4\2\20"+ + "\20\25\31\3\2\32\33\4\2\20\20\34\34\3\2\25\26\3\2\35%\3\2&\'\3\2()\2\u00fe"+ "\2\26\3\2\2\2\4\32\3\2\2\2\6^\3\2\2\2\b`\3\2\2\2\nh\3\2\2\2\fk\3\2\2\2"+ - "\16\u0087\3\2\2\2\20\u0091\3\2\2\2\22\u00b3\3\2\2\2\24\u00d3\3\2\2\2\26"+ + "\16\u0087\3\2\2\2\20\u0091\3\2\2\2\22\u00b5\3\2\2\2\24\u00d5\3\2\2\2\26"+ "\27\5\4\3\2\27\30\7\2\2\3\30\3\3\2\2\2\31\33\5\6\4\2\32\31\3\2\2\2\33"+ "\34\3\2\2\2\34\32\3\2\2\2\34\35\3\2\2\2\35\5\3\2\2\2\36 \7\3\2\2\37!\5"+ "\4\3\2 \37\3\2\2\2 !\3\2\2\2!\"\3\2\2\2\"_\7\4\2\2#$\5\f\7\2$%\7\66\2"+ @@ -1905,30 +1945,30 @@ public class KickCParser extends Parser { "\5\22\n\2\u0096\u0097\7\22\2\2\u0097\u0099\3\2\2\2\u0098\u0093\3\2\2\2"+ "\u0099\u009c\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b\21"+ "\3\2\2\2\u009c\u009a\3\2\2\2\u009d\u009e\b\n\1\2\u009e\u009f\7\5\2\2\u009f"+ - "\u00a0\5\22\n\2\u00a0\u00a1\7\6\2\2\u00a1\u00b4\3\2\2\2\u00a2\u00a3\7"+ + "\u00a0\5\22\n\2\u00a0\u00a1\7\6\2\2\u00a1\u00b6\3\2\2\2\u00a2\u00a3\7"+ "\66\2\2\u00a3\u00a5\7\5\2\2\u00a4\u00a6\5\24\13\2\u00a5\u00a4\3\2\2\2"+ - "\u00a5\u00a6\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00b4\7\6\2\2\u00a8\u00a9"+ - "\7\5\2\2\u00a9\u00aa\5\f\7\2\u00aa\u00ab\7\6\2\2\u00ab\u00ac\5\22\n\20"+ - "\u00ac\u00b4\3\2\2\2\u00ad\u00ae\t\2\2\2\u00ae\u00b4\5\22\n\r\u00af\u00b4"+ - "\7\66\2\2\u00b0\u00b4\7-\2\2\u00b1\u00b4\7+\2\2\u00b2\u00b4\7,\2\2\u00b3"+ - "\u009d\3\2\2\2\u00b3\u00a2\3\2\2\2\u00b3\u00a8\3\2\2\2\u00b3\u00ad\3\2"+ - "\2\2\u00b3\u00af\3\2\2\2\u00b3\u00b0\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3"+ - "\u00b2\3\2\2\2\u00b4\u00d0\3\2\2\2\u00b5\u00b6\f\f\2\2\u00b6\u00b7\t\3"+ - "\2\2\u00b7\u00cf\5\22\n\r\u00b8\u00b9\f\13\2\2\u00b9\u00ba\t\4\2\2\u00ba"+ - "\u00cf\5\22\n\f\u00bb\u00bc\f\n\2\2\u00bc\u00bd\t\5\2\2\u00bd\u00cf\5"+ - "\22\n\13\u00be\u00bf\f\t\2\2\u00bf\u00c0\t\6\2\2\u00c0\u00cf\5\22\n\n"+ - "\u00c1\u00c2\f\b\2\2\u00c2\u00c3\t\7\2\2\u00c3\u00cf\5\22\n\t\u00c4\u00c5"+ - "\f\7\2\2\u00c5\u00c6\t\b\2\2\u00c6\u00cf\5\22\n\b\u00c7\u00c8\f\17\2\2"+ - "\u00c8\u00c9\7\21\2\2\u00c9\u00ca\5\22\n\2\u00ca\u00cb\7\22\2\2\u00cb"+ - "\u00cf\3\2\2\2\u00cc\u00cd\f\16\2\2\u00cd\u00cf\t\t\2\2\u00ce\u00b5\3"+ - "\2\2\2\u00ce\u00b8\3\2\2\2\u00ce\u00bb\3\2\2\2\u00ce\u00be\3\2\2\2\u00ce"+ - "\u00c1\3\2\2\2\u00ce\u00c4\3\2\2\2\u00ce\u00c7\3\2\2\2\u00ce\u00cc\3\2"+ - "\2\2\u00cf\u00d2\3\2\2\2\u00d0\u00ce\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1"+ - "\23\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d3\u00d8\5\22\n\2\u00d4\u00d5\7\17"+ - "\2\2\u00d5\u00d7\5\22\n\2\u00d6\u00d4\3\2\2\2\u00d7\u00da\3\2\2\2\u00d8"+ - "\u00d6\3\2\2\2\u00d8\u00d9\3\2\2\2\u00d9\25\3\2\2\2\u00da\u00d8\3\2\2"+ - "\2\30\34 \',\61\67J[^esvx\u0082\u0087\u0091\u009a\u00a5\u00b3\u00ce\u00d0"+ - "\u00d8"; + "\u00a5\u00a6\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00b6\7\6\2\2\u00a8\u00a9"+ + "\7\5\2\2\u00a9\u00aa\5\f\7\2\u00aa\u00ab\7\6\2\2\u00ab\u00ac\5\22\n\21"+ + "\u00ac\u00b6\3\2\2\2\u00ad\u00ae\t\2\2\2\u00ae\u00b6\5\22\n\17\u00af\u00b0"+ + "\t\3\2\2\u00b0\u00b6\5\22\n\r\u00b1\u00b6\7\66\2\2\u00b2\u00b6\7-\2\2"+ + "\u00b3\u00b6\7+\2\2\u00b4\u00b6\7,\2\2\u00b5\u009d\3\2\2\2\u00b5\u00a2"+ + "\3\2\2\2\u00b5\u00a8\3\2\2\2\u00b5\u00ad\3\2\2\2\u00b5\u00af\3\2\2\2\u00b5"+ + "\u00b1\3\2\2\2\u00b5\u00b2\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b5\u00b4\3\2"+ + "\2\2\u00b6\u00d2\3\2\2\2\u00b7\u00b8\f\f\2\2\u00b8\u00b9\t\4\2\2\u00b9"+ + "\u00d1\5\22\n\r\u00ba\u00bb\f\13\2\2\u00bb\u00bc\t\5\2\2\u00bc\u00d1\5"+ + "\22\n\f\u00bd\u00be\f\n\2\2\u00be\u00bf\t\6\2\2\u00bf\u00d1\5\22\n\13"+ + "\u00c0\u00c1\f\t\2\2\u00c1\u00c2\t\7\2\2\u00c2\u00d1\5\22\n\n\u00c3\u00c4"+ + "\f\b\2\2\u00c4\u00c5\t\b\2\2\u00c5\u00d1\5\22\n\t\u00c6\u00c7\f\7\2\2"+ + "\u00c7\u00c8\t\t\2\2\u00c8\u00d1\5\22\n\b\u00c9\u00ca\f\20\2\2\u00ca\u00cb"+ + "\7\21\2\2\u00cb\u00cc\5\22\n\2\u00cc\u00cd\7\22\2\2\u00cd\u00d1\3\2\2"+ + "\2\u00ce\u00cf\f\16\2\2\u00cf\u00d1\t\2\2\2\u00d0\u00b7\3\2\2\2\u00d0"+ + "\u00ba\3\2\2\2\u00d0\u00bd\3\2\2\2\u00d0\u00c0\3\2\2\2\u00d0\u00c3\3\2"+ + "\2\2\u00d0\u00c6\3\2\2\2\u00d0\u00c9\3\2\2\2\u00d0\u00ce\3\2\2\2\u00d1"+ + "\u00d4\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d2\u00d3\3\2\2\2\u00d3\23\3\2\2"+ + "\2\u00d4\u00d2\3\2\2\2\u00d5\u00da\5\22\n\2\u00d6\u00d7\7\17\2\2\u00d7"+ + "\u00d9\5\22\n\2\u00d8\u00d6\3\2\2\2\u00d9\u00dc\3\2\2\2\u00da\u00d8\3"+ + "\2\2\2\u00da\u00db\3\2\2\2\u00db\25\3\2\2\2\u00dc\u00da\3\2\2\2\30\34"+ + " \',\61\67J[^esvx\u0082\u0087\u0091\u009a\u00a5\u00b5\u00d0\u00d2\u00da"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/dk/camelot64/kickc/parser/KickCVisitor.java b/src/dk/camelot64/kickc/parser/KickCVisitor.java index 56175d78d..06343039a 100644 --- a/src/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/dk/camelot64/kickc/parser/KickCVisitor.java @@ -174,6 +174,13 @@ public interface KickCVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitExprCall(KickCParser.ExprCallContext ctx); + /** + * Visit a parse tree produced by the {@code exprPreMod} + * labeled alternative in {@link KickCParser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprPreMod(KickCParser.ExprPreModContext ctx); /** * Visit a parse tree produced by the {@code exprBinary} * labeled alternative in {@link KickCParser#expr}. diff --git a/src/dk/camelot64/kickc/test/flipper-rex2.kc b/src/dk/camelot64/kickc/test/flipper-rex2.kc index 2497db2d2..a39f65d76 100644 --- a/src/dk/camelot64/kickc/test/flipper-rex2.kc +++ b/src/dk/camelot64/kickc/test/flipper-rex2.kc @@ -21,8 +21,7 @@ void prepare() { byte i=0; do { buffer[i] = i; - i++; - } while (i!=0) + } while (++i!=0) } // Flip buffer @@ -35,16 +34,13 @@ void flip() { do { buffer2[dstIdx] = buffer[srcIdx++]; dstIdx = dstIdx+16; - c--; - } while(c!=0) + } while(--c!=0) dstIdx--; - r--; - } while(r!=0) + } while(--r!=0) byte i=0; do { buffer[i] = buffer2[i]; - i++; - } while (i!=0) + } while (++i!=0) } // Plot buffer on screen @@ -56,9 +52,7 @@ void plot() { byte x=0; do { line[x] = buffer[i++]; - x++; - } while(x<16) + } while(++x<16) line = line+40; - y--; - } while(y!=0) + } while(--y!=0) } \ No newline at end of file diff --git a/src/dk/camelot64/kickc/test/postinc.kc b/src/dk/camelot64/kickc/test/postinc.kc index 231f5cf06..709edc075 100644 --- a/src/dk/camelot64/kickc/test/postinc.kc +++ b/src/dk/camelot64/kickc/test/postinc.kc @@ -3,6 +3,6 @@ byte b = 1; byte i=0; byte c = 0; do { - c = c + a++ + b++; + c = c + a++ + ++b; i++; } while (i<3) \ No newline at end of file