1
0
Files
otyaSMILEBASIC/SMILEBASIC/node.d
2016-12-31 13:40:44 +09:00

718 lines
15 KiB
D

module otya.smilebasic.node;
import otya.smilebasic.type;
import otya.smilebasic.token;
import std.container;
enum NodeType
{
Node,
Expression,
Constant,
BinaryOperator,
Variable,
CallFunction,
VoidExpression,
UnaryOperator,
IndexExpressions,
Statements,
FunctionBody,
Assign,
CallFunctionStatement,
Print,
Label,
Goto,
If,
For,
Gosub,
Return,
End,
Break,
Continue,
Var,
DefineVariable,
DefineArray,
ArrayAssign,
DefineFunction,
While,
Inc,
Data,
Read,
Restore,
On,
Input,
RepeatUntil,
Option,
Swap,
AssignRef,
VarRef,
XOn,
XOff,
Exec,
Use,
Linput,
CallSprite,
CallBG,
}
abstract class Node
{
NodeType type;
//式は複数行に渡って描けないのでStatementに置くべき
SourceLocation location;
}
abstract class Expression : Node
{
}
class Constant : Expression
{
TokenValue value;
this(TokenValue v, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Constant;
this.value = v;
}
}
class BinaryOperator : Expression
{
Expression item1;
TokenType operator;
Expression item2;
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, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.BinaryOperator;
this.item1 = i1;
}
this(Expression i1, TokenType o, Expression i2, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.BinaryOperator;
this.item1 = i1;
this.operator = o;
this.item2 = i2;
}
}
class UnaryOperator : Expression
{
TokenType operator;
Expression item;
this(TokenType o, Expression i, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.UnaryOperator;
this.operator = o;
this.item = i;
}
}
class Variable : Expression
{
wstring name;
this(wstring n, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Variable;
this.name = n;
}
}
class CallFunction : Expression
{
wstring name;
Expression[] args;
this(wstring n, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallFunction;
this.name = n;
args = new Expression[0];
}
void addArg(Expression arg)
{
args ~= arg;
}
}
class VoidExpression : Expression
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.VoidExpression;
}
}
abstract class Statement : Node
{
static Statement NOP = null;
}
class Statements : Statement
{
Statement[] statements;
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Statements;
statements = new Statement[0];
}
void addStatement(Statement statement)
{
statements ~= statement;
}
}
enum PrintArgumentType
{
Expression,//exp
Line,
Tab,//,
}
/*
*;は基本無視
*/
struct PrintArgument
{
PrintArgumentType type;
Expression expression;
this(PrintArgumentType type)
{
this.type = type;
this.expression = null;
}
this(PrintArgumentType type, Expression expression)
{
this.type = type;
this.expression = expression;
}
}
/*
*PRINTは関数ではないしmkIIと違って必ず:がいる
*関数と違ってFUNC(,,,)のような記述はエラー
*と言っても3.2で上の記述もエラーになりうる
*/
class Print : Statement
{
PrintArgument[] args;
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Print;
args = new PrintArgument[0];
}
void addArgument(Expression expression)
{
args ~= PrintArgument(PrintArgumentType.Expression, expression);
}
void addTab()
{
args ~= PrintArgument(PrintArgumentType.Tab);
}
void addLine()
{
args ~= PrintArgument(PrintArgumentType.Line);
}
}
class Assign : Statement
{
wstring name;
Expression expression;
this(wstring name, Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Assign;
this.name = name;
this.expression = expr;
}
}
class AssignRef : Statement
{
Expression left;
Expression expression;
this(Expression left, Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.AssignRef;
this.left = left;
this.expression = expr;
}
}
class Label : Statement
{
wstring label;
this(wstring name, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Label;
this.label = name;
}
}
class Goto : Statement
{
wstring label;
this(wstring name, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Goto;
this.label = name;
}
Expression labelexpr;
this(Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Goto;
this.labelexpr = expr;
}
}
class If : Statement
{
import std.typecons;
Expression condition;
Statements then;
Statements else_;
Tuple!(Statements, Expression)[] elseif;
this(Expression condition, Statements t, Statements e, Tuple!(Statements, Expression)[] elif, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.If;
this.condition = condition;
this.then = t;
this.else_ = e;
this.elseif = elif;
}
bool hasElse()
{
return !(else_ is null) && else_.statements.length != 0;
}
bool hasElseif()
{
return !(elseif is null) && elseif.length != 0;
}
}
class For : Statement
{
Assign initExpression;
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, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.For;
this.initExpression = assign;
this.toExpression = toExpression;
this.stepExpression = null;
this.statements = statements;
}
}
class Gosub : Statement
{
wstring label;
this(wstring name, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Gosub;
this.label = name;
}
Expression labelexpr;
this(Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Gosub;
this.labelexpr = expr;
}
}
class Return : Statement
{
Expression expression;
this(Expression expression, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Return;
this.expression = expression;
}
}
class End : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.End;
}
}
class Break : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Break;
}
}
class Continue : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Continue;
}
}
class Var : Statement
{
Statement[] define;
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Var;
this.define = new Statement[0];
}
void addDefineVar(DefineVariable dv)
{
this.define ~= dv;
}
void addDefineArray(DefineArray da)
{
this.define ~= da;
}
}
class DefineVariable : Statement
{
wstring name;
Expression expression;
this(wstring name, Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.DefineVariable;
this.name = name;
this.expression = expr;
}
}
class DefineArray : Statement
{
wstring name;
IndexExpressions dim;
this(wstring name, IndexExpressions dim, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.DefineArray;
this.name = name;
this.dim = dim;
}
}
class IndexExpressions : Expression
{
Expression[] expressions;
this(SourceLocation loc)
{
super.location = loc;
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, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.ArrayAssign;
this.name = name;
this.indexExpression = expr;
this.assignExpression = assign;
}
}
class DefineFunction : Statement
{
wstring[] arguments;
wstring[] outArguments;
wstring name;
Statements functionBody;
bool returnExpr;
bool isCommon;
this(wstring name, bool returnExpr, bool isCommon, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.DefineFunction;
this.name = name;
this.returnExpr = returnExpr;
this.isCommon = isCommon;
}
this(wstring name, bool isCommon, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.DefineFunction;
this.name = name;
this.returnExpr = false;
this.isCommon = isCommon;
}
void addArgument(wstring name)
{
this.arguments ~= name;
}
void addOutArgument(wstring name)
{
this.outArguments ~= name;
}
}
class CallFunctionStatement : Statement
{
wstring name;
Expression[] args;
Expression[] outVariable;
this(wstring n, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallFunctionStatement;
this.name = n;
args = new Expression[0];
}
void addArg(Expression arg)
{
args ~= arg;
}
void addOut(Expression var)
{
outVariable ~= var;
}
}
class While : Statement
{
Expression condExpression;
Statements statements;
this(Expression condExpression, Statements statements, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.While;
this.condExpression = condExpression;
this.statements = statements;
}
}
class Inc : Statement
{
Expression name;
Expression expression;
this(Expression name, Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Inc;
this.name = name;
this.expression = expr;
}
}
class Data : Statement
{
TokenValue[] data;
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Data;
this.data = new TokenValue[0];
}
void addData(TokenValue v)
{
data ~= v;
}
}
class Read : Statement
{
Expression[] variables;
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Read;
}
void addVariable(Expression lvalue)
{
variables ~= lvalue;
}
}
class Restore : Statement
{
Expression label;
this(Expression label, SourceLocation loc)
{
super.location = loc;
this.label = label;
this.type = NodeType.Restore;
}
}
class On : Statement
{
Expression condition;
bool isGosub;
wstring[] labels;
this(Expression expr, bool isgosub, SourceLocation loc)
{
super.location = loc;
this.condition = expr;
this.isGosub = isgosub;
this.labels = new wstring[0];
this.type = NodeType.On;
}
void addLabel(wstring label)
{
this.labels ~= label;
}
}
class Input : Statement
{
Expression message;
bool question;
Expression[] variables;
this(Expression message, bool question, SourceLocation loc)
{
super.location = loc;
this.message = message;
this.question = question;
this.variables = new Expression[0];
this.type = NodeType.Input;
}
void addVariable(Expression lvalue)
{
variables ~= lvalue;
}
}
class RepeatUntil : Statement
{
Expression condExpression;
Statements statements;
this(Expression condExpression, Statements statements, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.RepeatUntil;
this.condExpression = condExpression;
this.statements = statements;
}
}
class Option : Statement
{
wstring argument;
this(wstring arg, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Option;
argument = arg;
}
}
class Swap : Statement
{
Expression item1;
Expression item2;
this(Expression item1, Expression item2, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Swap;
this.item1 = item1;
this.item2 = item2;
}
}
class VarRef : Expression
{
Expression expression;
this(Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.VarRef;
this.expression = expr;
}
}
class XOn : Statement
{
wstring func;
this(wstring func, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.XOn;
this.func = func;
}
}
class XOff : Statement
{
wstring func;
this(wstring func, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.XOff;
this.func = func;
}
}
class Exec : Statement
{
Expression expression;
this(Expression e, SourceLocation loc)
{
super.location = loc;
expression = e;
this.type = NodeType.Exec;
}
}
class Use : Statement
{
Expression expression;
this(Expression e, SourceLocation loc)
{
super.location = loc;
expression = e;
this.type = NodeType.Use;
}
}
class Linput : Statement
{
bool hasGuide;
Expression guide;
Expression expression;
this(Expression guide, Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Linput;
this.hasGuide = true;
this.guide = guide;
this.expression = expr;
}
this(Expression expr, SourceLocation loc)
{
super.location = loc;
this.type = NodeType.Linput;
this.hasGuide = false;
this.expression = expr;
}
}
class CallSprite : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallSprite;
}
}
class CallBG : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallBG;
}
}