From 7c383dff1a65b615346dc5b58d8a999cb1018f16 Mon Sep 17 00:00:00 2001 From: otya128 Date: Wed, 10 Jun 2015 19:09:15 +0900 Subject: [PATCH] =?UTF-8?q?break,continue=E5=AE=9F=E8=A3=85,var,dim?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/compiler.d | 57 ++++++++++++++++++++++++++++++++++--------- SMILEBASIC/main.d | 5 ++++ SMILEBASIC/node.d | 41 ++++++++++++++++++++++++++++++- SMILEBASIC/parser.d | 42 +++++++++++++++++++++++++++++++ SMILEBASIC/token.d | 3 +++ SMILEBASIC/type.d | 46 +++++++++++++++++++++++++++++++++- 6 files changed, 180 insertions(+), 14 deletions(-) diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 11f9fe1..d32b16e 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -5,6 +5,19 @@ import otya.smilebasic.vm; import otya.smilebasic.type; import otya.smilebasic.error; import std.stdio; +class Scope +{ + GotoAddr breakAddr; + GotoAddr continueAddr; + this() + { + } + this(GotoAddr breakAddr, GotoAddr continueAddr) + { + this.breakAddr = breakAddr; + this.continueAddr = continueAddr; + } +} class Compiler { Statements statements; @@ -139,19 +152,19 @@ class Compiler break; } } - void compileIf(If node) + void compileIf(If node, Scope sc) { compileExpression(node.condition); //条件式がfalseならendif or elseに飛ぶ auto else_ = genCodeGotoFalse(); - compileStatements(node.then); + compileStatements(node.then, sc); //もしelseもあるのならば、endifに飛ぶ GotoAddr then; if(node.hasElse) { then = genCodeGoto(); else_.address = code.length; - compileStatements(node.else_); + compileStatements(node.else_, sc); then.address = code.length; } else @@ -160,9 +173,9 @@ class Compiler else_.address = code.length; } } - void compileFor(For node) + void compileFor(For node, Scope s) { - compileStatement(node.initExpression); + compileStatement(node.initExpression, s); auto forstart = code.length; compileExpression(node.stepExpression); genCodeImm(Value(0)); @@ -194,7 +207,9 @@ class Compiler genCodeOP(TokenType.Less); genCode(breakAddr); forAddr.address = code.length; - compileStatements(node.statements); + s = new Scope(new GotoAddr(-1), new GotoAddr(-1)); + compileStatements(node.statements, s); + s.continueAddr.address = code.length; //counterに加算する genCodePushGlobal(getGlobalVarIndex(node.initExpression.name)); compileExpression(node.stepExpression); @@ -202,16 +217,17 @@ class Compiler genCodePopGlobal(getGlobalVarIndex(node.initExpression.name)); genCodeGoto(forstart); breakAddr.address = code.length; + s.breakAddr.address = code.length; } - void compileStatements(Statements statements) + void compileStatements(Statements statements, Scope sc) { foreach(Statement s ; statements.statements) { - compileStatement(s); + compileStatement(s, sc); } } - void compileStatement(Statement i) + void compileStatement(Statement i, Scope s) { switch(i.type) { @@ -257,10 +273,10 @@ class Compiler } break; case NodeType.If: - compileIf(cast(If)i); + compileIf(cast(If)i, s); break; case NodeType.For: - compileFor(cast(For)i); + compileFor(cast(For)i, s); break; case NodeType.Gosub: { @@ -282,15 +298,32 @@ class Compiler case NodeType.End: genCode(new EndVM()); break; + case NodeType.Break: + if(s.breakAddr is null) + { + //syntax-error + break; + } + genCode(s.breakAddr); + break; + case NodeType.Continue: + if(s.continueAddr is null) + { + //syntax-error + break; + } + genCode(s.continueAddr); + break; default: stderr.writeln("Compile:NotImpl ", i.type); } } VM compile() { + Scope s = new Scope(); foreach(Statement i ; statements.statements) { - compileStatement(i); + compileStatement(i, s); } foreach(int i, Code c; code) { diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index 85d210b..f3c99b8 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -48,6 +48,11 @@ NEXT ?(1 OR 2 XOR 3) ?(1 OR 2 XOR 3 OR 4) ?@HELLOWORLD +FOR I=0 TO 10 + IF I==4 THEN BREAK + IF I==1 THEN CONTINUE + ?I +NEXT GOSUB @A END @A diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index d499f47..57840e1 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -26,6 +26,10 @@ enum NodeType Gosub, Return, End, + Break, + Continue, + DefineVariable, + DefineArray, } abstract class Node { @@ -273,4 +277,39 @@ class End : Statement this.type = NodeType.End; } } - +class Break : Statement +{ + this() + { + this.type = NodeType.Break; + } +} +class Continue : Statement +{ + this() + { + this.type = NodeType.Continue; + } +} +class DefineVariable : Statement +{ + wstring name; + Expression expression; + this(wstring name, Expression expr) + { + this.type = NodeType.DefineVariable; + this.name = name; + this.expression = expr; + } +} +class DefineArray : Statement +{ + wstring name; + int[] dim; + this(wstring name, int[] dim) + { + this.type = NodeType.DefineArray; + this.name = name; + this.dim = dim; + } +} diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index fd4429b..0ece249 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -52,6 +52,10 @@ class Lexical reserved["GOSUB"] = TokenType.Gosub; reserved["RETURN"] = TokenType.Return; reserved["END"] = TokenType.End; + reserved["BREAK"] = TokenType.Break; + reserved["CONTINUE"] = TokenType.Continue; + reserved["VAR"] = TokenType.Var; + reserved["DIM"] = TokenType.Var; reserved.rehash(); line = 1; } @@ -521,6 +525,16 @@ class Parser case TokenType.End: node = new End(); break; + case TokenType.Break: + node = new Break(); + break; + case TokenType.Continue: + node = new Continue(); + break; + case TokenType.Var: + lex.popFront(); + node = var(); + break; default: syntaxError(); break; @@ -528,6 +542,34 @@ class Parser lex.popFront(); return node; } + Statement var() + { + Token token = lex.front(); + if(token.type != TokenType.Iden) + { + //TODO:VAR("A")の実装 + syntaxError(); + return null; + } + wstring name = token.value.stringValue; + lex.popFront(); + token = lex.front(); + Expression expr; + //VAR iden=expr + if(token.type == TokenType.Equal) + { + lex.popFront(); + expr = expression(); + } + DefineVariable node = new DefineVariable(name, expr); + //VARの評価順は順番通り + //VAR iden[=expr], + if(token.type == TokenType.Comma) + { + lex.popFront(); + } + return node; + } For forStatement() { For node; diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index f334b5b..1c10c52 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -47,6 +47,9 @@ enum TokenType Gosub, Return, End, + Break, + Continue, + Var, } struct Token diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index f86567a..3a46349 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -18,7 +18,7 @@ struct Value int integerValue; double doubleValue; wstring stringValue; - int[] intArray; + Array!int intArray; } this(int value) { @@ -70,3 +70,47 @@ struct Value } } } +class Array(T) +{ + T[] array; + //最大要素数2^^31 + //4次元配列 + int[4] dim; + int dimCount; + this(int len) + { + dim[0] = len; + dim[1] = 0; + dim[2] = 0; + dim[3] = 0; + array = new T[len]; + dimCount = 1; + } + this(int[] dim) + { + int len = 1; + foreach(int i; dim) + { + len *= i; + } + array = new T[len]; + dimCount = dim.length; + } + T opIndex(int i1) + { + return array[i1]; + } + T opIndex(int i1, int i2) + { + return array[i1 * dim[0] + i2]; + } + T opIndex(int i1, int i2, int i3) + { + return array[i1 * dim[0] * dim[1] + i2 * dim[1] + i3]; + } + T opIndex(int i1, int i2, int i3, int i4) + { + return array[i1];//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3]; + } + +}