-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlangParser.py
256 lines (239 loc) · 7.09 KB
/
langParser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
from string import ascii_letters, digits
from langEnums import Types, ConditionType, Exceptions
def parse_escape_character(trimmed_string):
is_escape_char_detected = False
outstr = ""
for i in str(trimmed_string):
outchar = i
if i == "\\":
is_escape_char_detected = True
continue
if is_escape_char_detected:
is_escape_char_detected = False
if i == "n":
outchar = "\n"
elif i == "\\":
outchar = "\\"
elif i == "t":
outchar = "\t"
outstr += outchar
return outstr
def parse_string_list(command):
if isinstance(command, str):
command = [command]
res = " ".join(command)
# for i in command:
# res += i + " "
# res = res[:-1]
return res
def check_is_float(command):
is_float = False
if(not isinstance(command, str)):
command = str(command)
for i in command:
for j in i:
if j == ".":
is_float = True
break
return is_float
def try_parse_int(val):
try:
return int(val)
except ValueError:
return val
def convert_to_python_native_type(valtype, value):
"""
Returns a Converted to Python version of the value provided to a Type specified.
[PARAMETER] valtype: Target output type
[PARAMETER] value: The input value that will be converted.
[RETURNS] a Converted value. Else the input value If the type is not support yet by the Converter.
"""
if valtype == Types.Integer:
return int(value)
elif valtype == Types.Float:
return float(value)
elif value == Types.String:
return str(value[1:-1])
elif value == Types.Boolean:
if value == "true":
return True
elif value == "false":
return False
else:
return value
else: return value
def convert_types_enum_to_string(enumvalue):
if enumvalue == Types.Integer:
return "int"
elif enumvalue == Types.Float:
return "float"
elif enumvalue == Types.String:
return "string"
elif enumvalue == Types.Boolean:
return "bool"
elif enumvalue == Types.Dynamic:
return "dynamic"
elif enumvalue == Types.Tuple:
return "tuple"
elif enumvalue == Types.List:
return "list"
elif enumvalue == Types.Dictionary:
return "dictionary"
def convert_to_storyscript_native_type(valtype, value):
"""
Returns a Converted to StoryScript version of the value provided to a Type specified.
[PARAMETER] valtype: Target output type
[PARAMETER] value: The input value that will be converted.
[RETURNS] a Converted value. Else the input value If the type is not support yet by the Converter.
"""
if valtype == Types.Integer:
return str(value)
elif valtype == Types.Float:
return str(value)
elif value == Types.String:
return f"\"{value}\""
elif value == Types.Boolean:
if value: return "true"
else: return "false"
elif value == Types.Dynamic:
return f"new Dynamic ({value})"
else: return value
def trim_space(string):
out_str = ""
in_string = False
for i in string:
if i == "\"":
if in_string: in_string = False
else: in_string = True
if not in_string and i == " ":
continue
out_str += i
return out_str
def parse_type_from_value(value):
if not isinstance(value, str):
value = str(value)
is_float = check_is_float(value)
if(value.startswith('"') or value.endswith('"')):
if(not (value.startswith('"') and value.endswith('"'))):
return Exceptions.InvalidSyntax
return Types.String
elif(value == "true" or value == "false"):
return Types.Boolean
elif(value.startswith("new List")):
return Types.List
elif(value.startswith("new Dictionary")):
return Types.Dictionary
elif(value.startswith("new Tuple")):
return Types.Tuple
elif(value.startswith("new Dynamic")):
return Types.Dynamic
elif(is_float):
return Types.Float
elif(not is_float):
return Types.Integer
else: return Exceptions.InvalidSyntax
def parse_type_string(string):
if(string == "bool"):
return Types.Boolean
elif(string == "int"):
return Types.Integer
elif(string == "float"):
return Types.Float
elif(string == "list"):
return Types.List
elif(string == "dictionary"):
return Types.Dictionary
elif(string == "tuple"):
return Types.Tuple
elif(string == "dynamic"):
return Types.Dynamic
elif(string == "string"):
return Types.String
elif(string == "any"):
return Types.Any
else:
return Exceptions.InvalidSyntax
def check_naming_violation(name):
""" Returns If the variable naming valid or not """
if not isinstance(name, str):
name = str(name)
if name in ["if", "else", "var", "int",
"bool", "float", "list", "dictionary",
"tuple", "const", "override", "func",
"end", "print", "input", "throw",
"string", "typeof", "del", "namespace"]:
return False
elif name[0] in digits:
return False
else: return True
def parse_condition_expression(expr, analyse_command_method):
""" Parse If the condition is True or False """
# [:OperatorIndex] = Accessing a Message before the operator
# [OperatorIndex + 1:] = Accessing a Message after the operator
operator_index = 0
compare_operator = {">", "<", "==", "!=", ">=", "<="}
for i in expr:
if i in compare_operator:
break
operator_index += 1
resl, error = analyse_command_method(expr[:operator_index]) # Analyse the message on the left
if error: return resl, error
resr, error = analyse_command_method(expr[operator_index + 1:]) # Analyse the message on the right
if error: return resr, error
# Type conversion
restype = parse_type_from_value(resl)
resl = convert_to_python_native_type(restype, resl)
restype = parse_type_from_value(resr)
resr = convert_to_python_native_type(restype, resr)
if expr[operator_index] == "==": # If the operator was ==
if resl == resr: return True
elif expr[operator_index] == ">": # If the operator was >
if resl > resr: return True
elif expr[operator_index] == "<": # If the operator was <
if resl < resr: return True
elif expr[operator_index] == "!=": # If the operator was !=
if resl != resr: return True
elif expr[operator_index] == ">=": # If the operator was >=
if resl >= resr: return True
elif expr[operator_index] == "<=": # If the operator was <=
if resl <= resr: return True
else: return Exceptions.InvalidSyntax
return False
def parse_conditions(expr):
""" Separate expressions into a list of conditions """
conditionslist:list = [] # List of conditions
conditions:list = [] # List of condition
condition:list = [] # Condition
current_condition_type = ConditionType.Single # Current condition type
for i in expr:
if i == "and":
if current_condition_type != ConditionType.Single:
conditions.append(condition)
conditions.append(current_condition_type)
conditionslist.append(conditions)
conditions = []
condition = []
conditions.append(condition)
condition = []
current_condition_type = ConditionType.And
continue
if i == "or":
if current_condition_type != ConditionType.Single:
conditions.append(condition)
conditions.append(current_condition_type)
conditionslist.append(conditions)
conditions = []
condition = []
conditions.append(condition)
condition = []
current_condition_type = ConditionType.Or
continue
if i == "then":
conditions.append(condition)
conditions.append(current_condition_type)
conditionslist.append(conditions)
conditions = []
condition = []
break
condition.append(i)
return conditionslist