REPEAT~UNTILを実装
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -70,6 +70,8 @@ enum TokenType
|
||||
Call,
|
||||
Common,
|
||||
Elseif,
|
||||
Repeat,
|
||||
Until,
|
||||
}
|
||||
|
||||
struct Token
|
||||
|
||||
Reference in New Issue
Block a user