Add existing files
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import std.stdio;
|
||||
import ast;
|
||||
import parser;
|
||||
import runtimedata;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
Parser par;
|
||||
EvalReturn ret;
|
||||
Expr expr;
|
||||
|
||||
Variable[string] varStack;
|
||||
writeln("The SNOL environment is now active, you may proceed with giving your commands.");
|
||||
do
|
||||
{
|
||||
write("Command: ");
|
||||
try
|
||||
{
|
||||
par = Parser(readln());
|
||||
expr = par.parse();
|
||||
if (expr !is null)
|
||||
{
|
||||
|
||||
ret = expr.evaluate(varStack);
|
||||
}
|
||||
}
|
||||
catch(ParseException e)
|
||||
{
|
||||
writeln(e.msg);
|
||||
}
|
||||
catch(RunException e)
|
||||
{
|
||||
writeln(e.msg);
|
||||
}
|
||||
|
||||
}
|
||||
while (ret.type != EVAL_TYPE.EXIT);
|
||||
writeln("Interpreter is now terminated...");
|
||||
|
||||
}
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
module ast;
|
||||
import std.stdio;
|
||||
import runtimedata;
|
||||
import std.string;
|
||||
import std.conv;
|
||||
|
||||
abstract class Expr
|
||||
{
|
||||
|
||||
Expr masterExpr = null;
|
||||
|
||||
EvalReturn evaluate(ref Variable[string] varStack);
|
||||
|
||||
}
|
||||
|
||||
class FloatExpr : Expr
|
||||
{
|
||||
this(float val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
float value;
|
||||
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.FLOAT, value);
|
||||
}
|
||||
}
|
||||
|
||||
class IntExpr : Expr
|
||||
{
|
||||
this(int val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
int value;
|
||||
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.INTEGER, value);
|
||||
}
|
||||
}
|
||||
|
||||
class VarExpr : Expr
|
||||
{
|
||||
this(string var)
|
||||
{
|
||||
varName = var;
|
||||
}
|
||||
|
||||
string varName;
|
||||
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
const Variable* varPtr = (varName in varStack);
|
||||
if (varPtr is null)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.UNDEFINED_VAR, DATA_TYPE.NONE, varName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.VAR, DATA_TYPE.VAR_POINTER, varName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class OpExpr : Expr
|
||||
{
|
||||
this(char op, bool unary = false)
|
||||
{
|
||||
this.op = op;
|
||||
this.unary = unary;
|
||||
|
||||
}
|
||||
|
||||
bool unary;
|
||||
char op;
|
||||
Expr RHE;
|
||||
Expr LHE;
|
||||
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
EvalReturn left = void;
|
||||
if (!unary)
|
||||
{
|
||||
left = LHE.evaluate(varStack);
|
||||
}
|
||||
|
||||
EvalReturn right = RHE.evaluate(varStack);
|
||||
if (op == '=') //ASSIGN
|
||||
{
|
||||
if (right.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
throw new RunException("Error! ["~right.sVar ~ "] is not defined!");
|
||||
if (left.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
varStack[left.sVar] = Variable();
|
||||
|
||||
if (right.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
varStack[left.sVar].dataType = varStack[right.sVar].dataType;
|
||||
if (varStack[left.sVar].dataType == DATA_TYPE.INTEGER)
|
||||
varStack[left.sVar].iVal = varStack[right.sVar].iVal;
|
||||
else
|
||||
varStack[left.sVar].fVal = varStack[right.sVar].fVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (right.dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
varStack[left.sVar].iVal = right.iVal;
|
||||
varStack[left.sVar].dataType = right.dataType;
|
||||
}
|
||||
else if (right.dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
varStack[left.sVar].fVal = right.fVal;
|
||||
varStack[left.sVar].dataType = right.dataType;
|
||||
}
|
||||
}
|
||||
return EvalReturn(EVAL_TYPE.ASSIGN, DATA_TYPE.NONE, 0);
|
||||
|
||||
}
|
||||
else if (op == '-' && unary) //UNARY -
|
||||
{
|
||||
if (right.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
throw new RunException("Error! ["~right.sVar ~ "] is not defined!");
|
||||
if (right.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
if (varStack[right.sVar].dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.INTEGER, -varStack[right.sVar]
|
||||
.iVal);
|
||||
}
|
||||
else if (varStack[right.sVar].dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.FLOAT, -varStack[right.sVar].fVal);
|
||||
}
|
||||
}
|
||||
else if (right.type == EVAL_TYPE.NUMBER)
|
||||
{
|
||||
if (right.dataType == DATA_TYPE.INTEGER)
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.INTEGER, -right.iVal);
|
||||
else if (right.dataType == DATA_TYPE.FLOAT)
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.FLOAT, -right.fVal);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if (op == '+' && unary) //UNARY +
|
||||
{
|
||||
if (right.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
throw new RunException("Error! ["~right.sVar ~ "] is not defined!");
|
||||
if (right.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
if (varStack[right.sVar].dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.INTEGER, varStack[right.sVar]
|
||||
.iVal);
|
||||
}
|
||||
else if (varStack[right.sVar].dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.FLOAT, varStack[right.sVar].fVal);
|
||||
}
|
||||
}
|
||||
else if (right.type == EVAL_TYPE.NUMBER)
|
||||
{
|
||||
if (right.dataType == DATA_TYPE.INTEGER)
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.INTEGER, right.iVal);
|
||||
else if (right.dataType == DATA_TYPE.FLOAT)
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.FLOAT, right.fVal);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if (indexOf("*/+-%", op) > -1) // rest
|
||||
{
|
||||
if (right.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
throw new RunException("Error! ["~ right.sVar ~ "] is not defined!");
|
||||
if (left.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
throw new RunException("Error! ["~right.sVar ~ "] is not defined!");
|
||||
|
||||
DATA_TYPE r;
|
||||
DATA_TYPE l;
|
||||
|
||||
|
||||
|
||||
union Data
|
||||
{
|
||||
int Int;
|
||||
float Float;
|
||||
}
|
||||
Data leftData,rightData;
|
||||
|
||||
|
||||
if (right.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
if (varStack[right.sVar].dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
r = varStack[right.sVar].dataType;
|
||||
rightData.Int = varStack[right.sVar].iVal;
|
||||
}
|
||||
else if (varStack[right.sVar].dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
r = varStack[right.sVar].dataType;
|
||||
rightData.Float = varStack[right.sVar].fVal;
|
||||
}
|
||||
}
|
||||
else if (right.type == EVAL_TYPE.NUMBER)
|
||||
{
|
||||
if (right.dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
r = right.dataType;
|
||||
rightData.Int = right.iVal;
|
||||
}
|
||||
else if (right.dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
r = right.dataType;
|
||||
rightData.Float = right.fVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (left.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
if (varStack[left.sVar].dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
l = varStack[left.sVar].dataType;
|
||||
leftData.Int = varStack[left.sVar].iVal;
|
||||
}
|
||||
else if (varStack[left.sVar].dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
l = varStack[left.sVar].dataType;
|
||||
leftData.Float = varStack[left.sVar].fVal;
|
||||
}
|
||||
}
|
||||
else if (left.type == EVAL_TYPE.NUMBER)
|
||||
{
|
||||
if (left.dataType == DATA_TYPE.INTEGER)
|
||||
{
|
||||
l = right.dataType;
|
||||
leftData.Int = left.iVal;
|
||||
}
|
||||
else if (left.dataType == DATA_TYPE.FLOAT)
|
||||
{
|
||||
l = left.dataType;
|
||||
leftData.Float = left.fVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (l != r)
|
||||
throw new RunException("Error! Operands must be of the same type in an arithmetic operation!");
|
||||
|
||||
if (l == DATA_TYPE.INTEGER)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case '+':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Int + rightData.Int);
|
||||
case '-':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Int - rightData.Int);
|
||||
case '*':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Int * rightData.Int);
|
||||
case '/':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Int / rightData.Int);
|
||||
case '%':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Int % rightData.Int);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case '+':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Float + rightData.Float);
|
||||
case '-':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Float - rightData.Float);
|
||||
case '*':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Float * rightData.Float);
|
||||
case '/':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Float / rightData.Float);
|
||||
case '%':
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, l, leftData.Float % rightData.Float);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return EvalReturn(EVAL_TYPE.NUMBER, DATA_TYPE.NONE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class BEGExpr : Expr
|
||||
{
|
||||
|
||||
VarExpr RHE;
|
||||
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
|
||||
EvalReturn r = RHE.evaluate(varStack);
|
||||
|
||||
write("Input: ");
|
||||
string input = strip(readln());
|
||||
|
||||
if (isNumeric(input))
|
||||
{
|
||||
if (r.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
varStack[r.sVar] = Variable();
|
||||
try
|
||||
{
|
||||
varStack[r.sVar].iVal = to!int(input);
|
||||
varStack[r.sVar].dataType = DATA_TYPE.INTEGER;
|
||||
|
||||
}
|
||||
catch (ConvException e)
|
||||
{
|
||||
varStack[r.sVar].fVal = to!float(input);
|
||||
varStack[r.sVar].dataType = DATA_TYPE.FLOAT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RunException("Error! Cannot convert input");
|
||||
}
|
||||
|
||||
return EvalReturn(EVAL_TYPE.BEG, DATA_TYPE.NONE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class PRINTExpr : Expr
|
||||
{
|
||||
|
||||
VarExpr RHE;
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
EvalReturn r = RHE.evaluate(varStack);
|
||||
if (r.type == EVAL_TYPE.UNDEFINED_VAR)
|
||||
{
|
||||
writeln("SNOL> Error! [" ~ r.sVar ~ "] is not defined!");
|
||||
}
|
||||
else if (r.type == EVAL_TYPE.VAR)
|
||||
{
|
||||
Variable* v = (r.sVar in varStack);
|
||||
if (v.dataType == DATA_TYPE.INTEGER)
|
||||
writeln("SNOL> [" ~ r.sVar ~ "] = ", v.iVal);
|
||||
else
|
||||
writeln("SNOL> [" ~ r.sVar ~ "] = ", v.fVal);
|
||||
|
||||
}
|
||||
|
||||
return EvalReturn(EVAL_TYPE.PRINT, DATA_TYPE.NONE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class EXITExpr : Expr
|
||||
{
|
||||
override EvalReturn evaluate(ref Variable[string] varStack)
|
||||
{
|
||||
return EvalReturn(EVAL_TYPE.EXIT, DATA_TYPE.NONE, 0);
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
module lexer;
|
||||
import std.stdio;
|
||||
import core.stdc.ctype;
|
||||
import std.string;
|
||||
|
||||
enum TOKEN_TYPE
|
||||
{
|
||||
OPERATOR,
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
VARIABLE,
|
||||
PROCEDURE,
|
||||
|
||||
UNKNOWN,
|
||||
END_OF_TEXT
|
||||
}
|
||||
|
||||
struct Token
|
||||
{
|
||||
TOKEN_TYPE type;
|
||||
string data;
|
||||
|
||||
}
|
||||
|
||||
const string OPERATORS = "=+-*/%";
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
long position = 0;
|
||||
private string textToTokenize;
|
||||
this(string textToTokenize)
|
||||
{
|
||||
this.textToTokenize = textToTokenize;
|
||||
|
||||
}
|
||||
|
||||
Token getNextToken()
|
||||
{
|
||||
if (position >= textToTokenize.length)
|
||||
return Token(TOKEN_TYPE.END_OF_TEXT, null);
|
||||
string dataStr;
|
||||
char lastChar = textToTokenize[position];
|
||||
|
||||
while (isspace(lastChar))
|
||||
{
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
return Token(TOKEN_TYPE.END_OF_TEXT, null);
|
||||
lastChar = textToTokenize[position];
|
||||
}
|
||||
if (isalpha(lastChar))
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
lastChar = textToTokenize[++position];
|
||||
while (isalnum(lastChar))
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
break;
|
||||
else
|
||||
|
||||
lastChar = textToTokenize[position];
|
||||
}
|
||||
|
||||
if (dataStr == "BEG")
|
||||
return Token(TOKEN_TYPE.PROCEDURE, dataStr);
|
||||
|
||||
else if (dataStr == "PRINT")
|
||||
{
|
||||
return Token(TOKEN_TYPE.PROCEDURE, dataStr);
|
||||
}
|
||||
|
||||
else if (dataStr == "EXIT" && lastChar == '!')
|
||||
{
|
||||
position++;
|
||||
return Token(TOKEN_TYPE.PROCEDURE, dataStr);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
return Token(TOKEN_TYPE.VARIABLE, dataStr);
|
||||
}
|
||||
|
||||
}
|
||||
if (indexOf(OPERATORS, lastChar) > -1)
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
return Token(TOKEN_TYPE.OPERATOR, dataStr);
|
||||
}
|
||||
|
||||
if (isdigit(lastChar))
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
return Token(TOKEN_TYPE.INTEGER, dataStr);
|
||||
lastChar = textToTokenize[position];
|
||||
while (isdigit(lastChar))
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
return Token(TOKEN_TYPE.INTEGER, dataStr);
|
||||
lastChar = textToTokenize[position];
|
||||
|
||||
}
|
||||
|
||||
if (lastChar == '.')
|
||||
{
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
{
|
||||
position--;
|
||||
return Token(TOKEN_TYPE.INTEGER, dataStr);
|
||||
}
|
||||
lastChar = textToTokenize[position];
|
||||
while (isdigit(lastChar))
|
||||
{
|
||||
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
if (position >= textToTokenize.length)
|
||||
return Token(TOKEN_TYPE.FLOAT, dataStr);
|
||||
lastChar = textToTokenize[position];
|
||||
}
|
||||
if(dataStr[$-1] == '.')
|
||||
{
|
||||
position--;
|
||||
return Token(TOKEN_TYPE.INTEGER, dataStr[0..$-1]);
|
||||
}
|
||||
return Token(TOKEN_TYPE.FLOAT, dataStr);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return Token(TOKEN_TYPE.INTEGER, dataStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dataStr ~= lastChar;
|
||||
position++;
|
||||
return Token(TOKEN_TYPE.UNKNOWN, dataStr);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
module parser;
|
||||
import lexer;
|
||||
import ast;
|
||||
import std.stdio;
|
||||
import std.conv;
|
||||
import std.string;
|
||||
|
||||
class ParseException : Exception
|
||||
{
|
||||
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null) pure nothrow @nogc @safe
|
||||
{
|
||||
super(msg, file, line, nextInChain);
|
||||
}
|
||||
}
|
||||
|
||||
struct Parser
|
||||
{
|
||||
Lexer lex;
|
||||
Token[] tokens = [];
|
||||
Expr[] expr = [];
|
||||
|
||||
this(string textToParse)
|
||||
{
|
||||
lex = Lexer(textToParse);
|
||||
}
|
||||
|
||||
Expr parse()
|
||||
{
|
||||
syntaxSanityCheck();
|
||||
buildAST();
|
||||
|
||||
|
||||
Expr topExpr = null;
|
||||
if(expr.length < 1)
|
||||
return null;
|
||||
foreach (Expr key; expr)
|
||||
{
|
||||
if (key.masterExpr is null)
|
||||
{
|
||||
topExpr = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return topExpr;
|
||||
|
||||
}
|
||||
|
||||
private void syntaxSanityCheck()
|
||||
{
|
||||
Token currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
while (currentToken.type != TOKEN_TYPE.END_OF_TEXT)
|
||||
{
|
||||
//writeln(currentToken);
|
||||
|
||||
if (currentToken.type == TOKEN_TYPE.PROCEDURE && currentToken.data == "BEG")
|
||||
{
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.VARIABLE)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.END_OF_TEXT)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
}
|
||||
if (currentToken.type == TOKEN_TYPE.PROCEDURE && currentToken.data == "EXIT")
|
||||
{
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.END_OF_TEXT)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
}
|
||||
if (currentToken.type == TOKEN_TYPE.PROCEDURE && currentToken.data == "PRINT")
|
||||
{
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.VARIABLE)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.END_OF_TEXT)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
}
|
||||
else if (currentToken.type == TOKEN_TYPE.OPERATOR)
|
||||
{
|
||||
|
||||
if (currentToken.data == "=")
|
||||
{
|
||||
|
||||
if ((tokens.length > 1 || tokens.length == 0) && tokens[0].type != TOKEN_TYPE
|
||||
.VARIABLE)
|
||||
{
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
|
||||
}
|
||||
else if (currentToken.data == "-")
|
||||
{
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.VARIABLE && currentToken.type != TOKEN_TYPE.INTEGER && currentToken
|
||||
.type != TOKEN_TYPE.FLOAT)
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
if (tokens.length <= 2 || (tokens[$ - 3].type != TOKEN_TYPE.VARIABLE && tokens[$ - 3].type != TOKEN_TYPE
|
||||
.INTEGER && tokens[$ - 3].type != TOKEN_TYPE.FLOAT))
|
||||
{
|
||||
tokens[$ - 2].data = 'u' ~ tokens[$ - 2].data;
|
||||
}
|
||||
}
|
||||
else if (currentToken.data == "+")
|
||||
{
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.VARIABLE && currentToken.type != TOKEN_TYPE.INTEGER && currentToken
|
||||
.type != TOKEN_TYPE.FLOAT)
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
if (tokens.length <= 2 || (tokens[$ - 3].type != TOKEN_TYPE.VARIABLE && tokens[$ - 3].type != TOKEN_TYPE
|
||||
.INTEGER && tokens[$ - 3].type != TOKEN_TYPE.FLOAT))
|
||||
{
|
||||
tokens[$ - 2].data = 'u' ~ tokens[$ - 2].data;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tokens[$ - 2].type != TOKEN_TYPE.VARIABLE && tokens[$ - 2].type != TOKEN_TYPE.INTEGER && tokens[$ - 2]
|
||||
.type != TOKEN_TYPE.FLOAT)
|
||||
throw new ParseException(
|
||||
"Unknown command! Does not match any valid");
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
/*if(currentToken.type!=TOKEN_TYPE.VARIABLE && currentToken.type!=TOKEN_TYPE.INTEGER && currentToken.type!=TOKEN_TYPE.FLOAT)
|
||||
throw new ParseException("Wrong usage of '"~tokens[$-1].data~"' operator");*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (currentToken.type == TOKEN_TYPE.FLOAT || currentToken.type == TOKEN_TYPE.INTEGER || currentToken
|
||||
.type == TOKEN_TYPE.VARIABLE)
|
||||
{
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
if (currentToken.type != TOKEN_TYPE.OPERATOR && currentToken.type != TOKEN_TYPE
|
||||
.END_OF_TEXT)
|
||||
{
|
||||
|
||||
throw new ParseException("Unknown command! Does not match any valid command of the language.");
|
||||
}
|
||||
|
||||
}
|
||||
else if( currentToken.type == TOKEN_TYPE.UNKNOWN)
|
||||
{
|
||||
throw new ParseException("Unexpected token: " ~ currentToken.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
currentToken = lex.getNextToken();
|
||||
tokens ~= currentToken;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void opMaker(int id)
|
||||
{
|
||||
OpExpr opExpr = cast(OpExpr) expr[id];
|
||||
if (!opExpr.unary)
|
||||
{
|
||||
Expr leftExpr = expr[id - 1];
|
||||
while (leftExpr.masterExpr !is null)
|
||||
{
|
||||
leftExpr = leftExpr.masterExpr;
|
||||
}
|
||||
leftExpr.masterExpr = opExpr;
|
||||
opExpr.LHE = leftExpr;
|
||||
}
|
||||
|
||||
Expr rightExpr = expr[id + 1];
|
||||
while (rightExpr.masterExpr !is null)
|
||||
{
|
||||
rightExpr = rightExpr.masterExpr;
|
||||
}
|
||||
rightExpr.masterExpr = opExpr;
|
||||
opExpr.RHE = rightExpr;
|
||||
}
|
||||
|
||||
private void buildAST()
|
||||
{
|
||||
for (int i = 0; i < tokens.length; i++)
|
||||
{
|
||||
if (tokens[i].type == TOKEN_TYPE.END_OF_TEXT)
|
||||
break;
|
||||
else if (tokens[i].type == TOKEN_TYPE.FLOAT)
|
||||
expr ~= new FloatExpr(to!float(tokens[i].data));
|
||||
else if (tokens[i].type == TOKEN_TYPE.INTEGER)
|
||||
expr ~= new IntExpr(to!int(tokens[i].data));
|
||||
else if (tokens[i].type == TOKEN_TYPE.OPERATOR && tokens[i].data[0] == 'u')
|
||||
expr ~= new OpExpr(to!char(tokens[i].data[1]), true);
|
||||
else if (tokens[i].type == TOKEN_TYPE.OPERATOR)
|
||||
expr ~= new OpExpr(to!char(tokens[i].data));
|
||||
else if (tokens[i].type == TOKEN_TYPE.VARIABLE)
|
||||
expr ~= new VarExpr(to!string(tokens[i].data));
|
||||
else if (tokens[i].type == TOKEN_TYPE.PROCEDURE && tokens[i].data == "BEG")
|
||||
expr ~= new BEGExpr();
|
||||
else if (tokens[i].type == TOKEN_TYPE.PROCEDURE && tokens[i].data == "PRINT")
|
||||
expr ~= new PRINTExpr();
|
||||
else if (tokens[i].type == TOKEN_TYPE.PROCEDURE && tokens[i].data == "EXIT")
|
||||
expr ~= new EXITExpr();
|
||||
|
||||
}
|
||||
if(expr.length < 1)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < expr.length; i++) // unary
|
||||
{
|
||||
if (typeid(expr[i]) == typeid(OpExpr) && (cast(OpExpr) expr[i]).unary)
|
||||
{
|
||||
opMaker(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < expr.length; i++) // * / %
|
||||
{
|
||||
if (typeid(expr[i]) == typeid(OpExpr) && indexOf("*/%", (cast(OpExpr) expr[i]).op) > -1 && !(
|
||||
cast(OpExpr) expr[i]).unary)
|
||||
{
|
||||
opMaker(i);
|
||||
}
|
||||
|
||||
}
|
||||
for (int i = 0; i < expr.length; i++) // + -
|
||||
{
|
||||
if (typeid(expr[i]) == typeid(OpExpr) && indexOf("+-", (cast(OpExpr) expr[i]).op) > -1 && !(
|
||||
cast(OpExpr) expr[i]).unary)
|
||||
{
|
||||
opMaker(i);
|
||||
}
|
||||
|
||||
}
|
||||
for (int i = 0; i < expr.length; i++) // =
|
||||
{
|
||||
if (typeid(expr[i]) == typeid(OpExpr) && indexOf("=", (cast(OpExpr) expr[i]).op) > -1 && !(
|
||||
cast(OpExpr) expr[i]).unary)
|
||||
{
|
||||
opMaker(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//PROCEDURES expr
|
||||
if (typeid(expr[0]) == typeid(BEGExpr))
|
||||
{
|
||||
BEGExpr begExpr = (cast(BEGExpr) expr[0]);
|
||||
VarExpr rightExpr = cast(VarExpr) expr[1];
|
||||
rightExpr.masterExpr = begExpr;
|
||||
begExpr.RHE = rightExpr;
|
||||
}
|
||||
else if (typeid(expr[0]) == typeid(PRINTExpr))
|
||||
{
|
||||
PRINTExpr printExpr = (cast(PRINTExpr) expr[0]);
|
||||
VarExpr rightExpr = cast(VarExpr) expr[1];
|
||||
rightExpr.masterExpr = printExpr;
|
||||
printExpr.RHE = rightExpr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
module runtimedata;
|
||||
|
||||
|
||||
enum DEBUG = true;
|
||||
|
||||
class RunException : Exception
|
||||
{
|
||||
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null) pure nothrow @nogc @safe
|
||||
{
|
||||
super(msg, file, line, nextInChain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum DATA_TYPE
|
||||
{
|
||||
FLOAT,
|
||||
INTEGER,
|
||||
VAR_POINTER,
|
||||
NONE
|
||||
}
|
||||
enum EVAL_TYPE
|
||||
{
|
||||
NUMBER,
|
||||
UNDEFINED_VAR,
|
||||
VAR,
|
||||
PRINT,
|
||||
BEG,
|
||||
ASSIGN,
|
||||
EXIT
|
||||
}
|
||||
|
||||
struct EvalReturn
|
||||
{
|
||||
this(EVAL_TYPE type,DATA_TYPE dataType, float fVal )
|
||||
{
|
||||
this.type=type;
|
||||
this.dataType = dataType;
|
||||
this.fVal = fVal;
|
||||
}
|
||||
this(EVAL_TYPE type,DATA_TYPE dataType, int iVal)
|
||||
{
|
||||
this.type=type;
|
||||
this.dataType = dataType;
|
||||
this.iVal = iVal;
|
||||
|
||||
}
|
||||
this(EVAL_TYPE type,DATA_TYPE dataType, string sVar)
|
||||
{
|
||||
this.type=type;
|
||||
this.dataType = dataType;
|
||||
this.sVar = sVar;
|
||||
|
||||
}
|
||||
|
||||
EVAL_TYPE type;
|
||||
DATA_TYPE dataType;
|
||||
union
|
||||
{
|
||||
float fVal;
|
||||
int iVal;
|
||||
string sVar;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Variable
|
||||
{
|
||||
DATA_TYPE dataType;
|
||||
union
|
||||
{
|
||||
float fVal;
|
||||
int iVal;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user