1use anyhow::anyhow;
2use std::cmp::PartialEq;
3use std::fmt::Display;
4
5pub trait Token {
6 type Tag: Display + PartialEq;
7 fn tag(&self) -> Self::Tag;
8 fn lexeme(&self) -> &str;
9}
10
11pub trait Lexer {
12 type Token: Token;
13 fn next_token(&mut self) -> anyhow::Result<Self::Token>;
14}
15
16pub struct ParserState<L: Lexer> {
17 lexer: L,
18 pub current: L::Token,
19}
20
21impl<L: Lexer> ParserState<L> {
22 pub fn new(mut lexer: L) -> anyhow::Result<Self> {
23 let current = lexer.next_token()?;
24 Ok(Self { lexer, current })
25 }
26
27 pub fn advance(&mut self) -> anyhow::Result<()> {
28 self.current = self.lexer.next_token()?;
29 Ok(())
30 }
31
32 pub fn advance_keep_current(&mut self) -> anyhow::Result<L::Token> {
33 let kept = std::mem::replace(&mut self.current, self.lexer.next_token()?);
34 Ok(kept)
35 }
36
37 pub fn matches(&mut self, expected_tag: <L::Token as Token>::Tag) -> anyhow::Result<bool> {
38 let is_match = self.current.tag() == expected_tag;
39 if is_match {
40 self.advance()?;
41 }
42 Ok(is_match)
43 }
44
45 pub fn expect(&mut self, expected_tag: <L::Token as Token>::Tag) -> anyhow::Result<()> {
46 if self.current.tag() == expected_tag {
47 self.advance()?;
48 Ok(())
49 } else {
50 Err(anyhow!(
51 "expected `{}` but got `{}`",
52 expected_tag,
53 self.current.lexeme()
54 ))
55 }
56 }
57
58 pub fn expect_lexeme(&mut self, tag: <L::Token as Token>::Tag) -> anyhow::Result<String> {
59 if self.current.tag() == tag {
60 let token = self.advance_keep_current()?;
61 Ok(token.lexeme().to_string())
62 } else {
63 Err(anyhow!(
64 "expected `{}` but found `{}`",
65 tag,
66 self.current.lexeme()
67 ))
68 }
69 }
70}