1
0

配列代入の構文解析を実装,配列宣言,配列参照を実装

This commit is contained in:
otya128
2015-06-12 20:25:53 +09:00
parent c050d4e066
commit 61020e9941
6 changed files with 225 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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, " ");

View File

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