Parse a Unicode class in either the single character notation, `\pN` or the multi-character bracketed notation, `\p{Greek}`. This assumes the parser is positioned at the `p` (or `P` for negation) and will advance the parser to the character immediately following the class. Note that this does not check whether the class name is valid or not.
(&self)
| 2025 | /// |
| 2026 | /// Note that this does not check whether the class name is valid or not. |
| 2027 | fn parse_unicode_class(&self) -> Result<ast::ClassUnicode> { |
| 2028 | assert!(self.char() == 'p' || self.char() == 'P'); |
| 2029 | |
| 2030 | let mut scratch = self.parser().scratch.borrow_mut(); |
| 2031 | scratch.clear(); |
| 2032 | |
| 2033 | let negated = self.char() == 'P'; |
| 2034 | if !self.bump_and_bump_space() { |
| 2035 | return Err(self.error( |
| 2036 | self.span(), |
| 2037 | ast::ErrorKind::EscapeUnexpectedEof, |
| 2038 | )); |
| 2039 | } |
| 2040 | let (start, kind) = |
| 2041 | if self.char() == '{' { |
| 2042 | let start = self.span_char().end; |
| 2043 | while self.bump_and_bump_space() && self.char() != '}' { |
| 2044 | scratch.push(self.char()); |
| 2045 | } |
| 2046 | if self.is_eof() { |
| 2047 | return Err(self.error( |
| 2048 | self.span(), |
| 2049 | ast::ErrorKind::EscapeUnexpectedEof, |
| 2050 | )); |
| 2051 | } |
| 2052 | assert_eq!(self.char(), '}'); |
| 2053 | self.bump(); |
| 2054 | |
| 2055 | let name = scratch.as_str(); |
| 2056 | if let Some(i) = name.find("!=") { |
| 2057 | (start, ast::ClassUnicodeKind::NamedValue { |
| 2058 | op: ast::ClassUnicodeOpKind::NotEqual, |
| 2059 | name: name[..i].to_string(), |
| 2060 | value: name[i+2..].to_string(), |
| 2061 | }) |
| 2062 | } else if let Some(i) = name.find(':') { |
| 2063 | (start, ast::ClassUnicodeKind::NamedValue { |
| 2064 | op: ast::ClassUnicodeOpKind::Colon, |
| 2065 | name: name[..i].to_string(), |
| 2066 | value: name[i+1..].to_string(), |
| 2067 | }) |
| 2068 | } else if let Some(i) = name.find('=') { |
| 2069 | (start, ast::ClassUnicodeKind::NamedValue { |
| 2070 | op: ast::ClassUnicodeOpKind::Equal, |
| 2071 | name: name[..i].to_string(), |
| 2072 | value: name[i+1..].to_string(), |
| 2073 | }) |
| 2074 | } else { |
| 2075 | (start, ast::ClassUnicodeKind::Named(name.to_string())) |
| 2076 | } |
| 2077 | } else { |
| 2078 | let start = self.pos(); |
| 2079 | let c = self.char(); |
| 2080 | self.bump_and_bump_space(); |
| 2081 | let kind = ast::ClassUnicodeKind::OneLetter(c); |
| 2082 | (start, kind) |
| 2083 | }; |
| 2084 | Ok(ast::ClassUnicode { |
no test coverage detected