use super::Diagnostic;
use super::lexer::PreambleToken;
use super::parser::Event;
use super::parser::Parser;
use super::tree::SyntaxKind;
use crate::lexer::VersionStatementToken;
pub mod v1;
mod macros {
macro_rules! expected {
($parser:ident, $marker:ident, $token:expr_2021) => {
if let Err(e) = $parser.expect($token) {
return Err(($marker, e));
}
};
($parser:ident, $marker:ident, $token:expr_2021, $name:literal) => {
if let Err(e) = $parser.expect_with_name($token, $name) {
return Err(($marker, e));
}
};
}
macro_rules! expected_in {
($parser:ident, $marker:ident, $set:ident $(, $names:literal)+ $(,)?) => {
if let Err(e) = $parser.expect_in($set, &[$($names),+]) {
return Err(($marker, e));
}
};
}
macro_rules! expected_fn {
($parser:ident, $marker:ident, $func:ident) => {
let inner = $parser.start();
if let Err((inner, e)) = $func($parser, inner) {
inner.abandon($parser);
return Err(($marker, e));
}
};
($parser:ident, $func:ident) => {
let inner = $parser.start();
if let Err((inner, e)) = $func($parser, inner) {
inner.abandon($parser);
return Err(e);
}
};
}
pub(crate) use expected;
pub(crate) use expected_fn;
pub(crate) use expected_in;
}
type PreambleParser<'a> = Parser<'a, PreambleToken>;
pub fn document(mut parser: PreambleParser<'_>) -> (Vec<Event>, Vec<Diagnostic>) {
let root = parser.start();
let (mut parser, diagnostic) = match parser.peek() {
Some((PreambleToken::VersionKeyword, _)) => {
match version_statement(parser) {
(parser, None) => {
let mut parser = parser.morph();
v1::items(&mut parser);
root.complete(&mut parser, SyntaxKind::RootNode);
let output = parser.finish();
return (output.events, output.diagnostics);
}
(parser, Some(diag)) => (parser, diag),
}
}
found => {
let mut diagnostic =
Diagnostic::error("a WDL document must start with a version statement");
if let Some((_, span)) = found {
diagnostic =
diagnostic.with_label("a version statement must come before this", span);
}
(parser, diagnostic)
}
};
parser.diagnostic(diagnostic);
parser.consume_remainder();
root.complete(&mut parser, SyntaxKind::RootNode);
let output = parser.finish();
(output.events, output.diagnostics)
}
fn version_statement(
mut parser: Parser<'_, PreambleToken>,
) -> (Parser<'_, PreambleToken>, Option<Diagnostic>) {
let marker = parser.start();
parser.require(PreambleToken::VersionKeyword);
let mut parser: Parser<'_, VersionStatementToken> = parser.morph();
if let Err(e) = parser.expect(VersionStatementToken::Version) {
marker.abandon(&mut parser);
return (parser.morph(), Some(e));
}
marker.complete(&mut parser, SyntaxKind::VersionStatementNode);
(parser.morph(), None)
}