def match__modifier(self, other): assert self.tail[0].head == 'modifier_name' and len(self.tail[0].tail) == 1 modifier_name = self.tail[0].tail[0] if modifier_name == ':is-parent': return [other] if (is_stree(other) and other.tail) else [] elif modifier_name == ':is-leaf': return [other] if not is_stree(other) else [] raise NotImplementedError("Didn't implement %s yet" % modifier_name)
def __default__(self, tree): # Expand/Flatten rules if requested in grammar to_expand = [i for i, subtree in enumerate(tree.tail) if is_stree(subtree) and ( (subtree.head == tree.head and subtree.head in self.rules_to_flatten) or (subtree.head in self.rules_to_expand) ) ] if to_expand: tree.expand_kids(*to_expand) # Remove empty trees ( XXX not strictly necessary, just cleaner... should I keep them?) to_remove = [i for i, subtree in enumerate(tree.tail) if is_stree(subtree) and not subtree.tail] if to_remove: tree.remove_kids(*to_remove)
def rule(self, tree): # rules_list unpacking # a : b (c|d) e # --> # a : b c e | b d e # # In actual terms: # # [rule [b] [rules_list [c] [d]] [e]] # --> # [rules_list [rule [b] [c] [e]] [rule [b] [d] [e]] ] # changed = False if self._flatten(tree): changed = True for i,child in enumerate(tree.tail): if is_stree(child) and child.head == 'rules_list': # found. now flatten new_rules_list = [] for option in child.tail: new_rules_list.append(STree('rule', [])) # for each rule in rules_list for j,child2 in enumerate(tree.tail): if j == i: new_rules_list[-1].tail.append(option) else: new_rules_list[-1].tail.append(child2) tree.head, tree.tail = 'rules_list', new_rules_list return True # changed return changed # Not changed
def match__elem_regexp(self, other): if is_stree(other): s = other.head else: s = other # hopefully string [regexp] = self.tail assert regexp[0] == regexp[-1] == '/' regexp = regexp[1:-1] return [other] if re.match(regexp, s) else []
def _simplify_token(self, tokendef): token_value = tokendef.tail[1] if is_stree(token_value): assert token_value.head == 'tokenvalue' regexp = ''.join( _unescape_token_def(d) if d.startswith("'") else self._simplify_token(self.tokendefs[d]) for d in token_value.tail ) tokendef.tail = list(tokendef.tail) # can't assign to a tuple tokendef.tail[1] = regexp return tokendef.tail[1]
def match__selector(self, other): elem = self.tail[-1] if is_stree(other): res = sum_list(other.map(elem._match)) else: res = sum_list([elem._match(item) for item in other]) # we were called by a selector_op if not res: return [] # shortcut if self.tail[0].head == 'selector_op': res = self.tail[0]._match_selector_op(res) return res
def rule(self, tree): # rules_list unpacking # a : b (c|d) e # --> # a : b c e | b d e # # In actual terms: # # [rule [b] [rules_list [c] [d]] [e]] # --> # [rules_list [rule [b] [c] [e]] [rule [b] [d] [e]] ] # changed = False if self._flatten(tree): changed = True for i,child in enumerate(tree.tail): if is_stree(child) and child.head == 'rules_list': # found. now flatten new_rules_list = [] for option in child.tail: new_rules_list.append(STree('rule', [])) # for each rule in rules_list for j,child2 in enumerate(tree.tail): if j == i: new_rules_list[-1].tail.append(option) else: new_rules_list[-1].tail.append(child2) tree.head, tree.tail = 'rules_list', new_rules_list return True # changed for i, child in enumerate(tree.tail): if isinstance(child, str) and child.startswith("'"): try: tok_name = self.tokendefs[child] except KeyError: tok_name = self._get_new_tok_name(child) # Add anonymous token self.tokendefs[child] = tok_name self._rules_to_add.append(STree('tokendef', [tok_name, child])) tree.tail[i] = tok_name changed = True return changed # Not changed
def __default__(self, tree): if len(tree.tail) <= 1: return tree return tree.__class__(tree.head, [x for x in tree.tail if is_stree(x)])
def _flatten(self, tree): to_expand = [i for i, subtree in enumerate(tree.tail) if is_stree(subtree) and subtree.head == tree.head] if to_expand: tree.expand_kids(*to_expand) return bool(to_expand)