def assignment_SA(parser, node, children):
    """
    Create parser rule for assignments and register attribute types
    on metaclass.
    """
    attr_name = children[0]
    op = children[1]
    rhs_rule, modifiers = children[2]
    cls = parser._current_cls
    target_cls = None

    if parser.debug:
        parser.dprint("Processing assignment {}{}...".format(attr_name, op))

    if parser.debug:
        parser.dprint("Creating attribute {}:{}".format(cls.__name__,
                                                        attr_name))
        parser.dprint("Assignment operation = {}".format(op))

    if attr_name in cls._tx_attrs:
        # If attribute already exists in the metamodel it is
        # multiple assignment to the same attribute.

        # Cannot use operator ?= on multiple assignments
        if op == '?=':
            line, col = parser.pos_to_linecol(node.position)
            raise TextXSemanticError(
                'Cannot use "?=" operator on multiple'
                ' assignments for attribute "{}" at {}'
                .format(attr_name, (line, col)), line, col)

        cls_attr = cls._tx_attrs[attr_name]
        # Must be a many multiplicity.
        # OneOrMore is "stronger" constraint.
        if cls_attr.mult is not MULT_ONEORMORE:
            cls_attr.mult = MULT_ZEROORMORE
    else:
        cls_attr = parser.metamodel._new_cls_attr(cls, name=attr_name,
                                                  position=node.position)

    # Keep track of metaclass references and containments
    if type(rhs_rule) is tuple and rhs_rule[0] == "obj_ref":
        cls_attr.cont = False
        cls_attr.ref = True
        # Override rhs by its PEG rule for further processing
        rhs_rule = rhs_rule[1]
        # Target class is not the same as target rule
        target_cls = rhs_rule.cls

    base_rule_name = rhs_rule.rule_name
    if op == '+=':
        assignment_rule = OneOrMore(
            nodes=[rhs_rule],
            rule_name='__asgn_oneormore', root=True)
        cls_attr.mult = MULT_ONEORMORE
    elif op == '*=':
        assignment_rule = ZeroOrMore(
            nodes=[rhs_rule],
            rule_name='__asgn_zeroormore', root=True)
        if cls_attr.mult is not MULT_ONEORMORE:
            cls_attr.mult = MULT_ZEROORMORE
    elif op == '?=':
        assignment_rule = Optional(
            nodes=[rhs_rule],
            rule_name='__asgn_optional', root=True)
        cls_attr.mult = MULT_OPTIONAL
        base_rule_name = 'BOOL'

        # ?= assigment should have default value of False.
        # so we shall mark it as such.
        cls_attr.bool_assignment = True

    else:
        assignment_rule = Sequence(
            nodes=[rhs_rule],
            rule_name='__asgn_plain', root=True)

    # Modifiers
    if modifiers:
        modifiers, position = modifiers
        # Sanity check. Modifiers do not make
        # sense for ?= and = operator at the moment.
        if op == '?=' or op == '=':
            line, col = parser.pos_to_linecol(position)
            raise TextXSyntaxError(
                'Modifiers are not allowed for "{}" operator at {}'
                .format(op, text((line, col))), line, col)

        # Separator modifier
        if 'sep' in modifiers:
            sep = modifiers['sep']
            assignment_rule = Sequence(
                nodes=[rhs_rule,
                       ZeroOrMore(nodes=[Sequence(nodes=[sep, rhs_rule])])],
                rule_name='__asgn_list', root=True)
            if op == "*=":
                assignment_rule.root = False
                assignment_rule = Optional(nodes=[assignment_rule],
                                           rule_name='__asgn_list', root=True)

        # End of line termination modifier
        if modifiers in 'eolterm':
            assignment_rule.eolterm = True

    if target_cls:
        attr_type = target_cls
    else:
        # Use STRING as default attr class
        attr_type = base_rule_name if base_rule_name else 'STRING'
    cls_attr.cls = ClassCrossRef(cls_name=attr_type, position=node.position)

    if parser.debug:
        parser.dprint("Created attribute {}:{}[cls={}, cont={}, "
                      "ref={}, mult={}, pos={}]"
                      .format(cls.__name__, attr_name, cls_attr.cls.cls_name,
                              cls_attr.cont, cls_attr.ref, cls_attr.mult,
                              cls_attr.position))

    assignment_rule._attr_name = attr_name
    assignment_rule._exp_str = attr_name    # For nice error reporting
    return assignment_rule
dataset/ETHPy150Open igordejanovic/textX/textx/textx.py/assignment_SA/swapped operands of `in`