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 clause within a conditional statement.
364    ConditionalStatementClauseNode,
365    /// Represents a scatter statement node.
366    ScatterStatementNode,
367    /// Represents a call statement node.
368    CallStatementNode,
369    /// Represents a call target node in a call statement.
370    CallTargetNode,
371    /// Represents a call alias node in a call statement.
372    CallAliasNode,
373    /// Represents an `after` clause node in a call statement.
374    CallAfterNode,
375    /// Represents a call input item node.
376    CallInputItemNode,
377
378    // WARNING: this must always be the last variant.
379    /// The exclusive maximum syntax kind value.
380    MAX,
381}
382
383impl SyntaxKind {
384    /// Returns whether the token is a symbolic [`SyntaxKind`].
385    ///
386    /// Generally speaking, symbolic [`SyntaxKind`]s have special meanings
387    /// during parsing—they are not real elements of the grammar but rather an
388    /// implementation detail.
389    pub fn is_symbolic(&self) -> bool {
390        matches!(
391            self,
392            Self::Abandoned | Self::Unknown | Self::Unparsed | Self::MAX
393        )
394    }
395
396    /// Describes the syntax kind.
397    pub fn describe(&self) -> &'static str {
398        match self {
399            Self::Unknown => unreachable!(),
400            Self::Unparsed => unreachable!(),
401            Self::Whitespace => "whitespace",
402            Self::Comment => "comment",
403            Self::Version => "version",
404            Self::Float => "float",
405            Self::Integer => "integer",
406            Self::Ident => "identifier",
407            Self::SingleQuote => "single quote",
408            Self::DoubleQuote => "double quote",
409            Self::OpenHeredoc => "open heredoc",
410            Self::CloseHeredoc => "close heredoc",
411            Self::ArrayTypeKeyword => "`Array` type keyword",
412            Self::BooleanTypeKeyword => "`Boolean` type keyword",
413            Self::FileTypeKeyword => "`File` type keyword",
414            Self::FloatTypeKeyword => "`Float` type keyword",
415            Self::IntTypeKeyword => "`Int` type keyword",
416            Self::MapTypeKeyword => "`Map` type keyword",
417            Self::ObjectTypeKeyword => "`Object` type keyword",
418            Self::PairTypeKeyword => "`Pair` type keyword",
419            Self::StringTypeKeyword => "`String` type keyword",
420            Self::AfterKeyword => "`after` keyword",
421            Self::AliasKeyword => "`alias` keyword",
422            Self::AsKeyword => "`as` keyword",
423            Self::CallKeyword => "`call` keyword",
424            Self::CommandKeyword => "`command` keyword",
425            Self::ElseKeyword => "`else` keyword",
426            Self::EnvKeyword => "`env` keyword",
427            Self::FalseKeyword => "`false` keyword",
428            Self::IfKeyword => "`if` keyword",
429            Self::InKeyword => "`in` keyword",
430            Self::ImportKeyword => "`import` keyword",
431            Self::InputKeyword => "`input` keyword",
432            Self::MetaKeyword => "`meta` keyword",
433            Self::NoneKeyword => "`None` keyword",
434            Self::NullKeyword => "`null` keyword",
435            Self::ObjectKeyword => "`object` keyword",
436            Self::OutputKeyword => "`output` keyword",
437            Self::ParameterMetaKeyword => "`parameter_meta` keyword",
438            Self::RuntimeKeyword => "`runtime` keyword",
439            Self::ScatterKeyword => "`scatter` keyword",
440            Self::StructKeyword => "`struct` keyword",
441            Self::TaskKeyword => "`task` keyword",
442            Self::ThenKeyword => "`then` keyword",
443            Self::TrueKeyword => "`true` keyword",
444            Self::VersionKeyword => "`version` keyword",
445            Self::WorkflowKeyword => "`workflow` keyword",
446            Self::DirectoryTypeKeyword => "`Directory` type keyword",
447            Self::HintsKeyword => "`hints` keyword",
448            Self::RequirementsKeyword => "`requirements` keyword",
449            Self::OpenBrace => "`{` symbol",
450            Self::CloseBrace => "`}` symbol",
451            Self::OpenBracket => "`[` symbol",
452            Self::CloseBracket => "`]` symbol",
453            Self::Assignment => "`=` symbol",
454            Self::Colon => "`:` symbol",
455            Self::Comma => "`,` symbol",
456            Self::OpenParen => "`(` symbol",
457            Self::CloseParen => "`)` symbol",
458            Self::QuestionMark => "`?` symbol",
459            Self::Exclamation => "`!` symbol",
460            Self::Plus => "`+` symbol",
461            Self::Minus => "`-` symbol",
462            Self::LogicalOr => "`||` symbol",
463            Self::LogicalAnd => "`&&` symbol",
464            Self::Asterisk => "`*` symbol",
465            Self::Exponentiation => "`**` symbol",
466            Self::Slash => "`/` symbol",
467            Self::Percent => "`%` symbol",
468            Self::Equal => "`==` symbol",
469            Self::NotEqual => "`!=` symbol",
470            Self::LessEqual => "`<=` symbol",
471            Self::GreaterEqual => "`>=` symbol",
472            Self::Less => "`<` symbol",
473            Self::Greater => "`>` symbol",
474            Self::Dot => "`.` symbol",
475            Self::LiteralStringText => "literal string text",
476            Self::LiteralCommandText => "literal command text",
477            Self::PlaceholderOpen => "placeholder open",
478            Self::Abandoned => unreachable!(),
479            Self::RootNode => "root node",
480            Self::VersionStatementNode => "version statement",
481            Self::ImportStatementNode => "import statement",
482            Self::ImportAliasNode => "import alias",
483            Self::StructDefinitionNode => "struct definition",
484            Self::TaskDefinitionNode => "task definition",
485            Self::WorkflowDefinitionNode => "workflow definition",
486            Self::UnboundDeclNode => "declaration without assignment",
487            Self::BoundDeclNode => "declaration with assignment",
488            Self::InputSectionNode => "input section",
489            Self::OutputSectionNode => "output section",
490            Self::CommandSectionNode => "command section",
491            Self::RequirementsSectionNode => "requirements section",
492            Self::RequirementsItemNode => "requirements item",
493            Self::TaskHintsSectionNode | Self::WorkflowHintsSectionNode => "hints section",
494            Self::TaskHintsItemNode | Self::WorkflowHintsItemNode => "hints item",
495            Self::WorkflowHintsObjectNode => "literal object",
496            Self::WorkflowHintsObjectItemNode => "literal object item",
497            Self::WorkflowHintsArrayNode => "literal array",
498            Self::RuntimeSectionNode => "runtime section",
499            Self::RuntimeItemNode => "runtime item",
500            Self::PrimitiveTypeNode => "primitive type",
501            Self::MapTypeNode => "map type",
502            Self::ArrayTypeNode => "array type",
503            Self::PairTypeNode => "pair type",
504            Self::ObjectTypeNode => "object type",
505            Self::TypeRefNode => "type reference",
506            Self::MetadataSectionNode => "metadata section",
507            Self::ParameterMetadataSectionNode => "parameter metadata section",
508            Self::MetadataObjectItemNode => "metadata object item",
509            Self::MetadataObjectNode => "metadata object",
510            Self::MetadataArrayNode => "metadata array",
511            Self::LiteralIntegerNode => "literal integer",
512            Self::LiteralFloatNode => "literal float",
513            Self::LiteralBooleanNode => "literal boolean",
514            Self::LiteralNoneNode => "literal `None`",
515            Self::LiteralNullNode => "literal null",
516            Self::LiteralStringNode => "literal string",
517            Self::LiteralPairNode => "literal pair",
518            Self::LiteralArrayNode => "literal array",
519            Self::LiteralMapNode => "literal map",
520            Self::LiteralMapItemNode => "literal map item",
521            Self::LiteralObjectNode => "literal object",
522            Self::LiteralObjectItemNode => "literal object item",
523            Self::LiteralStructNode => "literal struct",
524            Self::LiteralStructItemNode => "literal struct item",
525            Self::LiteralHintsNode => "literal hints",
526            Self::LiteralHintsItemNode => "literal hints item",
527            Self::LiteralInputNode => "literal input",
528            Self::LiteralInputItemNode => "literal input item",
529            Self::LiteralOutputNode => "literal output",
530            Self::LiteralOutputItemNode => "literal output item",
531            Self::ParenthesizedExprNode => "parenthesized expression",
532            Self::NameRefExprNode => "name reference expression",
533            Self::IfExprNode => "`if` expression",
534            Self::LogicalNotExprNode => "logical not expression",
535            Self::NegationExprNode => "negation expression",
536            Self::LogicalOrExprNode => "logical OR expression",
537            Self::LogicalAndExprNode => "logical AND expression",
538            Self::EqualityExprNode => "equality expression",
539            Self::InequalityExprNode => "inequality expression",
540            Self::LessExprNode => "less than expression",
541            Self::LessEqualExprNode => "less than or equal to expression",
542            Self::GreaterExprNode => "greater than expression",
543            Self::GreaterEqualExprNode => "greater than or equal to expression",
544            Self::AdditionExprNode => "addition expression",
545            Self::SubtractionExprNode => "subtraction expression",
546            Self::MultiplicationExprNode => "multiplication expression",
547            Self::DivisionExprNode => "division expression",
548            Self::ModuloExprNode => "modulo expression",
549            Self::ExponentiationExprNode => "exponentiation expression",
550            Self::CallExprNode => "call expression",
551            Self::IndexExprNode => "index expression",
552            Self::AccessExprNode => "access expression",
553            Self::PlaceholderNode => "placeholder",
554            Self::PlaceholderSepOptionNode => "placeholder `sep` option",
555            Self::PlaceholderDefaultOptionNode => "placeholder `default` option",
556            Self::PlaceholderTrueFalseOptionNode => "placeholder `true`/`false` option",
557            Self::ConditionalStatementNode => "conditional statement",
558            Self::ConditionalStatementClauseNode => "conditional statement clause",
559            Self::ScatterStatementNode => "scatter statement",
560            Self::CallStatementNode => "call statement",
561            Self::CallTargetNode => "call target",
562            Self::CallAliasNode => "call alias",
563            Self::CallAfterNode => "call `after` clause",
564            Self::CallInputItemNode => "call input item",
565            Self::MAX => unreachable!(),
566        }
567    }
568
569    /// Returns whether the [`SyntaxKind`] is trivia.
570    pub fn is_trivia(&self) -> bool {
571        matches!(self, Self::Whitespace | Self::Comment)
572    }
573
574    /// Returns whether the [`SyntaxKind`] is a keyword.
575    pub fn is_keyword(&self) -> bool {
576        matches!(
577            self,
578            SyntaxKind::AfterKeyword
579                | SyntaxKind::AliasKeyword
580                | SyntaxKind::ArrayTypeKeyword
581                | SyntaxKind::AsKeyword
582                | SyntaxKind::BooleanTypeKeyword
583                | SyntaxKind::CallKeyword
584                | SyntaxKind::CommandKeyword
585                | SyntaxKind::DirectoryTypeKeyword
586                | SyntaxKind::ElseKeyword
587                | SyntaxKind::EnvKeyword
588                | SyntaxKind::FalseKeyword
589                | SyntaxKind::FileTypeKeyword
590                | SyntaxKind::FloatTypeKeyword
591                | SyntaxKind::HintsKeyword
592                | SyntaxKind::IfKeyword
593                | SyntaxKind::ImportKeyword
594                | SyntaxKind::InKeyword
595                | SyntaxKind::InputKeyword
596                | SyntaxKind::IntTypeKeyword
597                | SyntaxKind::MapTypeKeyword
598                | SyntaxKind::MetaKeyword
599                | SyntaxKind::NoneKeyword
600                | SyntaxKind::NullKeyword
601                | SyntaxKind::ObjectKeyword
602                | SyntaxKind::ObjectTypeKeyword
603                | SyntaxKind::OutputKeyword
604                | SyntaxKind::PairTypeKeyword
605                | SyntaxKind::ParameterMetaKeyword
606                | SyntaxKind::RequirementsKeyword
607                | SyntaxKind::RuntimeKeyword
608                | SyntaxKind::ScatterKeyword
609                | SyntaxKind::StringTypeKeyword
610                | SyntaxKind::StructKeyword
611                | SyntaxKind::TaskKeyword
612                | SyntaxKind::ThenKeyword
613                | SyntaxKind::TrueKeyword
614                | SyntaxKind::VersionKeyword
615                | SyntaxKind::WorkflowKeyword
616        )
617    }
618
619    /// Returns whether the [`SyntaxKind`] is an operator.
620    pub fn is_operator(&self) -> bool {
621        matches!(
622            self,
623            SyntaxKind::Plus
624                | SyntaxKind::Minus
625                | SyntaxKind::Slash
626                | SyntaxKind::Percent
627                | SyntaxKind::Asterisk
628                | SyntaxKind::Exponentiation
629                | SyntaxKind::Equal
630                | SyntaxKind::NotEqual
631                | SyntaxKind::Less
632                | SyntaxKind::LessEqual
633                | SyntaxKind::Greater
634                | SyntaxKind::GreaterEqual
635                | SyntaxKind::LogicalAnd
636                | SyntaxKind::LogicalOr
637                | SyntaxKind::Exclamation
638                | SyntaxKind::Assignment
639                | SyntaxKind::QuestionMark
640                | SyntaxKind::Dot
641                | SyntaxKind::Colon
642        )
643    }
644}
645
646/// Every [`SyntaxKind`] variant.
647pub static ALL_SYNTAX_KIND: &[SyntaxKind] = SyntaxKind::VARIANTS;
648
649impl From<SyntaxKind> for rowan::SyntaxKind {
650    fn from(kind: SyntaxKind) -> Self {
651        rowan::SyntaxKind(kind as u16)
652    }
653}
654
655/// Represents the Workflow Definition Language (WDL).
656#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
657pub struct WorkflowDescriptionLanguage;
658
659impl rowan::Language for WorkflowDescriptionLanguage {
660    type Kind = SyntaxKind;
661
662    fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
663        assert!(raw.0 <= SyntaxKind::MAX as u16);
664        unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
665    }
666
667    fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
668        kind.into()
669    }
670}
671
672/// Represents a node in the concrete syntax tree.
673pub type SyntaxNode = rowan::SyntaxNode<WorkflowDescriptionLanguage>;
674/// Represents a token in the concrete syntax tree.
675pub type SyntaxToken = rowan::SyntaxToken<WorkflowDescriptionLanguage>;
676/// Represents an element (node or token) in the concrete syntax tree.
677pub type SyntaxElement = rowan::SyntaxElement<WorkflowDescriptionLanguage>;
678/// Represents node children in the concrete syntax tree.
679pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<WorkflowDescriptionLanguage>;
680
681/// Constructs a concrete syntax tree from a list of parser events.
682pub fn construct_tree(source: &str, mut events: Vec<Event>) -> SyntaxNode {
683    let mut builder = GreenNodeBuilder::default();
684    let mut ancestors = Vec::new();
685
686    for i in 0..events.len() {
687        match std::mem::replace(&mut events[i], Event::abandoned()) {
688            Event::NodeStarted {
689                kind,
690                forward_parent,
691            } => {
692                // Walk the forward parent chain, if there is one, and push
693                // each forward parent to the ancestors list
694                ancestors.push(kind);
695                let mut idx = i;
696                let mut fp: Option<usize> = forward_parent;
697                while let Some(distance) = fp {
698                    idx += distance;
699                    fp = match std::mem::replace(&mut events[idx], Event::abandoned()) {
700                        Event::NodeStarted {
701                            kind,
702                            forward_parent,
703                        } => {
704                            ancestors.push(kind);
705                            forward_parent
706                        }
707                        _ => unreachable!(),
708                    };
709                }
710
711                // As the current node was pushed first and then its ancestors, walk
712                // the list in reverse to start the "oldest" ancestor first
713                for kind in ancestors.drain(..).rev() {
714                    if kind != SyntaxKind::Abandoned {
715                        builder.start_node(kind.into());
716                    }
717                }
718            }
719            Event::NodeFinished => builder.finish_node(),
720            Event::Token { kind, span } => {
721                builder.token(kind.into(), &source[span.start()..span.end()])
722            }
723        }
724    }
725
726    SyntaxNode::new_root(builder.finish())
727}
728
729/// Represents an untyped concrete syntax tree.
730#[derive(Clone, PartialEq, Eq, Hash)]
731pub struct SyntaxTree(SyntaxNode);
732
733impl SyntaxTree {
734    /// Parses WDL source to produce a syntax tree.
735    ///
736    /// A syntax tree is always returned, even for invalid WDL documents.
737    ///
738    /// Additionally, the list of diagnostics encountered during the parse is
739    /// returned; if the list is empty, the tree is syntactically correct.
740    ///
741    /// However, additional validation is required to ensure the source is
742    /// a valid WDL document.
743    ///
744    /// # Example
745    ///
746    /// ```rust
747    /// # use wdl_grammar::SyntaxTree;
748    /// let (tree, diagnostics) = SyntaxTree::parse("version 1.1");
749    /// assert!(diagnostics.is_empty());
750    /// println!("{tree:#?}");
751    /// ```
752    pub fn parse(source: &str) -> (Self, Vec<Diagnostic>) {
753        let parser = Parser::new(Lexer::new(source));
754        let (events, mut diagnostics) = grammar::document(parser);
755        diagnostics.sort();
756        (Self(construct_tree(source, events)), diagnostics)
757    }
758
759    /// Gets the root syntax node of the tree.
760    pub fn root(&self) -> &SyntaxNode {
761        &self.0
762    }
763
764    /// Gets a copy of the underlying root green node for the tree.
765    pub fn green(&self) -> Cow<'_, GreenNodeData> {
766        self.0.green()
767    }
768
769    /// Converts the tree into a syntax node.
770    pub fn into_syntax(self) -> SyntaxNode {
771        self.0
772    }
773}
774
775impl fmt::Display for SyntaxTree {
776    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
777        self.0.fmt(f)
778    }
779}
780
781impl fmt::Debug for SyntaxTree {
782    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
783        self.0.fmt(f)
784    }
785}
786
787/// An extension trait for [`SyntaxToken`]s.
788pub trait SyntaxTokenExt {
789    /// Gets all of the substantial preceding trivia for an element.
790    fn preceding_trivia(&self) -> impl Iterator<Item = SyntaxToken>;
791
792    /// Get any inline comment directly following an element on the
793    /// same line.
794    fn inline_comment(&self) -> Option<SyntaxToken>;
795}
796
797impl SyntaxTokenExt for SyntaxToken {
798    fn preceding_trivia(&self) -> impl Iterator<Item = SyntaxToken> {
799        let mut tokens = VecDeque::new();
800        let mut cur = self.prev_token();
801        while let Some(token) = cur {
802            cur = token.prev_token();
803            // Stop at first non-trivia
804            if !token.kind().is_trivia() {
805                break;
806            }
807            // Stop if a comment is not on its own line
808            if token.kind() == SyntaxKind::Comment
809                && let Some(prev) = token.prev_token()
810            {
811                if prev.kind() == SyntaxKind::Whitespace {
812                    let has_newlines = prev.text().chars().any(|c| c == '\n');
813                    // If there are newlines in 'prev' then we know
814                    // that the comment is on its own line.
815                    // The comment may still be on its own line if
816                    // 'prev' does not have newlines and nothing comes
817                    // before 'prev'.
818                    if !has_newlines && prev.prev_token().is_some() {
819                        break;
820                    }
821                } else {
822                    // There is something else on this line before the comment.
823                    break;
824                }
825            }
826            // Filter out whitespace that is not substantial
827            match token.kind() {
828                SyntaxKind::Whitespace
829                    if token.text().chars().filter(|c| *c == '\n').count() > 1 =>
830                {
831                    tokens.push_front(token);
832                }
833                SyntaxKind::Comment => {
834                    tokens.push_front(token);
835                }
836                _ => {}
837            }
838        }
839        tokens.into_iter()
840    }
841
842    fn inline_comment(&self) -> Option<SyntaxToken> {
843        let mut next = self.next_token();
844        iter::from_fn(move || {
845            let cur = next.clone()?;
846            next = cur.next_token();
847            Some(cur)
848        })
849        .take_while(|t| {
850            // Stop at non-trivia
851            if !t.kind().is_trivia() {
852                return false;
853            }
854            // Stop on first whitespace containing a newline
855            if t.kind() == SyntaxKind::Whitespace {
856                return !t.text().chars().any(|c| c == '\n');
857            }
858            true
859        })
860        .find(|t| t.kind() == SyntaxKind::Comment)
861    }
862}
863
864#[cfg(test)]
865mod tests {
866    use super::*;
867    use crate::SyntaxTree;
868
869    #[test]
870    fn preceding_comments() {
871        let (tree, diagnostics) = SyntaxTree::parse(
872            "version 1.2
873
874# This comment should not be included
875task foo {} # This comment should not be included
876
877# Some
878# comments
879# are
880# long
881    
882# Others are short
883
884#     and, yet    another
885workflow foo {} # This should not be collected.
886
887# This comment should not be included either.",
888        );
889
890        assert!(diagnostics.is_empty());
891
892        let workflow = tree.root().last_child().unwrap();
893        assert_eq!(workflow.kind(), SyntaxKind::WorkflowDefinitionNode);
894        let token = workflow.first_token().unwrap();
895        let mut trivia = token.preceding_trivia();
896        assert_eq!(trivia.next().unwrap().text(), "\n\n");
897        assert_eq!(trivia.next().unwrap().text(), "# Some");
898        assert_eq!(trivia.next().unwrap().text(), "# comments");
899        assert_eq!(trivia.next().unwrap().text(), "# are");
900        assert_eq!(trivia.next().unwrap().text(), "# long");
901        assert_eq!(trivia.next().unwrap().text(), "\n    \n");
902        assert_eq!(trivia.next().unwrap().text(), "# Others are short");
903        assert_eq!(trivia.next().unwrap().text(), "\n\n");
904        assert_eq!(trivia.next().unwrap().text(), "#     and, yet    another");
905        assert!(trivia.next().is_none());
906    }
907
908    #[test]
909    fn inline_comment() {
910        let (tree, diagnostics) = SyntaxTree::parse(
911            "version 1.2
912
913# This comment should not be included
914task foo {}
915
916# This should not be collected.
917workflow foo {} # Here is a comment that should be collected.
918
919# This comment should not be included either.",
920        );
921
922        assert!(diagnostics.is_empty());
923
924        let workflow = tree.root().last_child().unwrap();
925        assert_eq!(workflow.kind(), SyntaxKind::WorkflowDefinitionNode);
926        let comment = workflow.last_token().unwrap().inline_comment().unwrap();
927        assert_eq!(
928            comment.text(),
929            "# Here is a comment that should be collected."
930        );
931    }
932}