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)
|
DEF CALLTEST(V)
|
||||||
RETURN V
|
RETURN V
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -656,7 +656,46 @@ class Compiler
|
|||||||
compileStatements(node.then, sc);
|
compileStatements(node.then, sc);
|
||||||
//もしelseもあるのならば、endifに飛ぶ
|
//もしelseもあるのならば、endifに飛ぶ
|
||||||
GotoAddr then;
|
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();
|
then = genCodeGoto();
|
||||||
else_.address = cast(int)code.length;
|
else_.address = cast(int)code.length;
|
||||||
|
|||||||
@@ -247,21 +247,28 @@ class Goto : Statement
|
|||||||
}
|
}
|
||||||
class If : Statement
|
class If : Statement
|
||||||
{
|
{
|
||||||
|
import std.typecons;
|
||||||
Expression condition;
|
Expression condition;
|
||||||
Statements then;
|
Statements then;
|
||||||
Statements else_;
|
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;
|
super.location = loc;
|
||||||
this.type = NodeType.If;
|
this.type = NodeType.If;
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
this.then = t;
|
this.then = t;
|
||||||
this.else_ = e;
|
this.else_ = e;
|
||||||
|
this.elseif = elif;
|
||||||
}
|
}
|
||||||
bool hasElse()
|
bool hasElse()
|
||||||
{
|
{
|
||||||
return !(else_ is null) && else_.statements.length != 0;
|
return !(else_ is null) && else_.statements.length != 0;
|
||||||
}
|
}
|
||||||
|
bool hasElseif()
|
||||||
|
{
|
||||||
|
return !(elseif is null) && elseif.length != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class For : Statement
|
class For : Statement
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class Lexical
|
|||||||
reserved["COMMON"] = TokenType.Common;
|
reserved["COMMON"] = TokenType.Common;
|
||||||
reserved["USE"] = TokenType.Use;
|
reserved["USE"] = TokenType.Use;
|
||||||
reserved["EXEC"] = TokenType.Exec;
|
reserved["EXEC"] = TokenType.Exec;
|
||||||
|
reserved["ELSEIF"] = TokenType.Elseif;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
}
|
}
|
||||||
this(wstring input)
|
this(wstring input)
|
||||||
@@ -708,6 +709,7 @@ class Parser
|
|||||||
flag = false;
|
flag = false;
|
||||||
if(type == TokenType.NewLine) break;
|
if(type == TokenType.NewLine) break;
|
||||||
if(type == TokenType.Else) break;
|
if(type == TokenType.Else) break;
|
||||||
|
if(type == TokenType.Elseif) break;
|
||||||
if(type == TokenType.Endif) break;
|
if(type == TokenType.Endif) break;
|
||||||
if(type == TokenType.Label)
|
if(type == TokenType.Label)
|
||||||
{
|
{
|
||||||
@@ -730,6 +732,7 @@ class Parser
|
|||||||
{
|
{
|
||||||
auto type = lex.front().type;
|
auto type = lex.front().type;
|
||||||
if(type == TokenType.Else) break;
|
if(type == TokenType.Else) break;
|
||||||
|
if(type == TokenType.Elseif) break;
|
||||||
if(type == TokenType.Endif) break;
|
if(type == TokenType.Endif) break;
|
||||||
auto statement = statement();
|
auto statement = statement();
|
||||||
if(statement != Statement.NOP)
|
if(statement != Statement.NOP)
|
||||||
@@ -1388,6 +1391,47 @@ class Parser
|
|||||||
}
|
}
|
||||||
token = lex.front();
|
token = lex.front();
|
||||||
lex.popFront();
|
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_;
|
Statements else_;
|
||||||
if(token.type == TokenType.Else)
|
if(token.type == TokenType.Else)
|
||||||
{
|
{
|
||||||
@@ -1399,14 +1443,14 @@ class Parser
|
|||||||
if(multiline)
|
if(multiline)
|
||||||
{
|
{
|
||||||
else_ = multilineIfStatements();
|
else_ = multilineIfStatements();
|
||||||
lex.popFront();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
else_ = ifStatements();
|
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_;
|
return if_;
|
||||||
}
|
}
|
||||||
Assign assign(wstring name)
|
Assign assign(wstring name)
|
||||||
@@ -1449,14 +1493,16 @@ class Parser
|
|||||||
}
|
}
|
||||||
if(token.type != TokenType.Colon && token.type != TokenType.NewLine &&
|
if(token.type != TokenType.Colon && token.type != TokenType.NewLine &&
|
||||||
token.type != TokenType.Semicolon && token.type != TokenType.Comma &&
|
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();
|
syntaxError();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(token.type == TokenType.Colon || token.type == TokenType.NewLine ||
|
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();
|
print.addLine();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ enum TokenType
|
|||||||
Exec,
|
Exec,
|
||||||
Call,
|
Call,
|
||||||
Common,
|
Common,
|
||||||
|
Elseif,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user