1use std::ops::Range;
2
3use lalrpop_util::lalrpop_mod;
4
5use crate::{
6 ast,
7 errors::{ExprResult, SyntaxError},
8 lexer::Lexer,
9 parser::grammar::ExprParser,
10 prelude::ExprError,
11};
12
13lalrpop_mod!(grammar);
14
15pub fn parse(source: &str) -> ExprResult<ast::Expr> {
17 let lexer: Lexer<'_> = Lexer::new(&source);
18 let tokens = lexer.collect::<Vec<_>>();
19
20 let mut errs = vec![];
21
22 let expr_parser = ExprParser::new();
23
24 let mut parser_errors = Vec::new();
25
26 let expr = match expr_parser.parse(&mut parser_errors, tokens) {
27 Ok(ast) => ast,
28 Err(err) => {
29 errs.push(err);
30 ast::Expr::Error
31 }
32 };
33
34 errs.extend(parser_errors);
35
36 let errs: Vec<(ExprError, Range<usize>)> = errs
37 .into_iter()
38 .map(|err| SyntaxError::from_parser_error(err, &source))
39 .collect();
40
41 if errs.is_empty() { Ok(expr) } else { Err(errs) }
42}