From 4b530f492edfc1a925afecbb62f802cc6580fb17 Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 13 Jun 2015 19:12:36 +0900 Subject: [PATCH] =?UTF-8?q?=E9=96=A2=E6=95=B0=E5=AE=9A=E7=BE=A9=E3=81=AE?= =?UTF-8?q?=E6=A7=8B=E6=96=87=E8=A7=A3=E6=9E=90=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/compiler.d | 40 ++++++++++++++++ SMILEBASIC/main.d | 6 +++ SMILEBASIC/node.d | 21 ++++++++ SMILEBASIC/parser.d | 109 +++++++++++++++++++++++++++++++++++++++++- SMILEBASIC/token.d | 1 + 5 files changed, 175 insertions(+), 2 deletions(-) diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 1ec576e..fc10181 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -18,6 +18,45 @@ class Scope this.continueAddr = continueAddr; } } +class Function +{ + int address; + wstring name; + int argumentIndex; + int variableIndex; + int[wstring] variable; + int[wstring] label; + this(int address, wstring name) + { + this.address = address; + this.name = name; + } + int getLocalVarIndex(wstring name) + { + int var = this.variable.get(name, 0); + if(var == 0) + { + //local変数をあたる + //それでもだめならOPTION STRICTならエラー + this.variable[name] = var = ++variableIndex; + } + return var; + } + int defineLocalVarIndex(wstring name) + { + int var = this.variable.get(name, 0); + if(var == 0) + { + this.variable[name] = var = ++variableIndex; + } + else + { + //error:二重定義 + throw new DuplicateVariable(); + } + return var; + } +} class Compiler { ValueType getType(wstring name) @@ -45,6 +84,7 @@ class Compiler Code[] code; int[wstring] global; int[wstring] globalLabel; + Function[wstring] functions; int globalIndex = 0; void genCode(Code c) { diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index c3041e9..0519575 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -63,6 +63,12 @@ END @A ?\"SUBROUTINE TEST\" RETURN +DEF A() + ?\"FUNCTION A\" +END +DEF B(A,B[],C) + ?\"FUNCTION B\" +END "); version(none) auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring); auto vm = parser.compile(); diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index f17faba..6978f9d 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -33,6 +33,7 @@ enum NodeType DefineVariable, DefineArray, ArrayAssign, + DefineFunction, } abstract class Node { @@ -359,3 +360,23 @@ class ArrayAssign : Statement this.assignExpression = assign; } } +class DefineFunction : Statement +{ + wstring[] arguments; + wstring[] outArguments; + wstring name; + Statements functionBody; + this(wstring name) + { + this.type = NodeType.DefineFunction; + this.name = name; + } + void addArgument(wstring name) + { + this.arguments ~= name; + } + void addOutArgument(wstring name) + { + this.outArguments ~= name; + } +} diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 751b94e..839100d 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -58,6 +58,7 @@ class Lexical reserved["CONTINUE"] = TokenType.Continue; reserved["VAR"] = TokenType.Var; reserved["DIM"] = TokenType.Var; + reserved["DEF"] = TokenType.Def; reserved.rehash(); line = 1; } @@ -402,8 +403,112 @@ class Parser auto statements = new Statements(); while(!lex.empty()) { - //if token == DEF - // + auto token = lex.front(); + Statement statement; + if(token.type == TokenType.Def) + { + statement = defineFunction(); + } + else + { + statement = this.statement(); + } + if(statement != Statement.NOP) + { + statements.addStatement(statement); + } + } + return statements; + } + wstring getFunctionArgument() + { + auto token = lex.front(); + if(token.type != TokenType.Iden) + { + syntaxError(); + return ""; + } + lex.popFront(); + if(lex.front().type == TokenType.LBracket) + { + lex.popFront(); + if(lex.front().type != TokenType.RBracket) + { + syntaxError(); + return ""; + } + lex.popFront(); + } + return token.value.stringValue; + } + DefineFunction defineFunction() + { + lex.popFront(); + auto token = lex.front(); + if(token.type != TokenType.Iden) + { + syntaxError(); + return null; + } + DefineFunction node = new DefineFunction(token.value.stringValue); + lex.popFront(); + token = lex.front(); + if(token.type == TokenType.LParen) + { + lex.popFront(); + //MEMO:引数に[]を付けようが扱いは同一 + while(true) + { + if(lex.front().type == TokenType.RParen) + { + lex.popFront(); + break; + } + wstring arg = getFunctionArgument(); + if(arg.length == 0) + { + return null; + } + node.addArgument(arg); + token = lex.front(); + if(token.type == TokenType.Comma) + { + lex.popFront(); + continue; + } + //MEMO:引数に[]を付けようが扱いは同一 + if(token.type == TokenType.RParen) + { + lex.popFront(); + break; + } + syntaxError(); + return null; + } + } + else + { + //void関数にRETURN核とsyntaxerror + writeln("NOTIMPL:DEF VOID"); + syntaxError(); + return null; + } + node.functionBody = functionStatements(); + return node; + } + Statements functionStatements() + { + auto statements = new Statements(); + while(true) + { + auto type = lex.front().type; + if(type == TokenType.End) break; + if(lex.empty()) + { + //TODO:DEF without edn + syntaxError(); + break; + } auto statement = statement(); if(statement != Statement.NOP) { diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index 2385c39..c41b04e 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -52,6 +52,7 @@ enum TokenType Var, LBracket,//[ RBracket,//] + Def, } struct Token