1
0

break,continue実装,var,dim実装中

This commit is contained in:
otya128
2015-06-10 19:09:15 +09:00
parent 2e9e966f0b
commit 7c383dff1a
6 changed files with 180 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -47,6 +47,9 @@ enum TokenType
Gosub,
Return,
End,
Break,
Continue,
Var,
}
struct Token

View File

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