def find(self, name): """ 沿着作用于链查找name的value """ try: return self[name] if (name in self._dict) else self.outer.find(name) except AttributeError as e: print(colorful('{0} 在作用域链上不存在!'.format(name), 'Red')) return 'not-define-yet'
def calc_value(self, env=Env.std_env()): """ 在指定环境中求值, 或者对环境造成改变 :param env: 表达式所在环境 :return:表达式的值 """ if self.static and self.value: print(colorful('静态表达式, 直接返回值', 'Bold')) return self.value res = None stype, child = self.stype, self.child if stype == 'number': res = child[0].calc_value(env) elif stype == 'integer': res = int(self._value) elif stype == 'decimal': res = float(self._value) elif stype == 'string': res = self._value elif stype == 'bool': res = True if self._value == '$T' else False elif stype == 'symbol': self._value = child[0].raw_value res = child[0].calc_value(env) elif stype == 'identifier': res = env.find(self._value) elif stype == 'op': res = env.find(self._value) elif stype == 'atom' or self.stype == 'func': res = child[0].calc_value(env) elif stype == 'lexp': res = child[0].calc_value(env) if child[0].stype == 'list': res = [res, ] res = args_restore(res) elif stype == 'lexp-seq': if len(child) > 1: res = (child[0].calc_value(env), ) + child[1].calc_value(env) else: res = (child[0].calc_value(env), ) # print 'this lexp-seq:', res elif stype == 'list': if len(child) == 3: res = child[1].calc_value(env) else: res = tuple() elif stype == 's-exp': func = child[1].calc_value(env) args = child[2].calc_value(env) if len(child) == 3: res = func() else: res = func(*[args_restore(arg) for arg in args]) elif stype == 'define-exp': # <define-exp> ::= <(> <define> <symbol> <lexp> <)> symbol = child[2].child[0].raw_value define(env, symbol, child[3]) res = symbol elif stype == 'args': if child[0].stype == 'symbol': res = (child[0].child[0].raw_value, ) else: res = child[0].calc_value(env) + (child[1].child[0].raw_value, ) elif stype == 'proc-body': if len(child) <= 1: res = child[0].calc_value(env) else: # 用语句块的最后一个语句作为语句块的值 _ = child[0].calc_value(env) res = child[1].calc_value(env) elif stype == 'lambda-exp': # <lambda-exp> ::= <(> <lambda> <(> <args> <)> <proc-body> <)> args = child[3].calc_value(env) body = child[5] # print 'args: ', args # print 'body:', body res = Procedure(args, body, env) elif stype == 'var-exps': if len(child) == 4: define(env, child[1].child[0].raw_value, child[2]) else: child[0].calc_value(env) define(env, child[2].child[0].raw_value, child[3]) elif stype == 'let-exp': # <let-exp> ::= <(> <let> <(> <var-exps> <)> <proc-body> <) let_env = Env.std_env(outer=env) child[3].calc_value(let_env) res = child[5].calc_value(let_env) elif stype == 'proc-define-exp': # <proc-define-exp> ::= <(> <define> <(> <symbol> <args> <)> <proc-body> <)> # <proc-define-exp> ::= <(> <define> <(> <symbol> <)> <proc-body> <)> if len(child) > 7: # 有参函数 symbol = child[3].child[0].raw_value args = child[4].calc_value(env) body = child[6] proc = Procedure(args, body, env) env[symbol] = proc else: symbol = child[3].child[0].raw_value args = tuple() body = child[5] proc = Procedure(args, body, env) env[symbol] = proc if symbol in env.dynamic_bind: # 如果之前是动态绑定key, 移除 del env.dynamic_bind[symbol] res = symbol elif stype == 'predicate': if child[0].calc_value(env): res = True else: res = False elif stype in ['consequent', 'alternate']: res = child[0].calc_value(env) elif stype == 'if-exp': # <if-exp> ::= <(> <if> <predicate> <consequent> <alternate> <)> if child[2].calc_value(env): res = child[3].calc_value(env) else: res = child[4].calc_value(env) elif stype == 'or-exp': # <or-exp> ::= <(> <or> <lexp-seq> <)> cnode = child[2] res = False while len(cnode.child) > 1: val = cnode.child[0].calc_value(env) if type(val) == list: val = args_restore(val) if val: res = val break else: cnode = cnode.child[1] else: val = cnode.calc_value(env)[0] if type(val) == list: val = args_restore(val) if val: res = val elif stype == 'and-exp': # <and-exp> ::= <(> <and> <lexp-seq> <)> cnode = child[2] res = True while len(cnode.child) > 1: val = cnode.child[0].calc_value(env) if type(val) == list: val = args_restore(val) if not val: res = val break else: cnode = cnode.child[1] else: val = cnode.calc_value(env)[0] if type(val) == list: val = args_restore(val) if not val: res = val if not self.static: self.value = res return res
def reduce(self, grammar): """ 规约动作, grammar为规约用的产身世 """ print('利用规则' + colorful('%s -> %s' % (grammar[0], ' '.join(grammar[1])), "Green"))
def shift(self, token): print(colorful('移近 {0} {1}'.format(token[0], token[1]), "Cyan"))
def compile(self): """ 利用 self.grammar 编译出dfa, 并构造分析表 :return: """ self.calc_first() alloc = 0 grammar = self.grammar dfa = DFA() que = Queue() dfa.start = DFANode(id=alloc, lr_items=self.closure(("start", tuple(), tuple(grammar["start"][0]), {'$'}))) self.idx_items = [dfa.start] que.put(dfa.start.lr_items) vis = dict() vis[frozen_items(dfa.start.lr_items)] = dfa.start while not que.empty(): lr_items = que.get() # if frozen_items(lr_items) in vis: # continue dfa_node = vis[frozen_items(lr_items)] # print 'u_items:' # print lr_items tmp = defaultdict(list) for item in lr_items: if item[2]: u_item = (item[0], item[1] + item[2][:1], item[2][1:], item[3]) tmp[item[2][0]].append(u_item) # 可能该状态有两个以上项目可以通过 item[2][0] 转换到新项目, 而新的项目集应该是他们的合集 for l_hand, items in tmp.iteritems(): vitem = defaultdict(set) for item in items: u_items = self.closure(item) for u_item in u_items: vitem[u_item[:-1]].update(u_item[3]) next_items = [core + (head, ) for core, head in vitem.iteritems()] if frozen_items(next_items) not in vis: que.put(next_items) alloc += 1 dfa_node.next[l_hand] = DFANode(id=alloc, lr_items=next_items) self.idx_items.append(dfa_node.next[l_hand]) # 插入新节点 vis[frozen_items(next_items)] = dfa_node.next[l_hand] else: dfa_node.next[l_hand] = vis[frozen_items(next_items)] # dfa.draw("LR", show_meta=["lr_items"], generate_id=False) self.lr_dfa = dfa # DFA 构造完成 # 构造分析表 lr_table = defaultdict(dict) que = Queue() que.put(dfa.start) vis = dict() while not que.empty(): tmp = que.get() if tmp in vis: continue vis[tmp] = 1 for item in tmp.lr_items: if item[2]: # 移进状态 if item[2][0] in lr_table[tmp.id]: if lr_table[tmp.id][item[2][0]]['action'] != 'shift': print(colorful('移近规约冲突', 'Red')) raise LRConflict() elif lr_table[tmp.id][item[2][0]]['next'] != \ tmp.next[item[2][0]].id: print(colorful('移近移近冲突', 'Red')) raise LRConflict() lr_table[tmp.id][item[2][0]] = \ dict(action="shift", next=tmp.next[item[2][0]].id) else: # 规约状态 for a in item[3]: if a in lr_table[tmp.id]: if lr_table[tmp.id][a]['action'] != 'reduce': print(colorful('移近规约冲突', 'Red')) raise LRConflict() elif lr_table[tmp.id][a]['grammar'] != item: print(colorful('规约规约冲突', 'Red')) raise LRConflict() lr_table[tmp.id][a] = dict(action="reduce", grammar=item) for next_node in tmp.next.values(): que.put(next_node) self.lr_table = lr_table return dfa
class ParseHandler(object): def __init__(self): self.ast = None self.exps = [] def shift(self, token): print(colorful('移近 {0} {1}'.format(token[0], token[1]), "Cyan")) def reduce(self, grammar): """ 规约动作, grammar为规约用的产身世 """ print('利用规则' + colorful('%s -> %s' % (grammar[0], ' '.join(grammar[1])), "Green")) # from util import colorful lex = Lex() lex.keyword = ['lambda', '[', ']', 'let', 'define', 'if', 'cond', 'or', 'and', '(', ')'] lex.read_lex('regular_lex.txt') lex.compile(grammar_type="regular") print(colorful('词法编译完成...', 'Yellow')) parser = LRParser() parser.read_grammar('schepy_grammar.txt') parser.compile() print(colorful('语法编译完成...', 'Yellow')) parser.show_dfa() while True: parser.parse(lex.lex(raw_input(), ignore=["limit"]), ParseHandler())
crash_on_ipy.init() from lex import Lex from parser import LRParser from util import colorful from runtime import ParseHandler, Env LEX = Lex() LEX.keyword = ['lambda', '[', ']', 'let', 'define', 'if', 'cond', 'or', 'and', '(', ')', '$T', '$F'] LEX.read_lex('regular_lex.txt') LEX.compile(grammar_type="regular") # lex.read_lex('regex_lex.txt') # lex.compile() print(colorful('词法编译完成...', 'Yellow')) PARSER = LRParser() PARSER.read_grammar('schepy_grammar.txt') PARSER.compile() print(colorful('语法编译完成...', 'Yellow')) GLOBAL_ENV = Env.std_env() while True: try: HANDLER = ParseHandler() EXP = raw_input(colorful('schepy => ', 'Cyan')) PARSER.parse(LEX.lex(EXP, ignore=["limit"]), HANDLER) print(';VALUE: ' + colorful(repr(HANDLER.ast.calc_value(env=GLOBAL_ENV)), "Magenta")) except (EOFError, KeyboardInterrupt) as e: CHOICE = raw_input(colorful('Do you really want to exit ([y]/n)?', "Red"))
def calc_value(self, env=Env.std_env()): """ 在指定环境中求值, 或者对环境造成改变 :param env: 表达式所在环境 :return:表达式的值 """ if self.static and self.value: print(colorful('静态表达式, 直接返回值', 'Bold')) return self.value res = None stype, child = self.stype, self.child if stype == 'number': res = child[0].calc_value(env) elif stype == 'integer': res = int(self._value) elif stype == 'decimal': res = float(self._value) elif stype == 'string': res = self._value elif stype == 'bool': res = True if self._value == '$T' else False elif stype == 'symbol': self._value = child[0].raw_value res = child[0].calc_value(env) elif stype == 'identifier': res = env.find(self._value) elif stype == 'op': res = env.find(self._value) elif stype == 'atom' or self.stype == 'func': res = child[0].calc_value(env) elif stype == 'lexp': res = child[0].calc_value(env) if child[0].stype == 'list': res = [ res, ] res = args_restore(res) elif stype == 'lexp-seq': if len(child) > 1: res = (child[0].calc_value(env), ) + child[1].calc_value(env) else: res = (child[0].calc_value(env), ) # print 'this lexp-seq:', res elif stype == 'list': if len(child) == 3: res = child[1].calc_value(env) else: res = tuple() elif stype == 's-exp': func = child[1].calc_value(env) args = child[2].calc_value(env) if len(child) == 3: res = func() else: res = func(*[args_restore(arg) for arg in args]) elif stype == 'define-exp': # <define-exp> ::= <(> <define> <symbol> <lexp> <)> symbol = child[2].child[0].raw_value define(env, symbol, child[3]) res = symbol elif stype == 'args': if child[0].stype == 'symbol': res = (child[0].child[0].raw_value, ) else: res = child[0].calc_value(env) + ( child[1].child[0].raw_value, ) elif stype == 'proc-body': if len(child) <= 1: res = child[0].calc_value(env) else: # 用语句块的最后一个语句作为语句块的值 _ = child[0].calc_value(env) res = child[1].calc_value(env) elif stype == 'lambda-exp': # <lambda-exp> ::= <(> <lambda> <(> <args> <)> <proc-body> <)> args = child[3].calc_value(env) body = child[5] # print 'args: ', args # print 'body:', body res = Procedure(args, body, env) elif stype == 'var-exps': if len(child) == 4: define(env, child[1].child[0].raw_value, child[2]) else: child[0].calc_value(env) define(env, child[2].child[0].raw_value, child[3]) elif stype == 'let-exp': # <let-exp> ::= <(> <let> <(> <var-exps> <)> <proc-body> <) let_env = Env.std_env(outer=env) child[3].calc_value(let_env) res = child[5].calc_value(let_env) elif stype == 'proc-define-exp': # <proc-define-exp> ::= <(> <define> <(> <symbol> <args> <)> <proc-body> <)> # <proc-define-exp> ::= <(> <define> <(> <symbol> <)> <proc-body> <)> if len(child) > 7: # 有参函数 symbol = child[3].child[0].raw_value args = child[4].calc_value(env) body = child[6] proc = Procedure(args, body, env) env[symbol] = proc else: symbol = child[3].child[0].raw_value args = tuple() body = child[5] proc = Procedure(args, body, env) env[symbol] = proc if symbol in env.dynamic_bind: # 如果之前是动态绑定key, 移除 del env.dynamic_bind[symbol] res = symbol elif stype == 'predicate': if child[0].calc_value(env): res = True else: res = False elif stype in ['consequent', 'alternate']: res = child[0].calc_value(env) elif stype == 'if-exp': # <if-exp> ::= <(> <if> <predicate> <consequent> <alternate> <)> if child[2].calc_value(env): res = child[3].calc_value(env) else: res = child[4].calc_value(env) elif stype == 'or-exp': # <or-exp> ::= <(> <or> <lexp-seq> <)> cnode = child[2] res = False while len(cnode.child) > 1: val = cnode.child[0].calc_value(env) if type(val) == list: val = args_restore(val) if val: res = val break else: cnode = cnode.child[1] else: val = cnode.calc_value(env)[0] if type(val) == list: val = args_restore(val) if val: res = val elif stype == 'and-exp': # <and-exp> ::= <(> <and> <lexp-seq> <)> cnode = child[2] res = True while len(cnode.child) > 1: val = cnode.child[0].calc_value(env) if type(val) == list: val = args_restore(val) if not val: res = val break else: cnode = cnode.child[1] else: val = cnode.calc_value(env)[0] if type(val) == list: val = args_restore(val) if not val: res = val if not self.static: self.value = res return res