Ejemplo n.º 1
0
def function_type_args() -> GrammarType:
    return Optional([
        # The `Not` rule is necessary to prevent the full_type rule to match, that prevents Arpeggio
        # to try the variadic dots rule
        Sequence(OneOrMore(full_type, Not('...'), sep=','),
                 Optional(',', Optional(full_type), function_variadic_dots)),
        Sequence(Optional(full_type), function_variadic_dots)
    ]), trailing_comma
Ejemplo n.º 2
0
def repeatable_expr_SA(parser, node, children):
    expr = children[0]
    rule = expr
    repeat_op = False
    suppress = False
    if len(children) > 1:
        # We can have repeat operator and/or suppression operator
        if len(children) > 2:
            repeat_op = children[1]
            suppress = True
        else:
            if children[1] == '-':
                suppress = True
            else:
                repeat_op = children[1]

        if repeat_op:
            if len(repeat_op) > 1:
                repeat_op, modifiers = repeat_op
            else:
                repeat_op = repeat_op[0]
                modifiers = None

            if repeat_op == '?':
                rule = Optional(nodes=[expr])
            elif repeat_op == '*':
                rule = ZeroOrMore(nodes=[expr])
            else:
                rule = OneOrMore(nodes=[expr])

            if modifiers:
                modifiers, position = modifiers
                # Sanity check. Modifiers do not make
                # sense for ? operator at the moment.
                if repeat_op == '?':
                    line, col = parser.pos_to_linecol(position)
                    raise TextXSyntaxError(
                        'Modifiers are not allowed for "?" operator at {}'.
                        format(text((line, col))), line, col)
                # Separator modifier
                if 'sep' in modifiers:
                    sep = modifiers['sep']
                    rule = Sequence(nodes=[
                        expr,
                        ZeroOrMore(nodes=[Sequence(nodes=[sep, expr])])
                    ])
                    if repeat_op == '*':
                        rule = Optional(nodes=[rule])

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

    # Mark rule for suppression
    rule.suppress = suppress

    return rule
Ejemplo n.º 3
0
def textx_rule_SA(parser, node, children):
    if len(children) > 2:
        rule_name, rule_params, rule = children
    else:
        rule_name, rule = children
        rule_params = {}

    if rule.rule_name.startswith('__asgn') or\
            (isinstance(rule, Match) and rule_params):
        # If it is assignment node it must be kept because it could be
        # e.g., single assignment in the rule.
        # Also, handle a special case where rule consists only of a single match
        # and there are rule modifiers defined.
        rule = Sequence(nodes=[rule],
                        rule_name=rule_name,
                        root=True,
                        **rule_params)
    else:
        if not isinstance(rule, RuleCrossRef):
            # Promote rule node to root node.
            rule.rule_name = rule_name
            rule.root = True
            for param in rule_params:
                setattr(rule, param, rule_params[param])

    # Connect meta-class and the PEG rule
    parser.metamodel._set_rule(rule_name, rule)

    return rule
Ejemplo n.º 4
0
def long_eq_arg():
    """long argument, equal sign and operand without whitespace :
         '--file=foobar.txt'
    """
    return Sequence((long_no_arg, eq, operand),
                    rule_name='long_eq_arg',
                    skipws=False)
Ejemplo n.º 5
0
def ol_first_option():
    # semantic analysis :
    #   - disallow short_stacked
    #   - is this a continuation of the prior option-list ?
    #   - disallow bar without a prior option-line
    return Sequence((Optional(bar), wx, option),
                    rule_name='ol_first_option',
                    skipws=False)
Ejemplo n.º 6
0
def required():
    return Sequence((
        l_paren,
        choice,
        r_paren,
    ),
                    rule_name="required",
                    skipws=True)
Ejemplo n.º 7
0
def optional():
    return Sequence((
        l_bracket,
        choice,
        r_bracket,
    ),
                    rule_name="optional",
                    skipws=True)
Ejemplo n.º 8
0
def option_description_section():
    return Sequence(
        (
            Optional(option_description_intro),
            OneOrMore(option_line),
            # [ EOF, blank_line ],
        ),
        rule_name='option_description_section',
        skipws=False)
Ejemplo n.º 9
0
    def quoted_string():
        def double_quoted():
            return '"', _(r'((\\")|[^"])*'), '"'

        def single_quoted():
            return "'", _(r"((\\')|[^'])*"), "'"

        # a sequence containing a single item -- the ordered choice
        return Sequence([double_quoted, single_quoted], skipws=False)
Ejemplo n.º 10
0
def option_list():
    # semantic analysis :
    #   - validate that series of option, operand, ol_bar, ol_comma and ol_space
    #     form a meaninful comma/bar/space option-list
    #   - disallow bar without a prior option-line
    return Sequence(
        (ol_first_option, ZeroOrMore(ol_term_with_separator)),
        # , Optional(EOF) ),
        rule_name='option_list',
        skipws=False)
Ejemplo n.º 11
0
def option_line():

    # It should not be necessary to incorporate EOF so often.
    # arpeggio.NoMatch: Expected comma or bar or space or '  ' or
    #   newline at position (1, 6) => '-f -x*'.

    return Sequence(
        (wx, option_list, Optional(
            (option_line_gap(), Optional(option_help()))), [EOF, newline]),
        rule_name='option_line',
        skipws=False)
Ejemplo n.º 12
0
    def visit_rule(self, node, children):
        rule_name = children[0]
        if len(children) > 2:
            retval = Sequence(nodes=children[1:])
        else:
            retval = children[1]

        retval.rule_name = rule_name
        retval.root = True

        # Keep a map of parser rules for cross reference
        # resolving.
        self.peg_rules[rule_name] = retval
        return retval
Ejemplo n.º 13
0
def textx_rule_SA(parser, node, children):
    if len(children[0]) > 2:
        rule_name, rule_params, rule = children[0]
    else:
        rule_name, rule = children[0]
        rule_params = {}
    rule = Sequence(nodes=[rule],
                    rule_name=rule_name,
                    root=True,
                    **rule_params)

    # Add PEG rule to the meta-class
    parser.metamodel.set_rule(rule_name, rule)

    return rule
Ejemplo n.º 14
0
        def _resolve_rule(rule):
            """
            Recursively resolve peg rule references.

            Args:
                rule(ParsingExpression or RuleCrossRef)
            """
            if not isinstance(rule, RuleCrossRef) and rule in resolved_rules:
                return rule
            resolved_rules.add(rule)

            if grammar_parser.debug:
                grammar_parser.dprint("Resolving rule: {}".format(rule))

            if type(rule) is RuleCrossRef:
                rule_name = rule.rule_name
                suppress = rule.suppress
                if rule_name in model_parser.metamodel:
                    rule = model_parser.metamodel[rule_name]._tx_peg_rule
                    if type(rule) is RuleCrossRef:
                        rule = _resolve_rule(rule)
                        model_parser.metamodel[rule_name]._tx_peg_rule = rule
                    if suppress:
                        # Special case. Suppression on rule reference.
                        _tx_class = rule._tx_class
                        rule = Sequence(nodes=[rule],
                                        rule_name=rule_name,
                                        suppress=suppress)
                        rule._tx_class = _tx_class
                else:
                    line, col = grammar_parser.pos_to_linecol(rule.position)
                    raise TextXSemanticError(
                        'Unexisting rule "{}" at position {}.'.format(
                            rule.rule_name, (line, col)),
                        line,
                        col,
                        filename=model_parser.metamodel.file_name)

            assert isinstance(rule, ParsingExpression),\
                "{}:{}".format(type(rule), text(rule))

            # Recurse into subrules, and resolve rules.
            for idx, child in enumerate(rule.nodes):
                if child not in resolved_rules:
                    child = _resolve_rule(child)
                    rule.nodes[idx] = child

            return rule
Ejemplo n.º 15
0
        def __init__(self, *args, **kwargs):
            super(TextXModelParser, self).__init__(*args, **kwargs)

            # By default first rule is starting rule
            # and must be followed by the EOF
            self.parser_model = Sequence(nodes=[top_rule, EOF()],
                                         rule_name='Model',
                                         root=True)
            self.comments_model = comments_model

            # Stack for metaclass instances
            self._inst_stack = []

            # Dict for cross-ref resolving
            # { id(class): { obj.name: obj}}
            self._instances = {}
Ejemplo n.º 16
0
        def __init__(self, *args, **kwargs):
            super(TextXModelParser, self).__init__(*args, **kwargs)

            # By default first rule is starting rule
            # and must be followed by the EOF
            self.parser_model = Sequence(
                nodes=[top_rule, EOF()], rule_name='Model', root=True)
            self.comments_model = comments_model

            # Stack for metaclass instances
            self._inst_stack = []

            # Dict for cross-ref resolving
            # { id(class): { obj.name: obj}}
            self._instances = {}

            # List to keep track of all cross-ref that need to be resolved
            # Contained elements are tuples: (instance, metaattr, cross-ref)
            self._crossrefs = []
Ejemplo n.º 17
0
def ol_term_with_separator():
    return Sequence((ol_separator, ol_term),
                    rule_name='ol_term_with_separator',
                    skipws=False)
Ejemplo n.º 18
0
def ol_comma():
    return Sequence(Optional(space),
                    comma,
                    Optional(space),
                    rule_name='ol_comma',
                    skipws=False)
Ejemplo n.º 19
0
def ol_bar():
    return Sequence(Optional(space),
                    bar,
                    Optional(space),
                    rule_name='ol_bar',
                    skipws=False)
Ejemplo n.º 20
0
def line():
    return Sequence(text, newline, rule_name='line', skipws=False)
Ejemplo n.º 21
0
def ol_space():
    return Sequence(space, Not(space), rule_name='ol_space', skipws=False)
Ejemplo n.º 22
0
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 'eolterm' in modifiers:
            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
Ejemplo n.º 23
0
    def visit_textx_rule(self, node, children):
        if len(children) > 2:
            rule_name, rule_params, root_rule = children
        else:
            rule_name, root_rule = children
            rule_params = {}

        if root_rule.rule_name.startswith('__asgn') or \
                ((isinstance(root_rule, Match) or
                  isinstance(root_rule, RuleCrossRef))
                 and rule_params):
            # If it is assignment node it must be kept because it could be
            # e.g. single assignment in the rule.
            # Also, handle a special case where rule consists only of a single
            # match or single rule reference and there are rule modifiers
            # defined.
            root_rule = Sequence(nodes=[root_rule],
                                 rule_name=rule_name,
                                 root=True,
                                 **rule_params)
        else:
            if not isinstance(root_rule, RuleCrossRef):
                # Promote rule node to root node.
                root_rule.rule_name = rule_name
                root_rule.root = True
                for param in rule_params:
                    setattr(root_rule, param, rule_params[param])

        # Connect meta-class and the PEG rule
        cls = self.metamodel[rule_name]
        cls._tx_peg_rule = root_rule
        root_rule._tx_class = cls

        # Update end position for this rule.
        cls._tx_position_end = node.position_end

        # Update multiplicities of attributes based on their parent
        # expressions.
        def _update_attr_multiplicities(rule, oc_branch_set, mult=MULT_ONE):

            if isinstance(rule, RuleCrossRef):
                return

            if isinstance(rule, OrderedChoice):
                for on in rule.nodes:
                    oc_branch_set = set()
                    _update_attr_multiplicities(on, oc_branch_set, mult)
            else:
                if isinstance(rule, OneOrMore):
                    mult = MULT_ONEORMORE
                elif isinstance(rule, ZeroOrMore):
                    if mult != MULT_ONEORMORE:
                        mult = MULT_ZEROORMORE

                if rule.rule_name.startswith('__asgn'):
                    cls_attr = cls._tx_attrs[rule._attr_name]
                    if mult in [MULT_ZEROORMORE, MULT_ONEORMORE]:
                        if rule.rule_name == '__asgn_optional':
                            raise TextXSemanticError(
                                'Can\'t use bool assignment '
                                'inside repetition in rule "{}" at {}.'.format(
                                    rule_name,
                                    self.grammar_parser.pos_to_linecol(
                                        node.position)))
                        if mult_lt(cls_attr.mult, mult):
                            cls_attr.mult = mult
                    # If multiplicity is not "many" still we can have
                    # "many" multiplicity if same attribute has been
                    # assigned multiple times in the same OrderedChoice
                    # branch.
                    elif rule._attr_name in oc_branch_set:
                        cls_attr.mult = MULT_ONEORMORE
                    else:
                        # Keep track of assignments in the current OC
                        # branch.
                        oc_branch_set.add(rule._attr_name)

                if rule is root_rule or not rule.root:
                    for n in rule.nodes:
                        _update_attr_multiplicities(n, oc_branch_set, mult)

        _update_attr_multiplicities(root_rule, set())

        return root_rule
Ejemplo n.º 24
0
def sequence_SA(parser, node, children):
    if len(children) > 1:
        return Sequence(nodes=children[:])
    else:
        return children[0]
Ejemplo n.º 25
0
 def visit_sequence(self, node, children):
     if len(children) == 1:
         return children[0]
     return Sequence(nodes=children[:])
Ejemplo n.º 26
0
def textx_rule_body_SA(parser, node, children):
    if len(children) > 1:
        return Sequence(nodes=children[:])
    else:
        return children[0]
Ejemplo n.º 27
0
def option_description_intro():
    # return OneOrMore ( Sequence ( ( Not(option_line_start), wx, text_line ) ),
    return OneOrMore(Sequence(
        (Not(option_line_start), wx, any_until_end_of_line)),
                     rule_name='option_description_intro',
                     skipws=False)
Ejemplo n.º 28
0
            def _inner_resolve(rule, cls_rule_name=None):
                if grammar_parser.debug:
                    grammar_parser.dprint("Resolving rule: {}".format(rule))

                # Save initial rule name to detect special abstract rule case.
                initial_rule_name = cls_rule_name \
                    if cls_rule_name else rule.rule_name

                if type(rule) is RuleCrossRef:
                    rule_name = rule.rule_name
                    suppress = rule.suppress
                    if rule_name in model_parser.metamodel:
                        rule = model_parser.metamodel[rule_name]._tx_peg_rule
                        if type(rule) is RuleCrossRef:
                            rule = _inner_resolve(rule)
                            model_parser.metamodel[rule_name]\
                                ._tx_peg_rule = rule
                        if suppress:
                            # Special case. Suppression on rule reference.
                            _tx_class = rule._tx_class
                            rule = Sequence(nodes=[rule],
                                            rule_name=rule_name,
                                            suppress=suppress)
                            rule._tx_class = _tx_class
                    else:
                        line, col = grammar_parser.pos_to_linecol(
                            rule.position)
                        raise TextXSemanticError(
                            'Unexisting rule "{}" at position {}.'.format(
                                rule.rule_name, (line, col)), line, col)

                assert isinstance(rule, ParsingExpression),\
                    "{}:{}".format(type(rule), text(rule))

                # If there is meta-class attributes collected than this
                # is a common rule
                if hasattr(rule, '_tx_class') and \
                        len(rule._tx_class._tx_attrs) > 0:
                    rule._tx_class._tx_type = RULE_COMMON

                # Recurse into subrules, resolve and determine rule types.
                for idx, child in enumerate(rule.nodes):
                    if child not in resolved_set:
                        resolved_set.add(rule)
                        child = _inner_resolve(child)
                        rule.nodes[idx] = child

                # Check if this rule is abstract
                # Abstract are root rules which haven't got any attributes
                # and reference at least one non-match rule.
                if initial_rule_name in model_parser.metamodel:
                    cls = model_parser.metamodel[initial_rule_name]
                    abstract = False
                    if rule.rule_name and initial_rule_name != rule.rule_name:
                        abstract = model_parser.metamodel[
                            rule.rule_name]._tx_type != RULE_MATCH
                    else:
                        abstract = not cls._tx_attrs and \
                            any([c._tx_class._tx_type != RULE_MATCH
                                for c in rule.nodes if hasattr(c, '_tx_class')])

                    if abstract:
                        cls._tx_type = RULE_ABSTRACT
                        # Add inherited classes to this rule's meta-class
                        if rule.rule_name and initial_rule_name != rule.rule_name:
                            if rule._tx_class not in cls._tx_inh_by:
                                cls._tx_inh_by.append(rule._tx_class)
                        else:
                            for idx, child in enumerate(rule.nodes):
                                if child.root and hasattr(child, '_tx_class'):
                                    if child._tx_class not in cls._tx_inh_by:
                                        cls._tx_inh_by.append(child._tx_class)

                return rule
Ejemplo n.º 29
0
 def single_quoted_term():
     # Match everything that falls under a '' and also match escaped ' (\')
     return u"'", Sequence(OneOrMore(
         [_r(r'[^\x27\\]'), (u"\\", _r(r'.'))]),
                           skipws=False), u"'"
Ejemplo n.º 30
0
def document():
    return Sequence( body, EOF, rule_name='document' )