练习:使用 Result 进行重写

以下代码实现了一个非常简单的表达式语言解析器。不过,它通过 panic 机制来处理错误。请重写该代码,改用惯用的错误处理方式,并将错误传播到 main 函数的返回值。您可以随意使用 thiserror 和 anyhow。

提示:请先修复 parse 函数中的错误处理问题。该部分正常运行后,请更新 Tokenizer 以实现 Iterator<Item=Result<Token, TokenizerError>>,并在解析器中进行相应处理。

1. use std::iter::Peekable;
2. use std::str::Chars;

4. /// An arithmetic operator.
5. #[derive(Debug, PartialEq, Clone, Copy)]
6. enum Op {
7. Add,
8. Sub,
9. }

11. /// A token in the expression language.
12. #[derive(Debug, PartialEq)]
13. enum Token {
14. Number(String),
15. Identifier(String),
16. Operator(Op),
17. }

19. /// An expression in the expression language.
20. #[derive(Debug, PartialEq)]
21. enum Expression {
22. /// A reference to a variable.
23. Var(String),
24. /// A literal number.
25. Number(u32),
26. /// A binary operation.
27. Operation(Box<Expression>, Op, Box<Expression>),
28. }

30. fn tokenize(input: &str) -> Tokenizer {
31. return Tokenizer(input.chars().peekable());
32. }

34. struct Tokenizer<'a>(Peekable<Chars<'a>>);

36. impl<'a> Iterator for Tokenizer<'a> {
37. type Item = Token;

39. fn next(&mut self) -> Option<Token> {
40. let c = self.0.next()?;
41. match c {
42. '0'..='9' => {
43. let mut num = String::from(c);
44. while let Some(c @ '0'..='9') = self.0.peek() {
45. num.push(*c);
46. self.0.next();
47. }
48. Some(Token::Number(num))
49. }
50. 'a'..='z' => {
51. let mut ident = String::from(c);
52. while let Some(c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
53. ident.push(*c);
54. self.0.next();
55. }
56. Some(Token::Identifier(ident))
57. }
58. '+' => Some(Token::Operator(Op::Add)),
59. '-' => Some(Token::Operator(Op::Sub)),
60. _ => panic!("Unexpected character {c}"),
61. }
62. }
63. }

65. fn parse(input: &str) -> Expression {
66. let mut tokens = tokenize(input);

68. fn parse_expr<'a>(tokens: &mut Tokenizer<'a>) -> Expression {
69. let Some(tok) = tokens.next() else {
70. panic!("Unexpected end of input");
71. };
72. let expr = match tok {
73. Token::Number(num) => {
74. let v = num.parse().expect("Invalid 32-bit integer'");
75. Expression::Number(v)
76. }
77. Token::Identifier(ident) => Expression::Var(ident),
78. Token::Operator(_) => panic!("Unexpected token {tok:?}"),
79. };
80. // Look ahead to parse a binary operation if present.
81. match tokens.next() {
82. None => expr,
83. Some(Token::Operator(op)) => Expression::Operation(
84. Box::new(expr),
85. op,
86. Box::new(parse_expr(tokens)),
87. ),
88. Some(tok) => panic!("Unexpected token {tok:?}"),
89. }
90. }

92. parse_expr(&mut tokens)
93. }

95. fn main() {
96. let expr = parse("10+foo+20-30");
97. println!("{expr:?}");
98. }