1use super::Diagnostic;
4use super::Span;
5use super::lexer::PreambleToken;
6use super::parser::Event;
7use super::parser::Marker;
8use super::parser::Parser;
9use super::tree::SyntaxKind;
10use crate::SupportedVersion;
11use crate::lexer::VersionStatementToken;
12
13pub mod v1;
14
15mod macros {
17 macro_rules! expected {
21 ($parser:ident, $marker:ident, $token:expr_2021) => {
22 if let Err(e) = $parser.expect($token) {
23 return Err(($marker, e));
24 }
25 };
26 ($parser:ident, $marker:ident, $token:expr_2021, $name:literal) => {
27 if let Err(e) = $parser.expect_with_name($token, $name) {
28 return Err(($marker, e));
29 }
30 };
31 }
32
33 macro_rules! expected_in {
37 ($parser:ident, $marker:ident, $set:ident $(, $names:literal)+ $(,)?) => {
38 if let Err(e) = $parser.expect_in($set, &[$($names),+]) {
39 return Err(($marker, e));
40 }
41 };
42 }
43
44 macro_rules! expected_fn {
48 ($parser:ident, $marker:ident, $func:ident) => {
49 let inner = $parser.start();
50 if let Err((inner, e)) = $func($parser, inner) {
51 inner.abandon($parser);
52 return Err(($marker, e));
53 }
54 };
55 ($parser:ident, $func:ident) => {
56 let inner = $parser.start();
57 if let Err((inner, e)) = $func($parser, inner) {
58 inner.abandon($parser);
59 return Err(e);
60 }
61 };
62 }
63
64 pub(crate) use expected;
65 pub(crate) use expected_fn;
66 pub(crate) use expected_in;
67}
68
69type PreambleParser<'a> = Parser<'a, PreambleToken>;
71
72pub fn document(source: &str, mut parser: PreambleParser<'_>) -> (Vec<Event>, Vec<Diagnostic>) {
76 let root = parser.start();
77 let (mut parser, diagnostic) = match parser.peek() {
81 Some((PreambleToken::VersionKeyword, _)) => {
82 let marker = parser.start();
83 let (mut parser, res) = version_statement(parser, marker);
84 match res {
85 Ok(span) => {
86 let version = &source[span.start()..span.end()];
89
90 match version.parse::<SupportedVersion>() {
91 Ok(_) => {
92 let mut parser = parser.morph();
93 v1::items(&mut parser);
94 root.complete(&mut parser, SyntaxKind::RootNode);
95 let output = parser.finish();
96 return (output.events, output.diagnostics);
97 }
98 _ => (
99 parser,
100 Diagnostic::error(format!("unsupported WDL version `{version}`"))
101 .with_label("this version of WDL is not supported", span),
102 ),
103 }
104 }
105 Err((marker, e)) => {
106 marker.abandon(&mut parser);
107 (parser, e)
108 }
109 }
110 }
111 found => {
112 let mut diagnostic =
113 Diagnostic::error("a WDL document must start with a version statement");
114
115 if let Some((_, span)) = found {
116 diagnostic =
117 diagnostic.with_label("a version statement must come before this", span);
118 }
119
120 (parser, diagnostic)
121 }
122 };
123
124 parser.diagnostic(diagnostic);
128 parser.consume_remainder();
129 root.complete(&mut parser, SyntaxKind::RootNode);
130 let output = parser.finish();
131 (output.events, output.diagnostics)
132}
133
134pub fn version_statement(
138 mut parser: Parser<'_, PreambleToken>,
139 marker: Marker,
140) -> (
141 Parser<'_, PreambleToken>,
142 Result<Span, (Marker, Diagnostic)>,
143) {
144 parser.require(PreambleToken::VersionKeyword);
145
146 let mut parser: Parser<'_, VersionStatementToken> = parser.morph();
147 let span = match parser.expect(VersionStatementToken::Version) {
148 Ok(span) => span,
149 Err(e) => return (parser.morph(), Err((marker, e))),
150 };
151
152 marker.complete(&mut parser, SyntaxKind::VersionStatementNode);
153 (parser.morph(), Ok(span))
154}