def arr_brace(sym: SyntaxTree, context: SemanticContext): size = sym.childs[1].sym.val dims = [size] ll_dims = sym.childs[3].get_attr('dims') if ll_dims: dims.extend(ll_dims) sym.set_attr('dims', dims)
def expr_idn(sym: SyntaxTree, context: SemanticContext): var = sym.childs[0].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) operand = Operand(var, symbol.type) sym.set_attr("res", operand)
def struct_type(sym: SyntaxTree, context: SemanticContext): vardl = sym.childs[2] eles = vardl.get_attr('eles') sym_width = vardl.get_attr('width') sym_type = STypeRecord(eles) sym.set_attr('type', sym_type) sym.set_attr('width', sym_width)
def stmt_s(sym: SyntaxTree, context: SemanticContext): saddr = sym.childs[1].get_attr('quad') s1nl = sym.childs[0].get_attr('nl') s2nl = sym.childs[2].get_attr('nl') if s1nl: context.back_patch(s1nl, saddr) sym.set_attr('nl', s2nl)
def optimize(syntax_tree, sql): if syntax_tree.operator == 'SELECT': condition = syntax_tree.condition sql = condition.split('&') relation = [] for i in range(len(sql)): if search(sql[i]) is not None: relation.append(search(sql[i])) syntax_tree = optimize(syntax_tree.left_child, sql) elif syntax_tree.operator == 'PROJECTION': syntax_tree.left_child = optimize(syntax_tree.left_child, sql) elif syntax_tree.operator == 'JOIN': first_tree = SyntaxTree() first_tree.operator = 'SELECT' first_tree.condition = sql[0] first_tree.left_child = syntax_tree.left_child syntax_tree.left_child = first_tree if len(sql) == 1: return syntax_tree second_tree = SyntaxTree() second_tree.operator = 'SELECT' second_tree.condition = sql[1] second_tree.right_child = syntax_tree.right_child syntax_tree.right_child = second_tree return syntax_tree
def arr_ref_one(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) var = sym.childs[0].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) elif not isinstance(symbol.type, STypeArray): return -1, "{} is not a valid array".format(var) index_res = sym.childs[2].get_attr('res') # get offset ele_type = symbol.type.get_ele_type() if index_res != 0: res1 = context.gen_tmp() ele_type_width = get_type_width(ele_type) context.gen_ins("*", index_res, ele_type_width, res1) res2 = context.gen_tmp() context.gen_ins('&', var, None, res2) res = context.gen_tmp() context.gen_ins('+', res2, res1, res) else: res = context.gen_tmp() context.gen_ins('&', var, None, res) res_type = STypePtr(ele_type) sym.set_attr('res', Operand(res, res_type))
def arr_ref(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) operand = sym.childs[0].get_attr('res') last_res = operand.val last_type = operand.type arr_type = last_type.get_ref_type() if not isinstance(arr_type, STypeArray): return -1, "Too many array brackets" ele_type = arr_type.get_ele_type() index_operand = sym.childs[2].get_attr('res') index_res = index_operand.val index_type = index_operand.type if index_type != TokenType.INT: return -1, "Array index must be int" if index_res != 0: res1 = context.gen_tmp() ele_type_width = get_type_width(ele_type) context.gen_ins("*", index_res, ele_type_width, res1) res = context.gen_tmp() context.gen_ins('+', last_res, res1, res) else: res = last_res res_type = STypePtr(ele_type) sym.set_attr('res', Operand(res, res_type))
def stmt_if(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[1] sym_s = sym.childs[4] sstart = sym.childs[3].get_attr('quad') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(btl, sstart) snl = bfl + sym_s.get_attr('nl') sym.set_attr('nl', snl)
def sub_val(sym: SyntaxTree, context: SemanticContext): tok = sym.childs[1].sym if tok.type == TokenType.CINT: res_type = TokenType.INT elif tok.type == TokenType.CFLOAT: res_type = TokenType.FLOAT else: assert False, "Invalid Type {}".format(tok.type) sym.set_attr("res", Operand(-tok.val, res_type))
def bool_expr2(sym: SyntaxTree, context: SemanticContext): sym_g = sym.childs[0] sym_h = sym.childs[3] quad = sym.childs[2].get_attr('quad') gtl = sym_g.get_attr('tl') htl = sym_h.get_attr('tl') gfl = sym_g.get_attr('fl') hfl = sym_h.get_attr('fl') context.back_patch(gtl, quad) sym.set_attr('tl', htl) sym.set_attr('fl', gfl + hfl)
def bool_expr1(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[0] sym_g = sym.childs[3] quad = sym.childs[2].get_attr('quad') btl = sym_b.get_attr('tl') gtl = sym_g.get_attr('tl') bfl = sym_b.get_attr('fl') gfl = sym_g.get_attr('fl') context.back_patch(bfl, quad) sym.set_attr('tl', btl + gtl) sym.set_attr('fl', gfl)
def param_list_one(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[1].sym.val context.add_sym(child_name, child_type) params = [{ 'name': child_name, 'type': child_type, 'width': child_width }] sym.set_attr('params', params)
def stmt_while(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[2] sym_s = sym.childs[6] bstart = sym.childs[1].get_attr('quad') sstart = sym.childs[5].get_attr('quad') snl = sym_s.get_attr('nl') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(snl, bstart) context.back_patch(btl, sstart) context.gen_ins('goto', None, None, bstart) sym.set_attr('nl', bfl)
def array_type(sym: SyntaxTree, context: SemanticContext): dims = sym.childs[1].get_attr('dims') prim_type = sym.childs[0].get_attr('type') prim_width = sym.childs[0].get_attr('width') if dims: sym_type = STypeArray(prim_type, dims) ele_num = reduce(lambda total, x: total * x, dims) else: sym_type = prim_type ele_num = 1 sym.set_attr('type', sym_type) sym.set_attr('width', prim_width * ele_num)
def var_decl_list_begin(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[0].get_attr('name') eles = { child_name: { "type": child_type, "width": child_width, "offset": 0 } } sym.set_attr('eles', eles) sym.set_attr('offset', child_width)
def prim_type(sym: SyntaxTree, context: SemanticContext): sym_type = sym.childs[0].sym.type sym.set_attr("type", sym_type) if sym_type == TokenType.CHAR: width = 1 elif sym_type == TokenType.SHORT: width = 2 elif sym_type == TokenType.INT or sym_type == TokenType.FLOAT: width = 4 elif sym_type == TokenType.DOUBLE: width = 8 else: assert False, "Unknown Type {}".format(str(sym_type)) sym.set_attr("width", width)
def bool_expr5(sym: SyntaxTree, context: SemanticContext): toktype = sym.childs[0].childs[0].sym.type start = context.addr sym.set_attr('start', start) if toktype == TokenType.TRUE: ins = context.gen_ins('goto', None, None, None) stl = [ins] sfl = [] else: ins = context.gen_ins('goto', None, None, None) stl = [] sfl = [ins] sym.set_attr('tl', stl) sym.set_attr('fl', sfl)
def stmt_if_else(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[1] sym_s1 = sym.childs[4] sym_s2 = sym.childs[10] else_gate = sym.childs[6] s1start = sym.childs[3].get_attr('quad') s2start = sym.childs[9].get_attr('quad') s1nl = sym_s1.get_attr('nl') s2nl = sym_s2.get_attr('nl') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(btl, s1start) context.back_patch(bfl, s2start) snl = s1nl + s2nl + else_gate.get_attr('nl') sym.set_attr('nl', snl)
def wrapper(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) op = func(sym, context) ysym = sym.childs[0] fsym = sym.childs[2] yres = ysym.get_attr('res') fres = fsym.get_attr('res') res = context.gen_tmp() res_type = deduce_type(yres.type, fres.type) context.gen_ins(op, yres.val, fres.val, res) sym.set_attr('res', Operand(res, res_type)) if res_type is None: return -1, "Can't do {} on {} and {}".format( op, str(yres.type), str(fres.type))
def build_sentence(tree: SyntaxTree, wordBank: WordBank, default: str) -> str: sentence = [{'text': default, 'is_word': False}] while not is_complete_sentence(sentence): for x in range(len(sentence)): if sentence[x]['is_word']: continue con = sentence[x]['text'] rules = tree.get_rules(con) if len(rules) == 0: sentence[x] = {'text': wordBank.random_word( con), 'is_word': True} break rule = rules[random.randrange(len(rules))] rule = [{'text': r, 'is_word': False} for r in rule] sentence = sentence[:x] + rule + sentence[x + 1:] break out = "" for word in sentence: if len(out) != 0: out += " " out += word['text'] return out
def parse(sql_statement): sql = sql_statement.split() execute_tree = SyntaxTree() index = 0 while True: if index >= len(sql): break #处理一元运算符 elif sql[index] == 'SELECT' or sql[index] == 'PROJECTION': execute_tree.operator = sql[index] index += 2 # 从[开始到]里面的全部记录下来 condition = '' while sql[index] != ']': condition += sql[index] condition += ' ' index += 1 index += 1 execute_tree.condition = condition #处理二元运算符 elif sql[index] == 'JOIN': # 连接操作需要创建子树,所以分开写 execute_tree.operator = sql[index] execute_tree.left_child = SyntaxTree() execute_tree.left_child.attribute = sql[index - 1] execute_tree.right_child = SyntaxTree() execute_tree.right_child.attribute = sql[index + 1] index += 1 #处理子查询,进行递归 elif sql[index] == '(': index += 1 statement = '' while index < len(sql) and sql[index] != ')': statement += sql[index] statement += ' ' index += 1 index += 1 execute_tree.left_child = parse(statement) else: index += 1 return execute_tree
def param_list(sym: SyntaxTree, context: SemanticContext): has_err = False err_strs = [] child_type = sym.childs[2].get_attr('type') child_width = sym.childs[2].get_attr('width') child_name = sym.childs[3].sym.val sym_param = sym.childs[0] params = list(sym_param.get_attr('params')) for param in params: if child_name == param['name']: has_err = True err_strs.append("Duplicate parameter {}".format(child_name)) context.add_sym(child_name, child_type) params.append({ 'name': child_name, 'type': child_type, 'width': child_width }) sym.set_attr('params', params) if has_err: return -1, '\n'.join(err_strs)
def parse(sql_statement): sql = sql_statement.split() execute_tree = SyntaxTree() index = 0 while True: if index >= len(sql): break elif sql[index] == 'SELECT' or sql[index] == 'PROJECTION': execute_tree.operator = sql[index] index += 2 # 从[开始到]里面的全部记录下来 condition = '' while sql[index] != ']': condition += sql[index] condition += ' ' index += 1 index += 1 execute_tree.condition = condition elif sql[index] == 'JOIN': # 连接操作需要创建子树,所以分开写 execute_tree.operator = sql[index] execute_tree.left_child = SyntaxTree() execute_tree.left_child.attribute = sql[index - 1] execute_tree.right_child = SyntaxTree() execute_tree.right_child.attribute = sql[index + 1] index += 1 elif sql[index] == '(': # 每次遇到这个说明需要创建一棵子树,由于题目中的查询都是只有一个分支,所以可以直接进入下一个子树中 index += 1 statement = '' while index < len(sql) and sql[index] != ')': statement += sql[index] statement += ' ' index += 1 index += 1 execute_tree.left_child = parse(statement) else: index += 1 return execute_tree
def var_decl(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[1].sym.val sym.set_attr('type', child_type) sym.set_attr('width', child_width) sym.set_attr('name', child_name)
def var_decl_list(sym: SyntaxTree, context: SemanticContext): has_err = False vard = sym.childs[1] child_type = vard.get_attr('type') child_width = vard.get_attr('width') child_name = vard.get_attr('name') vardl = sym.childs[0] eles = dict(vardl.get_attr('eles')) offset = vardl.get_attr('offset') if child_name in eles: has_err = True else: eles[child_name] = { "type": child_type, "width": child_width, "offset": offset } offset += child_width sym.set_attr('eles', eles) sym.set_attr('offset', offset) if has_err: return -1, "Duplicate record attribute {}".format(child_name)
def stmt_call(sym: SyntaxTree, context: SemanticContext): fname = sym.childs[1].sym.val symbol = context.lookup_sym(fname) if not symbol: return -1, "Function {} is not defined".format(fname) args = sym.childs[3].get_attr('args') res = Operand(context.gen_tmp(), symbol.type.ret_type) context.gen_ins('call', symbol, len(args), res) sym.set_attr('res', res) args_len = len(args) params_len = len(symbol.type.param_types) if args_len < params_len: return -1, "Too few arguments was given" if args_len > params_len: return -1, "Too many arguments was given" for i in range(args_len): if args[i].type != symbol.type.param_types[i] and\ deduce_type(args[i].type, symbol.type.param_types[i]) is None: args_str = ', '.join(map(lambda arg: str(arg.type), args)) params_str = ', '.join(map(str, symbol.type.param_types)) return -1, "Incompatible parameter types {}({}). expected {}({})".format( fname, args_str, fname, params_str)
def record_ref(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) var = sym.childs[0].sym.val attr = sym.childs[2].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) elif not isinstance(symbol.type, STypeRecord): return -1, "{} is not a valid structure".format(var) offset = symbol.type.get_ele_offset(attr) if offset is None: return -1, "{} has no attribute {}".format(var, attr) if offset != 0: res1 = context.gen_tmp() context.gen_ins("&", var, None, res1) res = context.gen_tmp() context.gen_ins('+', res1, offset, res) else: res = context.gen_tmp() context.gen_ins("&", var, None, res) res_type = STypePtr(symbol.type.get_ele_type(attr)) sym.set_attr('res', Operand(res, res_type))
def bool_expr4(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) res1 = sym.childs[0].get_attr('res') res2 = sym.childs[2].get_attr('res') relop = RELOPS[sym.childs[1].childs[0].sym.type] ins1 = context.gen_ins(relop, res1, res2, None) sym.set_attr('tl', [ins1]) ins2 = context.gen_ins('goto', None, None, None) sym.set_attr('fl', [ins2])
from syntaxtree import SyntaxTree from wordbank import WordBank import config import builder if __name__ == '__main__': tree = SyntaxTree() config.load_rules('rules.config', tree) bank = WordBank() config.load_words('words.csv', bank) print(builder.build_sentence(tree, bank, 'S'))
def analyze(self, toks, text, semantic=False, context=None): if not toks: return SyntaxTree(TokenType.END), [] err_strs = [] status_stack = [0] sym_stack = [SyntaxTree(TokenType.END)] tok_idx = 0 accept = False if context is None: context = SemanticContext() if toks[-1] != TokenType.END: toks = toks + [Token(TokenType.END, None, 0, -1)] while tok_idx < len(toks): tok = toks[tok_idx] if tok.type == TokenType.CCOMMENT: tok_idx += 1 continue toktype = tok.type status = status_stack[-1] if self._has_error(status, toktype): err_strs.append(self._gen_err_str(tok, text)) tok_idx += 1 continue act, number = self.action_table[status][toktype] if act == ActionType.MOVE: tok_idx += 1 status_stack.append(number) sym_stack.append(SyntaxTree(tok)) elif act == ActionType.REDUCE: production = self.productions[number] parent = SyntaxTree(production.lhs) for exp_sym in reversed(production.rhs): status_stack.pop() sym = sym_stack.pop() assert sym.get_sym_name() == str( exp_sym), "Expect {} but get {}".format( exp_sym, sym.get_sym_name()) parent.add_child(sym) parent.childs = parent.childs[::-1] sym_stack.append(parent) act, idx = self.action_table[status_stack[-1]][parent.sym] assert act == ActionType.GOTO status_stack.append(idx) # do action if semantic and production.action: print(production.action.name) try: ret = production.action.do_action(parent, context) if ret: err_code, message = ret else: err_code = 0 except Exception as ex: print(''.join(ex.args)) if err_code: node = parent while node.childs: node = node.childs[0] row, col = count_position(text, node.sym.start) err_strs.append("{}:{} {}".format(row, col, message)) elif act == ActionType.ACCEPT: accept = True break else: assert False if not accept: err_strs.append("Expect More Token") sym = SyntaxTree("Incomplete") while sym_stack: sym.add_child(sym_stack.pop()) sym_stack.append(sym) return sym_stack.pop(), err_strs