def _NameInClass(self, negated_tok, tok): # type: (Token, Token) -> class_literal_term_t """ Like the above, but 'dot' doesn't mean anything. And `d` is a literal 'd', not `digit`. """ if negated_tok: # For error messages negated_speck = speck(negated_tok.id, negated_tok.span_id) else: negated_speck = None val = tok.val # A bare, unquoted character literal. In the grammar, this is expressed as # range_char without an ending. # d is NOT 'digit', it's a literal 'd'! if len(val) == 1: # Expr_Name matches VAR_NAME_RE, which starts with [a-zA-Z_] assert tok.id in (Id.Expr_Name, Id.Expr_DecInt) if negated_tok: # [~d] is not allowed, only [~digit] p_die("Can't negate this symbol", token=tok) return class_literal_term.CharLiteral(tok) # digit, word, but not d, w, etc. if val in POSIX_CLASSES: return posix_class(negated_speck, val) perl = PERL_CLASSES.get(val) if perl is not None: return perl_class(negated_speck, perl) p_die("%r isn't a character class", val, token=tok)
def _NonRangeChars(self, p_node): # type: (PNode) -> class_literal_term_t """ \" \u123 '#' """ assert p_node.typ == grammar_nt.range_char, p_node children = p_node.children typ = children[0].typ if ISNONTERMINAL(typ): p_child = children[0] if typ == grammar_nt.braced_var_sub: return cast(braced_var_sub, p_child.children[1].tok) if typ == grammar_nt.dq_string: return cast(double_quoted, p_child.children[1].tok) if typ == grammar_nt.sq_string: return cast(single_quoted, p_child.children[1].tok) if typ == grammar_nt.simple_var_sub: return simple_var_sub(children[0].tok) if typ == grammar_nt.char_literal: return class_literal_term.CharLiteral(children[0].tok) raise NotImplementedError() else: # Look up PerlClass and PosixClass return self._NameInClass(None, children[0].tok)