ラベルとGOTOを実�
This commit is contained in:
@@ -50,6 +50,7 @@ enum CodeType
|
|||||||
Gosub,
|
Gosub,
|
||||||
Print,
|
Print,
|
||||||
PopG,
|
PopG,
|
||||||
|
GotoS,
|
||||||
}
|
}
|
||||||
abstract class Code
|
abstract class Code
|
||||||
{
|
{
|
||||||
@@ -167,7 +168,7 @@ class Operate : Code
|
|||||||
vm.push(l);
|
vm.push(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Goto : Code
|
class GotoAddr : Code
|
||||||
{
|
{
|
||||||
int address;
|
int address;
|
||||||
this(int addr)
|
this(int addr)
|
||||||
@@ -180,6 +181,19 @@ class Goto : Code
|
|||||||
vm.pc = address - 1;
|
vm.pc = address - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class GotoS : Code
|
||||||
|
{
|
||||||
|
wstring label;
|
||||||
|
this(wstring label)
|
||||||
|
{
|
||||||
|
this.type = CodeType.GotoS;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
stderr.writeln("can't execute");
|
||||||
|
}
|
||||||
|
}
|
||||||
class Gosub : Code
|
class Gosub : Code
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class Compiler
|
|||||||
|
|
||||||
Code[] code;
|
Code[] code;
|
||||||
int[wstring] global;
|
int[wstring] global;
|
||||||
|
int[wstring] globalLabel;
|
||||||
int globalIndex = 0;
|
int globalIndex = 0;
|
||||||
void genCodeImm(Value value)
|
void genCodeImm(Value value)
|
||||||
{
|
{
|
||||||
@@ -32,6 +33,10 @@ class Compiler
|
|||||||
{
|
{
|
||||||
code ~= new Operate(op);
|
code ~= new Operate(op);
|
||||||
}
|
}
|
||||||
|
void genCodeGoto(wstring label)
|
||||||
|
{
|
||||||
|
code ~= new GotoS(label);
|
||||||
|
}
|
||||||
int defineGlobalVarIndex(wstring name)
|
int defineGlobalVarIndex(wstring name)
|
||||||
{
|
{
|
||||||
int global = this.global.get(name, 0);
|
int global = this.global.get(name, 0);
|
||||||
@@ -129,10 +134,28 @@ class Compiler
|
|||||||
genCodePopGlobal(getGlobalVarIndex(assign.name));
|
genCodePopGlobal(getGlobalVarIndex(assign.name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NodeType.Label:
|
||||||
|
{
|
||||||
|
auto label = cast(Label)i;
|
||||||
|
globalLabel[label.label] = code.length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NodeType.Goto:
|
||||||
|
{
|
||||||
|
genCodeGoto((cast(Goto)i).label);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach(int i, Code c; code)
|
||||||
|
{
|
||||||
|
if(c.type == CodeType.GotoS)
|
||||||
|
{
|
||||||
|
code[i] = new GotoAddr(globalLabel[(cast(GotoS)c).label]);
|
||||||
|
}
|
||||||
|
}
|
||||||
return new VM(code, globalIndex + 1, global);
|
return new VM(code, globalIndex + 1, global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ int main(string[] argv)
|
|||||||
writeln(parser.calc());
|
writeln(parser.calc());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parser = new Parser("A=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A");
|
auto parser = new Parser("@A\nA=1+2+3+4\nPRINT 1+1,2+3;10-5,A:A=A*2:PRINT A:GOTO@A");
|
||||||
auto vm = parser.compile();
|
auto vm = parser.compile();
|
||||||
vm.run();
|
vm.run();
|
||||||
readln();
|
readln();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ enum NodeType
|
|||||||
Assign,
|
Assign,
|
||||||
CallFunctionStatement,
|
CallFunctionStatement,
|
||||||
Print,
|
Print,
|
||||||
|
Label,
|
||||||
|
Goto,
|
||||||
}
|
}
|
||||||
abstract class Node
|
abstract class Node
|
||||||
{
|
{
|
||||||
@@ -171,3 +173,21 @@ class Assign : Statement
|
|||||||
this.expression = expr;
|
this.expression = expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class Label : Statement
|
||||||
|
{
|
||||||
|
wstring label;
|
||||||
|
this(wstring name)
|
||||||
|
{
|
||||||
|
this.type = NodeType.Label;
|
||||||
|
this.label = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Goto : Statement
|
||||||
|
{
|
||||||
|
wstring label;
|
||||||
|
this(wstring name)
|
||||||
|
{
|
||||||
|
this.type = NodeType.Goto;
|
||||||
|
this.label = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Lexical
|
|||||||
reserved["XOR"] = TokenType.Xor;
|
reserved["XOR"] = TokenType.Xor;
|
||||||
reserved["NOT"] = TokenType.Not;
|
reserved["NOT"] = TokenType.Not;
|
||||||
reserved["PRINT"] = TokenType.Print;
|
reserved["PRINT"] = TokenType.Print;
|
||||||
|
reserved["GOTO"] = TokenType.Goto;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
line = 1;
|
line = 1;
|
||||||
}
|
}
|
||||||
@@ -106,6 +107,25 @@ class Lexical
|
|||||||
token = Token(TokenType.Iden, Value(iden));
|
token = Token(TokenType.Iden, Value(iden));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(c == '@')
|
||||||
|
{
|
||||||
|
//ラベル(もしくは文字列)
|
||||||
|
wstring iden;
|
||||||
|
iden ~= c;
|
||||||
|
i++;
|
||||||
|
for(;i < code.length;i++)
|
||||||
|
{
|
||||||
|
c = code[i];
|
||||||
|
if(!c.isAlpha())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iden ~= c;
|
||||||
|
}
|
||||||
|
token = Token(TokenType.Label, Value(iden));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(table[cast(char)c] == TokenType.Unknown)
|
if(table[cast(char)c] == TokenType.Unknown)
|
||||||
{
|
{
|
||||||
//error
|
//error
|
||||||
@@ -310,6 +330,12 @@ class Parser
|
|||||||
case TokenType.Colon:
|
case TokenType.Colon:
|
||||||
case TokenType.NewLine:
|
case TokenType.NewLine:
|
||||||
break;
|
break;
|
||||||
|
case TokenType.Label:
|
||||||
|
return new Label(token.value.stringValue);
|
||||||
|
case TokenType.Goto:
|
||||||
|
lex.popFront();
|
||||||
|
token = lex.front();
|
||||||
|
return new Goto(token.value.stringValue);
|
||||||
default:
|
default:
|
||||||
syntaxError();
|
syntaxError();
|
||||||
break;
|
break;
|
||||||
@@ -464,6 +490,10 @@ class Parser
|
|||||||
if(token.type != TokenType.RParen)
|
if(token.type != TokenType.RParen)
|
||||||
//error
|
//error
|
||||||
{}
|
{}
|
||||||
|
break;
|
||||||
|
case TokenType.Label://3.1
|
||||||
|
//文字列リテラル
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return node;
|
return node;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ enum TokenType
|
|||||||
Semicolon,
|
Semicolon,
|
||||||
NewLine,
|
NewLine,
|
||||||
Assign,
|
Assign,
|
||||||
|
Label,
|
||||||
|
Goto,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user