add files
parent
a89fea250c
commit
4ac0ac96eb
|
@ -0,0 +1,6 @@
|
|||
write 1 & 1;
|
||||
write "Hallo Welt";
|
||||
write "Hallo" & "Welt";
|
||||
write 1 & "Welt";
|
||||
x := 4711;
|
||||
write x;
|
|
@ -0,0 +1,4 @@
|
|||
write 1+"1";
|
||||
write 1+true;
|
||||
write 1 & "1";
|
||||
write "1"&false;
|
|
@ -0,0 +1,7 @@
|
|||
testlist := [1,2,"Hallo",4,5,null,false,true];
|
||||
trace testlist;
|
||||
trace testlist is number;
|
||||
trace testlist is list;
|
||||
trace testlist is not list;
|
||||
trace count testlist;
|
||||
trace first testlist;
|
|
@ -0,0 +1,9 @@
|
|||
a := 4711;
|
||||
trace time a;
|
||||
b := 2020-01-01T12:00:00;
|
||||
time a := b;
|
||||
c := a;
|
||||
time c := now;
|
||||
trace time c;
|
||||
trace time a;
|
||||
trace time [1,2,3];
|
|
@ -0,0 +1,24 @@
|
|||
testlist := [100, 200, 50, 120, 150, 90] ;
|
||||
|
||||
trace testlist where [true, false, false, true, true, false];
|
||||
trace testlist where it is less than or equal 100;
|
||||
trace testlist where it is within 80 to 120;
|
||||
trace testlist where it is within 100 to [100,110,120,130,140,150];
|
||||
|
||||
trace testlist where 2 * it / 3 is within 80 to 120;
|
||||
|
||||
testlist[2] := 199;
|
||||
trace testlist;
|
||||
|
||||
x := 100;
|
||||
y := 200;
|
||||
z := 300;
|
||||
|
||||
time of x := 2020-06-08T15:15:15;
|
||||
time of y := 2020-06-09T11:11:00;
|
||||
time of z := 2020-06-10T12:00:00;
|
||||
|
||||
xyz := [x,y,z];
|
||||
|
||||
trace xyz where it occurs before time of z;
|
||||
trace xyz where they occurred after time of x;
|
|
@ -0,0 +1,16 @@
|
|||
for x in 12 ... 18 do
|
||||
|
||||
bmi := x * 2.3;
|
||||
|
||||
if bmi is greater than or equal 40 then
|
||||
trace "Adipositas III";
|
||||
elseif bmi is greater than or equal 35 then
|
||||
trace "Adipositas II";
|
||||
elseif bmi is greater than or equal 30 then
|
||||
trace "Adipositas I";
|
||||
else
|
||||
trace "Keine Adipositas";
|
||||
endif;
|
||||
enddo;
|
||||
|
||||
//trace bmi;
|
|
@ -0,0 +1,294 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from datetime import date
|
||||
|
||||
class BaseType(ABC):
|
||||
@abstractmethod
|
||||
def __str__(self):
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
self.time = NullType(False)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
#def __eq__(self,b):
|
||||
# return BoolType(str(type(self).__name__) is b)
|
||||
|
||||
def __and__(self,other):
|
||||
if isinstance(other, StrType):
|
||||
return StrType(str(self) + str(other))
|
||||
return NullType()
|
||||
|
||||
def IS(self,b,invert=False):
|
||||
if b is type(self):
|
||||
return BoolType(True)
|
||||
return BoolType(False)
|
||||
|
||||
def NOT(self,b,invert=False):
|
||||
return NullType()
|
||||
|
||||
def ISNOT(self,b,invert=False):
|
||||
return ~self.IS(b)
|
||||
|
||||
def LISTACCESS(self,b):
|
||||
return NullType()
|
||||
|
||||
def TIME(self):
|
||||
return self.time
|
||||
|
||||
|
||||
class NumType(BaseType):
|
||||
def __init__(self, value: (int, float)):
|
||||
super().__init__()
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
value = float(value)
|
||||
if not isinstance(value, (int, float)):
|
||||
raise TypeError(f"Expected a number, got {type(value)}")
|
||||
self.value = value
|
||||
|
||||
def __mul__(self,other):
|
||||
if isinstance(other, NumType):
|
||||
return NumType(self.value * other.value)
|
||||
if isinstance(other, ListType):
|
||||
return ListType([item * self for item in other.value])
|
||||
return NullType()
|
||||
|
||||
def __truediv__(self,other):
|
||||
if isinstance(other, NumType):
|
||||
return NumType(self.value / other.value)
|
||||
if isinstance(other, ListType):
|
||||
return ListType([item / self for item in other.value])
|
||||
return NullType()
|
||||
|
||||
def __add__(self,other):
|
||||
if isinstance(other, NumType):
|
||||
return NumType(self.value + other.value)
|
||||
return NullType()
|
||||
|
||||
def __sub__(self,other):
|
||||
if isinstance(other, NumType):
|
||||
return NumType(self.value - other.value)
|
||||
return NullType()
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return BoolType(self.value > other.value)
|
||||
return NullType
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return BoolType(self.value < other.value)
|
||||
return NullType
|
||||
|
||||
def __ge__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return BoolType(self.value >= other.value)
|
||||
if isinstance(other, ListType):
|
||||
return ListType([self >= item for item in other.value])
|
||||
return NullType
|
||||
|
||||
def __le__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return BoolType(self.value <= other.value)
|
||||
if isinstance(other, ListType):
|
||||
return ListType([self <= item for item in other.value])
|
||||
return NullType
|
||||
|
||||
def __pow__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return NumType(self.value ** other.value)
|
||||
return NullType
|
||||
|
||||
def __neg__(self):
|
||||
return NumType(-self.value)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
def IS(self,b,invert=False):
|
||||
if b is type(self):
|
||||
return BoolType(True)
|
||||
if type(b) is self:
|
||||
return BoolType(self.value == b.value)
|
||||
if type(b) is Condition:
|
||||
return b.value(self)
|
||||
return BoolType(False)
|
||||
|
||||
class StrType(BaseType):
|
||||
def __init__(self, value: str):
|
||||
super().__init__()
|
||||
if not isinstance(value, str):
|
||||
raise TypeError(f"Expected a string, got {type(value)}")
|
||||
self.value = value
|
||||
|
||||
def __and__(self,other):
|
||||
return StrType(str(self) + str(other))
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
class BoolType(BaseType):
|
||||
def __init__(self, value: bool):
|
||||
super().__init__()
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError(f"Expected a boolean, got {type(value)}")
|
||||
self.value = value
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.value == other.value
|
||||
|
||||
def __bool__(self):
|
||||
return self.value
|
||||
|
||||
def __invert__(self):
|
||||
return BoolType(not self.value)
|
||||
|
||||
def __str__(self):
|
||||
if self.value:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
|
||||
def __and__(self,other):
|
||||
if isinstance(other, BoolType):
|
||||
return BoolType(self.value and other.value)
|
||||
return NullType
|
||||
|
||||
def NOT(self):
|
||||
return ~self
|
||||
|
||||
class ListType(BaseType):
|
||||
def __init__(self, value: list):
|
||||
super().__init__()
|
||||
if not isinstance(value, list):
|
||||
raise TypeError(f"Expected a list, got {type(value)}")
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return f"[{', '.join(str(item) for item in self.value)}]"
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return ListType([item > other for item in self.value])
|
||||
return NullType
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return ListType([item < other for item in self.value])
|
||||
return NullType
|
||||
|
||||
def __ge__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return ListType([item >= other for item in self.value])
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item >= b_item for a_item, b_item in zip(self.value, other.value)])
|
||||
return NullType
|
||||
|
||||
def __le__(self, other):
|
||||
if isinstance(other, NumType):
|
||||
return ListType([item <= other for item in self.value])
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item <= b_item for a_item, b_item in zip(self.value, other.value)])
|
||||
return NullType
|
||||
|
||||
def __and__(self,other):
|
||||
if isinstance(other, BoolType) or isinstance(other, NumType):
|
||||
return ListType([item and other for item in self.value])
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item and b_item for a_item, b_item in zip(self.value, other.value)])
|
||||
return NullType
|
||||
|
||||
def __or__(self,other):
|
||||
if isinstance(other, BoolType) or isinstance(other, NumType):
|
||||
return ListType([item or other for item in self.value])
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item or b_item for a_item, b_item in zip(self.value, other.value)])
|
||||
return NullType
|
||||
|
||||
def __truediv__(self,other):
|
||||
if isinstance(other, NumType):
|
||||
return ListType([item / other for item in self.value])
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item / b_item for a_item, b_item in zip(self.value, other.value)])
|
||||
return NullType
|
||||
|
||||
def WHERE(self,other):
|
||||
if isinstance(other, ListType) and len(self.value) == len(other.value):
|
||||
return ListType([a_item for a_item, b_item in zip(self.value, other.value) if b_item])
|
||||
return NullType
|
||||
|
||||
def IS(self,a,invert=False):
|
||||
if a is NumType:
|
||||
return ListType([item.IS(a) for item in self.value])
|
||||
if a is type(self):
|
||||
return BoolType(True^invert)
|
||||
if type(a) is Condition:
|
||||
return a.value(self)
|
||||
else:
|
||||
return BoolType(False^invert)
|
||||
|
||||
def OCCURS(self,a):
|
||||
if type(a) is Condition:
|
||||
return ListType([a.value(item.time) for item in self.value])
|
||||
|
||||
def NOT(self):
|
||||
return ListType([~item for item in self.value])
|
||||
|
||||
def LISTACCESS(self,a):
|
||||
if type(a) is NumType:
|
||||
return self.value[a.value]
|
||||
return NullType()
|
||||
|
||||
def LISTINDEXASSIGN(self,a,b):
|
||||
if type(a) is NumType:
|
||||
self.value[a.value-1] = b
|
||||
#self.value.insert(a.value,b)
|
||||
return NullType()
|
||||
|
||||
def TIME(self):
|
||||
return ListType([item.time for item in self.value])
|
||||
|
||||
class DateType(BaseType):
|
||||
def __init__(self, value: date):
|
||||
super().__init__()
|
||||
if not isinstance(value, date):
|
||||
raise TypeError(f"Expected a date, got {type(value)}")
|
||||
self.value = value
|
||||
|
||||
def __gt__(self, other):
|
||||
if isinstance(other, DateType):
|
||||
return BoolType(self.value > other.value)
|
||||
return NullType
|
||||
|
||||
def __lt__(self, other):
|
||||
if isinstance(other, DateType):
|
||||
return BoolType(self.value < other.value)
|
||||
return NullType
|
||||
|
||||
def __str__(self):
|
||||
return self.value.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
|
||||
class Condition(BaseType):
|
||||
def __init__(self, condition):
|
||||
self.value = condition
|
||||
|
||||
def __and__(self, other):
|
||||
return Condition(lambda x: self.value(x) and other.value(x))
|
||||
|
||||
def __or__(self,other):
|
||||
return Condition(lambda x: self.value(x) or other.value(x))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
class NullType(BaseType):
|
||||
def __init__(self, has_time=True):
|
||||
if has_time:
|
||||
super().__init__()
|
||||
|
||||
def __str__(self):
|
||||
return "Null"
|
|
@ -0,0 +1,664 @@
|
|||
%include {
|
||||
|
||||
#include "grammar.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "cJSON.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
int get_token_id (char*);
|
||||
const char *getValue (cJSON *token);
|
||||
const char *getLine (cJSON *token);
|
||||
cJSON *unary (char *fname, cJSON *a);
|
||||
cJSON *binary (char *fname, cJSON *a, cJSON *b);
|
||||
cJSON *ternary (char *fname, cJSON *a, cJSON *b, cJSON *c);
|
||||
char *linenumber;
|
||||
char *curtoken;
|
||||
char *curtype;
|
||||
}
|
||||
|
||||
|
||||
%code {
|
||||
|
||||
using namespace std;
|
||||
typedef struct {char *value; int line;} token;
|
||||
|
||||
token* create_token (char *value, int line) {
|
||||
token *t = (token*) malloc (sizeof (token));
|
||||
t->value = strdup (value);
|
||||
t->line = line;
|
||||
return t;
|
||||
}
|
||||
|
||||
const char * getValue (cJSON* token) {
|
||||
return cJSON_GetObjectItem (token, "value")->valuestring;
|
||||
}
|
||||
|
||||
|
||||
const char * getLine (cJSON* token) {
|
||||
return cJSON_GetObjectItem (token, "line")->valuestring;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
char *result;
|
||||
std::string line;
|
||||
std::string input = "";
|
||||
while (std::getline(std::cin, line)) {
|
||||
input += line + "\n";
|
||||
}
|
||||
if (input == "") {
|
||||
cout << "Empty input";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_Parse(input.c_str());
|
||||
|
||||
if (!root) {
|
||||
cout << "JSON invalid\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void* pParser = ParseAlloc (malloc);
|
||||
int num = cJSON_GetArraySize (root);
|
||||
|
||||
for (int i = 0; i < num; i++ ) {
|
||||
|
||||
// Knoten im Token-Stream auslesen
|
||||
cJSON *node = cJSON_GetArrayItem(root,i);
|
||||
|
||||
char *line = cJSON_GetArrayItem(node,0)->valuestring;
|
||||
char *type = cJSON_GetArrayItem(node,1)->valuestring;
|
||||
char *value = cJSON_GetArrayItem(node,2)->valuestring;
|
||||
|
||||
cJSON *tok = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(tok, "value", value);
|
||||
cJSON_AddStringToObject(tok, "line", line);
|
||||
|
||||
linenumber = line;
|
||||
curtoken = value;
|
||||
curtype = type;
|
||||
// THE und Kommentare werden ueberlesen
|
||||
if (strcmp(type, "THE") == 0) continue;
|
||||
if (strcmp(type, "COMMENT") == 0) continue;
|
||||
if (strcmp(type, "MCOMMENT") == 0) continue;
|
||||
|
||||
int tokenid = get_token_id (type);
|
||||
Parse (pParser, tokenid, tok);
|
||||
|
||||
}
|
||||
Parse (pParser, 0, 0);
|
||||
ParseFree(pParser, free );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////
|
||||
///////////////////////
|
||||
// TOKENS
|
||||
///////////////////////
|
||||
///////////////////////
|
||||
|
||||
int get_token_id (char *token) {
|
||||
if (strcmp(token, "AMBERSAND") == 0) return AMBERSAND;
|
||||
if (strcmp(token, "ASSIGN") == 0) return ASSIGN;
|
||||
if (strcmp(token, "AND") == 0) return AND;
|
||||
if (strcmp(token, "AFTER") == 0) return AFTER;
|
||||
if (strcmp(token, "BEFORE") == 0) return BEFORE;
|
||||
if (strcmp(token, "BETWEEN") == 0) return BETWEEN;
|
||||
if (strcmp(token, "COS") == 0) return COS;
|
||||
if (strcmp(token, "COMMA") == 0) return COMMA;
|
||||
if (strcmp(token, "COUNT") == 0) return COUNT;
|
||||
if (strcmp(token, "DIVIDE") == 0) return DIVIDE;
|
||||
if (strcmp(token, "DO") == 0) return DO;
|
||||
if (strcmp(token, "EQUAL") == 0) return EQUAL;
|
||||
if (strcmp(token, "ENDDO") == 0) return ENDDO;
|
||||
if (strcmp(token, "ENDIF") == 0) return ENDIF;
|
||||
if (strcmp(token, "ELSE") == 0) return ELSE;
|
||||
if (strcmp(token, "ELSEIF") == 0) return ELSEIF;
|
||||
if (strcmp(token, "FIRST") == 0) return FIRST;
|
||||
if (strcmp(token, "FOR") == 0) return FOR;
|
||||
if (strcmp(token, "GT") == 0) return GT;
|
||||
if (strcmp(token, "GREATER") == 0) return GREATER;
|
||||
if (strcmp(token, "IDENTIFIER") == 0) return IDENTIFIER;
|
||||
if (strcmp(token, "IS") == 0) return IS;
|
||||
if (strcmp(token, "ISNOT") == 0) return ISNOT;
|
||||
if (strcmp(token, "IF") == 0) return IF;
|
||||
if (strcmp(token, "IT") == 0) return IT;
|
||||
if (strcmp(token, "THEY") == 0) return IT;
|
||||
if (strcmp(token, "IN") == 0) return IN;
|
||||
if (strcmp(token, "LIST") == 0) return LIST;
|
||||
if (strcmp(token, "LPAR") == 0) return LPAR;
|
||||
if (strcmp(token, "RPAR") == 0) return RPAR;
|
||||
if (strcmp(token, "LSPAR") == 0) return LSPAR;
|
||||
if (strcmp(token, "RSPAR") == 0) return RSPAR;
|
||||
if (strcmp(token, "LT") == 0) return LT;
|
||||
if (strcmp(token, "LESS") == 0) return LESS;
|
||||
if (strcmp(token, "MINUS") == 0) return MINUS;
|
||||
if (strcmp(token, "NUMBER") == 0) return NUMBER;
|
||||
if (strcmp(token, "NUMTOKEN") == 0) return NUMTOKEN;
|
||||
if (strcmp(token, "NULLTOKEN") == 0) return NULLTOKEN;
|
||||
if (strcmp(token, "OR") == 0) return OR;
|
||||
if (strcmp(token, "OF") == 0) return OF;
|
||||
if (strcmp(token, "OCCURS") == 0) return OCCURS;
|
||||
if (strcmp(token, "OCCURRED") == 0) return OCCURS;
|
||||
if (strcmp(token, "PLUS") == 0) return PLUS;
|
||||
if (strcmp(token, "POWER") == 0) return POWER;
|
||||
if (strcmp(token, "SEMICOLON") == 0) return SEMICOLON;
|
||||
if (strcmp(token, "SIN") == 0) return SIN;
|
||||
if (strcmp(token, "STRTOKEN") == 0) return STRTOKEN;
|
||||
if (strcmp(token, "TIMETOKEN") == 0) return TIMETOKEN;
|
||||
if (strcmp(token, "TIMES") == 0) return TIMES;
|
||||
if (strcmp(token, "TIME") == 0) return TIME;
|
||||
if (strcmp(token, "TRACE") == 0) return TRACE;
|
||||
if (strcmp(token, "THAN") == 0) return THAN;
|
||||
if (strcmp(token, "THEN") == 0) return THEN;
|
||||
if (strcmp(token, "TO") == 0) return TO;
|
||||
if (strcmp(token, "RANGE") == 0) return RANGE;
|
||||
if (strcmp(token, "WRITE") == 0) return WRITE;
|
||||
if (strcmp(token, "WHERE") == 0) return WHERE;
|
||||
if (strcmp(token, "NOW") == 0) return NOW;
|
||||
if (strcmp(token, "NOT") == 0) return NOT;
|
||||
if (strcmp(token, "TRUE") == 0) return TRUE;
|
||||
if (strcmp(token, "FALSE") == 0) return FALSE;
|
||||
if (strcmp(token, "WITHIN") == 0) return WITHIN;
|
||||
|
||||
printf ("{\"error\" : true, \"message\": \"UNKNOWN TOKEN TYPE %s\"}\n", token);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
cJSON* unary (char* fname, cJSON* a)
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(arg, a);
|
||||
cJSON_AddStringToObject(res, "type", fname);
|
||||
cJSON_AddItemToObject(res, "arg", arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
cJSON* binary (char *fname, cJSON *a, cJSON *b)
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(arg, a);
|
||||
cJSON_AddItemToArray(arg, b);
|
||||
cJSON_AddStringToObject(res, "type", fname);
|
||||
cJSON_AddItemToObject(res, "arg", arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
cJSON* ternary (char *fname, cJSON *a, cJSON *b, cJSON *c)
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(arg, a);
|
||||
cJSON_AddItemToArray(arg, b);
|
||||
cJSON_AddItemToArray(arg, c);
|
||||
cJSON_AddStringToObject(res, "type", fname);
|
||||
cJSON_AddItemToObject(res, "arg", arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
%syntax_error {
|
||||
printf ("{\"error\" : true, \"message\": \"Syntax Error: Compiler reports unexpected token \\\"%s\\\" of type \\\"%s\\\" in line %s\"}\n", curtoken, curtype, linenumber);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
%token_type {cJSON *}
|
||||
%default_type {cJSON *}
|
||||
|
||||
///////////////////////
|
||||
///////////////////////
|
||||
// PRECEDENCE
|
||||
///////////////////////
|
||||
///////////////////////
|
||||
%left WHERE .
|
||||
%left OR .
|
||||
%left AND .
|
||||
%left AMBERSAND .
|
||||
%right NOT .
|
||||
%left IS ISNOT GT LT LESS GREATER LESSEQUAL GREATEREQUAL WITHIN OCCURS AFTER BEFORE BETWEEN RANGE .
|
||||
%left PLUS MINUS .
|
||||
%left TIMES DIVIDE .
|
||||
%right POWER .
|
||||
%right SIN COS .
|
||||
%right UMINUS .
|
||||
%right TIME FIRST LAST COUNT LISTACCESS LSPAR .
|
||||
|
||||
|
||||
|
||||
///////////////////////
|
||||
// CODE
|
||||
///////////////////////
|
||||
|
||||
|
||||
|
||||
code ::= statementblock(sb) .
|
||||
{
|
||||
printf (cJSON_Print(sb));
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////
|
||||
// STATEMENTBLOCK
|
||||
///////////////////////
|
||||
|
||||
|
||||
statementblock(sb) ::= .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "STATEMENTBLOCK");
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(res, "statements", arg);
|
||||
sb = res;
|
||||
}
|
||||
|
||||
|
||||
statementblock(sb) ::= statementblock(a) statement(b) .
|
||||
{
|
||||
cJSON_AddItemToArray(cJSON_GetObjectItem ( a, "statements"), b);
|
||||
sb = a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// WRITE
|
||||
///////////////////////////
|
||||
|
||||
statement(r) ::= WRITE ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "WRITE");
|
||||
cJSON_AddItemToObject(res, "arg", e);
|
||||
r = res;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Trace
|
||||
///////////////////////////
|
||||
statement(r) ::= TRACE(a) ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "TRACE");
|
||||
cJSON_AddItemToObject(res, "arg", e);
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// ASSIGN
|
||||
///////////////////////////
|
||||
statement(r) ::= IDENTIFIER(a) ASSIGN ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "ASSIGN");
|
||||
cJSON_AddStringToObject(res, "varname", getValue(a));
|
||||
cJSON_AddItemToObject(res, "arg", e);
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// ASSIGN TIME OF
|
||||
///////////////////////////
|
||||
statement(r) ::= TIME of IDENTIFIER(a) ASSIGN ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "TIMEASSIGN");
|
||||
cJSON_AddStringToObject(res, "varname", getValue(a));
|
||||
cJSON_AddItemToObject(res, "arg", e);
|
||||
r = res;
|
||||
}
|
||||
|
||||
statement(r) ::= IDENTIFIER(a) LSPAR ex(b) RSPAR ASSIGN ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddStringToObject(res, "type", "LISTINDEXASSIGN");
|
||||
cJSON_AddStringToObject(res, "varname", getValue(a));
|
||||
cJSON_AddItemToArray(arg, b);
|
||||
cJSON_AddItemToArray(arg, e);
|
||||
cJSON_AddItemToObject(res, "arg", arg);
|
||||
r = res;
|
||||
}
|
||||
statement(r) ::= TIME of IDENTIFIER(a) LSPAR ex(b) RSPAR ASSIGN ex(e) SEMICOLON .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddStringToObject(res, "type", "LISTINDEXTIMEASSIGN");
|
||||
cJSON_AddStringToObject(res, "varname", getValue(a));
|
||||
cJSON_AddItemToArray(arg, b);
|
||||
cJSON_AddItemToArray(arg, e);
|
||||
cJSON_AddItemToObject(res, "arg", arg);
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// IF
|
||||
///////////////////////////
|
||||
ifconditionstatement ::= ifstartstatement .
|
||||
ifconditionstatement ::= elseifstatement .
|
||||
|
||||
ifstatement ::= ifstartstatement .
|
||||
ifstatement ::= elseifstatement .
|
||||
ifstatement ::= elsestatement .
|
||||
|
||||
|
||||
statement ::= ifstatement ENDIF SEMICOLON .
|
||||
|
||||
|
||||
ifstartstatement(r) ::= IF ex(c) THEN
|
||||
statementblock(s)
|
||||
.
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "IF");
|
||||
cJSON_AddItemToObject(res, "arg", c);
|
||||
cJSON_AddItemToObject(res, "statements", s);
|
||||
cJSON *elseifs = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(res, "elseif", elseifs);
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
elseifstatement(r) ::= ifconditionstatement(i)
|
||||
ELSEIF ex(c) THEN
|
||||
statementblock(s)
|
||||
.
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "ELSEIF");
|
||||
cJSON_AddItemToObject(res, "arg", c);
|
||||
cJSON_AddItemToObject(res, "statements", s);
|
||||
cJSON *elseifArray = cJSON_GetObjectItem(i, "elseif");
|
||||
cJSON_AddItemToArray(elseifArray, res);
|
||||
r = i;
|
||||
}
|
||||
|
||||
elsestatement(r) ::= ifconditionstatement(i)
|
||||
ELSE
|
||||
statementblock(s)
|
||||
.
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "ELSE");
|
||||
cJSON_AddItemToObject(res, "statements", s);
|
||||
cJSON_AddItemToObject(i, "else", res);
|
||||
r = i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// FOR
|
||||
///////////////////////////
|
||||
statement(r) ::= FOR IDENTIFIER(a) IN ex(e) DO
|
||||
statementblock(s)
|
||||
ENDDO SEMICOLON
|
||||
.
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON *arg = cJSON_CreateArray();
|
||||
cJSON_AddStringToObject(res, "type", "FOR");
|
||||
cJSON_AddStringToObject(res, "varname", getValue(a));
|
||||
cJSON_AddItemToObject(res, "arg", e);
|
||||
cJSON_AddItemToObject(res, "statements", s);
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ex(r) ::= LPAR ex(a) RPAR .
|
||||
{
|
||||
r = a;
|
||||
}
|
||||
|
||||
ex(r) ::= LSPAR RSPAR .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "EMPTYLIST");
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= LSPAR exlist(a) RSPAR .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "LIST");
|
||||
cJSON_AddItemToObject(res, "elements", a);
|
||||
r = res;
|
||||
}
|
||||
|
||||
exlist(r) ::= ex(a) .
|
||||
{
|
||||
cJSON *elem = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(elem, a);
|
||||
r = elem;
|
||||
}
|
||||
|
||||
exlist(r) ::= exlist(a) COMMA ex(b) .
|
||||
{
|
||||
cJSON_AddItemToArray(a,b);
|
||||
r = a;
|
||||
}
|
||||
|
||||
|
||||
ex(r) ::= NUMTOKEN (a).
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "NUMTOKEN");
|
||||
cJSON_AddStringToObject(res, "value", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
ex(r) ::= STRTOKEN (a).
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "STRTOKEN");
|
||||
cJSON_AddStringToObject(res, "value", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
|
||||
ex(r) ::= IDENTIFIER(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "VARIABLE");
|
||||
cJSON_AddStringToObject(res, "name", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= TIMETOKEN(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "TIMETOKEN");
|
||||
cJSON_AddStringToObject(res, "value", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= NULLTOKEN(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "NULLTOKEN");
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= LIST(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "LISTTYPE");
|
||||
cJSON_AddStringToObject(res, "value", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= NUMBER(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "NUMTYPE");
|
||||
cJSON_AddStringToObject(res, "name", getValue(a));
|
||||
cJSON_AddStringToObject(res, "line", getLine(a));
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= NOW(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "NOW");
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= IT(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "IT");
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= TRUE(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "BOOL");
|
||||
cJSON_AddStringToObject(res, "value", "1");
|
||||
r = res;
|
||||
}
|
||||
|
||||
ex(r) ::= FALSE(a) .
|
||||
{
|
||||
cJSON *res = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(res, "type", "BOOL");
|
||||
cJSON_AddStringToObject(res, "value", "0");
|
||||
r = res;
|
||||
}
|
||||
|
||||
of ::= .
|
||||
of ::= OF .
|
||||
is ::= .
|
||||
is ::= IS .
|
||||
|
||||
ex(r) ::= COS ex(a) .
|
||||
{r = unary ("COS", a); }
|
||||
|
||||
ex(r) ::= FIRST ex(a) .
|
||||
{r = unary ("FIRST", a); }
|
||||
|
||||
ex(r) ::= COUNT ex(a) .
|
||||
{r = unary ("COUNT", a); }
|
||||
|
||||
ex(r) ::= TIME of ex(a) .
|
||||
{r = unary ("TIME", a); }
|
||||
|
||||
ex(r) ::= NOT ex(a) .
|
||||
{r = unary ("NOT", a); }
|
||||
|
||||
ex(r) ::= SIN ex(a) .
|
||||
{r = unary ("SIN", a); }
|
||||
|
||||
ex(r) ::= LESS THAN ex(a) .
|
||||
{r = unary ("LESS", a); }
|
||||
|
||||
ex(r) ::= BEFORE ex(a) .
|
||||
{r = unary ("BEFORE", a); }
|
||||
|
||||
ex(r) ::= GREATER THAN ex(a) .
|
||||
{r = unary ("GREATER", a); }
|
||||
|
||||
ex(r) ::= AFTER ex(a) .
|
||||
{r = unary ("AFTER", a); }
|
||||
|
||||
ex(r) ::= LESS THAN OR EQUAL ex(a) .
|
||||
{r = unary ("LESSEQUAL", a); }
|
||||
|
||||
ex(r) ::= GREATER THAN OR EQUAL ex(a) .
|
||||
{r = unary ("GREATEREQUAL", a); }
|
||||
|
||||
ex(r) ::= WITHIN ex(a) TO ex(b).
|
||||
{r = binary ("WITHIN", a, b); }
|
||||
|
||||
ex(r) ::= BETWEEN ex(a) AND ex(b).
|
||||
{r = binary ("BETWEEN", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) AMBERSAND ex(b) .
|
||||
{r = binary ("AMBERSAND", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) AND ex(b) .
|
||||
{r = binary ("AND", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) OR ex(b) .
|
||||
{r = binary ("OR", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) WHERE ex(b) .
|
||||
{r = binary ("WHERE", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) OCCURS ex(b) .
|
||||
{r = binary ("OCCURS", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) IS ex(b) .
|
||||
{r = binary ("IS", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) IS NOT ex(b) .
|
||||
{r = binary ("ISNOT", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) PLUS ex(b) .
|
||||
{r = binary ("PLUS", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) MINUS ex(b) .
|
||||
{r = binary ("MINUS", a, b); }
|
||||
|
||||
ex(r) ::= MINUS ex(a) . [UMINUS]
|
||||
{r = unary ("UMINUS", a); }
|
||||
|
||||
ex(r) ::= ex(a) TIMES ex(b) .
|
||||
{r = binary ("TIMES", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) DIVIDE ex(b) .
|
||||
{r = binary ("DIVIDE", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) POWER ex(b) .
|
||||
{r = binary ("POWER", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) GT ex(b) .
|
||||
{r = binary ("GT", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) LT ex(b) .
|
||||
{r = binary ("LT", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) LSPAR ex(b) RSPAR .
|
||||
{r = binary ("LISTACCESS", a, b); }
|
||||
|
||||
ex(r) ::= ex(a) RANGE ex(b) .
|
||||
{r = binary ("RANGE", a, b); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
from datetime import datetime
|
||||
from collections import deque
|
||||
from arden_types import StrType, NumType, DateType, ListType, NullType, BoolType, Condition
|
||||
import math
|
||||
import copy
|
||||
class InterpreterError(Exception):
|
||||
pass
|
||||
|
||||
class Interpreter:
|
||||
def __init__(self):
|
||||
self.variables = {}
|
||||
self.it_queue = deque()
|
||||
|
||||
def interpret(self, node):
|
||||
node_type = node["type"]
|
||||
args = node.get('arg', [])
|
||||
if node_type == "WHERE":
|
||||
self.it_queue.append(self.interpret(args[0]))
|
||||
evaluated_args = [self.interpret(arg) for arg in (args if isinstance(args, list) else [args])]
|
||||
return getattr(self, node_type)(node, *evaluated_args)
|
||||
|
||||
def STATEMENTBLOCK(self,node):
|
||||
for stmt in node.get("statements"):
|
||||
self.interpret(stmt)
|
||||
|
||||
#Statements
|
||||
def WRITE(self,node,a):
|
||||
print(a)
|
||||
|
||||
def TRACE(self,node,a):
|
||||
print(f"LINE {node['line']}: {a}")
|
||||
|
||||
def ASSIGN(self,node,a):
|
||||
#self.variables.update({node.get("varname"): (self.variables.get(node.get("varname")[0],NullType()),a)})
|
||||
self.variables.update({node.get("varname"): copy.copy(a)})
|
||||
|
||||
def TIMEASSIGN(self,node,a):
|
||||
#self.variables.update({node.get("varname"): (a,self.variables.get(node.get("varname"))[1])})
|
||||
value = self.variables[node.get("varname")]
|
||||
value.time = a
|
||||
self.variables.update({node.get("varname"): copy.copy(value)})
|
||||
|
||||
def LISTINDEXASSIGN(self,node,a,b):
|
||||
value = self.variables[node.get("varname")]
|
||||
return value.LISTINDEXASSIGN(a,b)
|
||||
|
||||
def LISTINDEXTIMEASSIGN(self,node,a,b):
|
||||
value = self.variables[node.get("varname")]
|
||||
return value.LISTINDEXASSIGN(a,b)
|
||||
|
||||
def IF(self,node,a):
|
||||
if a:
|
||||
self.interpret(node.get("statements"))
|
||||
return
|
||||
for elseif in node.get("elseif"):
|
||||
if self.interpret(elseif):
|
||||
return
|
||||
else:
|
||||
if node.get("else"):
|
||||
self.interpret(node.get("else"))
|
||||
|
||||
def ELSEIF(self,node,a):
|
||||
if a:
|
||||
self.interpret(node.get("statements"))
|
||||
return True
|
||||
return False
|
||||
|
||||
def ELSE(self,node):
|
||||
self.interpret(node.get("statements"))
|
||||
|
||||
def FOR(self,node,a):
|
||||
for x in a.value:
|
||||
self.variables[node.get("varname")] = x
|
||||
self.interpret(node.get("statements"))
|
||||
del self.variables[node.get("varname")]
|
||||
|
||||
#Types
|
||||
def NUMTOKEN(self,node):
|
||||
return NumType(node.get("value"))
|
||||
|
||||
def STRTOKEN(self,node):
|
||||
return StrType(node.get("value"))
|
||||
|
||||
def TIMETOKEN(self,node):
|
||||
try:
|
||||
return DateType(datetime.strptime(node.get("value"), "%Y-%m-%dT%H:%M:%S"))
|
||||
except ValueError:
|
||||
return DateType(datetime.strptime(node.get("value"), "%Y-%m-%d"))
|
||||
|
||||
def NULLTOKEN(self,node):
|
||||
return NullType()
|
||||
|
||||
def NOW(self,node):
|
||||
return DateType(datetime.now())
|
||||
|
||||
def VARIABLE(self,node):
|
||||
return self.variables.get(node.get("name"))
|
||||
|
||||
def TIME(self,node,a):
|
||||
return a.TIME()
|
||||
|
||||
def LIST(self,node):
|
||||
return ListType([self.interpret(node) for node in node["elements"]])
|
||||
|
||||
def BOOL(self,node):
|
||||
return BoolType(True) if node.get("value") == "1" else BoolType(False)
|
||||
|
||||
def NULLTYPE(self,node):
|
||||
return NullType
|
||||
|
||||
def NUMTYPE(self,node):
|
||||
return NumType
|
||||
|
||||
def LISTTYPE(self,node):
|
||||
return ListType
|
||||
|
||||
def TRUE(self,node):
|
||||
return True
|
||||
|
||||
def FALSE(self,node):
|
||||
return False
|
||||
|
||||
def IT(self,node):
|
||||
if self.it_queue:
|
||||
return self.it_queue[-1]
|
||||
return NullType()
|
||||
|
||||
def LISTACCESS(self,node,a,b):
|
||||
return a.LISTACCESS(b)
|
||||
|
||||
#Binary Operators
|
||||
def AMBERSAND(self,node,a,b):
|
||||
return a & b
|
||||
|
||||
def PLUS(self,node,a,b):
|
||||
return a + b
|
||||
|
||||
def MINUS(self,node,a,b):
|
||||
return a - b
|
||||
|
||||
def TIMES(self,node,a,b):
|
||||
return a * b
|
||||
|
||||
def DIVIDE(self,node,a,b):
|
||||
return a / b
|
||||
|
||||
def POWER(self,node,a,b):
|
||||
return a ** b
|
||||
|
||||
def WHERE(self,node,a,b):
|
||||
res = a.WHERE(b)
|
||||
self.it_queue.pop()
|
||||
return res
|
||||
|
||||
def GT(self,node,a,b):
|
||||
return a > b
|
||||
|
||||
def LT(self,node,a,b):
|
||||
return a < b
|
||||
|
||||
def AND(self,node,a,b):
|
||||
return a & b
|
||||
|
||||
def OR(self,node,a,b):
|
||||
return a | b
|
||||
|
||||
def RANGE(self,node,a,b):
|
||||
rangelist = []
|
||||
x = range(a.value,b.value+1)
|
||||
for i in x:
|
||||
rangelist.append(NumType(i))
|
||||
return ListType(rangelist)
|
||||
|
||||
#Unary Operators
|
||||
def UMINUS(self,node,a):
|
||||
return -a
|
||||
|
||||
def COS(self,node,a):
|
||||
return NumType(math.cos(a))
|
||||
|
||||
def SIN(self,node,a):
|
||||
return NumType(math.sin(a))
|
||||
|
||||
def IS(self,node,a,b):
|
||||
return a.IS(b)
|
||||
|
||||
def ISNOT(self,node,a,b):
|
||||
return a.IS(b).NOT()
|
||||
|
||||
def OCCURS(self,node,a,b):
|
||||
return a.OCCURS(b)
|
||||
|
||||
def NOT(self,a):
|
||||
return ~a
|
||||
|
||||
def FIRST(self,node,a):
|
||||
return a.value[0]
|
||||
|
||||
def COUNT(self,node, a):
|
||||
return NumType(len(a.value))
|
||||
|
||||
#Conditions
|
||||
def LESS(self,node,a):
|
||||
return Condition(lambda x: x < a)
|
||||
|
||||
def BEFORE(self,node,a):
|
||||
return Condition(lambda x: x < a)
|
||||
|
||||
def GREATER(self,node,a):
|
||||
return Condition(lambda x: x > a)
|
||||
|
||||
def AFTER(self,node,a):
|
||||
return Condition(lambda x: x > a)
|
||||
|
||||
def LESSEQUAL(self,node,a):
|
||||
return Condition(lambda x: x <= a)
|
||||
|
||||
def GREATEREQUAL(self,node,a):
|
||||
return Condition(lambda x: x >= a)
|
||||
|
||||
def WITHIN(self,node,a,b):
|
||||
return Condition(lambda x: (a <= x) & (x <= b))
|
|
@ -0,0 +1,11 @@
|
|||
import subprocess
|
||||
import json
|
||||
class ParserError(Exception):
|
||||
pass
|
||||
class Parser:
|
||||
def parse(self,tokens):
|
||||
result = subprocess.run(['./parse.exe'], input=json.dumps(tokens, indent=4).encode('utf-8'),stdout=subprocess.PIPE)
|
||||
ast = json.loads(result.stdout.decode('utf-8'))
|
||||
if "error" in ast:
|
||||
raise ParserError(f"{ast['message']}")
|
||||
return json.loads(result.stdout.decode('utf-8'))
|
|
@ -0,0 +1,21 @@
|
|||
import argparse
|
||||
from tokenizer import Tokenizer
|
||||
from parser import Parser
|
||||
from interpreter import Interpreter
|
||||
import json
|
||||
|
||||
arg_parser = argparse.ArgumentParser(description="DSM")
|
||||
arg_parser.add_argument("input_file", type=str, help="The input file to process")
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
tokenizer = Tokenizer()
|
||||
parser = Parser()
|
||||
interpreter = Interpreter()
|
||||
#try:
|
||||
tokens = tokenizer.tokenize(args.input_file)
|
||||
#print(json.dumps(tokens, indent=4))
|
||||
ast = parser.parse(tokens)
|
||||
#print(json.dumps(ast, indent=4))
|
||||
interpreter.interpret(ast)
|
||||
#except Exception as e:
|
||||
# print(f"{type(e).__name__}: {e}")
|
|
@ -0,0 +1,59 @@
|
|||
import re
|
||||
import json
|
||||
class TokenizerError(Exception):
|
||||
pass
|
||||
class Tokenizer:
|
||||
def __init__(self):
|
||||
self.reserved = [
|
||||
'READ', 'WRITE', 'IF', 'THEN', 'ELSEIF', 'ELSE', 'ENDIF', 'FOR',
|
||||
'IN', 'DO', 'ENDDO', 'NOW', 'CURTIME', 'MINIMUM', 'MAXIMUM',
|
||||
'FIRST', 'LAST', 'SUM', 'AVERAGE', 'EARLIEST', 'LATEST', 'COS', 'SIN', 'TIME', 'OF', 'TRACE', 'TRUE', 'FALSE', 'IS', 'LIST', 'NUMBER', 'NOT', 'COUNT',
|
||||
'WHERE', 'IT', 'THEY', 'AND', 'OR', 'LESS', 'GREATER', 'THAN', 'TO', 'WITHIN', 'EQUAL', 'OCCURS', 'OCCURRED', 'AFTER', 'BEFORE'
|
||||
]
|
||||
self.regex_patterns = {
|
||||
"STRTOKEN": r'(".*?")',
|
||||
"TIMETOKEN": r'\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?',
|
||||
"COMMENT": r'//.*$',
|
||||
"SEMICOLON": r';',
|
||||
"COMMA": r',',
|
||||
"ASSIGN": r':=',
|
||||
"PLUS": r'\+',
|
||||
"MINUS": r'\-',
|
||||
"POWER": r'\*\*',
|
||||
"TIMES": r'\*',
|
||||
"DIVIDE": r'\/',
|
||||
"LPAR": r'\(',
|
||||
"RPAR": r'\)',
|
||||
"LSPAR": r'\[',
|
||||
"RSPAR": r'\]',
|
||||
"AMBERSAND": r'&',
|
||||
"NEQ": r'<>',
|
||||
"LT": r'<',
|
||||
"GT": r'>',
|
||||
"LTEQ": r'<=',
|
||||
"GTEQ": r'>=',
|
||||
"EQ": r'=',
|
||||
"RANGE": r'\.\.\.'
|
||||
}
|
||||
self.regex_patterns |= {
|
||||
"NULLTOKEN": r'\bNULL\b'
|
||||
}
|
||||
self.regex_patterns |= {i: rf'\b{i}\b' for i in self.reserved}
|
||||
self.regex_patterns |= {
|
||||
"NUMTOKEN": r'\d+(\.\d*)?',
|
||||
"IDENTIFIER": r'\w+'
|
||||
}
|
||||
self.combined_pattern = '|'.join(f'(?P<{name}>{pattern})' for name, pattern in self.regex_patterns.items())
|
||||
self.regex = re.compile(self.combined_pattern, re.IGNORECASE)
|
||||
|
||||
def tokenize(self, input_file):
|
||||
tokens = []
|
||||
with open(input_file, 'r') as file:
|
||||
for i, line in enumerate(file):
|
||||
for match in self.regex.finditer(line):
|
||||
token_type = match.lastgroup
|
||||
token_value = match.group(token_type)
|
||||
if token_type == "STRTOKEN":
|
||||
token_value = token_value.replace('"','')
|
||||
tokens.append([str(i + 1), token_type, token_value])
|
||||
return tokens
|
Loading…
Reference in New Issue