mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
156 lines
4.7 KiB
Python
156 lines
4.7 KiB
Python
'''
|
|
#########################################################################
|
|
# File : parser.py
|
|
# Author: mbinary
|
|
# Mail: zhuheqin1@gmail.com
|
|
# 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()
|