regen/sdk/ast_parser.rs
1use super::{Error, TokenStream, TokenType};
2
3/// ASTParser provides methods for parsing the language from token stream to:
4/// 1. List of tokens
5/// 2. Abstract Syntax Tree (AST) (either one or until the token stream is exhausted)
6///
7/// The generated language SDK will include implementation of this trait
8pub trait ASTParser {
9 /// Token type
10 ///
11 /// This type is generated in the environment. See [`crate::grammar::Tok`]
12 type T: TokenType;
13 /// AST root type
14 ///
15 /// This type is generated in the environment. See [`crate::grammar::ast::TopLevelStatement`].
16 /// Note that the first rule in the grammar file becomes the root.
17 type A;
18
19 /// Parse one AST root from the [`TokenStream`]
20 ///
21 /// Returns `None` when there's syntax error
22 fn parse_ast(&self, ts: &mut TokenStream<Self::T>) -> Option<Self::A>;
23
24 /// Create all ASTs from the source code, until the token stream is exhausted
25 ///
26 /// This method is useful for parsing multiple roots in a single source code,
27 /// for example, many statements where each statement is the target.
28 ///
29 /// On success, it returns a vector of ASTs. If there's any error, it returns an `Err` variant
30 /// with the ASTs that have been succesfully parsed, along with the errors.
31 fn parse_ast_all(&self, ts: &mut TokenStream<Self::T>) -> ASTResult<Self::A> {
32 let mut last_failed = false;
33 let mut asts = vec![];
34 let mut errors = vec![];
35
36 loop {
37 match self.parse_ast(ts) {
38 Some(ast) => {
39 last_failed = false;
40 asts.push(ast);
41 if ts.is_exhausted() {
42 break;
43 }
44 }
45 None => {
46 if let Some(token) = ts.consume() {
47 if !last_failed {
48 last_failed = true;
49 if let Some(err_token) = ts.get_guess_err_token() {
50 errors.push(Error::from_token_without_help(
51 err_token,
52 "Syntax error near this location".to_owned(),
53 ));
54 } else {
55 errors.push(Error::from_token_without_help(
56 token,
57 "Syntax error".to_owned(),
58 ));
59 }
60 }
61 } else {
62 break;
63 }
64 }
65 }
66 }
67 if errors.is_empty() {
68 Ok(asts)
69 } else {
70 Err((asts, errors))
71 }
72 }
73}
74
75pub type ASTResult<A> = Result<Vec<A>, (Vec<A>, Vec<Error>)>;