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

View File

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

View File

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

View File

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

View File

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

View File

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