1
0

FORを実�

This commit is contained in:
otya128
2015-06-07 13:28:19 +09:00
parent 46b7b2ede3
commit 65fe8558a2
6 changed files with 243 additions and 5 deletions

View File

@@ -33,6 +33,11 @@ class VM
} }
void pop(out Value value) void pop(out Value value)
{ {
if(stacki <= 0)
{
writeln("Stack underflow");
readln();
}
value = stack[--stacki]; value = stack[--stacki];
} }
Value testGetGlobaVariable(wstring name) Value testGetGlobaVariable(wstring name)
@@ -162,6 +167,24 @@ class Operate : Code
case TokenType.Div: case TokenType.Div:
ld /= rd; ld /= rd;
break; break;
case TokenType.Equal:
ld = ld == rd;
break;
case TokenType.NotEqual:
ld = ld != rd;
break;
case TokenType.Less:
ld = ld < rd;
break;
case TokenType.LessEqual:
ld = ld <= rd;
break;
case TokenType.Greater:
ld = ld > rd;
break;
case TokenType.GreaterEqual:
ld = ld >= rd;
break;
default: default:
writeln("NotImpl: ", operator); writeln("NotImpl: ", operator);
break; break;

View File

@@ -17,6 +17,10 @@ class Compiler
int[wstring] global; int[wstring] global;
int[wstring] globalLabel; int[wstring] globalLabel;
int globalIndex = 0; int globalIndex = 0;
void genCode(Code c)
{
code ~= c;
}
void genCodeImm(Value value) void genCodeImm(Value value)
{ {
code ~= new Push(value); code ~= new Push(value);
@@ -43,6 +47,12 @@ class Compiler
code ~= c; code ~= c;
return c; return c;
} }
GotoAddr genCodeGoto(int addr)
{
auto c = new GotoAddr(addr);
code ~= c;
return c;
}
GotoTrue genCodeGotoTrue() GotoTrue genCodeGotoTrue()
{ {
auto c = new GotoTrue(-1); auto c = new GotoTrue(-1);
@@ -137,6 +147,64 @@ class Compiler
else_.address = code.length; else_.address = code.length;
} }
} }
void compileFor(For node)
{
compileStatement(node.initExpression);
auto forstart = code.length;
compileExpression(node.stepExpression);
genCodeImm(Value(0));
//step>=0
genCodeOP(TokenType.GreaterEqual);
auto positiveZero = genCodeGotoTrue();//正の値または0
//stepが負の値の時の処理
//toよりcounterが小さい場合はBREAK
//to==counterの時はBREAKしない
//t c
//0>0 false
//FOR I=0 TO -1 STEP -1
//-1>0 false
//1>0 true
/*
genCodeImm(Value("Helloneg\n"));
compileExpression(node.toExpression);
genCodeImm(Value("\nTo\n"));
compileExpression(node.stepExpression);
genCodeImm(Value("Step\n"));
*/
//code ~= new PrintCode(5);
compileExpression(node.toExpression);
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
genCodeOP(TokenType.Greater);
auto breakAddr = genCodeGotoTrue();
auto forAddr = genCodeGoto();
positiveZero.address = code.length;
//stepが正の値の時の処理
//toよりcounterが大きい場合はBREAK
//t c
//0<0 false
//1<0 false
//0<1 true break
/*
genCodeImm(Value("HelloPositive\n"));
compileExpression(node.toExpression);
genCodeImm(Value("\nTo\n"));
compileExpression(node.stepExpression);
genCodeImm(Value("Step\n"));
code ~= new PrintCode(5);*/
compileExpression(node.toExpression);
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
genCodeOP(TokenType.Less);
genCode(breakAddr);
forAddr.address = code.length;
compileStatements(node.statements);
//counterに加算する
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
compileExpression(node.stepExpression);
genCodeOP(TokenType.Plus);
genCodePopGlobal(getGlobalVarIndex(node.initExpression.name));
genCodeGoto(forstart);
breakAddr.address = code.length;
}
void compileStatements(Statements statements) void compileStatements(Statements statements)
{ {
@@ -193,6 +261,9 @@ class Compiler
case NodeType.If: case NodeType.If:
compileIf(cast(If)i); compileIf(cast(If)i);
break; break;
case NodeType.For:
compileFor(cast(For)i);
break;
default: default:
stderr.writeln("Compile:NotImpl ", i.type); stderr.writeln("Compile:NotImpl ", i.type);
} }

View File

@@ -9,14 +9,19 @@ int main(string[] argv)
} }
auto parser = new Parser( auto parser = new Parser(
"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A //"@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2 PRINT A
IF 1 THEN PRINT 2 "IF 1 THEN PRINT 2
IF 0 THEN PRINT 4 ELSE PRINT 5 IF 0 THEN PRINT 4 ELSE PRINT 5
IF 0 THEN IF 0 THEN
PRINT 111 PRINT 111
ELSE ELSE
PRINT 222 PRINT 222
ENDIF ENDIF
FOR I=-2 TO -9 STEP -2
PRINT I
NEXT
?I
"); ");
auto vm = parser.compile(); auto vm = parser.compile();
vm.run(); vm.run();

View File

@@ -21,6 +21,7 @@ enum NodeType
Label, Label,
Goto, Goto,
If, If,
For,
} }
abstract class Node abstract class Node
{ {
@@ -209,3 +210,26 @@ class If : Statement
return !(else_ is null) && else_.statements.length != 0; return !(else_ is null) && else_.statements.length != 0;
} }
} }
class For : Statement
{
Assign initExpression;
Expression toExpression;
Expression stepExpression;
Statements statements;
this(Assign assign, Expression toExpression, Expression stepExpression, Statements statements)
{
this.type = NodeType.For;
this.initExpression = assign;
this.toExpression = toExpression;
this.stepExpression = stepExpression;
this.statements = statements;
}
this(Assign assign, Expression toExpression, Statements statements)
{
this.type = NodeType.For;
this.initExpression = assign;
this.toExpression = toExpression;
this.stepExpression = null;
this.statements = statements;
}
}

View File

@@ -33,6 +33,8 @@ class Lexical
table['\n'] = TokenType.NewLine; table['\n'] = TokenType.NewLine;
table['?'] = TokenType.Print; table['?'] = TokenType.Print;
table['='] = TokenType.Assign; table['='] = TokenType.Assign;
table['<'] = TokenType.Less;
table['>'] = TokenType.Greater;
reserved["OR"] = TokenType.Or; reserved["OR"] = TokenType.Or;
reserved["AND"] = TokenType.And; reserved["AND"] = TokenType.And;
reserved["XOR"] = TokenType.Xor; reserved["XOR"] = TokenType.Xor;
@@ -43,6 +45,8 @@ class Lexical
reserved["THEN"] = TokenType.Then; reserved["THEN"] = TokenType.Then;
reserved["ELSE"] = TokenType.Else; reserved["ELSE"] = TokenType.Else;
reserved["ENDIF"] = TokenType.Endif; reserved["ENDIF"] = TokenType.Endif;
reserved["FOR"] = TokenType.For;
reserved["NEXT"] = TokenType.Next;
reserved.rehash(); reserved.rehash();
line = 1; line = 1;
} }
@@ -111,6 +115,21 @@ class Lexical
token = Token(TokenType.Iden, Value(iden)); token = Token(TokenType.Iden, Value(iden));
break; break;
} }
if(c == '"')
{
i++;
wstring str;
for(;i < code.length;i++)
{
c = code[i];
if(c == '"')//"を閉じない文も許容
{
i++;
break;
}
str ~= c;
}
}
if(c == '@') if(c == '@')
{ {
//ラベル(もしくは文字列) //ラベル(もしくは文字列)
@@ -129,7 +148,30 @@ class Lexical
token = Token(TokenType.Label, Value(iden)); token = Token(TokenType.Label, Value(iden));
break; break;
} }
if(c == '=' && i + 1 < code.length && code[i + 1] == '=')
{
token = Token(TokenType.Equal);
i += 2;
break;
}
if(c == '!' && i + 1 < code.length && code[i + 1] == '=')
{
token = Token(TokenType.NotEqual);
i += 2;
break;
}
if(c == '<' && i + 1 < code.length && code[i + 1] == '=')
{
token = Token(TokenType.LessEqual);
i += 2;
break;
}
if(c == '>' && i + 1 < code.length && code[i + 1] == '=')
{
token = Token(TokenType.GreaterEqual);
i += 2;
break;
}
if(table[cast(char)c] == TokenType.Unknown) if(table[cast(char)c] == TokenType.Unknown)
{ {
//error //error
@@ -340,6 +382,22 @@ class Parser
} }
return statements; return statements;
} }
Statements forStatements()
{
auto statements = new Statements();
while(!lex.empty())
{
auto type = lex.front().type;
if(type == TokenType.Next) break;
auto statement = statement();
if(statement != Statement.NOP)
{
statements.addStatement(statement);
}
}
lex.popFront();
return statements;
}
void syntaxError() void syntaxError()
{ {
stderr.writeln("Syntax error (", lex.getLine(), ')', " Mysterious ", lex.front().type); stderr.writeln("Syntax error (", lex.getLine(), ')', " Mysterious ", lex.front().type);
@@ -362,7 +420,7 @@ class Parser
if(token.type == TokenType.Assign) if(token.type == TokenType.Assign)
{ {
node = assign(name); node = assign(name);
break; return node;
} }
//命令呼び出し //命令呼び出し
} }
@@ -381,6 +439,9 @@ class Parser
case TokenType.If: case TokenType.If:
node = if_(); node = if_();
return node; return node;
case TokenType.For:
node = forStatement();
break;
default: default:
syntaxError(); syntaxError();
break; break;
@@ -388,6 +449,45 @@ class Parser
lex.popFront(); lex.popFront();
return node; return node;
} }
For forStatement()
{
For node;
lex.popFront();
Statement initStatement = statement();
if(initStatement.type != NodeType.Assign)
{
syntaxError();
return null;
}
Assign init = cast(Assign)initStatement;
auto token = lex.front();
//TO,STEPは予約語ではない
if(token.type != TokenType.Iden || token.value.stringValue != "TO")
{
syntaxError();
return null;
}
lex.popFront();
Expression to = expression();
token = lex.front();
Expression step;
//TO,STEPは予約語ではない
if(token.type == TokenType.Iden && token.value.stringValue == "STEP")
{
lex.popFront();
step = expression();
}
else
{
//とりあえず
step = new Constant(Value(1));
}
token = lex.front();
Statements statements = forStatements();
node = new For(init, to, step, statements);
return node;
}
If if_() If if_()
{ {
lex.popFront(); lex.popFront();
@@ -430,7 +530,7 @@ class Parser
Statements else_; Statements else_;
if(token.type == TokenType.Else) if(token.type == TokenType.Else)
{ {
if(lex.front().type == TokenType.NewLine) if(!multiline && lex.front().type == TokenType.NewLine)
{ {
//3.1現在だとエラー //3.1現在だとエラー
syntaxError(); syntaxError();
@@ -438,6 +538,7 @@ class Parser
if(multiline) if(multiline)
{ {
else_ = multilineIfStatements(); else_ = multilineIfStatements();
lex.popFront();
} }
else else
{ {
@@ -603,6 +704,12 @@ class Parser
//文字列リテラル //文字列リテラル
break; break;
case TokenType.Minus:
//TODO:UnaryOperatorの実装
//とりあえず0-exprを作成
lex.popFront();
node = new BinaryOperator(new Constant(Value(0)), TokenType.Minus, expression());
return node;
default: default:
return node; return node;
} }

View File

@@ -30,6 +30,14 @@ enum TokenType
Then, Then,
Else, Else,
Endif, Endif,
For,
Next,
Equal,
NotEqual,
Less,//<
Greater,//>
LessEqual,
GreaterEqual,
} }
struct Token struct Token