Skip to main content

oni_comb_parser/text/
identifier.rs

1use crate::error::{ExpectError, Expected};
2use crate::fail::{Fail, PResult};
3use crate::input::Input;
4use crate::parser::Parser;
5use crate::str_input::StrInput;
6
7pub struct Identifier;
8
9pub fn identifier() -> Identifier {
10  Identifier
11}
12
13impl<'a> Parser<StrInput<'a>> for Identifier {
14  type Error = <StrInput<'a> as Input>::Error;
15  type Output = &'a str;
16
17  #[inline]
18  fn parse_next(&mut self, input: &mut StrInput<'a>) -> PResult<&'a str, Self::Error> {
19    let pos = input.offset();
20    let remaining = input.as_str();
21    let mut chars = remaining.chars();
22
23    match chars.next() {
24      Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
25      _ => {
26        return Err(Fail::Backtrack(Self::Error::from_expected(
27          pos,
28          Expected::Description("identifier"),
29        )));
30      }
31    }
32
33    let mut consumed = remaining.chars().next().unwrap().len_utf8();
34    for c in chars {
35      if c.is_ascii_alphanumeric() || c == '_' {
36        consumed += c.len_utf8();
37      } else {
38        break;
39      }
40    }
41
42    input.advance(consumed);
43    Ok(&remaining[..consumed])
44  }
45}