reqlang_expr/
parser.rs

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
15/// Parse source code in to an [`ast::Expr`].
16pub 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}