ELSEIFを実装
This commit is contained in:
@@ -1,3 +1,44 @@
|
||||
|
||||
VAR IFTEST=FALSE
|
||||
IF TRUE THEN
|
||||
IFTEST=TRUE
|
||||
ENDIF
|
||||
ASSERT__ IFTEST, "IF"
|
||||
|
||||
VAR IFTEST2=FALSE
|
||||
IF TRUE THEN IFTEST2=TRUE
|
||||
ASSERT__ IFTEST2, "IF"
|
||||
|
||||
VAR ELSETEST=FALSE
|
||||
IF FALSE THEN
|
||||
ELSE
|
||||
ELSETEST=TRUE
|
||||
ENDIF
|
||||
ASSERT__ ELSETEST, "ELSE"
|
||||
|
||||
VAR ELSETEST2=FALSE
|
||||
IF FALSE THEN ELSE ELSETEST2=TRUE:ENDIF
|
||||
ASSERT__ ELSETEST2, "ELSE"
|
||||
|
||||
|
||||
VAR ELSEIFTEST=FALSE
|
||||
IF FALSE THEN
|
||||
ELSEIFTEST=FALSE
|
||||
ELSEIF FALSE THEN
|
||||
ELSEIFTEST=FALSE
|
||||
ELSEIF TRUE THEN
|
||||
ELSEIFTEST=TRUE
|
||||
ELSEIF FALSE THEN
|
||||
ELSEIFTEST=FALSE
|
||||
ELSE
|
||||
ELSEIFTEST=FALSE
|
||||
ENDIF
|
||||
ASSERT__ ELSEIFTEST, "ELSEIFTEST"
|
||||
|
||||
VAR ELSEIFTEST2=FALSE
|
||||
IF FALSE THEN ELSEIFTEST2=FALSE ELSEIF FALSE THEN ELSEIFTEST2=FALSE ELSEIF TRUE THEN ELSEIFTEST2=TRUE ELSEIF FALSE THEN ELSEIFTEST2=FALSE ELSE ELSEIFTEST2=FALSE ENDIF
|
||||
ASSERT__ ELSEIFTEST2, "ELSEIFTEST"
|
||||
|
||||
DEF CALLTEST(V)
|
||||
RETURN V
|
||||
END
|
||||
|
||||
@@ -656,7 +656,46 @@ class Compiler
|
||||
compileStatements(node.then, sc);
|
||||
//もしelseもあるのならば、endifに飛ぶ
|
||||
GotoAddr then;
|
||||
if(node.hasElse)
|
||||
/*
|
||||
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();
|
||||
else_.address = cast(int)code.length;
|
||||
GotoFalse else2;
|
||||
foreach(t; node.elseif)
|
||||
{
|
||||
compileExpression(t[1], sc);
|
||||
else2 = genCodeGotoFalse();
|
||||
compileStatements(t[0], sc);
|
||||
genCode(then);
|
||||
else2.address = cast(int)code.length;
|
||||
}
|
||||
if(node.hasElse)
|
||||
compileStatements(node.else_, sc);
|
||||
then.address = cast(int)code.length;
|
||||
}
|
||||
else if(node.hasElse)
|
||||
{
|
||||
then = genCodeGoto();
|
||||
else_.address = cast(int)code.length;
|
||||
|
||||
@@ -247,21 +247,28 @@ class Goto : Statement
|
||||
}
|
||||
class If : Statement
|
||||
{
|
||||
import std.typecons;
|
||||
Expression condition;
|
||||
Statements then;
|
||||
Statements else_;
|
||||
this(Expression condition, Statements t, Statements e, SourceLocation loc)
|
||||
Tuple!(Statements, Expression)[] elseif;
|
||||
this(Expression condition, Statements t, Statements e, Tuple!(Statements, Expression)[] elif, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.If;
|
||||
this.condition = condition;
|
||||
this.then = t;
|
||||
this.else_ = e;
|
||||
this.elseif = elif;
|
||||
}
|
||||
bool hasElse()
|
||||
{
|
||||
return !(else_ is null) && else_.statements.length != 0;
|
||||
}
|
||||
bool hasElseif()
|
||||
{
|
||||
return !(elseif is null) && elseif.length != 0;
|
||||
}
|
||||
}
|
||||
class For : Statement
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ class Lexical
|
||||
reserved["COMMON"] = TokenType.Common;
|
||||
reserved["USE"] = TokenType.Use;
|
||||
reserved["EXEC"] = TokenType.Exec;
|
||||
reserved["ELSEIF"] = TokenType.Elseif;
|
||||
reserved.rehash();
|
||||
}
|
||||
this(wstring input)
|
||||
@@ -708,6 +709,7 @@ class Parser
|
||||
flag = false;
|
||||
if(type == TokenType.NewLine) break;
|
||||
if(type == TokenType.Else) break;
|
||||
if(type == TokenType.Elseif) break;
|
||||
if(type == TokenType.Endif) break;
|
||||
if(type == TokenType.Label)
|
||||
{
|
||||
@@ -730,6 +732,7 @@ class Parser
|
||||
{
|
||||
auto type = lex.front().type;
|
||||
if(type == TokenType.Else) break;
|
||||
if(type == TokenType.Elseif) break;
|
||||
if(type == TokenType.Endif) break;
|
||||
auto statement = statement();
|
||||
if(statement != Statement.NOP)
|
||||
@@ -1388,6 +1391,47 @@ class Parser
|
||||
}
|
||||
token = lex.front();
|
||||
lex.popFront();
|
||||
import std.typecons;
|
||||
Tuple!(Statements, Expression)[] elseif = new Tuple!(Statements, Expression)[0];
|
||||
while(token.type == TokenType.Elseif)
|
||||
{
|
||||
token = lex.front();
|
||||
auto elseifcond = expression();
|
||||
if(elseifcond is null)
|
||||
{
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
token = lex.front();
|
||||
if(token.type != TokenType.Then)
|
||||
{
|
||||
if(token.type != TokenType.Goto)
|
||||
{
|
||||
//IF expr GOSUBは不可
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if(token.type != TokenType.Goto)
|
||||
{
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
}
|
||||
if(!multiline && lex.front().type == TokenType.NewLine)
|
||||
{
|
||||
syntaxError();
|
||||
}
|
||||
if(multiline)
|
||||
{
|
||||
elseif ~= tuple(multilineIfStatements(), elseifcond);
|
||||
}
|
||||
else
|
||||
{
|
||||
elseif ~= tuple(ifStatements(), elseifcond);
|
||||
}
|
||||
token = lex.front();
|
||||
lex.popFront();
|
||||
}
|
||||
Statements else_;
|
||||
if(token.type == TokenType.Else)
|
||||
{
|
||||
@@ -1399,14 +1443,14 @@ class Parser
|
||||
if(multiline)
|
||||
{
|
||||
else_ = multilineIfStatements();
|
||||
lex.popFront();
|
||||
}
|
||||
else
|
||||
{
|
||||
else_ = ifStatements();
|
||||
}
|
||||
lex.popFront();
|
||||
}
|
||||
auto if_ = new If(expr, then, else_, lex.location);
|
||||
auto if_ = new If(expr, then, else_, elseif, lex.location);
|
||||
return if_;
|
||||
}
|
||||
Assign assign(wstring name)
|
||||
@@ -1449,14 +1493,16 @@ class Parser
|
||||
}
|
||||
if(token.type != TokenType.Colon && token.type != TokenType.NewLine &&
|
||||
token.type != TokenType.Semicolon && token.type != TokenType.Comma &&
|
||||
token.type != TokenType.Else && token.type != TokenType.Endif)
|
||||
token.type != TokenType.Else && token.type != TokenType.Endif &&
|
||||
token.type != TokenType.Elseif && token.type != TokenType.Print)
|
||||
{
|
||||
syntaxError();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(token.type == TokenType.Colon || token.type == TokenType.NewLine ||
|
||||
token.type == TokenType.Else || token.type == TokenType.Endif)
|
||||
token.type == TokenType.Else || token.type == TokenType.Endif ||
|
||||
token.type == TokenType.Elseif || token.type == TokenType.Print)
|
||||
{
|
||||
print.addLine();
|
||||
break;
|
||||
|
||||
@@ -69,6 +69,7 @@ enum TokenType
|
||||
Exec,
|
||||
Call,
|
||||
Common,
|
||||
Elseif,
|
||||
}
|
||||
|
||||
struct Token
|
||||
|
||||
Reference in New Issue
Block a user