From 2eaab2ef5556f18194eb4e4053ddeb7db1631b0a Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 6 Jun 2015 14:51:45 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=A9=E3=83=99=E3=83=AB=E3=81=A8GOTO?= =?UTF-8?q?=E3=82=92=E5=AE=9F=EF=BF=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/VM.d | 16 +++++++++++++++- SMILEBASIC/compiler.d | 23 +++++++++++++++++++++++ SMILEBASIC/main.d | 2 +- SMILEBASIC/node.d | 20 ++++++++++++++++++++ SMILEBASIC/parser.d | 30 ++++++++++++++++++++++++++++++ SMILEBASIC/token.d | 2 ++ 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index be59165..26936d3 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -50,6 +50,7 @@ enum CodeType Gosub, Print, PopG, + GotoS, } abstract class Code { @@ -167,7 +168,7 @@ class Operate : Code vm.push(l); } } -class Goto : Code +class GotoAddr : Code { int address; this(int addr) @@ -180,6 +181,19 @@ class Goto : Code vm.pc = address - 1; } } +class GotoS : Code +{ + wstring label; + this(wstring label) + { + this.type = CodeType.GotoS; + this.label = label; + } + override void execute(VM vm) + { + stderr.writeln("can't execute"); + } +} class Gosub : Code { diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 10bf727..9d44aa0 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -15,6 +15,7 @@ class Compiler Code[] code; int[wstring] global; + int[wstring] globalLabel; int globalIndex = 0; void genCodeImm(Value value) { @@ -32,6 +33,10 @@ class Compiler { code ~= new Operate(op); } + void genCodeGoto(wstring label) + { + code ~= new GotoS(label); + } int defineGlobalVarIndex(wstring name) { int global = this.global.get(name, 0); @@ -129,10 +134,28 @@ class Compiler genCodePopGlobal(getGlobalVarIndex(assign.name)); } break; + case NodeType.Label: + { + auto label = cast(Label)i; + globalLabel[label.label] = code.length; + } + break; + case NodeType.Goto: + { + genCodeGoto((cast(Goto)i).label); + } + break; default: stderr.writeln("Compile:NotImpl ", i.type); } } + foreach(int i, Code c; code) + { + if(c.type == CodeType.GotoS) + { + code[i] = new GotoAddr(globalLabel[(cast(GotoS)c).label]); + } + } return new VM(code, globalIndex + 1, global); } } diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index 1da1eed..89d58ff 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -8,7 +8,7 @@ int main(string[] argv) writeln(parser.calc()); } - auto parser = new Parser("A=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A"); + auto parser = new Parser("@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A:GOTO@A"); auto vm = parser.compile(); vm.run(); readln(); diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index 79dbc94..710a1ed 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -18,6 +18,8 @@ enum NodeType Assign, CallFunctionStatement, Print, + Label, + Goto, } abstract class Node { @@ -171,3 +173,21 @@ class Assign : Statement this.expression = expr; } } +class Label : Statement +{ + wstring label; + this(wstring name) + { + this.type = NodeType.Label; + this.label = name; + } +} +class Goto : Statement +{ + wstring label; + this(wstring name) + { + this.type = NodeType.Goto; + this.label = name; + } +} diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 15f5a4e..98f8bbb 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -38,6 +38,7 @@ class Lexical reserved["XOR"] = TokenType.Xor; reserved["NOT"] = TokenType.Not; reserved["PRINT"] = TokenType.Print; + reserved["GOTO"] = TokenType.Goto; reserved.rehash(); line = 1; } @@ -106,6 +107,25 @@ class Lexical token = Token(TokenType.Iden, Value(iden)); break; } + if(c == '@') + { + //ラベル(もしくは文字列) + wstring iden; + iden ~= c; + i++; + for(;i < code.length;i++) + { + c = code[i]; + if(!c.isAlpha()) + { + break; + } + iden ~= c; + } + token = Token(TokenType.Label, Value(iden)); + break; + } + if(table[cast(char)c] == TokenType.Unknown) { //error @@ -310,6 +330,12 @@ class Parser case TokenType.Colon: case TokenType.NewLine: break; + case TokenType.Label: + return new Label(token.value.stringValue); + case TokenType.Goto: + lex.popFront(); + token = lex.front(); + return new Goto(token.value.stringValue); default: syntaxError(); break; @@ -464,6 +490,10 @@ class Parser if(token.type != TokenType.RParen) //error {} + break; + case TokenType.Label://3.1 + //文字列リテラル + break; default: return node; diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index 1b38f86..05a59a4 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -25,6 +25,8 @@ enum TokenType Semicolon, NewLine, Assign, + Label, + Goto, } struct Token