def read_macro(macro):
    instructions = []

    for block in macro.split("*"):

        is_primitive = False
        is_equation = False

        found_equation_left_side = False
        found_primitive_code = False

        equation_left_side = 0
        primitive_code = 0

        unary_minus_allowed = False
        unary_minus = False

        if Token.EQUALS in block:
            is_equation = True
        else:
            is_primitive = True

        scanner = Scanner(block)

        # inlined here for compactness and convenience
        op_stack = []

        def pop():
            return op_stack.pop()

        def push(op):
            op_stack.append(op)

        def top():
            return op_stack[-1]

        def empty():
            return len(op_stack) == 0

        while not scanner.eof():

            c = scanner.getc()

            if c == ",":
                found_primitive_code = True

                # add all instructions on the stack to finish last modifier
                while not empty():
                    instructions.append((token_to_opcode(pop()), None))

                unary_minus_allowed = True

            elif c in Token.OPERATORS:
                if c == Token.SUB and unary_minus_allowed:
                    unary_minus = True
                    unary_minus_allowed = False
                    continue

                while not empty() and is_op(top()) and precedence(top()) >= precedence(c):
                    instructions.append((token_to_opcode(pop()), None))

                push(c)

            elif c == Token.LEFT_PARENS:
                push(c)

            elif c == Token.RIGHT_PARENS:
                while not empty() and top() != Token.LEFT_PARENS:
                    instructions.append((token_to_opcode(pop()), None))

                if empty():
                    raise ValueError("unbalanced parentheses")

                # discard "("
                pop()

            elif c.startswith("$"):
                n = scanner.readint()

                if is_equation and not found_equation_left_side:
                    equation_left_side = n
                else:
                    instructions.append((OpCode.LOAD, n))

            elif c == Token.EQUALS:
                found_equation_left_side = True

            elif c == "0":
                if is_primitive and not found_primitive_code:
                    instructions.append((OpCode.PUSH, scanner.readstr("*")))
                    found_primitive_code = True
                else:
                    # decimal or integer disambiguation
                    if '.' not in scanner.peek() or scanner.peek() == Token.EOF:
                        instructions.append((OpCode.PUSH, 0))

            elif c in "123456789.":
                scanner.ungetc()

                if is_primitive and not found_primitive_code:
                    primitive_code = scanner.readint()
                else:
                    n = scanner.readfloat()
                    if unary_minus:
                        unary_minus = False
                        n *= -1

                    instructions.append((OpCode.PUSH, n))
            else:
                # whitespace or unknown char
                pass

        # add all instructions on the stack to finish last modifier (if any)
        while not empty():
            instructions.append((token_to_opcode(pop()), None))

        # at end, we either have a primitive or a equation
        if is_primitive and found_primitive_code:
            instructions.append((OpCode.PRIM, primitive_code))

        if is_equation:
            instructions.append((OpCode.STORE, equation_left_side))

    return instructions
dataset/ETHPy150Open curtacircuitos/pcb-tools/gerber/am_read.py/read_macro/swapped operands of `not in`