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