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)
| 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 { |