1pub mod diagnostics;
6pub mod program;
7use diagnostics::Diagnostic;
8use lalrpop_util::{lexer::Token, ParseError};
9use program::Loc;
10#[cfg(test)]
11mod test;
12
13#[allow(clippy::all)]
14mod ola {
15 include!(concat!(env!("OUT_DIR"), "/ola.rs"));
16}
17
18pub fn parse(src: &str, file_no: usize) -> Result<program::SourceUnit, Vec<Diagnostic>> {
20 let parser_errors = &mut Vec::new();
21 let errors = &mut Vec::new();
22
23 let s = ola::SourceUnitParser::new().parse(file_no, parser_errors, src);
24
25 for e in parser_errors {
26 errors.push(parser_error(&e.error, file_no));
27 }
28
29 if let Err(e) = s {
30 errors.push(parser_error(&e, file_no));
31 return Err(errors.to_vec());
32 }
33
34 if !errors.is_empty() {
35 Err(errors.to_vec())
36 } else {
37 Ok(s.unwrap())
38 }
39}
40
41fn parser_error(error: &ParseError<usize, Token, &str>, file_no: usize) -> Diagnostic {
42 match &error {
43 ParseError::InvalidToken { location } => Diagnostic::parser_error(
44 Loc::File(file_no, *location, *location),
45 "invalid token".to_string(),
46 ),
47 ParseError::UnrecognizedToken {
48 token: (l, token, r),
49 expected,
50 } => Diagnostic::parser_error(
51 Loc::File(file_no, *l, *r),
52 format!(
53 "unrecognised token '{}', expected {}",
54 token,
55 expected.join(", ")
56 ),
57 ),
58 ParseError::User { error } => {
59 Diagnostic::parser_error(Loc::File(file_no, 0, 0), error.to_string())
60 }
61 ParseError::ExtraToken { token } => Diagnostic::parser_error(
62 Loc::File(file_no, token.0, token.2),
63 format!("extra token '{}' encountered", token.0),
64 ),
65 ParseError::UnrecognizedEOF { expected, location } => Diagnostic::parser_error(
66 Loc::File(file_no, *location, *location),
67 format!("unexpected end of file, expecting {}", expected.join(", ")),
68 ),
69 }
70}