位置情報を記録するようにした
This commit is contained in:
@@ -23,12 +23,6 @@ struct VMVariable
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
struct SourceLocation
|
||||
{
|
||||
int line;//何行目
|
||||
int pos;//何文字目
|
||||
byte slot;//スロット
|
||||
}
|
||||
class VM
|
||||
{
|
||||
DataTable globalDataTable;
|
||||
@@ -43,8 +37,9 @@ class VM
|
||||
int[wstring] globalLabel;
|
||||
int bp;
|
||||
PetitComputer petitcomputer;
|
||||
DebugInfo debugInfo;
|
||||
this(Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions, DataTable gdt/*GNU Debugging Tools*/,
|
||||
int[wstring] globalLabel)
|
||||
int[wstring] globalLabel, DebugInfo dinfo)
|
||||
{
|
||||
this.code = code;
|
||||
this.stack = new Value[16384];
|
||||
@@ -58,6 +53,7 @@ class VM
|
||||
this.functions = functions;
|
||||
this.globalDataTable = gdt;
|
||||
this.globalLabel = globalLabel;
|
||||
this.debugInfo = dinfo;
|
||||
}
|
||||
Code getCurrent()
|
||||
{
|
||||
@@ -75,6 +71,10 @@ class VM
|
||||
stderr.writeln("CompilerBug?:stack");
|
||||
}
|
||||
}
|
||||
SourceLocation currentLocation()
|
||||
{
|
||||
return debugInfo.getLocationByAddress(pc);
|
||||
}
|
||||
void init(PetitComputer petitcomputer)
|
||||
{
|
||||
this.petitcomputer = petitcomputer;
|
||||
|
||||
@@ -6,6 +6,26 @@ import otya.smilebasic.type;
|
||||
import otya.smilebasic.error;
|
||||
import otya.smilebasic.systemvariable;
|
||||
import std.stdio;
|
||||
class DebugInfo
|
||||
{
|
||||
int old;
|
||||
std.container.Array!SourceLocation location;
|
||||
this()
|
||||
{
|
||||
}
|
||||
void addLocation(SourceLocation loc, Code[] code)
|
||||
{
|
||||
for(int i = 0; i < code.length - old; i++)
|
||||
{
|
||||
location ~= loc;
|
||||
}
|
||||
old = location.length;
|
||||
}
|
||||
SourceLocation getLocationByAddress(int addr)
|
||||
{
|
||||
return location[addr];
|
||||
}
|
||||
}
|
||||
class Scope
|
||||
{
|
||||
GotoAddr breakAddr;
|
||||
@@ -152,8 +172,10 @@ class Compiler
|
||||
}
|
||||
}
|
||||
Statements statements;
|
||||
DebugInfo debugInfo;
|
||||
this(Statements statements)
|
||||
{
|
||||
this.debugInfo = new DebugInfo;
|
||||
this.statements = statements;
|
||||
code = new Code[0];
|
||||
global["DATE$"] = VMVariable(-1);
|
||||
@@ -930,6 +952,7 @@ class Compiler
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
this.debugInfo.addLocation(i.location, code);
|
||||
}
|
||||
VM compile()
|
||||
{
|
||||
@@ -1007,7 +1030,7 @@ class Compiler
|
||||
code[i] = new RestoreCode(s.data.label[restore.label], s.data);
|
||||
}
|
||||
}
|
||||
return new VM(code, globalIndex + 1, global, functions, s.data, globalLabel);
|
||||
return new VM(code, globalIndex + 1, global, functions, s.data, globalLabel, debugInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ enum NodeType
|
||||
abstract class Node
|
||||
{
|
||||
NodeType type;
|
||||
//式は複数行に渡って描けないのでStatementに置くべき
|
||||
SourceLocation location;
|
||||
}
|
||||
abstract class Expression : Node
|
||||
{
|
||||
@@ -52,8 +54,9 @@ abstract class Expression : Node
|
||||
class Constant : Expression
|
||||
{
|
||||
Value value;
|
||||
this(Value v)
|
||||
this(Value v, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Constant;
|
||||
this.value = v;
|
||||
}
|
||||
@@ -63,20 +66,23 @@ class BinaryOperator : Expression
|
||||
Expression item1;
|
||||
TokenType operator;
|
||||
Expression item2;
|
||||
this(BinaryOperator bop)
|
||||
this(BinaryOperator bop, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.BinaryOperator;
|
||||
this.item1 = bop.item1;
|
||||
this.operator = bop.operator;
|
||||
this.item2 = bop.item2;
|
||||
}
|
||||
this(Expression i1)
|
||||
this(Expression i1, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.BinaryOperator;
|
||||
this.item1 = i1;
|
||||
}
|
||||
this(Expression i1, TokenType o, Expression i2)
|
||||
this(Expression i1, TokenType o, Expression i2, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.BinaryOperator;
|
||||
this.item1 = i1;
|
||||
this.operator = o;
|
||||
@@ -87,8 +93,9 @@ class UnaryOperator : Expression
|
||||
{
|
||||
TokenType operator;
|
||||
Expression item;
|
||||
this(TokenType o, Expression i)
|
||||
this(TokenType o, Expression i, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.UnaryOperator;
|
||||
this.operator = o;
|
||||
this.item = i;
|
||||
@@ -97,8 +104,9 @@ class UnaryOperator : Expression
|
||||
class Variable : Expression
|
||||
{
|
||||
wstring name;
|
||||
this(wstring n)
|
||||
this(wstring n, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Variable;
|
||||
this.name = n;
|
||||
}
|
||||
@@ -107,8 +115,9 @@ class CallFunction : Expression
|
||||
{
|
||||
wstring name;
|
||||
Expression[] args;
|
||||
this(wstring n)
|
||||
this(wstring n, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.CallFunction;
|
||||
this.name = n;
|
||||
args = new Expression[0];
|
||||
@@ -120,8 +129,9 @@ class CallFunction : Expression
|
||||
}
|
||||
class VoidExpression : Expression
|
||||
{
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.VoidExpression;
|
||||
}
|
||||
}
|
||||
@@ -132,8 +142,9 @@ abstract class Statement : Node
|
||||
class Statements : Statement
|
||||
{
|
||||
Statement[] statements;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Statements;
|
||||
statements = new Statement[0];
|
||||
}
|
||||
@@ -176,8 +187,9 @@ struct PrintArgument
|
||||
class Print : Statement
|
||||
{
|
||||
PrintArgument[] args;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Print;
|
||||
args = new PrintArgument[0];
|
||||
}
|
||||
@@ -198,8 +210,9 @@ class Assign : Statement
|
||||
{
|
||||
wstring name;
|
||||
Expression expression;
|
||||
this(wstring name, Expression expr)
|
||||
this(wstring name, Expression expr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Assign;
|
||||
this.name = name;
|
||||
this.expression = expr;
|
||||
@@ -208,8 +221,9 @@ class Assign : Statement
|
||||
class Label : Statement
|
||||
{
|
||||
wstring label;
|
||||
this(wstring name)
|
||||
this(wstring name, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Label;
|
||||
this.label = name;
|
||||
}
|
||||
@@ -217,14 +231,16 @@ class Label : Statement
|
||||
class Goto : Statement
|
||||
{
|
||||
wstring label;
|
||||
this(wstring name)
|
||||
this(wstring name, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Goto;
|
||||
this.label = name;
|
||||
}
|
||||
Expression labelexpr;
|
||||
this(Expression expr)
|
||||
this(Expression expr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Goto;
|
||||
this.labelexpr = expr;
|
||||
}
|
||||
@@ -234,8 +250,9 @@ class If : Statement
|
||||
Expression condition;
|
||||
Statements then;
|
||||
Statements else_;
|
||||
this(Expression condition, Statements t, Statements e)
|
||||
this(Expression condition, Statements t, Statements e, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.If;
|
||||
this.condition = condition;
|
||||
this.then = t;
|
||||
@@ -252,16 +269,18 @@ class For : Statement
|
||||
Expression toExpression;
|
||||
Expression stepExpression;
|
||||
Statements statements;
|
||||
this(Assign assign, Expression toExpression, Expression stepExpression, Statements statements)
|
||||
this(Assign assign, Expression toExpression, Expression stepExpression, Statements statements, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.For;
|
||||
this.initExpression = assign;
|
||||
this.toExpression = toExpression;
|
||||
this.stepExpression = stepExpression;
|
||||
this.statements = statements;
|
||||
}
|
||||
this(Assign assign, Expression toExpression, Statements statements)
|
||||
this(Assign assign, Expression toExpression, Statements statements, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.For;
|
||||
this.initExpression = assign;
|
||||
this.toExpression = toExpression;
|
||||
@@ -272,14 +291,16 @@ class For : Statement
|
||||
class Gosub : Statement
|
||||
{
|
||||
wstring label;
|
||||
this(wstring name)
|
||||
this(wstring name, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Gosub;
|
||||
this.label = name;
|
||||
}
|
||||
Expression labelexpr;
|
||||
this(Expression expr)
|
||||
this(Expression expr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Gosub;
|
||||
this.labelexpr = expr;
|
||||
}
|
||||
@@ -287,38 +308,43 @@ class Gosub : Statement
|
||||
class Return : Statement
|
||||
{
|
||||
Expression expression;
|
||||
this(Expression expression)
|
||||
this(Expression expression, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Return;
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
class End : Statement
|
||||
{
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.End;
|
||||
}
|
||||
}
|
||||
class Break : Statement
|
||||
{
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Break;
|
||||
}
|
||||
}
|
||||
class Continue : Statement
|
||||
{
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Continue;
|
||||
}
|
||||
}
|
||||
class Var : Statement
|
||||
{
|
||||
Statement[] define;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Var;
|
||||
this.define = new Statement[0];
|
||||
}
|
||||
@@ -335,8 +361,9 @@ class DefineVariable : Statement
|
||||
{
|
||||
wstring name;
|
||||
Expression expression;
|
||||
this(wstring name, Expression expr)
|
||||
this(wstring name, Expression expr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.DefineVariable;
|
||||
this.name = name;
|
||||
this.expression = expr;
|
||||
@@ -346,8 +373,9 @@ class DefineArray : Statement
|
||||
{
|
||||
wstring name;
|
||||
IndexExpressions dim;
|
||||
this(wstring name, IndexExpressions dim)
|
||||
this(wstring name, IndexExpressions dim, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.DefineArray;
|
||||
this.name = name;
|
||||
this.dim = dim;
|
||||
@@ -356,8 +384,9 @@ class DefineArray : Statement
|
||||
class IndexExpressions : Expression
|
||||
{
|
||||
Expression[] expressions;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.IndexExpressions;
|
||||
this.expressions = new Expression[0];
|
||||
}
|
||||
@@ -371,8 +400,9 @@ class ArrayAssign : Statement
|
||||
wstring name;
|
||||
IndexExpressions indexExpression;
|
||||
Expression assignExpression;
|
||||
this(wstring name, IndexExpressions expr, Expression assign)
|
||||
this(wstring name, IndexExpressions expr, Expression assign, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.ArrayAssign;
|
||||
this.name = name;
|
||||
this.indexExpression = expr;
|
||||
@@ -386,14 +416,16 @@ class DefineFunction : Statement
|
||||
wstring name;
|
||||
Statements functionBody;
|
||||
bool returnExpr;
|
||||
this(wstring name, bool returnExpr)
|
||||
this(wstring name, bool returnExpr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.DefineFunction;
|
||||
this.name = name;
|
||||
this.returnExpr = returnExpr;
|
||||
}
|
||||
this(wstring name)
|
||||
this(wstring name, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.DefineFunction;
|
||||
this.name = name;
|
||||
this.returnExpr = false;
|
||||
@@ -412,8 +444,9 @@ class CallFunctionStatement : Statement
|
||||
wstring name;
|
||||
Expression[] args;
|
||||
wstring[] outVariable;
|
||||
this(wstring n)
|
||||
this(wstring n, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.CallFunctionStatement;
|
||||
this.name = n;
|
||||
args = new Expression[0];
|
||||
@@ -431,8 +464,9 @@ class While : Statement
|
||||
{
|
||||
Expression condExpression;
|
||||
Statements statements;
|
||||
this(Expression condExpression, Statements statements)
|
||||
this(Expression condExpression, Statements statements, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.While;
|
||||
this.condExpression = condExpression;
|
||||
this.statements = statements;
|
||||
@@ -442,8 +476,9 @@ class Inc : Statement
|
||||
{
|
||||
wstring name;
|
||||
Expression expression;
|
||||
this(wstring name, Expression expr)
|
||||
this(wstring name, Expression expr, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Inc;
|
||||
this.name = name;
|
||||
this.expression = expr;
|
||||
@@ -452,8 +487,9 @@ class Inc : Statement
|
||||
class Data : Statement
|
||||
{
|
||||
Value[] data;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Data;
|
||||
this.data = new Value[0];
|
||||
}
|
||||
@@ -465,8 +501,9 @@ class Data : Statement
|
||||
class Read : Statement
|
||||
{
|
||||
Expression[] variables;
|
||||
this()
|
||||
this(SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.type = NodeType.Read;
|
||||
}
|
||||
void addVariable(Expression lvalue)
|
||||
@@ -477,8 +514,9 @@ class Read : Statement
|
||||
class Restore : Statement
|
||||
{
|
||||
Expression label;
|
||||
this(Expression label)
|
||||
this(Expression label, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.label = label;
|
||||
this.type = NodeType.Restore;
|
||||
}
|
||||
@@ -488,8 +526,9 @@ class On : Statement
|
||||
Expression condition;
|
||||
bool isGosub;
|
||||
wstring[] labels;
|
||||
this(Expression expr, bool isgosub)
|
||||
this(Expression expr, bool isgosub, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.condition = expr;
|
||||
this.isGosub = isgosub;
|
||||
this.labels = new wstring[0];
|
||||
@@ -505,8 +544,9 @@ class Input : Statement
|
||||
Expression message;
|
||||
bool question;
|
||||
Expression[] variables;
|
||||
this(Expression message, bool question)
|
||||
this(Expression message, bool question, SourceLocation loc)
|
||||
{
|
||||
super.location = loc;
|
||||
this.message = message;
|
||||
this.question = question;
|
||||
this.variables = new Expression[0];
|
||||
|
||||
@@ -85,7 +85,9 @@ class Lexical
|
||||
{
|
||||
return c == '$' || c == '%' || c == '#';
|
||||
}
|
||||
SourceLocation location;
|
||||
Token token;
|
||||
private int pos;
|
||||
void popFront()
|
||||
{
|
||||
if(empty())
|
||||
@@ -316,9 +318,13 @@ class Lexical
|
||||
i++;
|
||||
}
|
||||
}
|
||||
pos = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.location.pos = i - this.pos;
|
||||
this.location.line = line;
|
||||
this.location.pos2 = index - 1;
|
||||
index = i;
|
||||
}
|
||||
Token front()
|
||||
@@ -367,6 +373,15 @@ unittest
|
||||
}
|
||||
class Parser
|
||||
{
|
||||
wstring getLine(SourceLocation loc)
|
||||
{
|
||||
import std.string;
|
||||
int mae = code[0 .. loc.pos2].lastIndexOf('\n');
|
||||
mae++;
|
||||
int ushiro = code[mae..$].indexOf('\n');
|
||||
if(ushiro == -1) ushiro = code.length;
|
||||
return code[mae .. mae + ushiro];
|
||||
}
|
||||
wstring code;
|
||||
Lexical lex;
|
||||
this(wstring input)
|
||||
@@ -488,7 +503,7 @@ class Parser
|
||||
Statements parseProgram()
|
||||
{
|
||||
lex.popFront();
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
while(!lex.empty())
|
||||
{
|
||||
auto token = lex.front();
|
||||
@@ -539,7 +554,7 @@ class Parser
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
DefineFunction node = new DefineFunction(token.value.stringValue);
|
||||
DefineFunction node = new DefineFunction(token.value.stringValue, lex.location);
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.LParen)
|
||||
@@ -630,7 +645,7 @@ class Parser
|
||||
}
|
||||
Statements functionStatements()
|
||||
{
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
while(true)
|
||||
{
|
||||
auto type = lex.front().type;
|
||||
@@ -651,7 +666,7 @@ class Parser
|
||||
}
|
||||
Statements ifStatements()
|
||||
{
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
bool flag = true;
|
||||
while(!lex.empty())
|
||||
{
|
||||
@@ -662,7 +677,7 @@ class Parser
|
||||
if(type == TokenType.Endif) break;
|
||||
if(type == TokenType.Label)
|
||||
{
|
||||
statements.addStatement(new Goto(lex.front.value.stringValue));
|
||||
statements.addStatement(new Goto(lex.front.value.stringValue, lex.location));
|
||||
lex.popFront;
|
||||
continue;
|
||||
}
|
||||
@@ -676,7 +691,7 @@ class Parser
|
||||
}
|
||||
Statements multilineIfStatements()
|
||||
{
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
while(!lex.empty())
|
||||
{
|
||||
auto type = lex.front().type;
|
||||
@@ -692,7 +707,7 @@ class Parser
|
||||
}
|
||||
Statements forStatements()
|
||||
{
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
while(!lex.empty())
|
||||
{
|
||||
auto type = lex.front().type;
|
||||
@@ -722,7 +737,7 @@ class Parser
|
||||
}
|
||||
Statements whileStatements()
|
||||
{
|
||||
auto statements = new Statements();
|
||||
auto statements = new Statements(lex.location);
|
||||
while(!lex.empty())
|
||||
{
|
||||
auto type = lex.front().type;
|
||||
@@ -774,7 +789,7 @@ class Parser
|
||||
return node;
|
||||
}
|
||||
//命令呼び出し
|
||||
auto func = new CallFunctionStatement(name);
|
||||
auto func = new CallFunctionStatement(name, lex.location);
|
||||
node = func;
|
||||
bool oldcomma;
|
||||
while(true)
|
||||
@@ -783,7 +798,7 @@ class Parser
|
||||
|
||||
if(token.type == TokenType.Comma)
|
||||
{
|
||||
func.addArg(new VoidExpression());
|
||||
func.addArg(new VoidExpression(lex.location));
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
}
|
||||
@@ -827,32 +842,32 @@ class Parser
|
||||
case TokenType.NewLine:
|
||||
break;
|
||||
case TokenType.Label:
|
||||
node = new Label(token.value.stringValue);
|
||||
node = new Label(token.value.stringValue, lex.location);
|
||||
break;
|
||||
case TokenType.Goto:
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Label)
|
||||
node = new Goto(token.value.stringValue);
|
||||
node = new Goto(token.value.stringValue, lex.location);
|
||||
else
|
||||
{
|
||||
auto e = expression();
|
||||
if(!e)
|
||||
syntaxError();
|
||||
node = new Goto(e);
|
||||
node = new Goto(e, lex.location);
|
||||
}
|
||||
break;
|
||||
case TokenType.Gosub:
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Label)
|
||||
node = new Gosub(token.value.stringValue);
|
||||
node = new Gosub(token.value.stringValue, lex.location);
|
||||
else
|
||||
{
|
||||
auto e = expression();
|
||||
if(!e)
|
||||
syntaxError();
|
||||
node = new Gosub(e);
|
||||
node = new Gosub(e, lex.location);
|
||||
}
|
||||
break;
|
||||
case TokenType.If:
|
||||
@@ -864,21 +879,21 @@ class Parser
|
||||
lex.popFront();
|
||||
if(isFuncReturnExpr)
|
||||
{
|
||||
node = new Return(expression());
|
||||
node = new Return(expression(), lex.location);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = new Return(null);
|
||||
node = new Return(null, lex.location);
|
||||
}
|
||||
return node;
|
||||
case TokenType.End:
|
||||
node = new End();
|
||||
node = new End(lex.location);
|
||||
break;
|
||||
case TokenType.Break:
|
||||
node = new Break();
|
||||
node = new Break(lex.location);
|
||||
break;
|
||||
case TokenType.Continue:
|
||||
node = new Continue();
|
||||
node = new Continue(lex.location);
|
||||
break;
|
||||
case TokenType.Var:
|
||||
lex.popFront();
|
||||
@@ -935,7 +950,7 @@ class Parser
|
||||
auto token = lex.front();
|
||||
if(token.type == TokenType.Semicolon || (token.type == TokenType.Comma && !isLValue(message)))
|
||||
{
|
||||
Input input = new Input(message, token.type == TokenType.Semicolon);
|
||||
Input input = new Input(message, token.type == TokenType.Semicolon, lex.location);
|
||||
do
|
||||
{
|
||||
lex.popFront();
|
||||
@@ -956,7 +971,7 @@ class Parser
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
Input input = new Input(null, true);
|
||||
Input input = new Input(null, true, lex.location);
|
||||
input.addVariable(message);
|
||||
do
|
||||
{
|
||||
@@ -982,11 +997,11 @@ class Parser
|
||||
On on;
|
||||
if(token.type == TokenType.Gosub)
|
||||
{
|
||||
on = new On(cond, true);//gosub
|
||||
on = new On(cond, true, lex.location);//gosub
|
||||
}
|
||||
else if(token.type == TokenType.Goto)
|
||||
{
|
||||
on = new On(cond, false);//gosub
|
||||
on = new On(cond, false, lex.location);//gosub
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1011,7 +1026,7 @@ class Parser
|
||||
}
|
||||
Data dataStatement()
|
||||
{
|
||||
Data data = new Data();
|
||||
Data data = new Data(lex.location);
|
||||
lex.popFront();
|
||||
auto token = lex.front();
|
||||
while(true)
|
||||
@@ -1051,7 +1066,7 @@ class Parser
|
||||
}
|
||||
Read readStatement()
|
||||
{
|
||||
Read read = new Read();
|
||||
Read read = new Read(lex.location);
|
||||
Token token;
|
||||
do
|
||||
{
|
||||
@@ -1075,7 +1090,7 @@ class Parser
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
return new Restore(label);
|
||||
return new Restore(label, lex.location);
|
||||
}
|
||||
Inc incStatement()
|
||||
{
|
||||
@@ -1105,17 +1120,17 @@ class Parser
|
||||
}
|
||||
else
|
||||
{
|
||||
expr = new Constant(Value(1));
|
||||
expr = new Constant(Value(1), lex.location);
|
||||
}
|
||||
if(dec)
|
||||
{
|
||||
expr = new BinaryOperator(new Constant(Value(0)), TokenType.Minus, expr);
|
||||
expr = new BinaryOperator(new Constant(Value(0), lex.location), TokenType.Minus, expr, lex.location);
|
||||
}
|
||||
return new Inc(var, expr);
|
||||
return new Inc(var, expr, lex.location);
|
||||
}
|
||||
IndexExpressions indexExpressions()
|
||||
{
|
||||
IndexExpressions ie = new IndexExpressions();
|
||||
IndexExpressions ie = new IndexExpressions(lex.location);
|
||||
int count = 0;
|
||||
while(true)
|
||||
{
|
||||
@@ -1160,12 +1175,12 @@ class Parser
|
||||
lex.popFront();
|
||||
auto expr = expression();
|
||||
token = lex.front();
|
||||
auto node = new ArrayAssign(name, ie, expr);
|
||||
auto node = new ArrayAssign(name, ie, expr, lex.location);
|
||||
return node;
|
||||
}
|
||||
Statement var()
|
||||
{
|
||||
Var var = new Var();
|
||||
Var var = new Var(lex.location);
|
||||
Token token;
|
||||
while(true)
|
||||
{
|
||||
@@ -1215,7 +1230,7 @@ class Parser
|
||||
if(token.type != TokenType.RBracket)
|
||||
return null;
|
||||
lex.popFront();
|
||||
DefineArray ary = new DefineArray(name, dim);
|
||||
DefineArray ary = new DefineArray(name, dim, lex.location);
|
||||
return ary;
|
||||
}
|
||||
else
|
||||
@@ -1228,7 +1243,7 @@ class Parser
|
||||
token = lex.front();
|
||||
}
|
||||
}
|
||||
DefineVariable node = new DefineVariable(name, expr);
|
||||
DefineVariable node = new DefineVariable(name, expr, lex.location);
|
||||
return node;
|
||||
}
|
||||
For forStatement()
|
||||
@@ -1263,11 +1278,11 @@ class Parser
|
||||
else
|
||||
{
|
||||
//とりあえず
|
||||
step = new Constant(Value(1));
|
||||
step = new Constant(Value(1), lex.location);
|
||||
}
|
||||
token = lex.front();
|
||||
Statements statements = forStatements();
|
||||
node = new For(init, to, step, statements);
|
||||
node = new For(init, to, step, statements, lex.location);
|
||||
return node;
|
||||
}
|
||||
While whileStatement()
|
||||
@@ -1280,7 +1295,7 @@ class Parser
|
||||
return null;
|
||||
}
|
||||
Statements statements = whileStatements();
|
||||
auto node = new While(expr, statements);
|
||||
auto node = new While(expr, statements, lex.location);
|
||||
return node;
|
||||
}
|
||||
If if_()
|
||||
@@ -1340,7 +1355,7 @@ class Parser
|
||||
else_ = ifStatements();
|
||||
}
|
||||
}
|
||||
auto if_ = new If(expr, then, else_);
|
||||
auto if_ = new If(expr, then, else_, lex.location);
|
||||
return if_;
|
||||
}
|
||||
Assign assign(wstring name)
|
||||
@@ -1349,12 +1364,12 @@ class Parser
|
||||
auto token = lex.front();//=の次
|
||||
Expression expr = expression();
|
||||
if(expr is null) return null;
|
||||
auto a = new Assign(name, expr);
|
||||
auto a = new Assign(name, expr, lex.location);
|
||||
return a;
|
||||
}
|
||||
Print print()
|
||||
{
|
||||
auto print = new Print();
|
||||
auto print = new Print(lex.location);
|
||||
bool addline = true;
|
||||
lex.popFront();
|
||||
auto token = lex.front();
|
||||
@@ -1429,7 +1444,7 @@ class Parser
|
||||
auto token = lex.front();
|
||||
if(order == getOPRank(token.type))
|
||||
{
|
||||
BinaryOperator op = new BinaryOperator(exp);
|
||||
BinaryOperator op = new BinaryOperator(exp, lex.location);
|
||||
while(order == getOPRank(token.type))
|
||||
{
|
||||
auto tt = token.type;
|
||||
@@ -1451,7 +1466,7 @@ class Parser
|
||||
write(tt, " ");
|
||||
if(order == getOPRank(token.type))
|
||||
{
|
||||
BinaryOperator op2 = new BinaryOperator(op);
|
||||
BinaryOperator op2 = new BinaryOperator(op, lex.location);
|
||||
op.item1 = op2;
|
||||
}
|
||||
version(none)stdout.flush();
|
||||
@@ -1470,14 +1485,14 @@ class Parser
|
||||
case TokenType.Integer:
|
||||
version(none)write(token.value.integerValue, ' ');
|
||||
version(none)stdout.flush();
|
||||
node = new Constant(token.value);
|
||||
node = new Constant(token.value, lex.location);
|
||||
break;
|
||||
case TokenType.Iden:
|
||||
if(!lex.empty())
|
||||
lex.popFront();
|
||||
if(lex.front().type == TokenType.LParen)
|
||||
{
|
||||
auto func = new CallFunction(token.value.stringValue);
|
||||
auto func = new CallFunction(token.value.stringValue, lex.location);
|
||||
node = func;
|
||||
//関数呼び出しだった
|
||||
while(true)
|
||||
@@ -1488,7 +1503,7 @@ class Parser
|
||||
if(token.type == TokenType.RParen) break;
|
||||
if(token.type == TokenType.Comma)
|
||||
{
|
||||
func.addArg(new VoidExpression());
|
||||
func.addArg(new VoidExpression(lex.location));
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
}
|
||||
@@ -1499,7 +1514,7 @@ class Parser
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Variable(token.value.stringValue);
|
||||
return new Variable(token.value.stringValue, lex.location);
|
||||
}
|
||||
break;
|
||||
case TokenType.LParen:
|
||||
@@ -1512,18 +1527,18 @@ class Parser
|
||||
break;
|
||||
case TokenType.Label://3.1
|
||||
//文字列リテラル
|
||||
node = new Constant(token.value);
|
||||
node = new Constant(token.value, lex.location);
|
||||
break;
|
||||
case TokenType.Minus:
|
||||
//TODO:UnaryOperatorの実装
|
||||
//とりあえず0-exprを作成
|
||||
lex.popFront();
|
||||
node = new BinaryOperator(new Constant(Value(0)), TokenType.Minus, factor());
|
||||
node = new BinaryOperator(new Constant(Value(0), lex.location), TokenType.Minus, factor(), lex.location);
|
||||
return node;
|
||||
case TokenType.LogicalNot:
|
||||
case TokenType.Not:
|
||||
lex.popFront();
|
||||
node = new UnaryOperator(token.type, factor());
|
||||
node = new UnaryOperator(token.type, factor(), lex.location);
|
||||
return node;
|
||||
default:
|
||||
return node;
|
||||
|
||||
@@ -1052,11 +1052,11 @@ class PetitComputer
|
||||
parser = new Parser(
|
||||
//readText("./SYS/GAME6TALK.TXT").to!wstring
|
||||
//readText("./SYS/GAME7EXPAD.TXT").to!wstring
|
||||
readText("./SYS/GAME4SHOOTER.TXT").to!wstring
|
||||
//readText("./SYS/GAME4SHOOTER.TXT").to!wstring
|
||||
//readText("./SYS/GAME2RPG.TXT").to!wstring
|
||||
//readText("./SYS/GAME1DOTRC.TXT").to!wstring
|
||||
//readText(input("LOAD PROGRAM:", true).to!string).to!wstring
|
||||
//readText("./SYS/EX8TECDEMO.TXT").to!wstring
|
||||
readText("./SYS/EX8TECDEMO.TXT").to!wstring
|
||||
//readText("./SYS/EX1TEXT.TXT").to!wstring
|
||||
//readText("FIZZBUZZ.TXT").to!wstring
|
||||
//readText("TEST.TXT").to!wstring
|
||||
@@ -1166,6 +1166,8 @@ class PetitComputer
|
||||
//gbox(0, 78, 78, 40, 40, RGB(255, 255, 0));
|
||||
int startcnt = SDL_GetTicks();
|
||||
float frame = 1000f / 60f;
|
||||
typeof(vm.currentLocation()) loc;
|
||||
debug bool trace = false;
|
||||
while (true)
|
||||
{
|
||||
uint elapse;
|
||||
@@ -1178,6 +1180,11 @@ class PetitComputer
|
||||
{
|
||||
//writefln("%04X:%s", vm.pc, vm.getCurrent);
|
||||
running = vm.runStep();
|
||||
debug if(trace && loc.line != vm.currentLocation.line)
|
||||
{
|
||||
loc = vm.currentLocation;
|
||||
printConsole(loc.line, ":", loc.pos, ":", parser.getLine(loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SmileBasicError sbe)
|
||||
@@ -1190,9 +1197,12 @@ class PetitComputer
|
||||
//printConsole(sbe.to!string);
|
||||
writeln(sbe.to!string);
|
||||
writeln(sbe.getErrorMessage2);
|
||||
loc = vm.currentLocation;
|
||||
printConsole(loc.line, ":", loc.pos, ":", parser.getLine(loc));
|
||||
}
|
||||
catch
|
||||
catch(Throwable t)
|
||||
{
|
||||
writeln(t);
|
||||
}
|
||||
}
|
||||
catch(Throwable t)
|
||||
@@ -1202,9 +1212,11 @@ class PetitComputer
|
||||
{
|
||||
printConsole(t.to!string);
|
||||
writeln(t);
|
||||
printConsole(parser.getLine(vm.currentLocation));
|
||||
}
|
||||
catch
|
||||
catch(Throwable t)
|
||||
{
|
||||
writeln(t);
|
||||
}
|
||||
}
|
||||
//elapse = SDL_GetTicks() - startTicks;
|
||||
|
||||
@@ -81,3 +81,9 @@ struct Token
|
||||
type = t;
|
||||
}
|
||||
}
|
||||
struct SourceLocation
|
||||
{
|
||||
int line;//何行目
|
||||
int pos;//何文字目
|
||||
int pos2;//全体から何文字目
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user