-
Notifications
You must be signed in to change notification settings - Fork 88
/
Copy pathdeclarationParser.py
155 lines (147 loc) · 4.7 KB
/
declarationParser.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
'''
#########################################################################
# File : parser.py
# Author: mbinary
# Mail: [email protected]
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2018-09-17 22:19
# Description:
#########################################################################
'''
import argparse
from token_scanner import gen_token
argp = argparse.ArgumentParser()
argp.add_argument('-c','--code',help="output generated code", action='store_true')
args = argp.parse_args()
CODE = args.code
class parser(object):
def __init__(self):
self.tokens =None
self.n = 0
self.i= 0
def isType(self,s):
return self.i<self.n and self.tokens[self.i].type==s
def isEnd(self):
return self.i>=self.n
def match(self,tp=None):
cur = self.tokens[self.i]
#print(self.i,tp,cur)
if tp is None or cur.type==tp:
self.i+=1
return cur
raise Exception('[parse error] Expect {}, got {}'.format(tp,cur.type))
def parse(self,tokens):
self.tokens=tokens
self.i = 0
self.n = len(self.tokens)
try:
self.statement()
if self.i<self.n:
print('[parse error] invalid statement')
except Exception as e:
print(e)
def statement(self):
pass
class declarationParser(parser):
type_size = {'INT':1,'POINTER':1,'VOID':1}
def statement(self):
'''non-terminate-symbol: translation_unit'''
while self.i<self.n:
for i in self.declaration():
print(i)
def declaration(self):
symType = self.declaration_specifiers()
li = self.init_declarator_list(symType)
self.match('SEMICOLON')
return li
def declaration_specifiers(self):
return self.type_specifier()
def type_specifier(self):
return self.match().value
def init_declarator_list(self,symType):
li = []
while 1:
li.append(self.init_declarator(symType))
if self.isType('COMMA'):
self.match()
else:break
return li
def init_declarator(self,symType):
return self.declarator(symType)
def declarator(self,symType):
np = self.pointer() # np>=0
tp = 'pointer(' *np + symType + ')'*np
return self.direct_declarator(tp)
def direct_declarator(self,tp):
args =''
inner = '$'
name = ''
if self.isType('NAME'):
name = self.match().value+'::'
elif self.isType('LEFT'): # (
self.match()
inner = self.declarator('$') #mark
self.match('RIGHT')
if self.isType('LEFT'):
self.match()
li = ['void']
if not self.isType('RIGHT'):
li = self.parameter_type_list()
self.match('RIGHT')
if self.isType('L2'):
raise Exception('[Error]: Array of Functions is not allowed')
args = ' X '.join(li)
elif self.isType('L2'):
li = []
while self.isType('L2'):
self.match()
assert self.isType('NUM')
li.append(int(self.match().value))
self.match('R2')
if self.isType('LEFT'):
raise Exception('[Error]: Array of Function can not be returned from functions')
for i in reversed(li):
tp = 'array({},{})'.format(i,tp)
if args!='':
tp = 'function( {args} => {tp})'.format(args=args,tp =tp )
return name+inner.replace('$',tp)
def pointer(self):
n = 0
while self.isType('POINTER'):
n+=1
self.match('POINTER')
return n
def parameter_type_list(self):
return self.parameter_list()
def parameter_list(self):
li = []
while 1:
argType = self.parameter_declaration()
li.append(argType)
if self.isType('COMMA'):
self.match()
else:break
return li
def parameter_declaration(self):
symType = self.declaration_specifiers()
return self.declarator(symType)
def testFromStdIO():
dp = declarationParser()
while 1:
s = input('>> ')
tk = [i for i in gen_token(s)]
dp.parse(tk)
def testFromFile(f= 'test.txt'):
dp = declarationParser()
with open(f,'r') as fp:
for line in fp:
line = line.strip(' \n')
if line.startswith('//') or line=='' :continue
print('>>',line)
tk =[i for i in gen_token(line)]
dp.parse(tk)
print()
if __name__=='__main__':
testFromFile()
testFromStdIO()