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>;