1
0

REPEAT~UNTILを実装

This commit is contained in:
otya128
2016-09-02 20:39:31 +09:00
parent 3e2cb7b8a7
commit 2f50fc5ba9
5 changed files with 103 additions and 22 deletions

View File

@@ -1,3 +1,35 @@
'REPEAT TEST
?"REPEAT(1)"
VAR REPEATTEST
REPEAT
REPEATTEST=TRUE
BREAK
ASSERT__ FALSE, "REPEAT"
UNTIL FALSE
ASSERT__ REPEATTEST, "REPEAT"
?"REPEAT(2)"
VAR REPEATTEST2
REPEAT
REPEATTEST2=1
CONTINUE
ASSERT__ FALSE, "REPEAT"
UNTIL REPEATTEST2
ASSERT__ REPEATTEST2, "REPEAT"
?"REPEAT(3)"
REPEAT
CONTINUE
ASSERT__ FALSE, "REPEAT"
UNTIL TRUE
?"REPEAT(4)"
VAR REPEATTEST4
REPEAT
REPEATTEST4=TRUE
UNTIL TRUE
ASSERT__ REPEATTEST4, "REPEAT"
VAR IFTEST=FALSE
IF TRUE THEN

View File

@@ -656,28 +656,6 @@ class Compiler
compileStatements(node.then, sc);
//もしelseもあるのならば、endifに飛ぶ
GotoAddr then;
/*
if 0 then
elseif 0 then
elseif 1 then
else
endif
push 0
gotofalse else
goto endif
else:
push 0
gototrue elif1else
push 1
gototrue elif2
goto else
elif1:
goto endif
elif2:
goto endif
else:
endif:
*/
if (node.hasElseif)
{
then = genCodeGoto();
@@ -765,6 +743,17 @@ class Compiler
s.breakAddr.address = cast(int)code.length;
breakAddr.address = cast(int)code.length;
}
void compileRepeat(RepeatUntil node, Scope s)
{
auto start = cast(int)code.length;
s = new Scope(new GotoAddr(-1), new GotoAddr(-1), s);
compileStatements(node.statements, s);
s.continueAddr.address = cast(int)code.length;
compileExpression(node.condExpression, s);
auto a = genCodeGotoFalse();
a.address = start;
s.breakAddr.address = cast(int)code.length;
}
void compileVar(Var node, Scope sc)
{
foreach(Statement v ; node.define)
@@ -1096,6 +1085,9 @@ class Compiler
case NodeType.Input:
compileInput(cast(Input)i, s);
break;
case NodeType.RepeatUntil:
compileRepeat(cast(RepeatUntil)i, s);
break;
default:
stderr.writeln("Compile:NotImpl ", i.type);
}

View File

@@ -41,6 +41,7 @@ enum NodeType
Restore,
On,
Input,
RepeatUntil,
}
abstract class Node
{
@@ -564,3 +565,16 @@ class Input : Statement
variables ~= lvalue;
}
}
class RepeatUntil : Statement
{
Expression condExpression;
Statements statements;
this(Expression condExpression, Statements statements, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.RepeatUntil;
this.condExpression = condExpression;
this.statements = statements;
}
}

View File

@@ -79,6 +79,8 @@ class Lexical
reserved["USE"] = TokenType.Use;
reserved["EXEC"] = TokenType.Exec;
reserved["ELSEIF"] = TokenType.Elseif;
reserved["REPEAT"] = TokenType.Repeat;
reserved["UNTIL"] = TokenType.Until;
reserved.rehash();
}
this(wstring input)
@@ -788,6 +790,21 @@ class Parser
lex.popFront();
return statements;
}
Statements repeatStatements()
{
auto statements = new Statements(lex.location);
while(!lex.empty())
{
auto type = lex.front().type;
if(type == TokenType.Until) break;
auto statement = statement();
if(statement != Statement.NOP)
{
statements.addStatement(statement);
}
}
return statements;
}
void syntaxError()
{
stderr.writeln("Syntax error (", lex.getLine(), ')', " Mysterious ", lex.front().type);
@@ -944,6 +961,9 @@ class Parser
case TokenType.While:
node = whileStatement();
break;
case TokenType.Repeat:
node = repeatStatement();
break;
case TokenType.Inc:
case TokenType.Dec:
return incStatement();
@@ -1352,6 +1372,27 @@ class Parser
auto node = new While(expr, statements, lex.location);
return node;
}
RepeatUntil repeatStatement()
{
lex.popFront();
Statements statements = repeatStatements();
auto token = lex.front;
if (token.type != TokenType.Until)
{
//TODO:REPEAT without UNTIL
syntaxError();
return null;
}
lex.popFront();
auto expr = expression();
if(expr is null)
{
syntaxError();
return null;
}
auto node = new RepeatUntil(expr, statements, lex.location);
return node;
}
If if_()
{
lex.popFront();

View File

@@ -70,6 +70,8 @@ enum TokenType
Call,
Common,
Elseif,
Repeat,
Until,
}
struct Token