def B(token_generator): token, token_id = token_generator.send(True) # func_is_read = match(token, token_id, table.READ) if match(token, token_id, table.READ) or match(token, token_id, table.WRITE): # 成功,冲刷 next(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.LEFT_BRACKET): err('In Line %d B : can not match (' % line_no) D(token_generator) if not is_var_exist(current_token, current_proc, 0, True): err('In Line %d B : can not find token %s' % (line_no, current_token)) # if func_is_read: # add_var(current_token, current_proc, 0, 'integer', plevel) token, token_id = next(token_generator) if not match(token, token_id, table.RIGHT_BRACKET): err('In Line %d B : can not match )' % line_no) elif match(token, token_id, table.IF): # 成功,冲刷 next(token_generator) U(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.THEN): err('In Line %d B : can not match then' % line_no) B(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.ELSE): err('In Line %d B : can not match else' % line_no) B(token_generator) else: Z(token_generator)
def S(token_generator, pname, ptype): global plevel, current_proc plevel += 1 # 注意到函数有且仅有一个参数,而刚进入函数体时,变量表中的最后一个必为此参数 if len(var_table) == 0: current_proc = Proc(pname, ptype, plevel) else: current_proc = Proc(pname, ptype, plevel) var_table[len(var_table) - 1].vproc = current_proc proc_table.append(current_proc) # 同时,由于在函数内可以直接把自身函数名当成一个变量来使用,所以需要把函数名加入到变量表 add_var(pname, current_proc, 0, 'integer', plevel) token, token_id = next(token_generator) if not match(token, token_id, table.BEGIN): err('In line %d S : Not start with begin' % line_no) H(token_generator) # token, token_id = next(token_generator) # if not match(token, token_id, table.SEMICOLON): # err('S : A ; must follow H') E(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.END): err('In Line %d S : there must be an \'end\'' % line_no) plevel -= 1 current_proc = proc_table[plevel - 1] return
def Z(token_generator): D(token_generator) if not is_var_exist(current_token, current_proc, 0, True): err('In Line %d Z : token %s not defined' % (line_no, current_token)) token, token_id = next(token_generator) if not match(token, token_id, table.ASSIGN): err('In Line %d Z : can not match := %s' % (line_no, token)) K(token_generator)
def H(token_generator): token, token_id = next(token_generator) if not match(token, token_id, table.INTEGER): err('In Line %d H : can not match integer' % line_no) V(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.SEMICOLON): err('In Line %d H : can not match ;' % line_no) _H(token_generator) return
def _H(token_generator): token, token_id = token_generator.send(True) # 没有匹配成功,可能是e,需要回退一步 if not match(token, token_id, table.INTEGER): return # 匹配integer成功,需要把重复的这个yield冲刷掉 next(token_generator) V(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.SEMICOLON): err('In Line %d H : can not match ;' % line_no) _H(token_generator)
def add_var(token, proc, kind, type, vlev): """ 只有两个地方会引入新变量: 1. 变量定义和函数定义 V 2. read B :param token: :param proc: :param kind: 分类vkind: 0..1(0—变量、1—形参) :param type: :param vlev: :return: """ if is_var_exist(token, proc=proc, kind=kind, expected=False): err('In line %d AddVar : can not define a variable in twice' % line_no) var_table.append(Variable(token, proc, kind, type, vlev, len(var_table))) for i in range(0, proc.plev): if proc_table[i].plev < vlev or (proc_table[i].plev == vlev and proc_table[i].adr == proc.adr): proc_table[i].ladr += 1
def V(token_generator): token, token_id = token_generator.send(True) if not match(token, token_id, table.FUNCTION): D(token_generator) add_var(current_token, current_proc, 0, 'integer', plevel) return # 冲刷掉当前token next(token_generator) D(token_generator) func_name = current_token token, token_id = next(token_generator) if not match(token, token_id, table.LEFT_BRACKET): err('In line %d V : can not match (' % line_no) M(token_generator) # 由于current_proc尚未生成,先赋值为当前proc,在进入函数时需要重新设置 add_var(current_token, current_proc, 1, 'integer', plevel + 1) token, token_id = next(token_generator) if not match(token, token_id, table.RIGHT_BRACKET): err('In Line %d V : can not match )' % line_no) token, token_id = next(token_generator) if not match(token, token_id, table.SEMICOLON): err('In Line %d V : can not match ;' % line_no) S(token_generator, func_name, 'integer')
def Y(token_generator): # 先检查是否是数字 if N(token_generator): _Q(token_generator) return # 然后检查是否是函数调用 D(token_generator) func_name = current_token token, token_id = token_generator.send(True) if not match(token, token_id, table.LEFT_BRACKET): # 不是函数调用 if not is_var_exist(current_token, current_proc, 0, True): err('In Line %d Y : %s is not defined' % (line_no, current_token)) _D(token_generator) return # 确实是函数 # 检查函数是否已定义 flag = False for proc in proc_table: if proc.pname == func_name: flag = True break if not flag: err('In Line %d P : function not defined' % line_no) # 冲刷 next(token_generator) K(token_generator) token, token_id = next(token_generator) if not match(token, token_id, table.RIGHT_BRACKET): err('In Line %d P : can not match )' % line_no)
def get_next_token(src_file): for line in src_file: token = '' for ch in line: if ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n': if token is not None and len(token) > 0: out_dyd(token, parse_token(token)) yield token token = '' elif token == '' and ch.isdigit(): err('must not be number start') # 三种情况,一个是单词结束,一个是算符结束,一个是两个算符并排,如); elif is_word_end(token, ch) or is_operation_end(token, ch) or \ (is_operation(token) and is_operation(ch) and not is_operation('%s%s' % (token, ch))): out_dyd(token, parse_token(token)) yield token token = ch else: token += ch out_dyd(table.EOLN, table.TOKEN_TABLE.get(table.EOLN)) # yield table.EOLN out_dyd(table.EOF, table.TOKEN_TABLE.get(table.EOF)) debug('finish')
def S(token_generator, pname, ptype): global plevel, current_proc plevel += 1 # 注意到函数有且仅有一个参数,而刚进入函数体时,变量表中的最后一个必为此参数 #变量表为空,说明是程序开始 if len(var_table) == 0: #初始化过程表 current_proc = Proc(pname, ptype, plevel) else: current_proc = Proc(pname, ptype, plevel) var_table[len(var_table) - 1].vproc = current_proc #把当前过程加入到过程表中 proc_table.append(current_proc) # 同时,由于在函数内可以直接把自身函数名当成一个变量来使用,所以需要把函数名加入到变量表 add_var(pname, current_proc, 0, 'integer', plevel) #由迭代器获取下一行的token及其种别码 token, token_id = next(token_generator) #查看token是否为begin if not match(token, token_id, table.BEGIN): err('In line %d S : Not start with begin' % line_no) #H非终结符子函数 H(token_generator) # token, token_id = next(token_generator) # if not match(token, token_id, table.SEMICOLON): # err('S : A ; must follow H') #E非终结符子函数 E(token_generator) #由迭代器获取下一行的token及其种别码 token, token_id = next(token_generator) #查看token是否为end if not match(token, token_id, table.END): err('In Line %d S : there must be an \'end\'' % line_no) #设置当前过程 plevel -= 1 current_proc = proc_table[plevel - 1] return
from lexer import lex from io_lib import err, debug import g from parser import parse __author__ = 'ay27' from table import init_token_table if __name__ == '__main__': try: g.pas_src = open(g.src_file_name) except OSError: err('can not open file %s' % g.src_file_name) exit(-1) if g.pas_src is None: err('can not open file %s' % g.src_file_name) exit(-1) init_token_table() debug('token table init finish') try: lex(g.pas_src) except IOError: err('something error') debug('lex finish') g.dyd = open('test.dyd') try: parse(g.dyd)
def O(token_generator): token, token_id = next(token_generator) if not match(token, token_id, None): err('In Line %d O : can not match %s' % (line_no, token))
def Q(token_generator): if not N(token_generator): err('In Line %d Q : match number error %s' % (line_no, current_token)) _Q(token_generator)
def D(token_generator): if not G(token_generator): err('In Line %d D : match %s error' % (line_no, current_token)) _D(token_generator) return