Ejemplo n.º 1
0
def p_element_declaration_constant(p):
    'element : IDENTIFIER EQU expr'
    name, lineno = p[1], p.lineno(1)
    if name in p.parser.const_table:
        warn("Overriding already defined constant {0}", name, lineno=lineno)
    try:
        p.parser.const_table[name] = Const(name, eval_expr(p[3], p, lineno), lineno)
    except SyntaxError: pass
    pass
Ejemplo n.º 2
0
def first_pass(ast, const_table, data_table, inst_table, errors):
    """The first pass assigns an address to variables (data segment) and
    labels, and checks for undefined references. It also warns about constants,
    variables and labels that are not used, and about mismatches between
    variable size and instruction size.
    """
    data_offset = inst_table[SIZE]
    code_offset = 0
    main_lineno = 0

    for elem in ast:
        if isinstance(elem, Var):
            data_table[elem.id].addr = data_offset
            data_offset += elem.size
        if isinstance(elem, Inst):
            if elem.label != '':
                if elem.label == MAIN: main_lineno = elem.lineno
                inst_table[elem.label].addr = code_offset
            code_offset += elem.size

            if len(elem.inst) == 3:
                _, _, label = elem.inst
                if label not in inst_table:
                    error("Undefined label {}", label, lineno=elem.lineno, errors=errors)
                else:
                    inst_table[label].used = True
            elif len(elem.inst) == 4:
                name, size, inst_type, value = elem.inst
                if inst_type == 'var':
                    if value not in data_table:
                        error("Undefined variable {}", value, lineno=elem.lineno, errors=errors)
                    else:
                        data_table[value].used = True
                        elem.inst = (name, size, 'ext', data_table[value].addr)

                        var_size = data_table[value].size
                        inst_size = 1 if name in INST_ONE_BYTE else 2
                        if inst_size != var_size:
                            warn("Size mismatch: instruction {0} expects {1:d} byte{2}, variable {3} has {4:d} byte{5}",
                                    name, inst_size, 's' if inst_size > 1 else '', value, var_size,
                                    's' if var_size > 1 else '', lineno=elem.lineno)
            elif len(elem.inst) == 5:
                _, _, inst_type, _, label = elem.inst
                if inst_type == 'imm-rel':
                    if label not in inst_table:
                        error("Undefined label {}", label, lineno=elem.lineno, errors=errors)
                    else:
                        inst_table[label].used = True

    # Warnings for unused constants, variables and labels
    for const in [k for k in const_table if const_table[k].used == False]:
        warn("Unused constant {}", const, lineno=const_table[const].lineno)

    for var in [k for k in data_table if k != SIZE and data_table[k].used == False]:
        warn("Unused variable {}", var, lineno=data_table[var].lineno)

    for label in [k for k in inst_table if k != SIZE and inst_table[k].used == False]:
        warn("Unused label {}", label, lineno=inst_table[label].lineno)

    if MAIN in inst_table and inst_table[MAIN].addr != MAIN_ADDR:
        error("Main label should be the first instruction",lineno=main_lineno, errors=errors)