From 39e5b5a89416b1902c1f25ab0c753d16a1c2464c Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 21 May 2017 12:56:11 +0200 Subject: [PATCH] Added do {} while(). Fixed relative jump labels. Added fib2 & y-usage. --- src/dk/camelot64/kickc/asm/AsmFragment.java | 14 +- .../kickc/asm/fragment/xby_neq_0_then_la1.asm | 2 + .../kickc/asm/fragment/yby=coby1.asm | 1 + .../kickc/asm/fragment/yby=zpby1.asm | 1 + .../asm/fragment/zpby1=yby_plus_zpby2.asm | 4 + .../camelot64/kickc/icl/ControlFlowBlock.java | 8 + .../icl/Pass1GenerateStatementSequence.java | 12 + .../kickc/icl/Pass3RegisterAllocation.java | 6 +- .../kickc/icl/Pass4CodeGeneration.java | 13 +- .../kickc/icl/RegisterAllocation.java | 26 +- src/dk/camelot64/kickc/parser/KickC.g4 | 1 + src/dk/camelot64/kickc/parser/KickC.tokens | 68 ++--- .../kickc/parser/KickCBaseListener.java | 12 + .../kickc/parser/KickCBaseVisitor.java | 7 + src/dk/camelot64/kickc/parser/KickCLexer.java | 247 +++++++++--------- .../camelot64/kickc/parser/KickCLexer.tokens | 68 ++--- .../camelot64/kickc/parser/KickCListener.java | 12 + .../camelot64/kickc/parser/KickCParser.java | 180 ++++++++----- .../camelot64/kickc/parser/KickCVisitor.java | 7 + src/dk/camelot64/kickc/test/Main.java | 13 +- src/dk/camelot64/kickc/test/fib2.kc | 10 + 21 files changed, 437 insertions(+), 275 deletions(-) create mode 100644 src/dk/camelot64/kickc/asm/fragment/xby_neq_0_then_la1.asm create mode 100644 src/dk/camelot64/kickc/asm/fragment/yby=coby1.asm create mode 100644 src/dk/camelot64/kickc/asm/fragment/yby=zpby1.asm create mode 100644 src/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_zpby2.asm create mode 100644 src/dk/camelot64/kickc/test/fib2.kc diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index c1f0aa66f..3df80db4f 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -32,7 +32,7 @@ public class AsmFragment { */ private String signature; - public AsmFragment(StatementConditionalJump conditionalJump, SymbolTable symbols) { + public AsmFragment(StatementConditionalJump conditionalJump, SymbolTable symbols, ControlFlowGraph graph, ControlFlowBlock block) { this.bindings = new HashMap<>(); this.symbols = symbols; StringBuilder signature = new StringBuilder(); @@ -48,7 +48,13 @@ public class AsmFragment { signature.append(bind(conditionalJump.getRValue2())); } signature.append("_then_"); - signature.append(bind(conditionalJump.getDestination())); + Label destination = conditionalJump.getDestination(); + ControlFlowBlock destinationBlock = graph.getBlock(destination); + String destinationLabel = destination.getName(); + if(destinationBlock.hasPhiStatements()) { + destinationLabel = destination.getName()+"_from_"+block.getLabel().getName(); + } + signature.append(bind(new Label(destinationLabel, false))); setSignature(signature.toString()); } @@ -172,6 +178,10 @@ public class AsmFragment { String name = "xby"; bindings.put(name, value); return name; + } else if (RegisterAllocation.RegisterType.REG_Y_BYTE.equals(register.getType())) { + String name = "yby"; + bindings.put(name, value); + return name; } else { throw new RuntimeException("Binding of register type not supported " + register.getType()); } diff --git a/src/dk/camelot64/kickc/asm/fragment/xby_neq_0_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/xby_neq_0_then_la1.asm new file mode 100644 index 000000000..0f99f0508 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby_neq_0_then_la1.asm @@ -0,0 +1,2 @@ +cpx #0 +bne {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/yby=coby1.asm b/src/dk/camelot64/kickc/asm/fragment/yby=coby1.asm new file mode 100644 index 000000000..c9907eace --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/yby=coby1.asm @@ -0,0 +1 @@ +ldy #{coby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/yby=zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/yby=zpby1.asm new file mode 100644 index 000000000..cc9e7b012 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/yby=zpby1.asm @@ -0,0 +1 @@ +ldy {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_zpby2.asm new file mode 100644 index 000000000..56a5f591f --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_zpby2.asm @@ -0,0 +1,4 @@ +tya +clc +adc {zpby2} +sta {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java index 07beaf984..12d411846 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -104,4 +104,12 @@ public class ControlFlowBlock { return label.hashCode(); } + public boolean hasPhiStatements() { + if(statements.size()>0) { + if(statements.get(0) instanceof StatementPhi) { + return true; + } + } + return false; + } } diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index 41bc59f0e..5de45ba40 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -97,6 +97,18 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { return null; } + @Override + public RValue visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { + Label beginJumpLabel = symbolTable.newIntermediateJumpLabel(); + StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel); + sequence.addStatement(beginJumpTarget); + this.visit(ctx.stmt()); + RValue rValue = this.visit(ctx.expr()); + Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel); + sequence.addStatement(doJmpStmt); + return null; + } + @Override public RValue visitStmtAssignment(KickCParser.StmtAssignmentContext ctx) { if(ctx.TYPE()!=null) { diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index be44c4180..05efa95c0 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -23,9 +23,9 @@ public class Pass3RegisterAllocation { } } allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("n1#1"), new RegisterAllocation.RegisterZpByte(8)); - allocation.allocate(symbols.getVariable("n1#2"), new RegisterAllocation.RegisterZpByte(8)); + allocation.allocate(symbols.getVariable("i#2"), RegisterAllocation.getRegisterX()); + allocation.allocate(symbols.getVariable("n1#1"), RegisterAllocation.getRegisterY()); + allocation.allocate(symbols.getVariable("n1#2"), RegisterAllocation.getRegisterY()); symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java index cc8184b7f..08499a86e 100644 --- a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java +++ b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java @@ -2,8 +2,6 @@ package dk.camelot64.kickc.icl; import dk.camelot64.kickc.asm.*; -import java.util.List; - /** * Code Generation of 6502 Assembler from ICL/SSA Control Flow Graph */ @@ -29,7 +27,7 @@ public class Pass4CodeGeneration { // Generate exit ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor(); if (defaultSuccessor != null) { - if(defaultSuccessor.getStatements().size()>0 && defaultSuccessor.getStatements().get(0) instanceof StatementPhi) { + if(defaultSuccessor.hasPhiStatements()) { genBlockPhiTransition(asm, block, defaultSuccessor); } asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getName().replace('@', 'B')); @@ -41,18 +39,18 @@ public class Pass4CodeGeneration { private void genStatements(AsmProgram asm, ControlFlowBlock block) { for (Statement statement : block.getStatements()) { if (!(statement instanceof StatementPhi)) { - genStatement(asm, statement); + genStatement(asm, statement, block); } } } - private void genStatement(AsmProgram asm, Statement statement) { + private void genStatement(AsmProgram asm, Statement statement, ControlFlowBlock block) { if (statement instanceof StatementAssignment) { AsmFragment asmFragment = new AsmFragment((StatementAssignment) statement, symbols); asm.addComment(statement + " // " + asmFragment.getSignature()); asmFragment.generate(asm); } else if (statement instanceof StatementConditionalJump) { - AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, symbols); + AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, symbols, graph, block); asm.addComment(statement + " // " + asmFragment.getSignature()); asmFragment.generate(asm); } else { @@ -61,8 +59,7 @@ public class Pass4CodeGeneration { } private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) { - List statements = block.getStatements(); - if (statements.size() > 0 && (statements.get(0) instanceof StatementPhi)) { + if(block.hasPhiStatements()) { for (ControlFlowBlock predecessor : block.getPredecessors()) { if(block.equals(predecessor.getConditionalSuccessor())) { genBlockPhiTransition(asm, predecessor, block); diff --git a/src/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/dk/camelot64/kickc/icl/RegisterAllocation.java index 683be78ea..69b9069bd 100644 --- a/src/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -36,7 +36,7 @@ public class RegisterAllocation { /** The register type. */ public enum RegisterType { - ZP_BYTE, ZP_BOOL, REG_X_BYTE + ZP_BYTE, ZP_BOOL, REG_Y_BYTE, REG_X_BYTE }; /** A zero page address used as a register for a single byte variable. */ @@ -136,10 +136,34 @@ public class RegisterAllocation { } } + /** The Y register. */ + public static class RegisterYByte implements Register { + @Override + public RegisterType getType() { + return RegisterType.REG_Y_BYTE; + } + + @Override + public String toString() { + return "reg byte y"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + return true; + } + } + public static Register getRegisterX() { return new RegisterXByte(); } + public static Register getRegisterY() { + return new RegisterYByte(); + } + @Override public String toString() { StringBuffer out = new StringBuffer(); diff --git a/src/dk/camelot64/kickc/parser/KickC.g4 b/src/dk/camelot64/kickc/parser/KickC.g4 index 791e091e2..19ad17d2e 100644 --- a/src/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/dk/camelot64/kickc/parser/KickC.g4 @@ -15,6 +15,7 @@ stmt | expr ';' #stmtExpr | 'if' '(' expr ')' stmt ( 'else' stmt )? #stmtIfElse | 'while' '(' expr ')' stmt #stmtWhile + | 'do' stmt 'while' '(' expr ')' #stmtDoWhile ; diff --git a/src/dk/camelot64/kickc/parser/KickC.tokens b/src/dk/camelot64/kickc/parser/KickC.tokens index 69c474e0f..fb63df5b8 100644 --- a/src/dk/camelot64/kickc/parser/KickC.tokens +++ b/src/dk/camelot64/kickc/parser/KickC.tokens @@ -26,20 +26,21 @@ T__24=25 T__25=26 T__26=27 T__27=28 -TYPE=29 -STRING=30 -BOOLEAN=31 -NUMBER=32 -NUMFLOAT=33 -BINFLOAT=34 -DECFLOAT=35 -HEXFLOAT=36 -NUMINT=37 -BININTEGER=38 -DECINTEGER=39 -HEXINTEGER=40 -NAME=41 -WS=42 +T__28=29 +TYPE=30 +STRING=31 +BOOLEAN=32 +NUMBER=33 +NUMFLOAT=34 +BINFLOAT=35 +DECFLOAT=36 +HEXFLOAT=37 +NUMINT=38 +BININTEGER=39 +DECINTEGER=40 +HEXINTEGER=41 +NAME=42 +WS=43 '{'=1 '}'=2 '='=3 @@ -49,22 +50,23 @@ WS=42 ')'=7 'else'=8 'while'=9 -'+'=10 -'-'=11 -'not'=12 -'!'=13 -'*'=14 -'/'=15 -'=='=16 -'!='=17 -'<>'=18 -'<'=19 -'<='=20 -'=<'=21 -'>='=22 -'=>'=23 -'>'=24 -'and'=25 -'&&'=26 -'or'=27 -'||'=28 +'do'=10 +'+'=11 +'-'=12 +'not'=13 +'!'=14 +'*'=15 +'/'=16 +'=='=17 +'!='=18 +'<>'=19 +'<'=20 +'<='=21 +'=<'=22 +'>='=23 +'=>'=24 +'>'=25 +'and'=26 +'&&'=27 +'or'=28 +'||'=29 diff --git a/src/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/dk/camelot64/kickc/parser/KickCBaseListener.java index dd59af9bd..1f24d9c7f 100644 --- a/src/dk/camelot64/kickc/parser/KickCBaseListener.java +++ b/src/dk/camelot64/kickc/parser/KickCBaseListener.java @@ -95,6 +95,18 @@ public class KickCBaseListener implements KickCListener { *

The default implementation does nothing.

*/ @Override public void exitStmtWhile(KickCParser.StmtWhileContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { } /** * {@inheritDoc} * diff --git a/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java index 01e0a560f..bbaa7ecaf 100644 --- a/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java +++ b/src/dk/camelot64/kickc/parser/KickCBaseVisitor.java @@ -60,6 +60,13 @@ public class KickCBaseVisitor extends AbstractParseTreeVisitor implements * {@link #visitChildren} on {@code ctx}.

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

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

+ */ + @Override public T visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * diff --git a/src/dk/camelot64/kickc/parser/KickCLexer.java b/src/dk/camelot64/kickc/parser/KickCLexer.java index 57d8252cc..ffa71b9e2 100644 --- a/src/dk/camelot64/kickc/parser/KickCLexer.java +++ b/src/dk/camelot64/kickc/parser/KickCLexer.java @@ -20,9 +20,9 @@ public class KickCLexer extends Lexer { T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, T__27=28, TYPE=29, STRING=30, BOOLEAN=31, - NUMBER=32, NUMFLOAT=33, BINFLOAT=34, DECFLOAT=35, HEXFLOAT=36, NUMINT=37, - BININTEGER=38, DECINTEGER=39, HEXINTEGER=40, NAME=41, WS=42; + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, TYPE=30, STRING=31, + BOOLEAN=32, NUMBER=33, NUMFLOAT=34, BINFLOAT=35, DECFLOAT=36, HEXFLOAT=37, + NUMINT=38, BININTEGER=39, DECINTEGER=40, HEXINTEGER=41, NAME=42, WS=43; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -35,23 +35,24 @@ public class KickCLexer extends Lexer { "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", - "T__25", "T__26", "T__27", "TYPE", "STRING", "BOOLEAN", "NUMBER", "NUMFLOAT", - "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", - "HEXINTEGER", "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", - "NAME_CHAR", "WS" + "T__25", "T__26", "T__27", "T__28", "TYPE", "STRING", "BOOLEAN", "NUMBER", + "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", + "DECINTEGER", "HEXINTEGER", "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", + "NAME_START", "NAME_CHAR", "WS" }; private static final String[] _LITERAL_NAMES = { null, "'{'", "'}'", "'='", "';'", "'if'", "'('", "')'", "'else'", "'while'", - "'+'", "'-'", "'not'", "'!'", "'*'", "'/'", "'=='", "'!='", "'<>'", "'<'", - "'<='", "'=<'", "'>='", "'=>'", "'>'", "'and'", "'&&'", "'or'", "'||'" + "'do'", "'+'", "'-'", "'not'", "'!'", "'*'", "'/'", "'=='", "'!='", "'<>'", + "'<'", "'<='", "'=<'", "'>='", "'=>'", "'>'", "'and'", "'&&'", "'or'", + "'||'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, "TYPE", "STRING", "BOOLEAN", "NUMBER", "NUMFLOAT", - "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", - "HEXINTEGER", "NAME", "WS" + null, null, null, null, null, null, "TYPE", "STRING", "BOOLEAN", "NUMBER", + "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", + "DECINTEGER", "HEXINTEGER", "NAME", "WS" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -111,121 +112,123 @@ public class KickCLexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2,\u0154\b\1\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2-\u0159\b\1\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\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ - ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3"+ - "\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13"+ - "\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21"+ - "\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\25\3\26\3\26"+ - "\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\32\3\32\3\33"+ - "\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36"+ - "\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36"+ - "\3\36\5\36\u00c5\n\36\3\37\3\37\3\37\3\37\7\37\u00cb\n\37\f\37\16\37\u00ce"+ - "\13\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3 \3 \5 \u00db\n \3!\3!\5!\u00df"+ - "\n!\3\"\3\"\3\"\5\"\u00e4\n\"\3#\3#\3#\3#\3#\5#\u00eb\n#\3#\7#\u00ee\n"+ - "#\f#\16#\u00f1\13#\3#\3#\6#\u00f5\n#\r#\16#\u00f6\3$\7$\u00fa\n$\f$\16"+ - "$\u00fd\13$\3$\3$\6$\u0101\n$\r$\16$\u0102\3%\3%\3%\3%\3%\5%\u010a\n%"+ - "\3%\7%\u010d\n%\f%\16%\u0110\13%\3%\3%\6%\u0114\n%\r%\16%\u0115\3&\3&"+ - "\3&\5&\u011b\n&\3\'\3\'\3\'\6\'\u0120\n\'\r\'\16\'\u0121\3\'\3\'\6\'\u0126"+ - "\n\'\r\'\16\'\u0127\5\'\u012a\n\'\3(\6(\u012d\n(\r(\16(\u012e\3)\3)\3"+ - ")\3)\3)\5)\u0136\n)\3)\6)\u0139\n)\r)\16)\u013a\3*\3*\3+\3+\3,\3,\3-\3"+ - "-\7-\u0145\n-\f-\16-\u0148\13-\3.\3.\3/\3/\3\60\6\60\u014f\n\60\r\60\16"+ - "\60\u0150\3\60\3\60\2\2\61\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25"+ - "\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32"+ - "\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S\2U\2W\2Y+[\2]\2_,"+ - "\3\2\n\3\2$$\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;"+ - "C\\aac|\5\2\13\f\17\17\"\"\2\u016c\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2"+ - "\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3"+ - "\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2"+ - "\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2"+ - "\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2"+ - "\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2"+ - "\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2"+ - "O\3\2\2\2\2Q\3\2\2\2\2Y\3\2\2\2\2_\3\2\2\2\3a\3\2\2\2\5c\3\2\2\2\7e\3"+ - "\2\2\2\tg\3\2\2\2\13i\3\2\2\2\rl\3\2\2\2\17n\3\2\2\2\21p\3\2\2\2\23u\3"+ - "\2\2\2\25{\3\2\2\2\27}\3\2\2\2\31\177\3\2\2\2\33\u0083\3\2\2\2\35\u0085"+ - "\3\2\2\2\37\u0087\3\2\2\2!\u0089\3\2\2\2#\u008c\3\2\2\2%\u008f\3\2\2\2"+ - "\'\u0092\3\2\2\2)\u0094\3\2\2\2+\u0097\3\2\2\2-\u009a\3\2\2\2/\u009d\3"+ - "\2\2\2\61\u00a0\3\2\2\2\63\u00a2\3\2\2\2\65\u00a6\3\2\2\2\67\u00a9\3\2"+ - "\2\29\u00ac\3\2\2\2;\u00c4\3\2\2\2=\u00c6\3\2\2\2?\u00da\3\2\2\2A\u00de"+ - "\3\2\2\2C\u00e3\3\2\2\2E\u00ea\3\2\2\2G\u00fb\3\2\2\2I\u0109\3\2\2\2K"+ - "\u011a\3\2\2\2M\u0129\3\2\2\2O\u012c\3\2\2\2Q\u0135\3\2\2\2S\u013c\3\2"+ - "\2\2U\u013e\3\2\2\2W\u0140\3\2\2\2Y\u0142\3\2\2\2[\u0149\3\2\2\2]\u014b"+ - "\3\2\2\2_\u014e\3\2\2\2ab\7}\2\2b\4\3\2\2\2cd\7\177\2\2d\6\3\2\2\2ef\7"+ - "?\2\2f\b\3\2\2\2gh\7=\2\2h\n\3\2\2\2ij\7k\2\2jk\7h\2\2k\f\3\2\2\2lm\7"+ - "*\2\2m\16\3\2\2\2no\7+\2\2o\20\3\2\2\2pq\7g\2\2qr\7n\2\2rs\7u\2\2st\7"+ - "g\2\2t\22\3\2\2\2uv\7y\2\2vw\7j\2\2wx\7k\2\2xy\7n\2\2yz\7g\2\2z\24\3\2"+ - "\2\2{|\7-\2\2|\26\3\2\2\2}~\7/\2\2~\30\3\2\2\2\177\u0080\7p\2\2\u0080"+ - "\u0081\7q\2\2\u0081\u0082\7v\2\2\u0082\32\3\2\2\2\u0083\u0084\7#\2\2\u0084"+ - "\34\3\2\2\2\u0085\u0086\7,\2\2\u0086\36\3\2\2\2\u0087\u0088\7\61\2\2\u0088"+ - " \3\2\2\2\u0089\u008a\7?\2\2\u008a\u008b\7?\2\2\u008b\"\3\2\2\2\u008c"+ - "\u008d\7#\2\2\u008d\u008e\7?\2\2\u008e$\3\2\2\2\u008f\u0090\7>\2\2\u0090"+ - "\u0091\7@\2\2\u0091&\3\2\2\2\u0092\u0093\7>\2\2\u0093(\3\2\2\2\u0094\u0095"+ - "\7>\2\2\u0095\u0096\7?\2\2\u0096*\3\2\2\2\u0097\u0098\7?\2\2\u0098\u0099"+ - "\7>\2\2\u0099,\3\2\2\2\u009a\u009b\7@\2\2\u009b\u009c\7?\2\2\u009c.\3"+ - "\2\2\2\u009d\u009e\7?\2\2\u009e\u009f\7@\2\2\u009f\60\3\2\2\2\u00a0\u00a1"+ - "\7@\2\2\u00a1\62\3\2\2\2\u00a2\u00a3\7c\2\2\u00a3\u00a4\7p\2\2\u00a4\u00a5"+ - "\7f\2\2\u00a5\64\3\2\2\2\u00a6\u00a7\7(\2\2\u00a7\u00a8\7(\2\2\u00a8\66"+ - "\3\2\2\2\u00a9\u00aa\7q\2\2\u00aa\u00ab\7t\2\2\u00ab8\3\2\2\2\u00ac\u00ad"+ - "\7~\2\2\u00ad\u00ae\7~\2\2\u00ae:\3\2\2\2\u00af\u00b0\7d\2\2\u00b0\u00b1"+ - "\7{\2\2\u00b1\u00b2\7v\2\2\u00b2\u00c5\7g\2\2\u00b3\u00b4\7y\2\2\u00b4"+ - "\u00b5\7q\2\2\u00b5\u00b6\7t\2\2\u00b6\u00c5\7f\2\2\u00b7\u00b8\7u\2\2"+ - "\u00b8\u00b9\7v\2\2\u00b9\u00ba\7t\2\2\u00ba\u00bb\7k\2\2\u00bb\u00bc"+ - "\7p\2\2\u00bc\u00c5\7i\2\2\u00bd\u00be\7d\2\2\u00be\u00bf\7q\2\2\u00bf"+ - "\u00c0\7q\2\2\u00c0\u00c1\7n\2\2\u00c1\u00c2\7g\2\2\u00c2\u00c3\7c\2\2"+ - "\u00c3\u00c5\7p\2\2\u00c4\u00af\3\2\2\2\u00c4\u00b3\3\2\2\2\u00c4\u00b7"+ - "\3\2\2\2\u00c4\u00bd\3\2\2\2\u00c5<\3\2\2\2\u00c6\u00cc\7$\2\2\u00c7\u00c8"+ - "\7^\2\2\u00c8\u00cb\7$\2\2\u00c9\u00cb\n\2\2\2\u00ca\u00c7\3\2\2\2\u00ca"+ - "\u00c9\3\2\2\2\u00cb\u00ce\3\2\2\2\u00cc\u00ca\3\2\2\2\u00cc\u00cd\3\2"+ - "\2\2\u00cd\u00cf\3\2\2\2\u00ce\u00cc\3\2\2\2\u00cf\u00d0\7$\2\2\u00d0"+ - ">\3\2\2\2\u00d1\u00d2\7v\2\2\u00d2\u00d3\7t\2\2\u00d3\u00d4\7w\2\2\u00d4"+ - "\u00db\7g\2\2\u00d5\u00d6\7h\2\2\u00d6\u00d7\7c\2\2\u00d7\u00d8\7n\2\2"+ - "\u00d8\u00d9\7u\2\2\u00d9\u00db\7g\2\2\u00da\u00d1\3\2\2\2\u00da\u00d5"+ - "\3\2\2\2\u00db@\3\2\2\2\u00dc\u00df\5C\"\2\u00dd\u00df\5K&\2\u00de\u00dc"+ - "\3\2\2\2\u00de\u00dd\3\2\2\2\u00dfB\3\2\2\2\u00e0\u00e4\5E#\2\u00e1\u00e4"+ - "\5G$\2\u00e2\u00e4\5I%\2\u00e3\u00e0\3\2\2\2\u00e3\u00e1\3\2\2\2\u00e3"+ - "\u00e2\3\2\2\2\u00e4D\3\2\2\2\u00e5\u00eb\7\'\2\2\u00e6\u00e7\7\62\2\2"+ - "\u00e7\u00eb\7d\2\2\u00e8\u00e9\7\62\2\2\u00e9\u00eb\7D\2\2\u00ea\u00e5"+ - "\3\2\2\2\u00ea\u00e6\3\2\2\2\u00ea\u00e8\3\2\2\2\u00eb\u00ef\3\2\2\2\u00ec"+ - "\u00ee\5S*\2\u00ed\u00ec\3\2\2\2\u00ee\u00f1\3\2\2\2\u00ef\u00ed\3\2\2"+ - "\2\u00ef\u00f0\3\2\2\2\u00f0\u00f2\3\2\2\2\u00f1\u00ef\3\2\2\2\u00f2\u00f4"+ - "\7\60\2\2\u00f3\u00f5\5S*\2\u00f4\u00f3\3\2\2\2\u00f5\u00f6\3\2\2\2\u00f6"+ - "\u00f4\3\2\2\2\u00f6\u00f7\3\2\2\2\u00f7F\3\2\2\2\u00f8\u00fa\5U+\2\u00f9"+ - "\u00f8\3\2\2\2\u00fa\u00fd\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fb\u00fc\3\2"+ - "\2\2\u00fc\u00fe\3\2\2\2\u00fd\u00fb\3\2\2\2\u00fe\u0100\7\60\2\2\u00ff"+ - "\u0101\5U+\2\u0100\u00ff\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0100\3\2\2"+ - "\2\u0102\u0103\3\2\2\2\u0103H\3\2\2\2\u0104\u010a\7&\2\2\u0105\u0106\7"+ - "\62\2\2\u0106\u010a\7z\2\2\u0107\u0108\7\62\2\2\u0108\u010a\7Z\2\2\u0109"+ - "\u0104\3\2\2\2\u0109\u0105\3\2\2\2\u0109\u0107\3\2\2\2\u010a\u010e\3\2"+ - "\2\2\u010b\u010d\5W,\2\u010c\u010b\3\2\2\2\u010d\u0110\3\2\2\2\u010e\u010c"+ - "\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u0111\3\2\2\2\u0110\u010e\3\2\2\2\u0111"+ - "\u0113\7\60\2\2\u0112\u0114\5W,\2\u0113\u0112\3\2\2\2\u0114\u0115\3\2"+ - "\2\2\u0115\u0113\3\2\2\2\u0115\u0116\3\2\2\2\u0116J\3\2\2\2\u0117\u011b"+ - "\5O(\2\u0118\u011b\5Q)\2\u0119\u011b\5M\'\2\u011a\u0117\3\2\2\2\u011a"+ - "\u0118\3\2\2\2\u011a\u0119\3\2\2\2\u011bL\3\2\2\2\u011c\u011d\7\62\2\2"+ - "\u011d\u011f\t\3\2\2\u011e\u0120\5S*\2\u011f\u011e\3\2\2\2\u0120\u0121"+ - "\3\2\2\2\u0121\u011f\3\2\2\2\u0121\u0122\3\2\2\2\u0122\u012a\3\2\2\2\u0123"+ - "\u0125\7\'\2\2\u0124\u0126\5S*\2\u0125\u0124\3\2\2\2\u0126\u0127\3\2\2"+ - "\2\u0127\u0125\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u012a\3\2\2\2\u0129\u011c"+ - "\3\2\2\2\u0129\u0123\3\2\2\2\u012aN\3\2\2\2\u012b\u012d\5U+\2\u012c\u012b"+ - "\3\2\2\2\u012d\u012e\3\2\2\2\u012e\u012c\3\2\2\2\u012e\u012f\3\2\2\2\u012f"+ - "P\3\2\2\2\u0130\u0136\7&\2\2\u0131\u0132\7\62\2\2\u0132\u0136\7z\2\2\u0133"+ - "\u0134\7\62\2\2\u0134\u0136\7Z\2\2\u0135\u0130\3\2\2\2\u0135\u0131\3\2"+ - "\2\2\u0135\u0133\3\2\2\2\u0136\u0138\3\2\2\2\u0137\u0139\5W,\2\u0138\u0137"+ - "\3\2\2\2\u0139\u013a\3\2\2\2\u013a\u0138\3\2\2\2\u013a\u013b\3\2\2\2\u013b"+ - "R\3\2\2\2\u013c\u013d\t\4\2\2\u013dT\3\2\2\2\u013e\u013f\t\5\2\2\u013f"+ - "V\3\2\2\2\u0140\u0141\t\6\2\2\u0141X\3\2\2\2\u0142\u0146\5[.\2\u0143\u0145"+ - "\5]/\2\u0144\u0143\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146"+ - "\u0147\3\2\2\2\u0147Z\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u014a\t\7\2\2"+ - "\u014a\\\3\2\2\2\u014b\u014c\t\b\2\2\u014c^\3\2\2\2\u014d\u014f\t\t\2"+ - "\2\u014e\u014d\3\2\2\2\u014f\u0150\3\2\2\2\u0150\u014e\3\2\2\2\u0150\u0151"+ - "\3\2\2\2\u0151\u0152\3\2\2\2\u0152\u0153\b\60\2\2\u0153`\3\2\2\2\32\2"+ - "\u00c4\u00ca\u00cc\u00da\u00de\u00e3\u00ea\u00ef\u00f6\u00fb\u0102\u0109"+ - "\u010e\u0115\u011a\u0121\u0127\u0129\u012e\u0135\u013a\u0146\u0150\3\b"+ + ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\3\2\3\2\3\3\3\3\3\4\3\4\3\5"+ + "\3\5\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3"+ + "\n\3\n\3\13\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\16\3\16\3\17\3\17\3"+ + "\20\3\20\3\21\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3"+ + "\25\3\26\3\26\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\32\3"+ + "\32\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3"+ + "\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3"+ + "\37\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u00ca\n\37\3 \3 \3 \3 \7 \u00d0"+ + "\n \f \16 \u00d3\13 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3!\5!\u00e0\n!\3\""+ + "\3\"\5\"\u00e4\n\"\3#\3#\3#\5#\u00e9\n#\3$\3$\3$\3$\3$\5$\u00f0\n$\3$"+ + "\7$\u00f3\n$\f$\16$\u00f6\13$\3$\3$\6$\u00fa\n$\r$\16$\u00fb\3%\7%\u00ff"+ + "\n%\f%\16%\u0102\13%\3%\3%\6%\u0106\n%\r%\16%\u0107\3&\3&\3&\3&\3&\5&"+ + "\u010f\n&\3&\7&\u0112\n&\f&\16&\u0115\13&\3&\3&\6&\u0119\n&\r&\16&\u011a"+ + "\3\'\3\'\3\'\5\'\u0120\n\'\3(\3(\3(\6(\u0125\n(\r(\16(\u0126\3(\3(\6("+ + "\u012b\n(\r(\16(\u012c\5(\u012f\n(\3)\6)\u0132\n)\r)\16)\u0133\3*\3*\3"+ + "*\3*\3*\5*\u013b\n*\3*\6*\u013e\n*\r*\16*\u013f\3+\3+\3,\3,\3-\3-\3.\3"+ + ".\7.\u014a\n.\f.\16.\u014d\13.\3/\3/\3\60\3\60\3\61\6\61\u0154\n\61\r"+ + "\61\16\61\u0155\3\61\3\61\2\2\62\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23"+ + "\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31"+ + "\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U\2W\2Y\2[,"+ + "]\2_\2a-\3\2\n\3\2$$\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|"+ + "\6\2\62;C\\aac|\5\2\13\f\17\17\"\"\2\u0171\2\3\3\2\2\2\2\5\3\2\2\2\2\7"+ + "\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2"+ + "\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2"+ + "\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2"+ + "\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2"+ + "\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2"+ + "\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M"+ + "\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2[\3\2\2\2\2a\3\2\2\2\3c\3\2"+ + "\2\2\5e\3\2\2\2\7g\3\2\2\2\ti\3\2\2\2\13k\3\2\2\2\rn\3\2\2\2\17p\3\2\2"+ + "\2\21r\3\2\2\2\23w\3\2\2\2\25}\3\2\2\2\27\u0080\3\2\2\2\31\u0082\3\2\2"+ + "\2\33\u0084\3\2\2\2\35\u0088\3\2\2\2\37\u008a\3\2\2\2!\u008c\3\2\2\2#"+ + "\u008e\3\2\2\2%\u0091\3\2\2\2\'\u0094\3\2\2\2)\u0097\3\2\2\2+\u0099\3"+ + "\2\2\2-\u009c\3\2\2\2/\u009f\3\2\2\2\61\u00a2\3\2\2\2\63\u00a5\3\2\2\2"+ + "\65\u00a7\3\2\2\2\67\u00ab\3\2\2\29\u00ae\3\2\2\2;\u00b1\3\2\2\2=\u00c9"+ + "\3\2\2\2?\u00cb\3\2\2\2A\u00df\3\2\2\2C\u00e3\3\2\2\2E\u00e8\3\2\2\2G"+ + "\u00ef\3\2\2\2I\u0100\3\2\2\2K\u010e\3\2\2\2M\u011f\3\2\2\2O\u012e\3\2"+ + "\2\2Q\u0131\3\2\2\2S\u013a\3\2\2\2U\u0141\3\2\2\2W\u0143\3\2\2\2Y\u0145"+ + "\3\2\2\2[\u0147\3\2\2\2]\u014e\3\2\2\2_\u0150\3\2\2\2a\u0153\3\2\2\2c"+ + "d\7}\2\2d\4\3\2\2\2ef\7\177\2\2f\6\3\2\2\2gh\7?\2\2h\b\3\2\2\2ij\7=\2"+ + "\2j\n\3\2\2\2kl\7k\2\2lm\7h\2\2m\f\3\2\2\2no\7*\2\2o\16\3\2\2\2pq\7+\2"+ + "\2q\20\3\2\2\2rs\7g\2\2st\7n\2\2tu\7u\2\2uv\7g\2\2v\22\3\2\2\2wx\7y\2"+ + "\2xy\7j\2\2yz\7k\2\2z{\7n\2\2{|\7g\2\2|\24\3\2\2\2}~\7f\2\2~\177\7q\2"+ + "\2\177\26\3\2\2\2\u0080\u0081\7-\2\2\u0081\30\3\2\2\2\u0082\u0083\7/\2"+ + "\2\u0083\32\3\2\2\2\u0084\u0085\7p\2\2\u0085\u0086\7q\2\2\u0086\u0087"+ + "\7v\2\2\u0087\34\3\2\2\2\u0088\u0089\7#\2\2\u0089\36\3\2\2\2\u008a\u008b"+ + "\7,\2\2\u008b \3\2\2\2\u008c\u008d\7\61\2\2\u008d\"\3\2\2\2\u008e\u008f"+ + "\7?\2\2\u008f\u0090\7?\2\2\u0090$\3\2\2\2\u0091\u0092\7#\2\2\u0092\u0093"+ + "\7?\2\2\u0093&\3\2\2\2\u0094\u0095\7>\2\2\u0095\u0096\7@\2\2\u0096(\3"+ + "\2\2\2\u0097\u0098\7>\2\2\u0098*\3\2\2\2\u0099\u009a\7>\2\2\u009a\u009b"+ + "\7?\2\2\u009b,\3\2\2\2\u009c\u009d\7?\2\2\u009d\u009e\7>\2\2\u009e.\3"+ + "\2\2\2\u009f\u00a0\7@\2\2\u00a0\u00a1\7?\2\2\u00a1\60\3\2\2\2\u00a2\u00a3"+ + "\7?\2\2\u00a3\u00a4\7@\2\2\u00a4\62\3\2\2\2\u00a5\u00a6\7@\2\2\u00a6\64"+ + "\3\2\2\2\u00a7\u00a8\7c\2\2\u00a8\u00a9\7p\2\2\u00a9\u00aa\7f\2\2\u00aa"+ + "\66\3\2\2\2\u00ab\u00ac\7(\2\2\u00ac\u00ad\7(\2\2\u00ad8\3\2\2\2\u00ae"+ + "\u00af\7q\2\2\u00af\u00b0\7t\2\2\u00b0:\3\2\2\2\u00b1\u00b2\7~\2\2\u00b2"+ + "\u00b3\7~\2\2\u00b3<\3\2\2\2\u00b4\u00b5\7d\2\2\u00b5\u00b6\7{\2\2\u00b6"+ + "\u00b7\7v\2\2\u00b7\u00ca\7g\2\2\u00b8\u00b9\7y\2\2\u00b9\u00ba\7q\2\2"+ + "\u00ba\u00bb\7t\2\2\u00bb\u00ca\7f\2\2\u00bc\u00bd\7u\2\2\u00bd\u00be"+ + "\7v\2\2\u00be\u00bf\7t\2\2\u00bf\u00c0\7k\2\2\u00c0\u00c1\7p\2\2\u00c1"+ + "\u00ca\7i\2\2\u00c2\u00c3\7d\2\2\u00c3\u00c4\7q\2\2\u00c4\u00c5\7q\2\2"+ + "\u00c5\u00c6\7n\2\2\u00c6\u00c7\7g\2\2\u00c7\u00c8\7c\2\2\u00c8\u00ca"+ + "\7p\2\2\u00c9\u00b4\3\2\2\2\u00c9\u00b8\3\2\2\2\u00c9\u00bc\3\2\2\2\u00c9"+ + "\u00c2\3\2\2\2\u00ca>\3\2\2\2\u00cb\u00d1\7$\2\2\u00cc\u00cd\7^\2\2\u00cd"+ + "\u00d0\7$\2\2\u00ce\u00d0\n\2\2\2\u00cf\u00cc\3\2\2\2\u00cf\u00ce\3\2"+ + "\2\2\u00d0\u00d3\3\2\2\2\u00d1\u00cf\3\2\2\2\u00d1\u00d2\3\2\2\2\u00d2"+ + "\u00d4\3\2\2\2\u00d3\u00d1\3\2\2\2\u00d4\u00d5\7$\2\2\u00d5@\3\2\2\2\u00d6"+ + "\u00d7\7v\2\2\u00d7\u00d8\7t\2\2\u00d8\u00d9\7w\2\2\u00d9\u00e0\7g\2\2"+ + "\u00da\u00db\7h\2\2\u00db\u00dc\7c\2\2\u00dc\u00dd\7n\2\2\u00dd\u00de"+ + "\7u\2\2\u00de\u00e0\7g\2\2\u00df\u00d6\3\2\2\2\u00df\u00da\3\2\2\2\u00e0"+ + "B\3\2\2\2\u00e1\u00e4\5E#\2\u00e2\u00e4\5M\'\2\u00e3\u00e1\3\2\2\2\u00e3"+ + "\u00e2\3\2\2\2\u00e4D\3\2\2\2\u00e5\u00e9\5G$\2\u00e6\u00e9\5I%\2\u00e7"+ + "\u00e9\5K&\2\u00e8\u00e5\3\2\2\2\u00e8\u00e6\3\2\2\2\u00e8\u00e7\3\2\2"+ + "\2\u00e9F\3\2\2\2\u00ea\u00f0\7\'\2\2\u00eb\u00ec\7\62\2\2\u00ec\u00f0"+ + "\7d\2\2\u00ed\u00ee\7\62\2\2\u00ee\u00f0\7D\2\2\u00ef\u00ea\3\2\2\2\u00ef"+ + "\u00eb\3\2\2\2\u00ef\u00ed\3\2\2\2\u00f0\u00f4\3\2\2\2\u00f1\u00f3\5U"+ + "+\2\u00f2\u00f1\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4"+ + "\u00f5\3\2\2\2\u00f5\u00f7\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f7\u00f9\7\60"+ + "\2\2\u00f8\u00fa\5U+\2\u00f9\u00f8\3\2\2\2\u00fa\u00fb\3\2\2\2\u00fb\u00f9"+ + "\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fcH\3\2\2\2\u00fd\u00ff\5W,\2\u00fe\u00fd"+ + "\3\2\2\2\u00ff\u0102\3\2\2\2\u0100\u00fe\3\2\2\2\u0100\u0101\3\2\2\2\u0101"+ + "\u0103\3\2\2\2\u0102\u0100\3\2\2\2\u0103\u0105\7\60\2\2\u0104\u0106\5"+ + "W,\2\u0105\u0104\3\2\2\2\u0106\u0107\3\2\2\2\u0107\u0105\3\2\2\2\u0107"+ + "\u0108\3\2\2\2\u0108J\3\2\2\2\u0109\u010f\7&\2\2\u010a\u010b\7\62\2\2"+ + "\u010b\u010f\7z\2\2\u010c\u010d\7\62\2\2\u010d\u010f\7Z\2\2\u010e\u0109"+ + "\3\2\2\2\u010e\u010a\3\2\2\2\u010e\u010c\3\2\2\2\u010f\u0113\3\2\2\2\u0110"+ + "\u0112\5Y-\2\u0111\u0110\3\2\2\2\u0112\u0115\3\2\2\2\u0113\u0111\3\2\2"+ + "\2\u0113\u0114\3\2\2\2\u0114\u0116\3\2\2\2\u0115\u0113\3\2\2\2\u0116\u0118"+ + "\7\60\2\2\u0117\u0119\5Y-\2\u0118\u0117\3\2\2\2\u0119\u011a\3\2\2\2\u011a"+ + "\u0118\3\2\2\2\u011a\u011b\3\2\2\2\u011bL\3\2\2\2\u011c\u0120\5Q)\2\u011d"+ + "\u0120\5S*\2\u011e\u0120\5O(\2\u011f\u011c\3\2\2\2\u011f\u011d\3\2\2\2"+ + "\u011f\u011e\3\2\2\2\u0120N\3\2\2\2\u0121\u0122\7\62\2\2\u0122\u0124\t"+ + "\3\2\2\u0123\u0125\5U+\2\u0124\u0123\3\2\2\2\u0125\u0126\3\2\2\2\u0126"+ + "\u0124\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u012f\3\2\2\2\u0128\u012a\7\'"+ + "\2\2\u0129\u012b\5U+\2\u012a\u0129\3\2\2\2\u012b\u012c\3\2\2\2\u012c\u012a"+ + "\3\2\2\2\u012c\u012d\3\2\2\2\u012d\u012f\3\2\2\2\u012e\u0121\3\2\2\2\u012e"+ + "\u0128\3\2\2\2\u012fP\3\2\2\2\u0130\u0132\5W,\2\u0131\u0130\3\2\2\2\u0132"+ + "\u0133\3\2\2\2\u0133\u0131\3\2\2\2\u0133\u0134\3\2\2\2\u0134R\3\2\2\2"+ + "\u0135\u013b\7&\2\2\u0136\u0137\7\62\2\2\u0137\u013b\7z\2\2\u0138\u0139"+ + "\7\62\2\2\u0139\u013b\7Z\2\2\u013a\u0135\3\2\2\2\u013a\u0136\3\2\2\2\u013a"+ + "\u0138\3\2\2\2\u013b\u013d\3\2\2\2\u013c\u013e\5Y-\2\u013d\u013c\3\2\2"+ + "\2\u013e\u013f\3\2\2\2\u013f\u013d\3\2\2\2\u013f\u0140\3\2\2\2\u0140T"+ + "\3\2\2\2\u0141\u0142\t\4\2\2\u0142V\3\2\2\2\u0143\u0144\t\5\2\2\u0144"+ + "X\3\2\2\2\u0145\u0146\t\6\2\2\u0146Z\3\2\2\2\u0147\u014b\5]/\2\u0148\u014a"+ + "\5_\60\2\u0149\u0148\3\2\2\2\u014a\u014d\3\2\2\2\u014b\u0149\3\2\2\2\u014b"+ + "\u014c\3\2\2\2\u014c\\\3\2\2\2\u014d\u014b\3\2\2\2\u014e\u014f\t\7\2\2"+ + "\u014f^\3\2\2\2\u0150\u0151\t\b\2\2\u0151`\3\2\2\2\u0152\u0154\t\t\2\2"+ + "\u0153\u0152\3\2\2\2\u0154\u0155\3\2\2\2\u0155\u0153\3\2\2\2\u0155\u0156"+ + "\3\2\2\2\u0156\u0157\3\2\2\2\u0157\u0158\b\61\2\2\u0158b\3\2\2\2\32\2"+ + "\u00c9\u00cf\u00d1\u00df\u00e3\u00e8\u00ef\u00f4\u00fb\u0100\u0107\u010e"+ + "\u0113\u011a\u011f\u0126\u012c\u012e\u0133\u013a\u013f\u014b\u0155\3\b"+ "\2\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); diff --git a/src/dk/camelot64/kickc/parser/KickCLexer.tokens b/src/dk/camelot64/kickc/parser/KickCLexer.tokens index 69c474e0f..fb63df5b8 100644 --- a/src/dk/camelot64/kickc/parser/KickCLexer.tokens +++ b/src/dk/camelot64/kickc/parser/KickCLexer.tokens @@ -26,20 +26,21 @@ T__24=25 T__25=26 T__26=27 T__27=28 -TYPE=29 -STRING=30 -BOOLEAN=31 -NUMBER=32 -NUMFLOAT=33 -BINFLOAT=34 -DECFLOAT=35 -HEXFLOAT=36 -NUMINT=37 -BININTEGER=38 -DECINTEGER=39 -HEXINTEGER=40 -NAME=41 -WS=42 +T__28=29 +TYPE=30 +STRING=31 +BOOLEAN=32 +NUMBER=33 +NUMFLOAT=34 +BINFLOAT=35 +DECFLOAT=36 +HEXFLOAT=37 +NUMINT=38 +BININTEGER=39 +DECINTEGER=40 +HEXINTEGER=41 +NAME=42 +WS=43 '{'=1 '}'=2 '='=3 @@ -49,22 +50,23 @@ WS=42 ')'=7 'else'=8 'while'=9 -'+'=10 -'-'=11 -'not'=12 -'!'=13 -'*'=14 -'/'=15 -'=='=16 -'!='=17 -'<>'=18 -'<'=19 -'<='=20 -'=<'=21 -'>='=22 -'=>'=23 -'>'=24 -'and'=25 -'&&'=26 -'or'=27 -'||'=28 +'do'=10 +'+'=11 +'-'=12 +'not'=13 +'!'=14 +'*'=15 +'/'=16 +'=='=17 +'!='=18 +'<>'=19 +'<'=20 +'<='=21 +'=<'=22 +'>='=23 +'=>'=24 +'>'=25 +'and'=26 +'&&'=27 +'or'=28 +'||'=29 diff --git a/src/dk/camelot64/kickc/parser/KickCListener.java b/src/dk/camelot64/kickc/parser/KickCListener.java index dfce0dcdd..7053c9c07 100644 --- a/src/dk/camelot64/kickc/parser/KickCListener.java +++ b/src/dk/camelot64/kickc/parser/KickCListener.java @@ -87,6 +87,18 @@ public interface KickCListener extends ParseTreeListener { * @param ctx the parse tree */ void exitStmtWhile(KickCParser.StmtWhileContext ctx); + /** + * Enter a parse tree produced by the {@code stmtDoWhile} + * labeled alternative in {@link KickCParser#stmt}. + * @param ctx the parse tree + */ + void enterStmtDoWhile(KickCParser.StmtDoWhileContext ctx); + /** + * Exit a parse tree produced by the {@code stmtDoWhile} + * labeled alternative in {@link KickCParser#stmt}. + * @param ctx the parse tree + */ + void exitStmtDoWhile(KickCParser.StmtDoWhileContext 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 44744aa15..ed8b3e6d3 100644 --- a/src/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/dk/camelot64/kickc/parser/KickCParser.java @@ -20,9 +20,9 @@ public class KickCParser extends Parser { T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, T__27=28, TYPE=29, STRING=30, BOOLEAN=31, - NUMBER=32, NUMFLOAT=33, BINFLOAT=34, DECFLOAT=35, HEXFLOAT=36, NUMINT=37, - BININTEGER=38, DECINTEGER=39, HEXINTEGER=40, NAME=41, WS=42; + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, TYPE=30, STRING=31, + BOOLEAN=32, NUMBER=33, NUMFLOAT=34, BINFLOAT=35, DECFLOAT=36, HEXFLOAT=37, + NUMINT=38, BININTEGER=39, DECINTEGER=40, HEXINTEGER=41, NAME=42, WS=43; public static final int RULE_file = 0, RULE_stmtSeq = 1, RULE_stmt = 2, RULE_expr = 3; public static final String[] ruleNames = { @@ -31,15 +31,16 @@ public class KickCParser extends Parser { private static final String[] _LITERAL_NAMES = { null, "'{'", "'}'", "'='", "';'", "'if'", "'('", "')'", "'else'", "'while'", - "'+'", "'-'", "'not'", "'!'", "'*'", "'/'", "'=='", "'!='", "'<>'", "'<'", - "'<='", "'=<'", "'>='", "'=>'", "'>'", "'and'", "'&&'", "'or'", "'||'" + "'do'", "'+'", "'-'", "'not'", "'!'", "'*'", "'/'", "'=='", "'!='", "'<>'", + "'<'", "'<='", "'=<'", "'>='", "'=>'", "'>'", "'and'", "'&&'", "'or'", + "'||'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, "TYPE", "STRING", "BOOLEAN", "NUMBER", "NUMFLOAT", - "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", - "HEXINTEGER", "NAME", "WS" + null, null, null, null, null, null, "TYPE", "STRING", "BOOLEAN", "NUMBER", + "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", + "DECINTEGER", "HEXINTEGER", "NAME", "WS" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -183,7 +184,7 @@ public class KickCParser extends Parser { setState(14); _errHandler.sync(this); _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__4) | (1L << T__5) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << TYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0) ); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__4) | (1L << T__5) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << TYPE) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0) ); } } catch (RecognitionException re) { @@ -268,6 +269,28 @@ public class KickCParser extends Parser { else return visitor.visitChildren(this); } } + public static class StmtDoWhileContext extends StmtContext { + public StmtContext stmt() { + return getRuleContext(StmtContext.class,0); + } + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public StmtDoWhileContext(StmtContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStmtDoWhile(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStmtDoWhile(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KickCVisitor ) return ((KickCVisitor)visitor).visitStmtDoWhile(this); + else return visitor.visitChildren(this); + } + } public static class StmtAssignmentContext extends StmtContext { public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); } public TerminalNode TYPE() { return getToken(KickCParser.TYPE, 0); } @@ -320,7 +343,7 @@ public class KickCParser extends Parser { enterRule(_localctx, 4, RULE_stmt); int _la; try { - setState(47); + setState(54); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { case 1: @@ -421,6 +444,24 @@ public class KickCParser extends Parser { stmt(); } break; + case 6: + _localctx = new StmtDoWhileContext(_localctx); + enterOuterAlt(_localctx, 6); + { + setState(47); + match(T__9); + setState(48); + stmt(); + setState(49); + match(T__8); + setState(50); + match(T__5); + setState(51); + expr(0); + setState(52); + match(T__6); + } + break; } } catch (RecognitionException re) { @@ -590,7 +631,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(60); + setState(67); _errHandler.sync(this); switch (_input.LA(1)) { case T__5: @@ -599,25 +640,25 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(50); + setState(57); match(T__5); - setState(51); + setState(58); expr(0); - setState(52); + setState(59); match(T__6); } break; - case T__9: case T__10: case T__11: case T__12: + case T__13: { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(54); + setState(61); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -625,7 +666,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(55); + setState(62); expr(10); } break; @@ -634,7 +675,7 @@ public class KickCParser extends Parser { _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(56); + setState(63); match(NAME); } break; @@ -643,7 +684,7 @@ public class KickCParser extends Parser { _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(57); + setState(64); match(NUMBER); } break; @@ -652,7 +693,7 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(58); + setState(65); match(STRING); } break; @@ -661,7 +702,7 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(59); + setState(66); match(BOOLEAN); } break; @@ -669,7 +710,7 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(79); + setState(86); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -677,18 +718,18 @@ public class KickCParser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(77); + setState(84); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(62); + setState(69); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(63); + setState(70); _la = _input.LA(1); - if ( !(_la==T__13 || _la==T__14) ) { + if ( !(_la==T__14 || _la==T__15) ) { _errHandler.recoverInline(this); } else { @@ -696,7 +737,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(64); + setState(71); expr(10); } break; @@ -704,11 +745,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(65); + setState(72); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(66); + setState(73); _la = _input.LA(1); - if ( !(_la==T__9 || _la==T__10) ) { + if ( !(_la==T__10 || _la==T__11) ) { _errHandler.recoverInline(this); } else { @@ -716,7 +757,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(67); + setState(74); expr(9); } break; @@ -724,11 +765,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(68); + setState(75); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(69); + setState(76); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__15) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -736,7 +777,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(70); + setState(77); expr(8); } break; @@ -744,11 +785,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(71); + setState(78); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(72); + setState(79); _la = _input.LA(1); - if ( !(_la==T__24 || _la==T__25) ) { + if ( !(_la==T__25 || _la==T__26) ) { _errHandler.recoverInline(this); } else { @@ -756,7 +797,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(73); + setState(80); expr(7); } break; @@ -764,11 +805,11 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(74); + setState(81); if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); - setState(75); + setState(82); _la = _input.LA(1); - if ( !(_la==T__26 || _la==T__27) ) { + if ( !(_la==T__27 || _la==T__28) ) { _errHandler.recoverInline(this); } else { @@ -776,14 +817,14 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(76); + setState(83); expr(6); } break; } } } - setState(81); + setState(88); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); } @@ -824,30 +865,31 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3,U\4\2\t\2\4\3\t\3"+ - "\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\3\6\3\17\n\3\r\3\16\3\20\3\4\3\4\3\4\3"+ - "\4\3\4\5\4\30\n\4\3\4\3\4\3\4\5\4\35\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+ - "\4\3\4\3\4\3\4\5\4*\n\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4\62\n\4\3\5\3\5\3\5"+ - "\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5?\n\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5"+ - "\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\7\5P\n\5\f\5\16\5S\13\5\3\5\2\3\b\6\2"+ - "\4\6\b\2\b\3\2\f\17\3\2\20\21\3\2\f\r\3\2\22\32\3\2\33\34\3\2\35\36\2"+ - "b\2\n\3\2\2\2\4\16\3\2\2\2\6\61\3\2\2\2\b>\3\2\2\2\n\13\5\4\3\2\13\f\7"+ - "\2\2\3\f\3\3\2\2\2\r\17\5\6\4\2\16\r\3\2\2\2\17\20\3\2\2\2\20\16\3\2\2"+ - "\2\20\21\3\2\2\2\21\5\3\2\2\2\22\23\7\3\2\2\23\24\5\4\3\2\24\25\7\4\2"+ - "\2\25\62\3\2\2\2\26\30\7\37\2\2\27\26\3\2\2\2\27\30\3\2\2\2\30\31\3\2"+ - "\2\2\31\34\7+\2\2\32\33\7\5\2\2\33\35\5\b\5\2\34\32\3\2\2\2\34\35\3\2"+ - "\2\2\35\36\3\2\2\2\36\62\7\6\2\2\37 \5\b\5\2 !\7\6\2\2!\62\3\2\2\2\"#"+ - "\7\7\2\2#$\7\b\2\2$%\5\b\5\2%&\7\t\2\2&)\5\6\4\2\'(\7\n\2\2(*\5\6\4\2"+ - ")\'\3\2\2\2)*\3\2\2\2*\62\3\2\2\2+,\7\13\2\2,-\7\b\2\2-.\5\b\5\2./\7\t"+ - "\2\2/\60\5\6\4\2\60\62\3\2\2\2\61\22\3\2\2\2\61\27\3\2\2\2\61\37\3\2\2"+ - "\2\61\"\3\2\2\2\61+\3\2\2\2\62\7\3\2\2\2\63\64\b\5\1\2\64\65\7\b\2\2\65"+ - "\66\5\b\5\2\66\67\7\t\2\2\67?\3\2\2\289\t\2\2\29?\5\b\5\f:?\7+\2\2;?\7"+ - "\"\2\2\63\3\2\2\2>8\3\2\2\2>:\3\2\2\2>;\3\2\2\2><\3"+ - "\2\2\2>=\3\2\2\2?Q\3\2\2\2@A\f\13\2\2AB\t\3\2\2BP\5\b\5\fCD\f\n\2\2DE"+ - "\t\4\2\2EP\5\b\5\13FG\f\t\2\2GH\t\5\2\2HP\5\b\5\nIJ\f\b\2\2JK\t\6\2\2"+ - "KP\5\b\5\tLM\f\7\2\2MN\t\7\2\2NP\5\b\5\bO@\3\2\2\2OC\3\2\2\2OF\3\2\2\2"+ - "OI\3\2\2\2OL\3\2\2\2PS\3\2\2\2QO\3\2\2\2QR\3\2\2\2R\t\3\2\2\2SQ\3\2\2"+ - "\2\n\20\27\34)\61>OQ"; + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3-\\\4\2\t\2\4\3\t"+ + "\3\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\3\6\3\17\n\3\r\3\16\3\20\3\4\3\4\3\4"+ + "\3\4\3\4\5\4\30\n\4\3\4\3\4\3\4\5\4\35\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ + "\3\4\3\4\3\4\3\4\5\4*\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ + "\3\4\3\4\5\49\n\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5F\n\5"+ + "\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\7\5W\n\5"+ + "\f\5\16\5Z\13\5\3\5\2\3\b\6\2\4\6\b\2\b\3\2\r\20\3\2\21\22\3\2\r\16\3"+ + "\2\23\33\3\2\34\35\3\2\36\37\2j\2\n\3\2\2\2\4\16\3\2\2\2\68\3\2\2\2\b"+ + "E\3\2\2\2\n\13\5\4\3\2\13\f\7\2\2\3\f\3\3\2\2\2\r\17\5\6\4\2\16\r\3\2"+ + "\2\2\17\20\3\2\2\2\20\16\3\2\2\2\20\21\3\2\2\2\21\5\3\2\2\2\22\23\7\3"+ + "\2\2\23\24\5\4\3\2\24\25\7\4\2\2\259\3\2\2\2\26\30\7 \2\2\27\26\3\2\2"+ + "\2\27\30\3\2\2\2\30\31\3\2\2\2\31\34\7,\2\2\32\33\7\5\2\2\33\35\5\b\5"+ + "\2\34\32\3\2\2\2\34\35\3\2\2\2\35\36\3\2\2\2\369\7\6\2\2\37 \5\b\5\2 "+ + "!\7\6\2\2!9\3\2\2\2\"#\7\7\2\2#$\7\b\2\2$%\5\b\5\2%&\7\t\2\2&)\5\6\4\2"+ + "\'(\7\n\2\2(*\5\6\4\2)\'\3\2\2\2)*\3\2\2\2*9\3\2\2\2+,\7\13\2\2,-\7\b"+ + "\2\2-.\5\b\5\2./\7\t\2\2/\60\5\6\4\2\609\3\2\2\2\61\62\7\f\2\2\62\63\5"+ + "\6\4\2\63\64\7\13\2\2\64\65\7\b\2\2\65\66\5\b\5\2\66\67\7\t\2\2\679\3"+ + "\2\2\28\22\3\2\2\28\27\3\2\2\28\37\3\2\2\28\"\3\2\2\28+\3\2\2\28\61\3"+ + "\2\2\29\7\3\2\2\2:;\b\5\1\2;<\7\b\2\2<=\5\b\5\2=>\7\t\2\2>F\3\2\2\2?@"+ + "\t\2\2\2@F\5\b\5\fAF\7,\2\2BF\7#\2\2CF\7!\2\2DF\7\"\2\2E:\3\2\2\2E?\3"+ + "\2\2\2EA\3\2\2\2EB\3\2\2\2EC\3\2\2\2ED\3\2\2\2FX\3\2\2\2GH\f\13\2\2HI"+ + "\t\3\2\2IW\5\b\5\fJK\f\n\2\2KL\t\4\2\2LW\5\b\5\13MN\f\t\2\2NO\t\5\2\2"+ + "OW\5\b\5\nPQ\f\b\2\2QR\t\6\2\2RW\5\b\5\tST\f\7\2\2TU\t\7\2\2UW\5\b\5\b"+ + "VG\3\2\2\2VJ\3\2\2\2VM\3\2\2\2VP\3\2\2\2VS\3\2\2\2WZ\3\2\2\2XV\3\2\2\2"+ + "XY\3\2\2\2Y\t\3\2\2\2ZX\3\2\2\2\n\20\27\34)8EVX"; 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 ccafef85a..c82e30341 100644 --- a/src/dk/camelot64/kickc/parser/KickCVisitor.java +++ b/src/dk/camelot64/kickc/parser/KickCVisitor.java @@ -57,6 +57,13 @@ public interface KickCVisitor extends ParseTreeVisitor { * @return the visitor result */ T visitStmtWhile(KickCParser.StmtWhileContext ctx); + /** + * Visit a parse tree produced by the {@code stmtDoWhile} + * labeled alternative in {@link KickCParser#stmt}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx); /** * Visit a parse tree produced by the {@code exprBinary} * labeled alternative in {@link KickCParser#expr}. diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index ca5ca6842..68c01db5b 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -4,9 +4,7 @@ import dk.camelot64.kickc.asm.AsmProgram; import dk.camelot64.kickc.icl.*; import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCParser; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.*; import java.io.IOException; import java.util.ArrayList; @@ -15,11 +13,18 @@ import java.util.List; /** Test my KickC Grammar */ public class Main { public static void main(String[] args) throws IOException { - CharStream input = CharStreams.fromFileName("src/dk/camelot64/kickc/test/fib.kc"); + final String fileName = "src/dk/camelot64/kickc/test/fib2.kc"; + final CharStream input = CharStreams.fromFileName(fileName); System.out.println(input.toString()); KickCLexer lexer = new KickCLexer(input); KickCParser parser = new KickCParser(new CommonTokenStream(lexer)); parser.setBuildParseTree(true); + parser.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + throw new RuntimeException("Error parsing file "+fileName+"\n - Line: "+line+"\n - Message: "+msg); + } + }); KickCParser.FileContext file = parser.file(); Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(); pass1GenerateStatementSequence.generate(file); diff --git a/src/dk/camelot64/kickc/test/fib2.kc b/src/dk/camelot64/kickc/test/fib2.kc new file mode 100644 index 000000000..2059e8cc5 --- /dev/null +++ b/src/dk/camelot64/kickc/test/fib2.kc @@ -0,0 +1,10 @@ +byte n1 = 0; +byte n2 = 1; +byte i = 12; +byte fib = 0; +do { + fib = n1 + n2; + n1 = n2; + n2 = fib; + i = i - 1; +} while(i!=0)