def p_word_ellipsis(p): ''' word : sub_rule ELLIPSIS ''' rule_name = Ellipsis_rules.get(p[1]) if rule_name is None: rule_name = crud.gensym('ellipsis') Ellipsis_rules[p[1]] = rule_name rule_text, type, offset, prep_code, params = p[1] p_fn_name_0, p_fn_name_n = \ crud.gensym('p_ellipsis'), crud.gensym('p_ellipsis') output(""" def $fn_name1(p): r''' $rule_name : ''' p[0] = () def $fn_name2(p): r''' $rule_name : $rule_name $production ''' $prep_code p[0] = p[1] + (p[$offset],) """, output_file = Output_file, fn_name1 = p_fn_name_0, rule_name = rule_name, fn_name2 = p_fn_name_n, production = rule_text, prep_code = prep_code % {'offset': offset + 2} if prep_code else '', offset = offset + 2) p[0] = rule_name, 'ellipsis', 0, None, None
def macro_expand(self, fn_symbol, ast_node, words_needed): _, condition, true_branch, false_branch = ast_node.args endif_label = crud.gensym('endif') if false_branch is None: new_args = ( ast.ast.from_parser(condition.get_syntax_position_info(), condition, kind='if-false', label=endif_label, expect='statement'), true_branch, ast.ast(kind='label', label=endif_label, expect='statement'), ) else: else_label = crud.gensym('else') new_args = ( ast.ast.from_parser(condition.get_syntax_position_info(), condition, kind='if-false', label=else_label, expect='statement'), true_branch, ast.ast(kind='jump', label=endif_label, expect='statement'), ast.ast(kind='label', label=else_label, expect='statement'), false_branch, ast.ast(kind='label', label=endif_label, expect='statement'), ) return ast_node.macro_expand(fn_symbol, words_needed, new_args, kind='series')
def p_zero_or_more_word(p): ''' word : sub_rule '*' ''' rule_name = Zero_or_more_rules.get(p[1]) if rule_name is None: rule_name = crud.gensym('zero_or_more') Zero_or_more_rules[p[1]] = rule_name rule_text, type, offset, prep_code, params = p[1] p_fn_name_0, p_fn_name_n = \ crud.gensym('p_zero_or_more'), crud.gensym('p_zero_or_more') output(""" def $fn_name1(p): r''' $rule_name : ''' p[0] = () def $fn_name2(p): r''' $rule_name : $rule_name $production ''' $prep_code p[0] = p[1] + (p[$offset],) """, output_file = Output_file, fn_name1 = p_fn_name_0, rule_name = rule_name, fn_name2 = p_fn_name_n, production = rule_text, prep_code = prep_code % {'offset': offset + 2} if prep_code else '', offset = offset + 2) p[0] = rule_name, 'tuple', 0, None, None
def p_opt_word(p): ''' word : sub_rule '?' ''' rule_name = Optional_rules.get(p[1]) if rule_name is None: rule_name = crud.gensym('optional') Optional_rules[p[1]] = rule_name rule_text, type, offset, prep_code, params = p[1] p_fn_name_0, p_fn_name_n = \ crud.gensym('p_optional'), crud.gensym('p_optional') output(""" def $fn_name1(p): r''' $rule_name : ''' p[0] = None def $fn_name2(p): r''' $rule_name : $production ''' $prep_code p[0] = p[$offset] """, output_file = Output_file, fn_name1 = p_fn_name_0, rule_name = rule_name, fn_name2 = p_fn_name_n, production = rule_text, prep_code = prep_code % {'offset': offset + 1} if prep_code else '', offset = offset + 1) p[0] = rule_name, type, 0, None, None
def more(self): global Current_block assert self.state != 'end_absolute', \ "%s: block missing label after jump" % self.name if self.state == 'end_fall_through': name = crud.gensym('block') self.write(name) Current_block = block(name, self.word_symbol_id) return True return False
def gen_alternatives(rule_name, alternatives, wrapup_fn, param_list = None): for words, lineno, lexpos in alternatives: p_fn_name = crud.gensym('p_' + rule_name) output(""" def $fn_name(p): r''' $rule_name : $production ''' """, output_file = Output_file, fn_name = p_fn_name, rule_name = rule_name, production = ' '.join(word[0] for word in words)) prep = [] args = [] last_arg = None tuple_offset = None has_ellipsis = False if param_list is not None: fn_word_params = param_list fn_word_offset = None else: fn_word_params = None fn_word_offset = None for i, (rule_text, type, offset, prep_code, params) in enumerate(words): if prep_code: prep.append(prep_code % {'offset': offset + i + 1}) if type == 'fn_word': if fn_word_params is not None: scanner_init.syntaxerror( "duplicate function words in production", lineno = lineno, lexpos = lexpos) fn_word_offset = offset + i + 1 fn_word_params = params else: assert not params, "non function word has parameters" if type == 'ignore': pass elif type == 'single_arg': args.append('args.append(p[%d])' % (offset + i + 1)) last_arg = offset + i + 1 elif type == 'tuple': args.append('args.append(p[%d])' % (offset + i + 1)) if tuple_offset is not None: if not has_ellipsis: tuple_offset = 'dup' else: tuple_offset = i elif type == 'ellipsis': args.append('args.extend(p[%d])' % (offset + i + 1)) has_ellipsis = True if prep: print >> Output_file, '\n'.join(' ' + p for p in prep) wrapup_fn(fn_word_params, fn_word_offset, args, last_arg, tuple_offset, has_ellipsis, lineno, lexpos) print >> Output_file
def p_one_or_more_word(p): ''' word : sub_rule '+' ''' rule_name = One_or_more_rules.get(p[1]) if rule_name is None: rule_name = crud.gensym('one_or_more') One_or_more_rules[p[1]] = rule_name rule_text, type, offset, prep_code, params = p[1] p_fn_name_1, p_fn_name_n = \ crud.gensym('p_one_or_more'), crud.gensym('p_one_or_more') prep = prep_code % {'offset': offset + 2} if prep_code else '' output(""" def $fn_name(p): r''' $rule_name : $production ''' $prep_code p[0] = (p[$offset],) """, output_file = Output_file, fn_name = p_fn_name_1, rule_name = rule_name, production = rule_text, prep_code = prep_code % {'offset': offset + 1} if prep_code else '', offset = offset + 1) output(""" def $fn_name(p): r''' $rule_name : $rule_name $production ''' $prep_code p[0] = p[1] + (p[$offset],) """, output_file = Output_file, fn_name = p_fn_name_n, rule_name = rule_name, production = rule_text, prep_code = prep_code % {'offset': offset + 2} if prep_code else '', offset = offset + 2) p[0] = rule_name, 'tuple', 0, None, None
def macro_expand(self, fn_symbol, ast_node, words_needed): #print "repeat.macro_expand" _, count, body = ast_node.args loop_label = crud.gensym('repeat') if not count: #print "no count" new_args = ( ast.ast(kind='label', label=loop_label, expect='statement'), body, ast.ast(kind='jump', label=loop_label, expect='statement'), ) else: count = count[0] #print "count", count if count.kind == 'int': assert count.int1 >= 0, \ "repeat must not have negative repeat count" if count.int1 == 0: return ast_node.macro_expand(fn_symbol, words_needed, (), kind='no-op') if count.int1 == 1: return ast_node.macro_expand(fn_symbol, words_needed, body, kind='series') first_jmp = () else: first_jmp = ( ast.ast(kind='jump', label=test, expect='statement'), ) loop_var = crud.gensym('repeat_var') symbol_id = \ symbol_table.symbol.create(loop_var, 'var', fn_symbol).id test = crud.gensym('repeat_test') new_args = ( ast.ast(ast.ast.word(symbol_table.get('set').id), (ast.ast.word(symbol_id), count, ), kind='call', expect='statement') \ .prepare(fn_symbol, words_needed), ) + first_jmp + ( ast.ast(kind='label', label=loop_label, expect='statement'), ) + body + ( ast.ast(ast.ast.word(symbol_table.get('set').id), (ast.ast.word(symbol_id), ast.ast(ast.ast.word(symbol_table.get('-').id), ast.ast.word(symbol_id), ast.ast(kind='int', int1=1), kind='call', ) \ .prepare(fn_symbol, words_needed), ), kind='call', expect='statement') \ .prepare(fn_symbol, words_needed), ast.ast(kind='label', label=test, expect='statement'), ast.ast(ast.ast.word(symbol_id, expect='condition'), kind='if-true', label=loop_label, expect='statement'), ) return ast_node.macro_expand(fn_symbol, words_needed, new_args, kind='series')
def compile(self): r'''Generates intermediate code for this AST node. ''' if self.kind in ('approx', 'int', 'ratio'): return block.Current_block.gen_triple( self.kind, self.int1, self.int2, syntax_position_info= self.get_syntax_position_info()) if self.kind == 'string': name = crud.gensym('strlit') sym = symbol_table.symbol.create(name, 'const') asm_block = assembler.block(self.word_symbol.id, 'flash', name) asm_block.append_inst('int16', str(len(self.str1))) asm_block.append_inst('bytes', repr(self.str1)) asm_block.write() return block.Current_block.gen_triple( 'global', sym.id, syntax_position_info=self.get_syntax_position_info()) if self.kind == 'call': if self.args and isinstance(self.args[0], ast) and \ self.args[0].kind == 'word': word_obj = symbol_table.get(self.args[0].label).word_obj compile_method = word_obj.get_method('compile', self.expect) return compile_method(self) else: raise AssertionError("call indirect not supported yet") if self.kind == 'word': sym = symbol_table.get_by_id(self.symbol_id) if sym.context is None: word_obj = symbol_table.get_by_id(self.symbol_id).word_obj compile_method = word_obj.get_method('compile', self.expect) ans = compile_method(self) return ans if sym.kind in ('parameter', 'var'): return block.Current_block.gen_triple('local', sym, syntax_position_info=self.get_syntax_position_info()) raise ValueError("%s.compile: unknown symbol.kind %r" % sym.kind) if self.kind in ('no-op', 'None'): return None if self.kind == 'label': block.new_label(self.label, self.word_symbol.id) return None if self.kind == 'jump': block.Current_block.unconditional_to(self.label) return None if self.kind == 'if-true': arg_triples = self.compile_args() block.Current_block.true_to(arg_triples[0], self.label) return None if self.kind == 'if-false': arg_triples = self.compile_args() block.Current_block.false_to(arg_triples[0], self.label) return None if self.kind == 'series': self.compile_args() return None if self.kind in ('ioreg', 'ioreg-bit'): if self.expect in ('value', 'condition'): return block.Current_block.gen_triple( 'input' if self.kind == 'ioreg' else 'input-bit', string=self.label, int1=self.int1, syntax_position_info=self.get_syntax_position_info()) else: raise AssertionError("ast node[%s]: expect %s not supported " "for %s" % (self.id, self.expect, self.kind)) raise AssertionError("ast node[%s]: unknown ast kind -- %s" % (self.id, self.kind))
def p_sub_rule2(p): ''' sub_rule : '(' alternatives ')' ''' rule_name = crud.gensym('sub_rule') gen_alternatives(rule_name, p[2], normal_wrapup) p[0] = rule_name, 'single_arg', 0, None, None