配列代入の構文解析を実装,配列宣言,配列参照を実装
This commit is contained in:
@@ -119,6 +119,9 @@ class PrintCode : Code
|
|||||||
case ValueType.Integer:
|
case ValueType.Integer:
|
||||||
write(arg.integerValue);
|
write(arg.integerValue);
|
||||||
break;
|
break;
|
||||||
|
case ValueType.Double:
|
||||||
|
write(arg.doubleValue);
|
||||||
|
break;
|
||||||
case ValueType.String:
|
case ValueType.String:
|
||||||
write(arg.stringValue);
|
write(arg.stringValue);
|
||||||
break;
|
break;
|
||||||
@@ -235,6 +238,16 @@ class Operate : Code
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vm.pop(l);
|
vm.pop(l);
|
||||||
|
if(l.type == ValueType.IntegerArray)
|
||||||
|
//l.type == ValueType.StringArray || l.type == ValueType.DoubleArray)
|
||||||
|
{
|
||||||
|
if(operator != TokenType.LBracket)
|
||||||
|
{
|
||||||
|
throw new TypeMismatch();
|
||||||
|
}
|
||||||
|
vm.push(Value(l.integerArray[ri]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(l.type == ValueType.String)
|
if(l.type == ValueType.String)
|
||||||
{
|
{
|
||||||
wstring ls = l.stringValue;
|
wstring ls = l.stringValue;
|
||||||
@@ -291,6 +304,9 @@ class Operate : Code
|
|||||||
case TokenType.GreaterEqual:
|
case TokenType.GreaterEqual:
|
||||||
vm.push(Value(3));
|
vm.push(Value(3));
|
||||||
return;
|
return;
|
||||||
|
case TokenType.LBracket:
|
||||||
|
vm.push(Value(ls[ri].to!wstring));
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
//type mismatch
|
//type mismatch
|
||||||
throw new TypeMismatch();
|
throw new TypeMismatch();
|
||||||
@@ -491,5 +507,47 @@ class EndVM : Code
|
|||||||
{
|
{
|
||||||
vm.end();
|
vm.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class NewArray : Code
|
||||||
|
{
|
||||||
|
ValueType type;
|
||||||
|
int index;
|
||||||
|
int size;
|
||||||
|
int[] dim;
|
||||||
|
this(ValueType type, int size, int index)
|
||||||
|
{
|
||||||
|
dim = new int[size];
|
||||||
|
this.size = size;
|
||||||
|
this.type = type;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
for(int i = size - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Value v;
|
||||||
|
vm.pop(v);
|
||||||
|
if(v.type == ValueType.Double)
|
||||||
|
{
|
||||||
|
dim[i] = cast(int)v.doubleValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(v.type == ValueType.Integer)
|
||||||
|
{
|
||||||
|
dim[i] = v.integerValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw new TypeMismatch();
|
||||||
|
}
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case ValueType.Integer:
|
||||||
|
vm.global[index].type = ValueType.IntegerArray;
|
||||||
|
vm.global[index].integerArray = new Array!int(dim);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new TypeMismatch();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,21 @@ class Scope
|
|||||||
}
|
}
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
|
ValueType getType(wstring name)
|
||||||
|
{
|
||||||
|
wchar s = name[name.length - 1];
|
||||||
|
switch(s)
|
||||||
|
{
|
||||||
|
case '$':
|
||||||
|
return ValueType.String;
|
||||||
|
case '#':
|
||||||
|
return ValueType.Double;
|
||||||
|
case '%':
|
||||||
|
return ValueType.Integer;
|
||||||
|
default:
|
||||||
|
return ValueType.Integer;//DEFINT時
|
||||||
|
}
|
||||||
|
}
|
||||||
Statements statements;
|
Statements statements;
|
||||||
this(Statements statements)
|
this(Statements statements)
|
||||||
{
|
{
|
||||||
@@ -219,7 +234,33 @@ class Compiler
|
|||||||
breakAddr.address = code.length;
|
breakAddr.address = code.length;
|
||||||
s.breakAddr.address = code.length;
|
s.breakAddr.address = code.length;
|
||||||
}
|
}
|
||||||
|
void compileVar(Var node, Scope sc)
|
||||||
|
{
|
||||||
|
foreach(Statement v ; node.define)
|
||||||
|
{
|
||||||
|
if(v.type == NodeType.DefineVariable)
|
||||||
|
{
|
||||||
|
DefineVariable var = cast(DefineVariable)v;
|
||||||
|
//TODO:local variable
|
||||||
|
defineGlobalVarIndex(var.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(v.type == NodeType.DefineArray)
|
||||||
|
{
|
||||||
|
DefineArray var = cast(DefineArray)v;
|
||||||
|
int siz = 0;
|
||||||
|
foreach_reverse(Expression expr; var.dim)
|
||||||
|
{
|
||||||
|
compileExpression(expr);
|
||||||
|
siz++;
|
||||||
|
if(siz == 4)
|
||||||
|
break;//4次元まで(パーサーで除去するけど万が一に備えて
|
||||||
|
}
|
||||||
|
genCode(new NewArray(getType(var.name), var.dim.length, defineGlobalVarIndex(var.name)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void compileStatements(Statements statements, Scope sc)
|
void compileStatements(Statements statements, Scope sc)
|
||||||
{
|
{
|
||||||
foreach(Statement s ; statements.statements)
|
foreach(Statement s ; statements.statements)
|
||||||
@@ -314,6 +355,9 @@ class Compiler
|
|||||||
}
|
}
|
||||||
genCode(s.continueAddr);
|
genCode(s.continueAddr);
|
||||||
break;
|
break;
|
||||||
|
case NodeType.Var:
|
||||||
|
compileVar(cast(Var)i, s);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ FOR I=0 TO 10
|
|||||||
IF I==1 THEN CONTINUE
|
IF I==1 THEN CONTINUE
|
||||||
?I
|
?I
|
||||||
NEXT
|
NEXT
|
||||||
VAR V
|
VAR V[10]
|
||||||
|
?V[0]
|
||||||
|
?\"ABC\"[1][0]
|
||||||
GOSUB @A
|
GOSUB @A
|
||||||
END
|
END
|
||||||
@A
|
@A
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ enum NodeType
|
|||||||
CallFunction,
|
CallFunction,
|
||||||
VoidExpression,
|
VoidExpression,
|
||||||
UnaryOperator,
|
UnaryOperator,
|
||||||
|
IndexExpressions,
|
||||||
|
|
||||||
Statements,
|
Statements,
|
||||||
FunctionBody,
|
FunctionBody,
|
||||||
@@ -31,6 +32,7 @@ enum NodeType
|
|||||||
Var,
|
Var,
|
||||||
DefineVariable,
|
DefineVariable,
|
||||||
DefineArray,
|
DefineArray,
|
||||||
|
ArrayAssign,
|
||||||
}
|
}
|
||||||
abstract class Node
|
abstract class Node
|
||||||
{
|
{
|
||||||
@@ -323,11 +325,37 @@ class DefineVariable : Statement
|
|||||||
class DefineArray : Statement
|
class DefineArray : Statement
|
||||||
{
|
{
|
||||||
wstring name;
|
wstring name;
|
||||||
int[] dim;
|
Expression[] dim;
|
||||||
this(wstring name, int[] dim)
|
this(wstring name, Expression[] dim)
|
||||||
{
|
{
|
||||||
this.type = NodeType.DefineArray;
|
this.type = NodeType.DefineArray;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.dim = dim;
|
this.dim = dim;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class IndexExpressions : Expression
|
||||||
|
{
|
||||||
|
Expression[] expressions;
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
this.type = NodeType.IndexExpressions;
|
||||||
|
this.expressions = new Expression[0];
|
||||||
|
}
|
||||||
|
void addExpression(Expression expr)
|
||||||
|
{
|
||||||
|
this.expressions ~= expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ArrayAssign : Statement
|
||||||
|
{
|
||||||
|
wstring name;
|
||||||
|
IndexExpressions indexExpression;
|
||||||
|
Expression assignExpression;
|
||||||
|
this(wstring name, IndexExpressions expr, Expression assign)
|
||||||
|
{
|
||||||
|
this.type = NodeType.ArrayAssign;
|
||||||
|
this.name = name;
|
||||||
|
this.indexExpression = expr;
|
||||||
|
this.assignExpression = assign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ class Parser
|
|||||||
case TokenType.And:
|
case TokenType.And:
|
||||||
return 7;//AND,OR,XOR
|
return 7;//AND,OR,XOR
|
||||||
case TokenType.Or:
|
case TokenType.Or:
|
||||||
return 9-1;//AND,OR,XOR
|
return 9;//AND,OR,XOR
|
||||||
case TokenType.Xor:
|
case TokenType.Xor:
|
||||||
return 9;//AND,OR,XOR
|
return 9;//AND,OR,XOR
|
||||||
case TokenType.Equal:
|
case TokenType.Equal:
|
||||||
@@ -327,6 +327,8 @@ class Parser
|
|||||||
case TokenType.IntDiv:
|
case TokenType.IntDiv:
|
||||||
case TokenType.Mod:
|
case TokenType.Mod:
|
||||||
return 3;//*,/,DIV,MOD
|
return 3;//*,/,DIV,MOD
|
||||||
|
case TokenType.LBracket:
|
||||||
|
return 2;//合ってるか不明
|
||||||
// return 2;//-,NOT,!
|
// return 2;//-,NOT,!
|
||||||
// return 1;//()
|
// return 1;//()
|
||||||
default:
|
default:
|
||||||
@@ -483,6 +485,11 @@ class Parser
|
|||||||
node = assign(name);
|
node = assign(name);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
if(token.type == TokenType.LBracket)//配列代入
|
||||||
|
{
|
||||||
|
node = arrayAssign(name);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
//命令呼び出し
|
//命令呼び出し
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -544,6 +551,48 @@ class Parser
|
|||||||
lex.popFront();
|
lex.popFront();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
IndexExpressions indexExpressions()
|
||||||
|
{
|
||||||
|
IndexExpressions ie = new IndexExpressions();
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
ie.addExpression(expression());
|
||||||
|
auto token = lex.front();
|
||||||
|
if(token.type == TokenType.Comma)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(token.type == TokenType.RBracket)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
syntaxError();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ie;
|
||||||
|
}
|
||||||
|
ArrayAssign arrayAssign(wstring name)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
auto ie = indexExpressions();
|
||||||
|
auto token = lex.front();
|
||||||
|
if(token.type != TokenType.RBracket)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
lex.popFront();
|
||||||
|
token = lex.front();
|
||||||
|
if(token.type != TokenType.Assign)
|
||||||
|
{
|
||||||
|
//=が欲しい
|
||||||
|
syntaxError();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
auto expr = expression();
|
||||||
|
auto node = new ArrayAssign(name, ie, expr);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
Statement var()
|
Statement var()
|
||||||
{
|
{
|
||||||
Var var = new Var();
|
Var var = new Var();
|
||||||
@@ -558,7 +607,14 @@ class Parser
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
auto v = defineVar();
|
auto v = defineVar();
|
||||||
var.addDefineVar(cast(DefineVariable)v);
|
if(v.type == NodeType.DefineVariable)
|
||||||
|
{
|
||||||
|
var.addDefineVar(cast(DefineVariable)v);
|
||||||
|
}
|
||||||
|
if(v.type == NodeType.DefineArray)
|
||||||
|
{
|
||||||
|
var.addDefineArray(cast(DefineArray)v);
|
||||||
|
}
|
||||||
//VARの評価順は順番通り
|
//VARの評価順は順番通り
|
||||||
//VAR iden[=expr],
|
//VAR iden[=expr],
|
||||||
if(token.type == TokenType.Comma)
|
if(token.type == TokenType.Comma)
|
||||||
@@ -585,18 +641,32 @@ class Parser
|
|||||||
if(token.type == TokenType.LBracket)
|
if(token.type == TokenType.LBracket)
|
||||||
{
|
{
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
|
Expression[] dim = new Expression[0];
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
expr = expression();
|
expr = expression();
|
||||||
token = lex.front();
|
token = lex.front();
|
||||||
|
if(token.type != TokenType.RBracket)
|
||||||
|
{
|
||||||
|
syntaxError();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dim ~= expr;
|
||||||
|
lex.popFront();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
DefineArray ary = new DefineArray(name, dim);
|
||||||
|
return ary;
|
||||||
}
|
}
|
||||||
//VAR iden=expr
|
else
|
||||||
if(token.type == TokenType.Equal)
|
|
||||||
{
|
{
|
||||||
lex.popFront();
|
//VAR iden=expr
|
||||||
expr = expression();
|
if(token.type == TokenType.Equal)
|
||||||
token = lex.front();
|
{
|
||||||
|
lex.popFront();
|
||||||
|
expr = expression();
|
||||||
|
token = lex.front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DefineVariable node = new DefineVariable(name, expr);
|
DefineVariable node = new DefineVariable(name, expr);
|
||||||
return node;
|
return node;
|
||||||
@@ -727,6 +797,7 @@ class Parser
|
|||||||
auto exp = expression();
|
auto exp = expression();
|
||||||
if(exp is null)
|
if(exp is null)
|
||||||
{
|
{
|
||||||
|
lex.popFront();
|
||||||
syntaxError();
|
syntaxError();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -790,6 +861,12 @@ class Parser
|
|||||||
op.operator = token.type;
|
op.operator = token.type;
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
op.item2 = term(order - 1, node);
|
op.item2 = term(order - 1, node);
|
||||||
|
if(tt == TokenType.LBracket)
|
||||||
|
{
|
||||||
|
//[演算子
|
||||||
|
if(lex.front().type != TokenType.RBracket) syntaxError();
|
||||||
|
lex.popFront();
|
||||||
|
}
|
||||||
token = lex.front();
|
token = lex.front();
|
||||||
version(none)
|
version(none)
|
||||||
write(tt, " ");
|
write(tt, " ");
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ struct Value
|
|||||||
int integerValue;
|
int integerValue;
|
||||||
double doubleValue;
|
double doubleValue;
|
||||||
wstring stringValue;
|
wstring stringValue;
|
||||||
Array!int intArray;
|
Array!int integerArray;
|
||||||
|
Array!double doubleArray;
|
||||||
|
Array!wstring stringArray;
|
||||||
}
|
}
|
||||||
this(int value)
|
this(int value)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user