FORを実�
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ enum TokenType
|
|||||||
Then,
|
Then,
|
||||||
Else,
|
Else,
|
||||||
Endif,
|
Endif,
|
||||||
|
For,
|
||||||
|
Next,
|
||||||
|
Equal,
|
||||||
|
NotEqual,
|
||||||
|
Less,//<
|
||||||
|
Greater,//>
|
||||||
|
LessEqual,
|
||||||
|
GreaterEqual,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user