1
0

ELSEIFを実装

This commit is contained in:
otya128
2016-09-02 16:12:23 +09:00
parent 57de8e07d3
commit 7cb0b26880
5 changed files with 140 additions and 6 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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
{ {

View File

@@ -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;

View File

@@ -69,6 +69,7 @@ enum TokenType
Exec, Exec,
Call, Call,
Common, Common,
Elseif,
} }
struct Token struct Token