1. ```
use thiserror::Error;
```
2. ```
use std::iter::Peekable;
```
3. ```
use std::str::Chars;
```
5. ```
/// An arithmetic operator.
```
6. ```
#[derive(Debug, PartialEq, Clone, Copy)]
```
7. ```
enum Op {
```
8. ```
Add,
```
9. ```
Sub,
```
10. ```
}
```
12. ```
/// A token in the expression language.
```
13. ```
#[derive(Debug, PartialEq)]
```
14. ```
enum Token {
```
15. ```
Number(String),
```
16. ```
Identifier(String),
```
17. ```
Operator(Op),
```
18. ```
}
```
20. ```
/// An expression in the expression language.
```
21. ```
#[derive(Debug, PartialEq)]
```
22. ```
enum Expression {
```
23. ```
/// A reference to a variable.
```
24. ```
Var(String),
```
25. ```
/// A literal number.
```
26. ```
Number(u32),
```
27. ```
/// A binary operation.
```
28. ```
Operation(Box<Expression>, Op, Box<Expression>),
```
29. ```
}
```
31. ```
fn tokenize(input: &str) -> Tokenizer {
```
32. ```
return Tokenizer(input.chars().peekable());
```
33. ```
}
```
35. ```
#[derive(Debug, Error)]
```
36. ```
enum TokenizerError {
```
37. ```
#[error("Unexpected character '{0}' in input")]
```
38. ```
UnexpectedCharacter(char),
```
39. ```
}
```
41. ```
struct Tokenizer<'a>(Peekable<Chars<'a>>);
```
43. ```
impl<'a> Tokenizer<'a> {
```
44. ```
fn collect_number(&mut self, first_char: char) -> Token {
```
45. ```
let mut num = String::from(first_char);
```
46. ```
while let Some(&c @ '0'..='9') = self.0.peek() {
```
47. ```
num.push(c);
```
48. ```
self.0.next();
```
49. ```
}
```
50. ```
Token::Number(num)
```
51. ```
}
```
53. ```
fn collect_identifier(&mut self, first_char: char) -> Token {
```
54. ```
let mut ident = String::from(first_char);
```
55. ```
while let Some(&c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
```
56. ```
ident.push(c);
```
57. ```
self.0.next();
```
58. ```
}
```
59. ```
Token::Identifier(ident)
```
60. ```
}
```
61. ```
}
```
63. ```
impl<'a> Iterator for Tokenizer<'a> {
```
64. ```
type Item = Result<Token, TokenizerError>;
```
66. ```
fn next(&mut self) -> Option<Result<Token, TokenizerError>> {
```
67. ```
let c = self.0.next()?;
```
68. ```
match c {
```
69. ```
'0'..='9' => Some(Ok(self.collect_number(c))),
```
70. ```
'a'..='z' | '_' => Some(Ok(self.collect_identifier(c))),
```
71. ```
'+' => Some(Ok(Token::Operator(Op::Add))),
```
72. ```
'-' => Some(Ok(Token::Operator(Op::Sub))),
```
73. ```
_ => Some(Err(TokenizerError::UnexpectedCharacter(c))),
```
74. ```
}
```
75. ```
}
```
76. ```
}
```
78. ```
#[derive(Debug, Error)]
```
79. ```
enum ParserError {
```
80. ```
#[error("Tokenizer error: {0}")]
```
81. ```
TokenizerError(#[from] TokenizerError),
```
82. ```
#[error("Unexpected end of input")]
```
83. ```
UnexpectedEOF,
```
84. ```
#[error("Unexpected token {0:?}")]
```
85. ```
UnexpectedToken(Token),
```
86. ```
#[error("Invalid number")]
```
87. ```
InvalidNumber(#[from] std::num::ParseIntError),
```
88. ```
}
```
90. ```
fn parse(input: &str) -> Result<Expression, ParserError> {
```
91. ```
let mut tokens = tokenize(input);
```
93. ```
fn parse_expr<'a>(
```
94. ```
tokens: &mut Tokenizer<'a>,
```
95. ```
) -> Result<Expression, ParserError> {
```
96. ```
let tok = tokens.next().ok_or(ParserError::UnexpectedEOF)??;
```
97. ```
let expr = match tok {
```
98. ```
Token::Number(num) => {
```
99. ```
let v = num.parse()?;
```
100. ```
Expression::Number(v)
```
101. ```
}
```
102. ```
Token::Identifier(ident) => Expression::Var(ident),
```
103. ```
Token::Operator(_) => return Err(ParserError::UnexpectedToken(tok)),
```
104. ```
};
```
105. ```
// Look ahead to parse a binary operation if present.
```
106. ```
Ok(match tokens.next() {
```
107. ```
None => expr,
```
108. ```
Some(Ok(Token::Operator(op))) => Expression::Operation(
```
109. ```
Box::new(expr),
```
110. ```
op,
```
111. ```
Box::new(parse_expr(tokens)?),
```
112. ```
),
```
113. ```
Some(Err(e)) => return Err(e.into()),
```
114. ```
Some(Ok(tok)) => return Err(ParserError::UnexpectedToken(tok)),
```
115. ```
})
```
116. ```
}
```
118. ```
parse_expr(&mut tokens)
```
119. ```
}
```
121. ```
fn main() -> anyhow::Result<()> {
```
122. ```
let expr = parse("10+foo+20-30")?;
```
123. ```
println!("{expr:?}");
```
124. ```
Ok(())
```
125. ```
}
```