Skip to content
This repository was archived by the owner on Apr 25, 2023. It is now read-only.

Commit 75894ae

Browse files
committed
Worked hard on copy-pasting the parser from the dev branch
1 parent 51443a0 commit 75894ae

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

ilanguage/Main/parser.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
2+
import iast as ast
3+
class ParserError(BaseException):
4+
def __init__(self,name,help,line,errcode=0):
5+
self.name = name
6+
self.help = help
7+
self.line = line+1
8+
self.errcode = errcode
9+
10+
def __str__(self):
11+
return "Parser error: " + self.name.upper() + "(errno " + str(self.errcode) + ") - (line " + str(self.line) + "):\n" + self.help
12+
13+
14+
15+
class Parser:
16+
def __init__(self,tokens):
17+
self.tokens = tokens
18+
19+
def tokenstolist(self,tokenlist):
20+
l = []
21+
for token in tokenlist:
22+
l.append(token.type)
23+
return l
24+
25+
def parseoneof(self,tokens,line,local,funcs):
26+
for f in funcs:
27+
retval = f(tokens,line,local)
28+
if retval is not None:
29+
return retval
30+
def splittokens(self,tokens,splitter):
31+
tl = [[]]
32+
i = 0
33+
for t in tokens:
34+
if t.type == splitter:
35+
i += 1
36+
tl.append([])
37+
else: tl[i].append(t)
38+
return tl
39+
40+
def parse_function_definition(self,tokens,line,local):
41+
if tokens[0].type == "BASETYPE":
42+
if tokens[1].type == "NAME":
43+
split = self.splittokens(tokens,"CLAMP_CLOSE")
44+
if len(split)==2:
45+
split[0] = split[0][1:]
46+
if tokens[3].type == "CLAMP_OPEN":
47+
pass
48+
49+
50+
51+
def parse_value(self,tokens,line,local,list=0):
52+
if len(tokens) == 1:
53+
if tokens[0].type in ["BOOL","STRING","FLOAT","INT","HEX"]:
54+
return ast.StaticValue(tokens[0].type.lower(),tokens[0].value)
55+
elif tokens[0].value == "null":
56+
return ast.StaticValue("null","null")
57+
print(tokens)
58+
if tokens[0].type == "INDEX_OPEN" and tokens[-1].type == "INDEX_CLOSE":
59+
typ = None
60+
lis = ast.StaticList(None,[],list+1)
61+
if tokens[1:-1] == []:
62+
typ = "emptylist"
63+
lis.type = typ
64+
return lis
65+
for buf in self.splittokens(tokens[1:-1],"SEPERATOR"):
66+
tree = self.parseoneof(buf,line,local,[self.parse_value])
67+
if typ is None: typ = tree.type
68+
if tree.type != typ: typ = "dynamic"
69+
lis.values.append(tree)
70+
if tokens[1:-1] == []:
71+
typ = "emptylist"
72+
lis.type = typ
73+
return lis
74+
75+
76+
77+
def parse(self,tokens = None,start:ast.AST=ast.Main(),local=0,startline=0):
78+
line = startline
79+
if tokens is None:
80+
tokens = self.tokens
81+
print("parsing...")
82+
index = 0
83+
buffer = []
84+
block = 0
85+
while index < len(tokens):
86+
#print(buffer)
87+
if tokens[index].type == "NEWLINE":
88+
line += 1
89+
else: buffer.append(tokens[index])
90+
if tokens[index].type == "BLOCK_OPEN":
91+
block += 1
92+
elif tokens[index].type == "BLOCK_CLOSE":
93+
block -= 1
94+
ast.delete_locals(block+1)
95+
if block == 0 and tokens[index].type == "END_CMD":
96+
tree = self.parseoneof(buffer,line,local + block,[self.parse_define_variable, self.parse_import])
97+
#if tree is None: pass
98+
start.last().nexttask = tree
99+
buffer = []
100+
index += 1
101+
return start
102+
103+
def parse_import(self,tokens,line,local):
104+
if tokens[0].type == "IMPORT":
105+
if tokens[1].type == "NAME":
106+
#if len(tokens) == 3 and tokens[2].type == "END_CMD":
107+
return ast.Import(tokens[1].value)
108+
109+
else: raise ParserError("notaname",
110+
"Expected a module name after 'import'",
111+
line)
112+
113+
114+
def parse_define_variable(self,tokens,line,local):
115+
tl : list = self.tokenstolist(tokens)
116+
#valid = True
117+
indef = False
118+
listdimension = 0
119+
if tl[0] == "INDEFINITE":
120+
indef = True
121+
tl = tl[1:]
122+
tokens = tokens[1:]
123+
if tl[0] == "BASETYPE":
124+
if tl[1] == "INDEX_OPEN":
125+
i = 1
126+
while tl[i] == "INDEX_OPEN" and tl[i + 1] == "INDEX_CLOSE":
127+
listdimension += 1
128+
i += 2
129+
if tl[i-1] != "INDEX_CLOSE":
130+
raise ParserError("unclosedindex", """In this line there is an unclosed '['. This is needed to have a working list""", line)
131+
132+
tl = [tl[0]] + tl[i:]
133+
#print(tl)
134+
tokens = [tokens[0]] + tokens[i:]
135+
136+
if tl[1] == "NAME":
137+
if tl[2] == "END_CMD": # e.g. ?int my_int;
138+
if not tokens[1].value in ast.known_vars:
139+
print("Variable found")
140+
ast.known_vars[tokens[1].value] = ast.Variable(tokens[1].value,tokens[0].value,local,listdimension,line,indef)
141+
return ast.DefineVariableNovalue(tokens[1].value,tokens[0].value,listdimension,indef)
142+
else:
143+
raise ParserError("varoverlap",
144+
"This variable seems overlapping with an already existing one ('" + str(ast.known_vars[tokens[1].value].name) + "', line " + str(ast.known_vars[tokens[1].value].line) + ")",
145+
line)
146+
elif tl[2] == "SET":
147+
if tl[3] == "END_CMD": raise ParserError("nosetvalue",
148+
"It looks like you forgot to set a value here or you put in a '=' where you didn't want it.",
149+
line)
150+
elif tl[-1] == "END_CMD":
151+
#print(tokens[3:-1])
152+
tree = self.parseoneof(tokens[3:-1],line,local,[self.parse_value])
153+
if tree is not None and (tree.type == tokens[0].value or tokens[0].value == "dynamic" or (indef and tree.type == "null") or tree.type == "emptylist"):
154+
if not tokens[1].value in ast.known_vars:
155+
ast.known_vars[tokens[1].value] = ast.Variable(tokens[1].value, tokens[0].value, local,
156+
listdimension, line, indef)
157+
return ast.DefineVariable(tokens[1].value, tokens[0].value, listdimension, indef,tree)
158+
else:
159+
raise ParserError("varoverlap",
160+
"This variable seems overlapping with an already existing one ('" + str(
161+
ast.known_vars[tokens[1].value].name) + "', line " + str(
162+
ast.known_vars[tokens[1].value].line) + ")",
163+
line)
164+
raise ParserError("unmatchingtype",
165+
"The return type of this variable (" + str(tree) + ") does not match the vars expected (" + int(indef)*"?" + str(tokens[0].value) + listdimension*"[]" + ")",
166+
line)
167+
else:
168+
raise ParserError("noendcmd",
169+
"This Command seems to have no ';', which is required at the end of every Command",
170+
line)
171+
else:
172+
raise ParserError("noendcmd", """This Command seems to have no ';', which is required at the end of every Command""", line)
173+
elif indef:
174+
raise ParserError("unusedindef","""The '?' in this line could not be used, this could be because the rest of the declaration is wrong.""",line)
175+

0 commit comments

Comments
 (0)