def grammar(): return Sequence((*body), rule_name='grammar', skipws=skipws)
def document(): return Sequence(body, EOF, rule_name='document')
def visit_sequence(self, node, children): if len(children) == 1: return children[0] return Sequence(nodes=children[:])
def control_structure_body_stub() -> GrammarType: return Sequence(control_structure_body_stub_inner)
def char() -> GrammarType: return ('\'', Sequence(RegExMatch(r'\\[abefnrtv0\\]|[^\']', str_repr='character'), skipws=False), '\'')
def grammar(): return Sequence("one", "two", "three", suppress=True), "four"
def suffix_operator_value() -> GrammarType: return writable_value, Sequence(['++', '--'], skipws=False)
def string(): return '"', Sequence( ZeroOrMore( non_quote_char ), skipws=False ), '"' def opt_stmt_sep(): return Optional( statement_sep )
def common_rule_body_SA(parser, node, children): return Sequence(nodes=children[:])
def itself(): name = f"by_itself" return name, Sequence((rule, EOF)), s, (t_s, )
def grammar(): return Sequence((OneOrMore(OrderedChoice(elements)), EOF), rule_name="grammar")
def grammar(_words): body = OneOrMore(OrderedChoice([rule, _words, catchall, newline])) return Sequence((body, EOF))
def visit_sequence(self, node, children): if len(children) > 1: return Sequence(nodes=children[:]) else: # If only one child rule exists reduce. return children[0]
def ol_first_option(): return Sequence ( ( And(ws), OrderedChoice( [ _long, _short ] ) ), rule_name='ol_first_option', skipws=False )
def argument(): # EOF causes hang in optional/required return Sequence((wx, OrderedChoice([option, operand, command])), rule_name="argument", skipws=True)
def sequence_SA(parser, node, children): return Sequence(nodes=children[:])
def usage_pattern(): # usage_pattern = OR? program choice? return Sequence((Optional(OR), program, Optional(choice)), rule_name="usage_pattern", skipws=True)
def body(): return Sequence(OneOrMore(OrderedChoice([option, operand, ws])), EOF, rule_name='body', skipws=False)
def disambiguated_prefix_operator_value() -> GrammarType: return "", Sequence(['++', '--'], And(['ref', compound_identifier]), skipws=False)
def grammar(): return Sequence(OneOrMore(OrderedChoice([option, operand, ws])), EOF, rule_name='grammar', skipws=False)
def control_structure_body_stub_inner() -> GrammarType: return open_brace, Sequence( [control_structure_body_stub_braces, control_structure_potential_closing_brace], close_brace, skipws=False )
def usage_intro(): # skipws=False is required to match when whitespace proceeds 'usage' return Sequence((_(USAGE_INTRO_REGEX, skipws=False), ZeroOrMore(newline, skipws=False), wx()), rule_name="usage_intro", skipws=False)
def function_arguments() -> GrammarType: return (Optional([Sequence(OneOrMore(variable_declaration_assignable, sep=','), Optional(',', Optional(full_type), function_variadic_dots)), Sequence(Optional(full_type), function_variadic_dots)]), trailing_comma)
def usage_section(): return Sequence((usage_intro, OneOrMore(usage_line)), rule_name="usage_section", skipws=True)
def line(): return Sequence(text, newline, rule_name='line', skipws=False)
def choice(): return Sequence((expression, ZeroOrMore((bar, expression))), rule_name="choice", skipws=True)
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
def repeatable(): return Sequence((term, Optional(repeating)), rule_name="repeatable", skipws=True)
def visit_assignment(self, 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 = self._current_cls target_cls = None if self.debug: self.dprint("Processing assignment {}{}...".format(attr_name, op)) if self.debug: self.dprint("Creating attribute {}:{}".format( cls.__name__, attr_name)) self.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 = self.grammar_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] else: cls_attr = self.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 = self.grammar_parser.pos_to_linecol(position) raise TextXSyntaxError( 'Modifiers are not allowed for "{}" operator at {}'.format( op, text((line, col))), line, col) # Separator modifier assignment_rule.sep = modifiers.get('sep', None) # 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' if not cls_attr.cls: cls_attr.cls = ClassCrossRef(cls_name=attr_type, position=node.position) else: # cls cross ref might already be set in case of multiple assignment # to the same attribute. If types are not the same we shall use # OBJECT as generic type. if cls_attr.cls.cls_name != attr_type: cls_attr.cls.cls_name = 'OBJECT' if self.debug: self.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
def grammar(): return Sequence((OneOrMore(OrderedChoice([*rule_list], )), EOF), rule_name='grammar', skipws=False)