とりあえず構文木を一部作るようにして計算させた
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import std.stdio;
|
||||
import otya.smilebasic.parser;
|
||||
int main(string[] argv)
|
||||
{
|
||||
writeln("Hello D-World!");
|
||||
auto parser = new Parser("1+2");
|
||||
writeln();
|
||||
writeln(parser.calc());
|
||||
readln();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import otya.smilebasic.type;
|
||||
import otya.smilebasic.token;
|
||||
enum NodeType
|
||||
{
|
||||
Node = 0b1,
|
||||
Node,
|
||||
Expression,
|
||||
Constant,
|
||||
BinaryOperator,
|
||||
@@ -20,6 +20,7 @@ class Constant : Expression
|
||||
Value value;
|
||||
this(Value v)
|
||||
{
|
||||
this.type = NodeType.Constant;
|
||||
this.value = v;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +29,12 @@ class BinaryOperator : Expression
|
||||
Expression item1;
|
||||
TokenType operator;
|
||||
Expression item2;
|
||||
this(Expression i1, TokenType o)
|
||||
{
|
||||
this.type = NodeType.BinaryOperator;
|
||||
this.item1 = i1;
|
||||
this.operator = o;
|
||||
}
|
||||
this(Expression i1, TokenType o, Expression i2)
|
||||
{
|
||||
this.type = NodeType.BinaryOperator;
|
||||
|
||||
@@ -3,13 +3,24 @@ import otya.smilebasic.token;
|
||||
import otya.smilebasic.type;
|
||||
import otya.smilebasic.node;
|
||||
import std.ascii;
|
||||
import std.stdio;
|
||||
class Lexical
|
||||
{
|
||||
TokenType[] table;
|
||||
wstring code;
|
||||
int index;
|
||||
this(wstring input)
|
||||
{
|
||||
this.code = input;
|
||||
table = new TokenType[256];
|
||||
for(int i = 0;i<256;i++)
|
||||
{
|
||||
table[i] = TokenType.Unknown;
|
||||
}
|
||||
table['+'] = TokenType.Plus;
|
||||
table['-'] = TokenType.Minus;
|
||||
table['*'] = TokenType.Mul;
|
||||
table['/'] = TokenType.Div;
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
@@ -18,6 +29,11 @@ class Lexical
|
||||
Token token;
|
||||
void popFront()
|
||||
{
|
||||
if(empty())
|
||||
{
|
||||
token = Token(TokenType.Unknown);
|
||||
return;
|
||||
}
|
||||
int i = index;
|
||||
for(;i < code.length;i++)
|
||||
{
|
||||
@@ -38,8 +54,12 @@ class Lexical
|
||||
token = Token(TokenType.Integer, Value(num));
|
||||
break;
|
||||
}
|
||||
if(table[cast(char)c] == TokenType.Unknown)
|
||||
{
|
||||
//error
|
||||
|
||||
}
|
||||
token = Token(table[cast(char)c]);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
index = i;
|
||||
@@ -111,19 +131,93 @@ class Parser
|
||||
return 4;//+,-(bin)
|
||||
case TokenType.Mul:
|
||||
case TokenType.Div:
|
||||
// return 3;//*,/,DIV,MOD
|
||||
return 3;//*,/,DIV,MOD
|
||||
// return 2;//-,NOT,!
|
||||
// return 1;//()
|
||||
default:
|
||||
return 0;//TODO:エラーにすべきかは実装次第
|
||||
}
|
||||
}
|
||||
void expression(Expression node)
|
||||
int calc()
|
||||
{
|
||||
term(8, node);
|
||||
auto exp = expression();
|
||||
return calc(exp);
|
||||
}
|
||||
void term(int order, Expression node)
|
||||
int calc(Expression exp)
|
||||
{
|
||||
|
||||
switch(exp.type)
|
||||
{
|
||||
case NodeType.Constant:
|
||||
return (cast(Constant)exp).value.integerValue;
|
||||
case NodeType.BinaryOperator:
|
||||
{
|
||||
auto binop = cast(BinaryOperator)exp;
|
||||
auto i1 = calc(binop.item1);
|
||||
auto i2 = calc(binop.item2);
|
||||
switch(binop.operator)
|
||||
{
|
||||
case TokenType.Plus:
|
||||
return i1 + i2;
|
||||
case TokenType.Minus:
|
||||
return i1 - i2;
|
||||
case TokenType.Mul:
|
||||
return i1 * i2;
|
||||
case TokenType.Div:
|
||||
return i1 / i2;
|
||||
default:
|
||||
return - - -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return - - -1;
|
||||
}
|
||||
}
|
||||
Expression expression()
|
||||
{
|
||||
Expression node = null;
|
||||
lex.popFront();
|
||||
return term(8, node);
|
||||
}
|
||||
Expression term(int order, Expression node)
|
||||
{
|
||||
if(order == 1)
|
||||
{
|
||||
return factor();
|
||||
}
|
||||
Expression exp = term(order - 1, node);
|
||||
auto token = lex.front();
|
||||
if(order == getOPRank(token.type))
|
||||
{
|
||||
BinaryOperator op = new BinaryOperator(exp, token.type);
|
||||
while(order == getOPRank(token.type))
|
||||
{
|
||||
auto tt = token.type;
|
||||
lex.popFront();
|
||||
op.item2 = term(order - 1, node);
|
||||
token = lex.front();
|
||||
write(tt, " ");
|
||||
stdout.flush();
|
||||
}
|
||||
return op;
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
Expression factor()
|
||||
{
|
||||
auto token = lex.front();
|
||||
Expression node = null;
|
||||
switch(token.type)
|
||||
{
|
||||
case TokenType.Integer:
|
||||
write(token.value.integerValue, ' ');
|
||||
stdout.flush();
|
||||
node = new Constant(Value(token.value.integerValue));
|
||||
break;
|
||||
default:
|
||||
return node;
|
||||
}
|
||||
if(!lex.empty())lex.popFront();
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,8 @@ struct Token
|
||||
type = t;
|
||||
value = v;
|
||||
}
|
||||
this(TokenType t)
|
||||
{
|
||||
type = t;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user