1
0

関数定義の構文解析を実�

This commit is contained in:
otya128
2015-06-13 19:12:36 +09:00
parent 09ff06ec56
commit 4b530f492e
5 changed files with 175 additions and 2 deletions

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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)
{

View File

@@ -52,6 +52,7 @@ enum TokenType
Var,
LBracket,//[
RBracket,//]
Def,
}
struct Token