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