MCPcopy Create free account
hub / github.com/davidblewett/rure-python / maybe_parse_ascii_class

Method maybe_parse_ascii_class

regex/regex-syntax/src/ast/parse.rs:1957–2019  ·  view source on GitHub ↗

Attempt to parse an ASCII character class, e.g., `[:alnum:]`. This assumes the parser is positioned at the opening `[`. If no valid ASCII character class could be found, then this does not advance the parser and `None` is returned. Otherwise, the parser is advanced to the first byte following the closing `]` and the corresponding ASCII class is returned.

(&self)

Source from the content-addressed store, hash-verified

1955 /// advanced to the first byte following the closing `]` and the
1956 /// corresponding ASCII class is returned.
1957 fn maybe_parse_ascii_class(&self) -> Option<ast::ClassAscii> {
1958 // ASCII character classes are interesting from a parsing perspective
1959 // because parsing cannot fail with any interesting error. For example,
1960 // in order to use an ASCII character class, it must be enclosed in
1961 // double brackets, e.g., `[[:alnum:]]`. Alternatively, you might think
1962 // of it as "ASCII character characters have the syntax `[:NAME:]`
1963 // which can only appear within character brackets." This means that
1964 // things like `[[:lower:]A]` are legal constructs.
1965 //
1966 // However, if one types an incorrect ASCII character class, e.g.,
1967 // `[[:loower:]]`, then we treat that as a normal nested character
1968 // class containing the characters `:elorw`. One might argue that we
1969 // should return an error instead since the repeated colons give away
1970 // the intent to write an ASCII class. But what if the user typed
1971 // `[[:lower]]` instead? How can we tell that was intended to be an
1972 // ASCII class and not just a normal nested class?
1973 //
1974 // Reasonable people can probably disagree over this, but for better
1975 // or worse, we implement semantics that never fails at the expense
1976 // of better failure modes.
1977 assert_eq!(self.char(), '[');
1978 // If parsing fails, then we back up the parser to this starting point.
1979 let start = self.pos();
1980 let mut negated = false;
1981 if !self.bump() || self.char() != ':' {
1982 self.parser().pos.set(start);
1983 return None;
1984 }
1985 if !self.bump() {
1986 self.parser().pos.set(start);
1987 return None;
1988 }
1989 if self.char() == '^' {
1990 negated = true;
1991 if !self.bump() {
1992 self.parser().pos.set(start);
1993 return None;
1994 }
1995 }
1996 let name_start = self.offset();
1997 while self.char() != ':' && self.bump() {}
1998 if self.is_eof() {
1999 self.parser().pos.set(start);
2000 return None;
2001 }
2002 let name = &self.pattern()[name_start..self.offset()];
2003 if !self.bump_if(":]") {
2004 self.parser().pos.set(start);
2005 return None;
2006 }
2007 let kind = match ast::ClassAsciiKind::from_name(name) {
2008 Some(kind) => kind,
2009 None => {
2010 self.parser().pos.set(start);
2011 return None;
2012 }
2013 };
2014 Some(ast::ClassAscii {

Callers 1

parse_set_classMethod · 0.80

Calls 8

bumpMethod · 0.80
parserMethod · 0.80
offsetMethod · 0.80
bump_ifMethod · 0.80
posMethod · 0.45
charMethod · 0.45
is_eofMethod · 0.45
patternMethod · 0.45

Tested by

no test coverage detected