wdl_grammar/
tree.rs

1//! Module for the concrete syntax tree (CST) representation.
2
3pub mod dive;
4
5use std::borrow::Cow;
6use std::collections::VecDeque;
7use std::fmt;
8use std::iter;
9
10use rowan::GreenNodeBuilder;
11use rowan::GreenNodeData;
12use strum::VariantArray;
13
14use super::Diagnostic;
15use super::grammar;
16use super::lexer::Lexer;
17use super::parser::Event;
18use crate::parser::Parser;
19
20/// Represents the kind of syntax element (node or token) in a WDL concrete
21/// syntax tree (CST).
22///
23/// Nodes have at least one token child and represent a syntactic construct.
24///
25/// Tokens are terminal and represent any span of the source.
26///
27/// This enumeration is a union of all supported WDL tokens and nodes.
28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, VariantArray)]
29#[repr(u16)]
30pub enum SyntaxKind {
31    /// The token is unknown to WDL.
32    Unknown,
33    /// The token represents unparsed source.
34    ///
35    /// Unparsed source occurs in WDL source files with unsupported versions.
36    Unparsed,
37    /// A whitespace token.
38    Whitespace,
39    /// A comment token.
40    Comment,
41    /// A WDL version token.
42    Version,
43    /// A literal float token.
44    Float,
45    /// A literal integer token.
46    Integer,
47    /// An identifier token.
48    Ident,
49    /// A single quote token.
50    SingleQuote,
51    /// A double quote token.
52    DoubleQuote,
53    /// An open heredoc token.
54    OpenHeredoc,
55    /// A close heredoc token.
56    CloseHeredoc,
57    /// The `Array` type keyword token.
58    ArrayTypeKeyword,
59    /// The `Boolean` type keyword token.
60    BooleanTypeKeyword,
61    /// The `File` type keyword token.
62    FileTypeKeyword,
63    /// The `Float` type keyword token.
64    FloatTypeKeyword,
65    /// The `Int` type keyword token.
66    IntTypeKeyword,
67    /// The `Map` type keyword token.
68    MapTypeKeyword,
69    /// The `Object` type keyword token.
70    ObjectTypeKeyword,
71    /// The `Pair` type keyword token.
72    PairTypeKeyword,
73    /// The `String` type keyword token.
74    StringTypeKeyword,
75    /// The `after` keyword token.
76    AfterKeyword,
77    /// The `alias` keyword token.
78    AliasKeyword,
79    /// The `as` keyword token.
80    AsKeyword,
81    /// The `call` keyword token.
82    CallKeyword,
83    /// The `command` keyword token.
84    CommandKeyword,
85    /// The `else` keyword token.
86    ElseKeyword,
87    /// The `env` keyword token.
88    EnvKeyword,
89    /// The `false` keyword token.
90    FalseKeyword,
91    /// The `if` keyword token.
92    IfKeyword,
93    /// The `in` keyword token.
94    InKeyword,
95    /// The `import` keyword token.
96    ImportKeyword,
97    /// The `input` keyword token.
98    InputKeyword,
99    /// The `meta` keyword token.
100    MetaKeyword,
101    /// The `None` keyword.
102    NoneKeyword,
103    /// The `null` keyword token.
104    NullKeyword,
105    /// The `object` keyword token.
106    ObjectKeyword,
107    /// The `output` keyword token.
108    OutputKeyword,
109    /// The `parameter_meta` keyword token.
110    ParameterMetaKeyword,
111    /// The `runtime` keyword token.
112    RuntimeKeyword,
113    /// The `scatter` keyword token.
114    ScatterKeyword,
115    /// The `struct` keyword token.
116    StructKeyword,
117    /// The `task` keyword token.
118    TaskKeyword,
119    /// The `then` keyword token.
120    ThenKeyword,
121    /// The `true` keyword token.
122    TrueKeyword,
123    /// The `version` keyword token.
124    VersionKeyword,
125    /// The `workflow` keyword token.
126    WorkflowKeyword,
127    /// The 1.2 `Directory` type keyword token.
128    DirectoryTypeKeyword,
129    /// The 1.2 `hints` keyword token.
130    HintsKeyword,
131    /// The 1.2 `requirements` keyword token.
132    RequirementsKeyword,
133    /// The `{` symbol token.
134    OpenBrace,
135    /// The `}` symbol token.
136    CloseBrace,
137    /// The `[` symbol token.
138    OpenBracket,
139    /// The `]` symbol token.
140    CloseBracket,
141    /// The `=` symbol token.
142    Assignment,
143    /// The `:` symbol token.
144    Colon,
145    /// The `,` symbol token.
146    Comma,
147    /// The `(` symbol token.
148    OpenParen,
149    /// The `)` symbol token.
150    CloseParen,
151    /// The `?` symbol token.
152    QuestionMark,
153    /// The `!` symbol token.
154    Exclamation,
155    /// The `+` symbol token.
156    Plus,
157    /// The `-` symbol token.
158    Minus,
159    /// The `||` symbol token.
160    LogicalOr,
161    /// The `&&` symbol token.
162    LogicalAnd,
163    /// The `*` symbol token.
164    Asterisk,
165    /// The `**` symbol token.
166    Exponentiation,
167    /// The `/` symbol token.
168    Slash,
169    /// The `%` symbol token.
170    Percent,
171    /// The `==` symbol token.
172    Equal,
173    /// The `!=` symbol token.
174    NotEqual,
175    /// The `<=` symbol token.
176    LessEqual,
177    /// The `>=` symbol token.
178    GreaterEqual,
179    /// The `<` symbol token.
180    Less,
181    /// The `>` symbol token.
182    Greater,
183    /// The `.` symbol token.
184    Dot,
185    /// A literal text part of a string.
186    LiteralStringText,
187    /// A literal text part of a command.
188    LiteralCommandText,
189    /// A placeholder open token.
190    PlaceholderOpen,
191
192    /// Abandoned nodes are nodes that encountered errors.
193    ///
194    /// Children of abandoned nodes are re-parented to the parent of
195    /// the abandoned node.
196    ///
197    /// As this is an internal implementation of error recovery,
198    /// hide this variant from the documentation.
199    #[doc(hidden)]
200    Abandoned,
201    /// Represents the WDL document root node.
202    RootNode,
203    /// Represents a version statement node.
204    VersionStatementNode,
205    /// Represents an import statement node.
206    ImportStatementNode,
207    /// Represents an import alias node.
208    ImportAliasNode,
209    /// Represents a struct definition node.
210    StructDefinitionNode,
211    /// Represents a task definition node.
212    TaskDefinitionNode,
213    /// Represents a workflow definition node.
214    WorkflowDefinitionNode,
215    /// Represents an unbound declaration node.
216    UnboundDeclNode,
217    /// Represents a bound declaration node.
218    BoundDeclNode,
219    /// Represents an input section node.
220    InputSectionNode,
221    /// Represents an output section node.
222    OutputSectionNode,
223    /// Represents a command section node.
224    CommandSectionNode,
225    /// Represents a requirements section node.
226    RequirementsSectionNode,
227    /// Represents a requirements item node.
228    RequirementsItemNode,
229    /// Represents a hints section node in a task.
230    TaskHintsSectionNode,
231    /// Represents a hints section node in a workflow.
232    WorkflowHintsSectionNode,
233    /// Represents a hints item node in a task.
234    TaskHintsItemNode,
235    /// Represents a hints item node in a workflow.
236    WorkflowHintsItemNode,
237    /// Represents a literal object in a workflow hints item value.
238    WorkflowHintsObjectNode,
239    /// Represents an item in a workflow hints object.
240    WorkflowHintsObjectItemNode,
241    /// Represents a literal array in a workflow hints item value.
242    WorkflowHintsArrayNode,
243    /// Represents a runtime section node.
244    RuntimeSectionNode,
245    /// Represents a runtime item node.
246    RuntimeItemNode,
247    /// Represents a primitive type node.
248    PrimitiveTypeNode,
249    /// Represents a map type node.
250    MapTypeNode,
251    /// Represents an array type node.
252    ArrayTypeNode,
253    /// Represents a pair type node.
254    PairTypeNode,
255    /// Represents an object type node.
256    ObjectTypeNode,
257    /// Represents a type reference node.
258    TypeRefNode,
259    /// Represents a metadata section node.
260    MetadataSectionNode,
261    /// Represents a parameter metadata section node.
262    ParameterMetadataSectionNode,
263    /// Represents a metadata object item node.
264    MetadataObjectItemNode,
265    /// Represents a metadata object node.
266    MetadataObjectNode,
267    /// Represents a metadata array node.
268    MetadataArrayNode,
269    /// Represents a literal integer node.
270    LiteralIntegerNode,
271    /// Represents a literal float node.
272    LiteralFloatNode,
273    /// Represents a literal boolean node.
274    LiteralBooleanNode,
275    /// Represents a literal `None` node.
276    LiteralNoneNode,
277    /// Represents a literal null node.
278    LiteralNullNode,
279    /// Represents a literal string node.
280    LiteralStringNode,
281    /// Represents a literal pair node.
282    LiteralPairNode,
283    /// Represents a literal array node.
284    LiteralArrayNode,
285    /// Represents a literal map node.
286    LiteralMapNode,
287    /// Represents a literal map item node.
288    LiteralMapItemNode,
289    /// Represents a literal object node.
290    LiteralObjectNode,
291    /// Represents a literal object item node.
292    LiteralObjectItemNode,
293    /// Represents a literal struct node.
294    LiteralStructNode,
295    /// Represents a literal struct item node.
296    LiteralStructItemNode,
297    /// Represents a literal hints node.
298    LiteralHintsNode,
299    /// Represents a literal hints item node.
300    LiteralHintsItemNode,
301    /// Represents a literal input node.
302    LiteralInputNode,
303    /// Represents a literal input item node.
304    LiteralInputItemNode,
305    /// Represents a literal output node.
306    LiteralOutputNode,
307    /// Represents a literal output item node.
308    LiteralOutputItemNode,
309    /// Represents a parenthesized expression node.
310    ParenthesizedExprNode,
311    /// Represents a name reference expression node.
312    NameRefExprNode,
313    /// Represents an `if` expression node.
314    IfExprNode,
315    /// Represents a logical not expression node.
316    LogicalNotExprNode,
317    /// Represents a negation expression node.
318    NegationExprNode,
319    /// Represents a logical `OR` expression node.
320    LogicalOrExprNode,
321    /// Represents a logical `AND` expression node.
322    LogicalAndExprNode,
323    /// Represents an equality expression node.
324    EqualityExprNode,
325    /// Represents an inequality expression node.
326    InequalityExprNode,
327    /// Represents a "less than" expression node.
328    LessExprNode,
329    /// Represents a "less than or equal to" expression node.
330    LessEqualExprNode,
331    /// Represents a "greater than" expression node.
332    GreaterExprNode,
333    /// Represents a "greater than or equal to" expression node.
334    GreaterEqualExprNode,
335    /// Represents an addition expression node.
336    AdditionExprNode,
337    /// Represents a subtraction expression node.
338    SubtractionExprNode,
339    /// Represents a multiplication expression node.
340    MultiplicationExprNode,
341    /// Represents a division expression node.
342    DivisionExprNode,
343    /// Represents a modulo expression node.
344    ModuloExprNode,
345    /// Represents a exponentiation expr node.
346    ExponentiationExprNode,
347    /// Represents a call expression node.'
348    CallExprNode,
349    /// Represents an index expression node.
350    IndexExprNode,
351    /// Represents an an access expression node.
352    AccessExprNode,
353    /// Represents a placeholder node in a string literal.
354    PlaceholderNode,
355    /// Placeholder `sep` option node.
356    PlaceholderSepOptionNode,
357    /// Placeholder `default` option node.
358    PlaceholderDefaultOptionNode,
359    /// Placeholder `true`/`false` option node.
360    PlaceholderTrueFalseOptionNode,
361    /// Represents a conditional statement node.
362    ConditionalStatementNode,
363    /// Represents a scatter statement node.
364    ScatterStatementNode,
365    /// Represents a call statement node.
366    CallStatementNode,
367    /// Represents a call target node in a call statement.
368    CallTargetNode,
369    /// Represents a call alias node in a call statement.
370    CallAliasNode,
371    /// Represents an `after` clause node in a call statement.
372    CallAfterNode,
373    /// Represents a call input item node.
374    CallInputItemNode,
375
376    // WARNING: this must always be the last variant.
377    /// The exclusive maximum syntax kind value.
378    MAX,
379}
380
381impl SyntaxKind {
382    /// Returns whether the token is a symbolic [`SyntaxKind`].
383    ///
384    /// Generally speaking, symbolic [`SyntaxKind`]s have special meanings
385    /// during parsing—they are not real elements of the grammar but rather an
386    /// implementation detail.
387    pub fn is_symbolic(&self) -> bool {
388        matches!(
389            self,
390            Self::Abandoned | Self::Unknown | Self::Unparsed | Self::MAX
391        )
392    }
393
394    /// Describes the syntax kind.
395    pub fn describe(&self) -> &'static str {
396        match self {
397            Self::Unknown => unreachable!(),
398            Self::Unparsed => unreachable!(),
399            Self::Whitespace => "whitespace",
400            Self::Comment => "comment",
401            Self::Version => "version",
402            Self::Float => "float",
403            Self::Integer => "integer",
404            Self::Ident => "identifier",
405            Self::SingleQuote => "single quote",
406            Self::DoubleQuote => "double quote",
407            Self::OpenHeredoc => "open heredoc",
408            Self::CloseHeredoc => "close heredoc",
409            Self::ArrayTypeKeyword => "`Array` type keyword",
410            Self::BooleanTypeKeyword => "`Boolean` type keyword",
411            Self::FileTypeKeyword => "`File` type keyword",
412            Self::FloatTypeKeyword => "`Float` type keyword",
413            Self::IntTypeKeyword => "`Int` type keyword",
414            Self::MapTypeKeyword => "`Map` type keyword",
415            Self::ObjectTypeKeyword => "`Object` type keyword",
416            Self::PairTypeKeyword => "`Pair` type keyword",
417            Self::StringTypeKeyword => "`String` type keyword",
418            Self::AfterKeyword => "`after` keyword",
419            Self::AliasKeyword => "`alias` keyword",
420            Self::AsKeyword => "`as` keyword",
421            Self::CallKeyword => "`call` keyword",
422            Self::CommandKeyword => "`command` keyword",
423            Self::ElseKeyword => "`else` keyword",
424            Self::EnvKeyword => "`env` keyword",
425            Self::FalseKeyword => "`false` keyword",
426            Self::IfKeyword => "`if` keyword",
427            Self::InKeyword => "`in` keyword",
428            Self::ImportKeyword => "`import` keyword",
429            Self::InputKeyword => "`input` keyword",
430            Self::MetaKeyword => "`meta` keyword",
431            Self::NoneKeyword => "`None` keyword",
432            Self::NullKeyword => "`null` keyword",
433            Self::ObjectKeyword => "`object` keyword",
434            Self::OutputKeyword => "`output` keyword",
435            Self::ParameterMetaKeyword => "`parameter_meta` keyword",
436            Self::RuntimeKeyword => "`runtime` keyword",
437            Self::ScatterKeyword => "`scatter` keyword",
438            Self::StructKeyword => "`struct` keyword",
439            Self::TaskKeyword => "`task` keyword",
440            Self::ThenKeyword => "`then` keyword",
441            Self::TrueKeyword => "`true` keyword",
442            Self::VersionKeyword => "`version` keyword",
443            Self::WorkflowKeyword => "`workflow` keyword",
444            Self::DirectoryTypeKeyword => "`Directory` type keyword",
445            Self::HintsKeyword => "`hints` keyword",
446            Self::RequirementsKeyword => "`requirements` keyword",
447            Self::OpenBrace => "`{` symbol",
448            Self::CloseBrace => "`}` symbol",
449            Self::OpenBracket => "`[` symbol",
450            Self::CloseBracket => "`]` symbol",
451            Self::Assignment => "`=` symbol",
452            Self::Colon => "`:` symbol",
453            Self::Comma => "`,` symbol",
454            Self::OpenParen => "`(` symbol",
455            Self::CloseParen => "`)` symbol",
456            Self::QuestionMark => "`?` symbol",
457            Self::Exclamation => "`!` symbol",
458            Self::Plus => "`+` symbol",
459            Self::Minus => "`-` symbol",
460            Self::LogicalOr => "`||` symbol",
461            Self::LogicalAnd => "`&&` symbol",
462            Self::Asterisk => "`*` symbol",
463            Self::Exponentiation => "`**` symbol",
464            Self::Slash => "`/` symbol",
465            Self::Percent => "`%` symbol",
466            Self::Equal => "`==` symbol",
467            Self::NotEqual => "`!=` symbol",
468            Self::LessEqual => "`<=` symbol",
469            Self::GreaterEqual => "`>=` symbol",
470            Self::Less => "`<` symbol",
471            Self::Greater => "`>` symbol",
472            Self::Dot => "`.` symbol",
473            Self::LiteralStringText => "literal string text",
474            Self::LiteralCommandText => "literal command text",
475            Self::PlaceholderOpen => "placeholder open",
476            Self::Abandoned => unreachable!(),
477            Self::RootNode => "root node",
478            Self::VersionStatementNode => "version statement",
479            Self::ImportStatementNode => "import statement",
480            Self::ImportAliasNode => "import alias",
481            Self::StructDefinitionNode => "struct definition",
482            Self::TaskDefinitionNode => "task definition",
483            Self::WorkflowDefinitionNode => "workflow definition",
484            Self::UnboundDeclNode => "declaration without assignment",
485            Self::BoundDeclNode => "declaration with assignment",
486            Self::InputSectionNode => "input section",
487            Self::OutputSectionNode => "output section",
488            Self::CommandSectionNode => "command section",
489            Self::RequirementsSectionNode => "requirements section",
490            Self::RequirementsItemNode => "requirements item",
491            Self::TaskHintsSectionNode | Self::WorkflowHintsSectionNode => "hints section",
492            Self::TaskHintsItemNode | Self::WorkflowHintsItemNode => "hints item",
493            Self::WorkflowHintsObjectNode => "literal object",
494            Self::WorkflowHintsObjectItemNode => "literal object item",
495            Self::WorkflowHintsArrayNode => "literal array",
496            Self::RuntimeSectionNode => "runtime section",
497            Self::RuntimeItemNode => "runtime item",
498            Self::PrimitiveTypeNode => "primitive type",
499            Self::MapTypeNode => "map type",
500            Self::ArrayTypeNode => "array type",
501            Self::PairTypeNode => "pair type",
502            Self::ObjectTypeNode => "object type",
503            Self::TypeRefNode => "type reference",
504            Self::MetadataSectionNode => "metadata section",
505            Self::ParameterMetadataSectionNode => "parameter metadata section",
506            Self::MetadataObjectItemNode => "metadata object item",
507            Self::MetadataObjectNode => "metadata object",
508            Self::MetadataArrayNode => "metadata array",
509            Self::LiteralIntegerNode => "literal integer",
510            Self::LiteralFloatNode => "literal float",
511            Self::LiteralBooleanNode => "literal boolean",
512            Self::LiteralNoneNode => "literal `None`",
513            Self::LiteralNullNode => "literal null",
514            Self::LiteralStringNode => "literal string",
515            Self::LiteralPairNode => "literal pair",
516            Self::LiteralArrayNode => "literal array",
517            Self::LiteralMapNode => "literal map",
518            Self::LiteralMapItemNode => "literal map item",
519            Self::LiteralObjectNode => "literal object",
520            Self::LiteralObjectItemNode => "literal object item",
521            Self::LiteralStructNode => "literal struct",
522            Self::LiteralStructItemNode => "literal struct item",
523            Self::LiteralHintsNode => "literal hints",
524            Self::LiteralHintsItemNode => "literal hints item",
525            Self::LiteralInputNode => "literal input",
526            Self::LiteralInputItemNode => "literal input item",
527            Self::LiteralOutputNode => "literal output",
528            Self::LiteralOutputItemNode => "literal output item",
529            Self::ParenthesizedExprNode => "parenthesized expression",
530            Self::NameRefExprNode => "name reference expression",
531            Self::IfExprNode => "`if` expression",
532            Self::LogicalNotExprNode => "logical not expression",
533            Self::NegationExprNode => "negation expression",
534            Self::LogicalOrExprNode => "logical OR expression",
535            Self::LogicalAndExprNode => "logical AND expression",
536            Self::EqualityExprNode => "equality expression",
537            Self::InequalityExprNode => "inequality expression",
538            Self::LessExprNode => "less than expression",
539            Self::LessEqualExprNode => "less than or equal to expression",
540            Self::GreaterExprNode => "greater than expression",
541            Self::GreaterEqualExprNode => "greater than or equal to expression",
542            Self::AdditionExprNode => "addition expression",
543            Self::SubtractionExprNode => "subtraction expression",
544            Self::MultiplicationExprNode => "multiplication expression",
545            Self::DivisionExprNode => "division expression",
546            Self::ModuloExprNode => "modulo expression",
547            Self::ExponentiationExprNode => "exponentiation expression",
548            Self::CallExprNode => "call expression",
549            Self::IndexExprNode => "index expression",
550            Self::AccessExprNode => "access expression",
551            Self::PlaceholderNode => "placeholder",
552            Self::PlaceholderSepOptionNode => "placeholder `sep` option",
553            Self::PlaceholderDefaultOptionNode => "placeholder `default` option",
554            Self::PlaceholderTrueFalseOptionNode => "placeholder `true`/`false` option",
555            Self::ConditionalStatementNode => "conditional statement",
556            Self::ScatterStatementNode => "scatter statement",
557            Self::CallStatementNode => "call statement",
558            Self::CallTargetNode => "call target",
559            Self::CallAliasNode => "call alias",
560            Self::CallAfterNode => "call `after` clause",
561            Self::CallInputItemNode => "call input item",
562            Self::MAX => unreachable!(),
563        }
564    }
565
566    /// Returns whether the [`SyntaxKind`] is trivia.
567    pub fn is_trivia(&self) -> bool {
568        matches!(self, Self::Whitespace | Self::Comment)
569    }
570
571    /// Returns whether the [`SyntaxKind`] is a keyword.
572    pub fn is_keyword(&self) -> bool {
573        matches!(
574            self,
575            SyntaxKind::AfterKeyword
576                | SyntaxKind::AliasKeyword
577                | SyntaxKind::ArrayTypeKeyword
578                | SyntaxKind::AsKeyword
579                | SyntaxKind::BooleanTypeKeyword
580                | SyntaxKind::CallKeyword
581                | SyntaxKind::CommandKeyword
582                | SyntaxKind::DirectoryTypeKeyword
583                | SyntaxKind::ElseKeyword
584                | SyntaxKind::EnvKeyword
585                | SyntaxKind::FalseKeyword
586                | SyntaxKind::FileTypeKeyword
587                | SyntaxKind::FloatTypeKeyword
588                | SyntaxKind::HintsKeyword
589                | SyntaxKind::IfKeyword
590                | SyntaxKind::ImportKeyword
591                | SyntaxKind::InKeyword
592                | SyntaxKind::InputKeyword
593                | SyntaxKind::IntTypeKeyword
594                | SyntaxKind::MapTypeKeyword
595                | SyntaxKind::MetaKeyword
596                | SyntaxKind::NoneKeyword
597                | SyntaxKind::NullKeyword
598                | SyntaxKind::ObjectKeyword
599                | SyntaxKind::ObjectTypeKeyword
600                | SyntaxKind::OutputKeyword
601                | SyntaxKind::PairTypeKeyword
602                | SyntaxKind::ParameterMetaKeyword
603                | SyntaxKind::RequirementsKeyword
604                | SyntaxKind::RuntimeKeyword
605                | SyntaxKind::ScatterKeyword
606                | SyntaxKind::StringTypeKeyword
607                | SyntaxKind::StructKeyword
608                | SyntaxKind::TaskKeyword
609                | SyntaxKind::ThenKeyword
610                | SyntaxKind::TrueKeyword
611                | SyntaxKind::VersionKeyword
612                | SyntaxKind::WorkflowKeyword
613        )
614    }
615
616    /// Returns whether the [`SyntaxKind`] is an operator.
617    pub fn is_operator(&self) -> bool {
618        matches!(
619            self,
620            SyntaxKind::Plus
621                | SyntaxKind::Minus
622                | SyntaxKind::Slash
623                | SyntaxKind::Percent
624                | SyntaxKind::Asterisk
625                | SyntaxKind::Exponentiation
626                | SyntaxKind::Equal
627                | SyntaxKind::NotEqual
628                | SyntaxKind::Less
629                | SyntaxKind::LessEqual
630                | SyntaxKind::Greater
631                | SyntaxKind::GreaterEqual
632                | SyntaxKind::LogicalAnd
633                | SyntaxKind::LogicalOr
634                | SyntaxKind::Exclamation
635                | SyntaxKind::Assignment
636                | SyntaxKind::QuestionMark
637                | SyntaxKind::Dot
638                | SyntaxKind::Colon
639        )
640    }
641}
642
643/// Every [`SyntaxKind`] variant.
644pub static ALL_SYNTAX_KIND: &[SyntaxKind] = SyntaxKind::VARIANTS;
645
646impl From<SyntaxKind> for rowan::SyntaxKind {
647    fn from(kind: SyntaxKind) -> Self {
648        rowan::SyntaxKind(kind as u16)
649    }
650}
651
652/// Represents the Workflow Definition Language (WDL).
653#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
654pub struct WorkflowDescriptionLanguage;
655
656impl rowan::Language for WorkflowDescriptionLanguage {
657    type Kind = SyntaxKind;
658
659    fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
660        assert!(raw.0 <= SyntaxKind::MAX as u16);
661        unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
662    }
663
664    fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
665        kind.into()
666    }
667}
668
669/// Represents a node in the concrete syntax tree.
670pub type SyntaxNode = rowan::SyntaxNode<WorkflowDescriptionLanguage>;
671/// Represents a token in the concrete syntax tree.
672pub type SyntaxToken = rowan::SyntaxToken<WorkflowDescriptionLanguage>;
673/// Represents an element (node or token) in the concrete syntax tree.
674pub type SyntaxElement = rowan::SyntaxElement<WorkflowDescriptionLanguage>;
675/// Represents node children in the concrete syntax tree.
676pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<WorkflowDescriptionLanguage>;
677
678/// Constructs a concrete syntax tree from a list of parser events.
679pub fn construct_tree(source: &str, mut events: Vec<Event>) -> SyntaxNode {
680    let mut builder = GreenNodeBuilder::default();
681    let mut ancestors = Vec::new();
682
683    for i in 0..events.len() {
684        match std::mem::replace(&mut events[i], Event::abandoned()) {
685            Event::NodeStarted {
686                kind,
687                forward_parent,
688            } => {
689                // Walk the forward parent chain, if there is one, and push
690                // each forward parent to the ancestors list
691                ancestors.push(kind);
692                let mut idx = i;
693                let mut fp: Option<usize> = forward_parent;
694                while let Some(distance) = fp {
695                    idx += distance;
696                    fp = match std::mem::replace(&mut events[idx], Event::abandoned()) {
697                        Event::NodeStarted {
698                            kind,
699                            forward_parent,
700                        } => {
701                            ancestors.push(kind);
702                            forward_parent
703                        }
704                        _ => unreachable!(),
705                    };
706                }
707
708                // As the current node was pushed first and then its ancestors, walk
709                // the list in reverse to start the "oldest" ancestor first
710                for kind in ancestors.drain(..).rev() {
711                    if kind != SyntaxKind::Abandoned {
712                        builder.start_node(kind.into());
713                    }
714                }
715            }
716            Event::NodeFinished => builder.finish_node(),
717            Event::Token { kind, span } => {
718                builder.token(kind.into(), &source[span.start()..span.end()])
719            }
720        }
721    }
722
723    SyntaxNode::new_root(builder.finish())
724}
725
726/// Represents an untyped concrete syntax tree.
727#[derive(Clone, PartialEq, Eq, Hash)]
728pub struct SyntaxTree(SyntaxNode);
729
730impl SyntaxTree {
731    /// Parses WDL source to produce a syntax tree.
732    ///
733    /// A syntax tree is always returned, even for invalid WDL documents.
734    ///
735    /// Additionally, the list of diagnostics encountered during the parse is
736    /// returned; if the list is empty, the tree is syntactically correct.
737    ///
738    /// However, additional validation is required to ensure the source is
739    /// a valid WDL document.
740    ///
741    /// # Example
742    ///
743    /// ```rust
744    /// # use wdl_grammar::SyntaxTree;
745    /// let (tree, diagnostics) = SyntaxTree::parse("version 1.1");
746    /// assert!(diagnostics.is_empty());
747    /// println!("{tree:#?}");
748    /// ```
749    pub fn parse(source: &str) -> (Self, Vec<Diagnostic>) {
750        let parser = Parser::new(Lexer::new(source));
751        let (events, mut diagnostics) = grammar::document(parser);
752        diagnostics.sort();
753        (Self(construct_tree(source, events)), diagnostics)
754    }
755
756    /// Gets the root syntax node of the tree.
757    pub fn root(&self) -> &SyntaxNode {
758        &self.0
759    }
760
761    /// Gets a copy of the underlying root green node for the tree.
762    pub fn green(&self) -> Cow<'_, GreenNodeData> {
763        self.0.green()
764    }
765
766    /// Converts the tree into a syntax node.
767    pub fn into_syntax(self) -> SyntaxNode {
768        self.0
769    }
770}
771
772impl fmt::Display for SyntaxTree {
773    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
774        self.0.fmt(f)
775    }
776}
777
778impl fmt::Debug for SyntaxTree {
779    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
780        self.0.fmt(f)
781    }
782}
783
784/// An extension trait for [`SyntaxToken`]s.
785pub trait SyntaxTokenExt {
786    /// Gets all of the substantial preceding trivia for an element.
787    fn preceding_trivia(&self) -> impl Iterator<Item = SyntaxToken>;
788
789    /// Get any inline comment directly following an element on the
790    /// same line.
791    fn inline_comment(&self) -> Option<SyntaxToken>;
792}
793
794impl SyntaxTokenExt for SyntaxToken {
795    fn preceding_trivia(&self) -> impl Iterator<Item = SyntaxToken> {
796        let mut tokens = VecDeque::new();
797        let mut cur = self.prev_token();
798        while let Some(token) = cur {
799            cur = token.prev_token();
800            // Stop at first non-trivia
801            if !token.kind().is_trivia() {
802                break;
803            }
804            // Stop if a comment is not on its own line
805            if token.kind() == SyntaxKind::Comment
806                && let Some(prev) = token.prev_token()
807            {
808                if prev.kind() == SyntaxKind::Whitespace {
809                    let has_newlines = prev.text().chars().any(|c| c == '\n');
810                    // If there are newlines in 'prev' then we know
811                    // that the comment is on its own line.
812                    // The comment may still be on its own line if
813                    // 'prev' does not have newlines and nothing comes
814                    // before 'prev'.
815                    if !has_newlines && prev.prev_token().is_some() {
816                        break;
817                    }
818                } else {
819                    // There is something else on this line before the comment.
820                    break;
821                }
822            }
823            // Filter out whitespace that is not substantial
824            match token.kind() {
825                SyntaxKind::Whitespace
826                    if token.text().chars().filter(|c| *c == '\n').count() > 1 =>
827                {
828                    tokens.push_front(token);
829                }
830                SyntaxKind::Comment => {
831                    tokens.push_front(token);
832                }
833                _ => {}
834            }
835        }
836        tokens.into_iter()
837    }
838
839    fn inline_comment(&self) -> Option<SyntaxToken> {
840        let mut next = self.next_token();
841        iter::from_fn(move || {
842            let cur = next.clone()?;
843            next = cur.next_token();
844            Some(cur)
845        })
846        .take_while(|t| {
847            // Stop at non-trivia
848            if !t.kind().is_trivia() {
849                return false;
850            }
851            // Stop on first whitespace containing a newline
852            if t.kind() == SyntaxKind::Whitespace {
853                return !t.text().chars().any(|c| c == '\n');
854            }
855            true
856        })
857        .find(|t| t.kind() == SyntaxKind::Comment)
858    }
859}
860
861#[cfg(test)]
862mod tests {
863    use super::*;
864    use crate::SyntaxTree;
865
866    #[test]
867    fn preceding_comments() {
868        let (tree, diagnostics) = SyntaxTree::parse(
869            "version 1.2
870
871# This comment should not be included
872task foo {} # This comment should not be included
873
874# Some
875# comments
876# are
877# long
878    
879# Others are short
880
881#     and, yet    another
882workflow foo {} # This should not be collected.
883
884# This comment should not be included either.",
885        );
886
887        assert!(diagnostics.is_empty());
888
889        let workflow = tree.root().last_child().unwrap();
890        assert_eq!(workflow.kind(), SyntaxKind::WorkflowDefinitionNode);
891        let token = workflow.first_token().unwrap();
892        let mut trivia = token.preceding_trivia();
893        assert_eq!(trivia.next().unwrap().text(), "\n\n");
894        assert_eq!(trivia.next().unwrap().text(), "# Some");
895        assert_eq!(trivia.next().unwrap().text(), "# comments");
896        assert_eq!(trivia.next().unwrap().text(), "# are");
897        assert_eq!(trivia.next().unwrap().text(), "# long");
898        assert_eq!(trivia.next().unwrap().text(), "\n    \n");
899        assert_eq!(trivia.next().unwrap().text(), "# Others are short");
900        assert_eq!(trivia.next().unwrap().text(), "\n\n");
901        assert_eq!(trivia.next().unwrap().text(), "#     and, yet    another");
902        assert!(trivia.next().is_none());
903    }
904
905    #[test]
906    fn inline_comment() {
907        let (tree, diagnostics) = SyntaxTree::parse(
908            "version 1.2
909
910# This comment should not be included
911task foo {}
912
913# This should not be collected.
914workflow foo {} # Here is a comment that should be collected.
915
916# This comment should not be included either.",
917        );
918
919        assert!(diagnostics.is_empty());
920
921        let workflow = tree.root().last_child().unwrap();
922        assert_eq!(workflow.kind(), SyntaxKind::WorkflowDefinitionNode);
923        let comment = workflow.last_token().unwrap().inline_comment().unwrap();
924        assert_eq!(
925            comment.text(),
926            "# Here is a comment that should be collected."
927        );
928    }
929}