1
0

ラベルとGOTOを実�

This commit is contained in:
otya128
2015-06-06 14:51:45 +09:00
parent 88ad0392a1
commit 2eaab2ef55
6 changed files with 91 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,8 @@ enum TokenType
Semicolon, Semicolon,
NewLine, NewLine,
Assign, Assign,
Label,
Goto,
} }
struct Token struct Token