Skip to main content

fml_syntax/
kind.rs

1//! Token and node kinds of the FML syntax tree.
2
3/// Every token and node kind in an FML syntax tree.
4///
5/// FML keywords are contextual: `source`, `group`, `where` and the rest are also valid element
6/// names. The lexer therefore produces [`SyntaxKind::Ident`] for every word and the parser decides
7/// what a word means from where it appears.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
9#[repr(u16)]
10pub enum SyntaxKind {
11    // Trivia.
12    Whitespace = 0,
13    LineComment,
14    BlockComment,
15
16    // Literals and names.
17    Ident,
18    /// `` `name` ``
19    DelimitedIdent,
20    /// `'text'`
21    SingleQuotedString,
22    /// `"text"`
23    DoubleQuotedString,
24    /// `"""` … `"""`, used for markdown metadata values.
25    TripleQuotedString,
26    Integer,
27    Decimal,
28    /// `10L`
29    LongNumber,
30    /// `@2024-01-01`
31    Date,
32    /// `@2024-01-01T10:00:00Z`
33    DateTime,
34    /// `@T10:00`
35    Time,
36    /// `$this`, `$index`, `$total`
37    DollarIdent,
38
39    // Punctuation.
40    /// `///` at the start of a metadata line.
41    MetadataPrefix,
42    LParen,
43    RParen,
44    LBrace,
45    RBrace,
46    LBracket,
47    RBracket,
48    Comma,
49    Semicolon,
50    Colon,
51    Dot,
52    /// `..`
53    DotDot,
54    /// `->`
55    Arrow,
56    /// `=`
57    Eq,
58    /// `==`
59    EqEq,
60    /// `!=`
61    Neq,
62    /// `~`
63    Tilde,
64    /// `!~`
65    NotTilde,
66    Lt,
67    Le,
68    Gt,
69    Ge,
70    /// `<<`
71    Shl,
72    /// `>>`
73    Shr,
74    Plus,
75    Minus,
76    Star,
77    Slash,
78    Amp,
79    Pipe,
80    Percent,
81    /// A character the lexer does not recognise, or an unterminated literal.
82    Unknown,
83
84    // Nodes: map structure.
85    SourceFile,
86    /// `/// key = value`
87    Metadata,
88    /// `conceptmap "url" { … }`
89    ConceptMap,
90    /// `prefix s = "url"`
91    ConceptMapPrefix,
92    /// `unmapped for s = provided`
93    ConceptMapUnmapped,
94    /// `s:code - t:code`
95    ConceptMapEntry,
96    /// `s:code`
97    ConceptMapCode,
98    /// The relationship operator between two concept map codes.
99    ConceptMapRelation,
100    /// `map "url" = "name"`
101    MapDeclaration,
102    /// `uses "url" alias Name as source`
103    UsesDeclaration,
104    /// `alias Name`
105    UsesAlias,
106    /// `imports "url"`
107    ImportsDeclaration,
108    /// `let name = expression;`
109    ConstantDeclaration,
110    /// `group Name(…) extends Base <<types>> { … }`
111    Group,
112    /// `(source src : Type, target tgt : Type)`
113    ParameterList,
114    /// `source src : Type`
115    Parameter,
116    /// `: Type`
117    TypeAnnotation,
118    /// `extends Base`
119    ExtendsClause,
120    /// `<<types>>` or `<<type+>>`
121    TypeMode,
122    /// `{ rule; rule; }`
123    RuleBlock,
124    Rule,
125    /// The sources of a rule, separated by commas.
126    SourceList,
127    Source,
128    /// `0..*`
129    Cardinality,
130    /// `default (expression)`
131    DefaultClause,
132    /// `first`, `not_first`, `last`, `not_last`, `only_one`
133    SourceListMode,
134    /// `as name`
135    Alias,
136    /// `where (expression)`
137    WhereClause,
138    /// `check (expression)`
139    CheckClause,
140    /// `log (expression)`
141    LogClause,
142    /// The targets of a rule, separated by commas.
143    TargetList,
144    Target,
145    /// `= transform` on a target.
146    Transform,
147    /// `first`, `last`, `single`, `share id`, `collate`
148    TargetListMode,
149    /// `name(arguments)`, a transform or a group invocation.
150    Invocation,
151    /// `(argument, argument)`
152    ArgumentList,
153    /// `then Group(a, b) { … }`
154    DependentClause,
155    /// `: field, field`, in the batch identity rule form.
156    IdentityList,
157    /// `"name"` after a rule.
158    RuleName,
159    /// `a.b.c`
160    QualifiedName,
161
162    // Nodes: FHIRPath expressions.
163    /// A literal value.
164    Literal,
165    /// `5 'mg'`, `3 days`
166    Quantity,
167    /// `name` in an expression.
168    NameRef,
169    /// `%name`
170    ExternalConstant,
171    /// `(expression)`
172    ParenExpr,
173    /// `expression.member` or `expression.function(…)`
174    MemberExpr,
175    /// `function(arguments)`
176    CallExpr,
177    /// `expression[index]`
178    IndexExpr,
179    /// `-expression`
180    PrefixExpr,
181    /// `left op right`
182    BinaryExpr,
183    /// `expression is Type`, `expression as Type`
184    TypeExpr,
185    /// `{}`
186    NullLiteral,
187
188    /// Tokens the parser could not place.
189    Error,
190}
191
192impl SyntaxKind {
193    /// Whitespace and comments.
194    pub fn is_trivia(self) -> bool {
195        matches!(
196            self,
197            SyntaxKind::Whitespace | SyntaxKind::LineComment | SyntaxKind::BlockComment
198        )
199    }
200
201    pub fn is_comment(self) -> bool {
202        matches!(self, SyntaxKind::LineComment | SyntaxKind::BlockComment)
203    }
204
205    fn from_raw(raw: u16) -> SyntaxKind {
206        assert!(raw <= SyntaxKind::Error as u16, "invalid syntax kind {raw}");
207        // SAFETY: `SyntaxKind` is `repr(u16)` with contiguous discriminants from 0 to `Error`.
208        unsafe { std::mem::transmute::<u16, SyntaxKind>(raw) }
209    }
210}
211
212impl From<SyntaxKind> for rowan::SyntaxKind {
213    fn from(kind: SyntaxKind) -> Self {
214        rowan::SyntaxKind(kind as u16)
215    }
216}
217
218/// The rowan language tag for FML trees.
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
220pub enum FmlLanguage {}
221
222impl rowan::Language for FmlLanguage {
223    type Kind = SyntaxKind;
224
225    fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
226        SyntaxKind::from_raw(raw.0)
227    }
228
229    fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
230        kind.into()
231    }
232}
233
234pub type SyntaxNode = rowan::SyntaxNode<FmlLanguage>;
235pub type SyntaxToken = rowan::SyntaxToken<FmlLanguage>;
236pub type SyntaxElement = rowan::SyntaxElement<FmlLanguage>;