配列代入の構文解析を実装,配列宣言,配列参照を実装
This commit is contained in:
@@ -119,6 +119,9 @@ class PrintCode : Code
|
||||
case ValueType.Integer:
|
||||
write(arg.integerValue);
|
||||
break;
|
||||
case ValueType.Double:
|
||||
write(arg.doubleValue);
|
||||
break;
|
||||
case ValueType.String:
|
||||
write(arg.stringValue);
|
||||
break;
|
||||
@@ -235,6 +238,16 @@ class Operate : Code
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
wstring ls = l.stringValue;
|
||||
@@ -291,6 +304,9 @@ class Operate : Code
|
||||
case TokenType.GreaterEqual:
|
||||
vm.push(Value(3));
|
||||
return;
|
||||
case TokenType.LBracket:
|
||||
vm.push(Value(ls[ri].to!wstring));
|
||||
return;
|
||||
default:
|
||||
//type mismatch
|
||||
throw new TypeMismatch();
|
||||
@@ -491,5 +507,47 @@ class EndVM : Code
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
this(Statements statements)
|
||||
{
|
||||
@@ -219,7 +234,33 @@ class Compiler
|
||||
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)
|
||||
{
|
||||
foreach(Statement s ; statements.statements)
|
||||
@@ -314,6 +355,9 @@ class Compiler
|
||||
}
|
||||
genCode(s.continueAddr);
|
||||
break;
|
||||
case NodeType.Var:
|
||||
compileVar(cast(Var)i, s);
|
||||
break;
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,9 @@ FOR I=0 TO 10
|
||||
IF I==1 THEN CONTINUE
|
||||
?I
|
||||
NEXT
|
||||
VAR V
|
||||
VAR V[10]
|
||||
?V[0]
|
||||
?\"ABC\"[1][0]
|
||||
GOSUB @A
|
||||
END
|
||||
@A
|
||||
|
||||
@@ -13,6 +13,7 @@ enum NodeType
|
||||
CallFunction,
|
||||
VoidExpression,
|
||||
UnaryOperator,
|
||||
IndexExpressions,
|
||||
|
||||
Statements,
|
||||
FunctionBody,
|
||||
@@ -31,6 +32,7 @@ enum NodeType
|
||||
Var,
|
||||
DefineVariable,
|
||||
DefineArray,
|
||||
ArrayAssign,
|
||||
}
|
||||
abstract class Node
|
||||
{
|
||||
@@ -323,11 +325,37 @@ class DefineVariable : Statement
|
||||
class DefineArray : Statement
|
||||
{
|
||||
wstring name;
|
||||
int[] dim;
|
||||
this(wstring name, int[] dim)
|
||||
Expression[] dim;
|
||||
this(wstring name, Expression[] dim)
|
||||
{
|
||||
this.type = NodeType.DefineArray;
|
||||
this.name = name;
|
||||
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:
|
||||
return 7;//AND,OR,XOR
|
||||
case TokenType.Or:
|
||||
return 9-1;//AND,OR,XOR
|
||||
return 9;//AND,OR,XOR
|
||||
case TokenType.Xor:
|
||||
return 9;//AND,OR,XOR
|
||||
case TokenType.Equal:
|
||||
@@ -327,6 +327,8 @@ class Parser
|
||||
case TokenType.IntDiv:
|
||||
case TokenType.Mod:
|
||||
return 3;//*,/,DIV,MOD
|
||||
case TokenType.LBracket:
|
||||
return 2;//合ってるか不明
|
||||
// return 2;//-,NOT,!
|
||||
// return 1;//()
|
||||
default:
|
||||
@@ -483,6 +485,11 @@ class Parser
|
||||
node = assign(name);
|
||||
return node;
|
||||
}
|
||||
if(token.type == TokenType.LBracket)//配列代入
|
||||
{
|
||||
node = arrayAssign(name);
|
||||
return node;
|
||||
}
|
||||
//命令呼び出し
|
||||
}
|
||||
break;
|
||||
@@ -544,6 +551,48 @@ class Parser
|
||||
lex.popFront();
|
||||
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()
|
||||
{
|
||||
Var var = new Var();
|
||||
@@ -558,7 +607,14 @@ class Parser
|
||||
return null;
|
||||
}
|
||||
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 iden[=expr],
|
||||
if(token.type == TokenType.Comma)
|
||||
@@ -585,18 +641,32 @@ class Parser
|
||||
if(token.type == TokenType.LBracket)
|
||||
{
|
||||
lex.popFront();
|
||||
Expression[] dim = new Expression[0];
|
||||
while(true)
|
||||
{
|
||||
expr = expression();
|
||||
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
|
||||
if(token.type == TokenType.Equal)
|
||||
else
|
||||
{
|
||||
lex.popFront();
|
||||
expr = expression();
|
||||
token = lex.front();
|
||||
//VAR iden=expr
|
||||
if(token.type == TokenType.Equal)
|
||||
{
|
||||
lex.popFront();
|
||||
expr = expression();
|
||||
token = lex.front();
|
||||
}
|
||||
}
|
||||
DefineVariable node = new DefineVariable(name, expr);
|
||||
return node;
|
||||
@@ -727,6 +797,7 @@ class Parser
|
||||
auto exp = expression();
|
||||
if(exp is null)
|
||||
{
|
||||
lex.popFront();
|
||||
syntaxError();
|
||||
continue;
|
||||
}
|
||||
@@ -790,6 +861,12 @@ class Parser
|
||||
op.operator = token.type;
|
||||
lex.popFront();
|
||||
op.item2 = term(order - 1, node);
|
||||
if(tt == TokenType.LBracket)
|
||||
{
|
||||
//[演算子
|
||||
if(lex.front().type != TokenType.RBracket) syntaxError();
|
||||
lex.popFront();
|
||||
}
|
||||
token = lex.front();
|
||||
version(none)
|
||||
write(tt, " ");
|
||||
|
||||
@@ -18,7 +18,9 @@ struct Value
|
||||
int integerValue;
|
||||
double doubleValue;
|
||||
wstring stringValue;
|
||||
Array!int intArray;
|
||||
Array!int integerArray;
|
||||
Array!double doubleArray;
|
||||
Array!wstring stringArray;
|
||||
}
|
||||
this(int value)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user