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
|
VAR IFTEST=FALSE
|
||||||
IF TRUE THEN
|
IF TRUE THEN
|
||||||
|
|||||||
@@ -656,28 +656,6 @@ class Compiler
|
|||||||
compileStatements(node.then, sc);
|
compileStatements(node.then, sc);
|
||||||
//もしelseもあるのならば、endifに飛ぶ
|
//もしelseもあるのならば、endifに飛ぶ
|
||||||
GotoAddr then;
|
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)
|
if (node.hasElseif)
|
||||||
{
|
{
|
||||||
then = genCodeGoto();
|
then = genCodeGoto();
|
||||||
@@ -765,6 +743,17 @@ class Compiler
|
|||||||
s.breakAddr.address = cast(int)code.length;
|
s.breakAddr.address = cast(int)code.length;
|
||||||
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)
|
void compileVar(Var node, Scope sc)
|
||||||
{
|
{
|
||||||
foreach(Statement v ; node.define)
|
foreach(Statement v ; node.define)
|
||||||
@@ -1096,6 +1085,9 @@ class Compiler
|
|||||||
case NodeType.Input:
|
case NodeType.Input:
|
||||||
compileInput(cast(Input)i, s);
|
compileInput(cast(Input)i, s);
|
||||||
break;
|
break;
|
||||||
|
case NodeType.RepeatUntil:
|
||||||
|
compileRepeat(cast(RepeatUntil)i, s);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ enum NodeType
|
|||||||
Restore,
|
Restore,
|
||||||
On,
|
On,
|
||||||
Input,
|
Input,
|
||||||
|
RepeatUntil,
|
||||||
}
|
}
|
||||||
abstract class Node
|
abstract class Node
|
||||||
{
|
{
|
||||||
@@ -564,3 +565,16 @@ class Input : Statement
|
|||||||
variables ~= lvalue;
|
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["USE"] = TokenType.Use;
|
||||||
reserved["EXEC"] = TokenType.Exec;
|
reserved["EXEC"] = TokenType.Exec;
|
||||||
reserved["ELSEIF"] = TokenType.Elseif;
|
reserved["ELSEIF"] = TokenType.Elseif;
|
||||||
|
reserved["REPEAT"] = TokenType.Repeat;
|
||||||
|
reserved["UNTIL"] = TokenType.Until;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
}
|
}
|
||||||
this(wstring input)
|
this(wstring input)
|
||||||
@@ -788,6 +790,21 @@ class Parser
|
|||||||
lex.popFront();
|
lex.popFront();
|
||||||
return statements;
|
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()
|
void syntaxError()
|
||||||
{
|
{
|
||||||
stderr.writeln("Syntax error (", lex.getLine(), ')', " Mysterious ", lex.front().type);
|
stderr.writeln("Syntax error (", lex.getLine(), ')', " Mysterious ", lex.front().type);
|
||||||
@@ -944,6 +961,9 @@ class Parser
|
|||||||
case TokenType.While:
|
case TokenType.While:
|
||||||
node = whileStatement();
|
node = whileStatement();
|
||||||
break;
|
break;
|
||||||
|
case TokenType.Repeat:
|
||||||
|
node = repeatStatement();
|
||||||
|
break;
|
||||||
case TokenType.Inc:
|
case TokenType.Inc:
|
||||||
case TokenType.Dec:
|
case TokenType.Dec:
|
||||||
return incStatement();
|
return incStatement();
|
||||||
@@ -1352,6 +1372,27 @@ class Parser
|
|||||||
auto node = new While(expr, statements, lex.location);
|
auto node = new While(expr, statements, lex.location);
|
||||||
return node;
|
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_()
|
If if_()
|
||||||
{
|
{
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ enum TokenType
|
|||||||
Call,
|
Call,
|
||||||
Common,
|
Common,
|
||||||
Elseif,
|
Elseif,
|
||||||
|
Repeat,
|
||||||
|
Until,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user