1use logos::{Lexer, Logos};
18pub use rowan::Direction;
19pub use rowan::GreenNode;
22pub use rowan::GreenNodeBuilder;
26pub use rowan::Language;
27pub use rowan::SyntaxText;
28pub use rowan::TextLen;
29pub use rowan::TextRange;
30pub use rowan::TextSize;
31pub use rowan::WalkEvent;
32use std::fmt;
33use std::fmt::Formatter;
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Logos)]
36#[allow(non_camel_case_types)]
37#[repr(u16)]
38pub enum SyntaxKind {
39 #[regex(r"[ \t]+")]
44 TK_WHITESPACE = 0,
45 #[regex(r"((\n)|(\r\n))+")]
46 TK_LINE_BREAK,
47 #[regex(r"([a-zA-Z]|([@\#_\$][a-zA-Z])|_)[a-zA-Z0-9_\-]*")]
51 TK_WORD,
52 #[regex(r"twig(\:[a-zA-Z0-9_\-]+)+")]
54 TK_TWIG_COMPONENT_NAME,
55 #[regex(r"[0-9]+(\.[0-9]+)?([Ee][\+\-][0-9]+)?")]
57 TK_NUMBER,
58 #[regex(r"\&(([a-zA-Z][a-zA-Z0-9]*)|(\#[0-9]+)|(\#x[0-9a-fA-F]+));")]
60 TK_HTML_ESCAPE_CHARACTER,
61 #[token(".")]
62 TK_DOT,
63 #[token("..")]
64 TK_DOUBLE_DOT,
65 #[token("...")]
66 TK_TRIPLE_DOT,
67 #[token(",")]
68 TK_COMMA,
69 #[token(":")]
70 TK_COLON,
71 #[token(";")]
72 TK_SEMICOLON,
73 #[token("!")]
74 TK_EXCLAMATION_MARK,
75 #[token("!=")]
76 TK_EXCLAMATION_MARK_EQUALS,
77 #[token("!==")]
78 TK_EXCLAMATION_MARK_DOUBLE_EQUALS,
79 #[token("?")]
80 TK_QUESTION_MARK,
81 #[token("??")]
82 TK_DOUBLE_QUESTION_MARK,
83 #[token("%")]
84 TK_PERCENT,
85 #[token("~")]
86 TK_TILDE,
87 #[token("|")]
88 TK_SINGLE_PIPE,
89 #[token("||")]
90 TK_DOUBLE_PIPE,
91 #[token("&")]
92 TK_AMPERSAND,
93 #[token("&&")]
94 TK_DOUBLE_AMPERSAND,
95 #[token("/")]
96 TK_FORWARD_SLASH,
97 #[token("//")]
98 TK_DOUBLE_FORWARD_SLASH,
99 #[token("\\")]
100 TK_BACKWARD_SLASH,
101 #[token("(")]
102 TK_OPEN_PARENTHESIS,
103 #[token(")")]
104 TK_CLOSE_PARENTHESIS,
105 #[token("{")]
106 TK_OPEN_CURLY,
107 #[token("}")]
108 TK_CLOSE_CURLY,
109 #[token("[")]
110 TK_OPEN_SQUARE,
111 #[token("]")]
112 TK_CLOSE_SQUARE,
113 #[token("<")]
114 TK_LESS_THAN,
115 #[token("<=")]
116 TK_LESS_THAN_EQUAL,
117 #[token("<=>")]
118 TK_LESS_THAN_EQUAL_GREATER_THAN,
119 #[token("</")]
120 TK_LESS_THAN_SLASH,
121 #[token("<!")]
122 TK_LESS_THAN_EXCLAMATION_MARK,
123 #[token("DOCTYPE", ignore(case))]
124 TK_DOCTYPE,
125 #[token(">")]
126 TK_GREATER_THAN,
127 #[token(">=")]
128 TK_GREATER_THAN_EQUAL,
129 #[token("=>")]
130 TK_EQUAL_GREATER_THAN,
131 #[token("/>")]
132 TK_SLASH_GREATER_THAN,
133 #[token("<!--")]
134 TK_LESS_THAN_EXCLAMATION_MARK_MINUS_MINUS,
135 #[token("-->")]
136 TK_MINUS_MINUS_GREATER_THAN,
137 #[token("=")]
138 TK_EQUAL,
139 #[token("==")]
140 TK_DOUBLE_EQUAL,
141 #[token("===")]
142 TK_TRIPLE_EQUAL,
143 #[token("+")]
144 TK_PLUS,
145 #[token("-")]
146 TK_MINUS,
147 #[token("*")]
148 TK_STAR,
149 #[token("**")]
150 TK_DOUBLE_STAR,
151 #[token("\"")]
152 TK_DOUBLE_QUOTES,
153 #[token("'")]
154 TK_SINGLE_QUOTES,
155 #[token("`")]
156 TK_GRAVE_ACCENT_QUOTES,
157 #[token("{%")]
158 TK_CURLY_PERCENT,
159 #[token("%}")]
160 TK_PERCENT_CURLY,
161 #[token("{{")]
162 TK_OPEN_CURLY_CURLY,
163 #[token("}}")]
164 TK_CLOSE_CURLY_CURLY,
165 #[token("{#")]
166 TK_OPEN_CURLY_HASHTAG,
167 #[token("#}")]
168 TK_HASHTAG_CLOSE_CURLY,
169 #[token("#")]
170 TK_HASHTAG,
171
172 #[token("true", ignore(case))]
173 TK_TRUE,
174 #[token("false", ignore(case))]
175 TK_FALSE,
176
177 #[token("block")]
179 TK_BLOCK,
180 #[token("endblock")]
181 TK_ENDBLOCK,
182 #[token("if")]
183 TK_IF,
184 #[token("elseif")]
185 TK_ELSE_IF,
186 #[token("else")]
187 TK_ELSE,
188 #[token("endif")]
189 TK_ENDIF,
190 #[token("apply")]
191 TK_APPLY,
192 #[token("endapply")]
193 TK_ENDAPPLY,
194 #[token("autoescape")]
195 TK_AUTOESCAPE,
196 #[token("endautoescape")]
197 TK_ENDAUTOESCAPE,
198 #[token("cache")]
199 TK_CACHE,
200 #[token("endcache")]
201 TK_ENDCACHE,
202 #[token("deprecated")]
203 TK_DEPRECATED,
204 #[token("do")]
205 TK_DO,
206 #[token("embed")]
207 TK_EMBED,
208 #[token("endembed")]
209 TK_ENDEMBED,
210 #[token("extends")]
211 TK_EXTENDS,
212 #[token("flush")]
213 TK_FLUSH,
214 #[token("for")]
215 TK_FOR,
216 #[token("endfor")]
217 TK_ENDFOR,
218 #[token("from")]
219 TK_FROM,
220 #[token("import")]
221 TK_IMPORT,
222 #[token("macro")]
223 TK_MACRO,
224 #[token("endmacro")]
225 TK_ENDMACRO,
226 #[token("sandbox")]
227 TK_SANDBOX,
228 #[token("endsandbox")]
229 TK_ENDSANDBOX,
230 #[token("set")]
231 TK_SET,
232 #[token("endset")]
233 TK_ENDSET,
234 #[token("use")]
235 TK_USE,
236 #[token("verbatim")]
237 TK_VERBATIM,
238 #[token("endverbatim")]
239 TK_ENDVERBATIM,
240 #[token("only")]
241 TK_ONLY,
242 #[token("ignore missing")]
243 TK_IGNORE_MISSING,
244 #[token("with")]
245 TK_WITH,
246 #[token("endwith")]
247 TK_ENDWITH,
248 #[token("ttl")]
249 TK_TTL,
250 #[token("tags")]
251 TK_TAGS,
252 #[token("props")]
253 TK_PROPS,
254 #[token("component")]
255 TK_COMPONENT,
256 #[token("endcomponent")]
257 TK_ENDCOMPONENT,
258 #[token("not", cb_not)]
260 TK_NOT,
261 TK_NOT_IN,
262 #[token("or")]
263 TK_OR,
264 #[token("and")]
265 TK_AND,
266 #[token("b-or")]
267 TK_BINARY_OR,
268 #[token("b-xor")]
269 TK_BINARY_XOR,
270 #[token("b-and")]
271 TK_BINARY_AND,
272 #[token("in")]
273 TK_IN,
274 #[token("matches")]
275 TK_MATCHES,
276 #[token("starts with")]
277 TK_STARTS_WITH,
278 #[token("ends with")]
279 TK_ENDS_WITH,
280 #[token("is", cb_is)]
281 TK_IS,
282 TK_IS_NOT,
283 #[token("even")]
285 TK_EVEN,
286 #[token("odd")]
287 TK_ODD,
288 #[token("defined")]
289 TK_DEFINED,
290 #[token("same as")]
291 TK_SAME_AS,
292 #[token("as")]
293 TK_AS,
294 #[token("none", ignore(case))]
295 TK_NONE,
296 #[token("null", ignore(case))]
297 TK_NULL,
298 #[token("divisible by")]
299 TK_DIVISIBLE_BY,
300 #[token("constant")]
301 TK_CONSTANT,
302 #[token("empty")]
303 TK_EMPTY,
304 #[token("iterable")]
305 TK_ITERABLE,
306 #[token("max")]
308 TK_MAX,
309 #[token("min")]
310 TK_MIN,
311 #[token("range")]
312 TK_RANGE,
313 #[token("cycle")]
314 TK_CYCLE,
315 #[token("random")]
316 TK_RANDOM,
317 #[token("date")]
318 TK_DATE,
319 #[token("include")]
320 TK_INCLUDE,
321 #[token("source")]
322 TK_SOURCE,
323
324 #[token("trans")]
326 TK_TRANS,
327 #[token("endtrans")]
328 TK_ENDTRANS,
329
330 #[token("sw_extends")]
332 TK_SW_EXTENDS,
333 #[token("sw_silent_feature_call")]
334 TK_SW_SILENT_FEATURE_CALL,
335 #[token("endsw_silent_feature_call")]
336 TK_ENDSW_SILENT_FEATURE_CALL,
337 #[token("sw_include")]
338 TK_SW_INCLUDE,
339 #[token("return")]
340 TK_RETURN,
341 #[token("sw_icon")]
342 TK_SW_ICON,
343 #[token("sw_thumbnails")]
344 TK_SW_THUMBNAILS,
345 #[token("style")]
346 TK_STYLE,
347
348 #[token("ludtwig-ignore-file", ignore(case))]
350 TK_LUDTWIG_IGNORE_FILE,
351 #[token("ludtwig-ignore", ignore(case))]
352 TK_LUDTWIG_IGNORE,
353 TK_UNKNOWN, BODY,
360 TWIG_VAR,
361 TWIG_EXPRESSION, TWIG_BINARY_EXPRESSION,
363 TWIG_UNARY_EXPRESSION,
364 TWIG_PARENTHESES_EXPRESSION,
365 TWIG_CONDITIONAL_EXPRESSION,
366
367 TWIG_OPERAND, TWIG_ACCESSOR, TWIG_FILTER, TWIG_INDEX_LOOKUP, TWIG_INDEX, TWIG_INDEX_RANGE, TWIG_FUNCTION_CALL,
376 TWIG_ARROW_FUNCTION, TWIG_ARGUMENTS,
378 TWIG_NAMED_ARGUMENT,
379
380 TWIG_LITERAL_STRING,
382 TWIG_LITERAL_STRING_INNER,
383 TWIG_LITERAL_STRING_INTERPOLATION,
384 TWIG_LITERAL_NUMBER,
385 TWIG_LITERAL_ARRAY,
386 TWIG_LITERAL_ARRAY_INNER,
387 TWIG_LITERAL_NULL,
388 TWIG_LITERAL_BOOLEAN,
389 TWIG_LITERAL_HASH,
390 TWIG_LITERAL_HASH_ITEMS,
391 TWIG_LITERAL_HASH_PAIR,
392 TWIG_LITERAL_HASH_KEY,
393 TWIG_LITERAL_HASH_VALUE,
394 TWIG_LITERAL_NAME,
395
396 TWIG_COMMENT,
398 TWIG_BLOCK,
400 TWIG_STARTING_BLOCK,
401 TWIG_ENDING_BLOCK,
402 TWIG_IF,
404 TWIG_IF_BLOCK,
405 TWIG_ELSE_IF_BLOCK,
406 TWIG_ELSE_BLOCK,
407 TWIG_ENDIF_BLOCK,
408 TWIG_SET,
410 TWIG_SET_BLOCK,
411 TWIG_ENDSET_BLOCK,
412 TWIG_ASSIGNMENT,
413 TWIG_FOR,
415 TWIG_FOR_BLOCK,
416 TWIG_FOR_ELSE_BLOCK,
417 TWIG_ENDFOR_BLOCK,
418 TWIG_EXTENDS,
420 TWIG_INCLUDE,
422 TWIG_INCLUDE_WITH,
423 TWIG_USE,
425 TWIG_OVERRIDE,
426 TWIG_APPLY,
428 TWIG_APPLY_STARTING_BLOCK,
429 TWIG_APPLY_ENDING_BLOCK,
430 TWIG_AUTOESCAPE,
432 TWIG_AUTOESCAPE_STARTING_BLOCK,
433 TWIG_AUTOESCAPE_ENDING_BLOCK,
434 TWIG_DEPRECATED,
436 TWIG_DO,
438 TWIG_EMBED,
440 TWIG_EMBED_STARTING_BLOCK,
441 TWIG_EMBED_ENDING_BLOCK,
442 TWIG_FLUSH,
444 TWIG_FROM, TWIG_IMPORT,
448 TWIG_SANDBOX,
450 TWIG_SANDBOX_STARTING_BLOCK,
451 TWIG_SANDBOX_ENDING_BLOCK,
452 TWIG_VERBATIM,
454 TWIG_VERBATIM_STARTING_BLOCK,
455 TWIG_VERBATIM_ENDING_BLOCK,
456 TWIG_MACRO,
458 TWIG_MACRO_STARTING_BLOCK,
459 TWIG_MACRO_ENDING_BLOCK,
460 TWIG_WITH,
462 TWIG_WITH_STARTING_BLOCK,
463 TWIG_WITH_ENDING_BLOCK,
464 TWIG_CACHE,
466 TWIG_CACHE_TTL,
467 TWIG_CACHE_TAGS,
468 TWIG_CACHE_STARTING_BLOCK,
469 TWIG_CACHE_ENDING_BLOCK,
470 TWIG_PROPS,
472 TWIG_PROP_DECLARATION,
473 TWIG_COMPONENT,
475 TWIG_COMPONENT_STARTING_BLOCK,
476 TWIG_COMPONENT_ENDING_BLOCK,
477
478 TWIG_TRANS,
480 TWIG_TRANS_STARTING_BLOCK,
481 TWIG_TRANS_ENDING_BLOCK,
482
483 SHOPWARE_TWIG_SW_EXTENDS,
485 SHOPWARE_TWIG_SW_INCLUDE,
486 SHOPWARE_SILENT_FEATURE_CALL,
487 SHOPWARE_SILENT_FEATURE_CALL_STARTING_BLOCK,
488 SHOPWARE_SILENT_FEATURE_CALL_ENDING_BLOCK,
489 SHOPWARE_RETURN,
490 SHOPWARE_ICON,
491 SHOPWARE_ICON_STYLE,
492 SHOPWARE_THUMBNAILS,
493 SHOPWARE_THUMBNAILS_WITH,
494
495 HTML_DOCTYPE,
497 HTML_ATTRIBUTE_LIST,
498 HTML_ATTRIBUTE,
499 HTML_STRING, HTML_STRING_INNER, HTML_TEXT, HTML_RAW_TEXT, HTML_COMMENT,
504 HTML_TAG,
505 HTML_STARTING_TAG,
506 HTML_ENDING_TAG,
507
508 LUDTWIG_DIRECTIVE_FILE_IGNORE,
510 LUDTWIG_DIRECTIVE_IGNORE,
511 LUDTWIG_DIRECTIVE_RULE_LIST,
512 ERROR, ROOT, }
519
520fn cb_not(lexer: &mut Lexer<'_, SyntaxKind>) -> SyntaxKind {
522 const SUFFIX: &str = " in";
523 if lexer.remainder().starts_with(SUFFIX) {
524 let after = lexer.remainder().get(SUFFIX.len()..);
525 if after.is_none_or(|s| s.starts_with([' ', '\t', '\n']) || s.is_empty()) {
526 lexer.bump(SUFFIX.len());
527 SyntaxKind::TK_NOT_IN
528 } else {
529 SyntaxKind::TK_NOT
530 }
531 } else {
532 SyntaxKind::TK_NOT
533 }
534}
535
536fn cb_is(lexer: &mut Lexer<'_, SyntaxKind>) -> SyntaxKind {
538 const SUFFIX: &str = " not";
539 if lexer.remainder().starts_with(SUFFIX) {
540 let after = lexer.remainder().get(SUFFIX.len()..);
541 if after.is_none_or(|s| s.starts_with([' ', '\t', '\n']) || s.is_empty()) {
542 lexer.bump(SUFFIX.len());
543 SyntaxKind::TK_IS_NOT
544 } else {
545 SyntaxKind::TK_IS
546 }
547 } else {
548 SyntaxKind::TK_IS
549 }
550}
551
552#[macro_export]
553macro_rules! T {
554 [ws] => { $crate::syntax::untyped::SyntaxKind::TK_WHITESPACE };
555 [lb] => { $crate::syntax::untyped::SyntaxKind::TK_LINE_BREAK };
556 [word] => { $crate::syntax::untyped::SyntaxKind::TK_WORD };
557 [twig component name] => { $crate::syntax::untyped::SyntaxKind::TK_TWIG_COMPONENT_NAME };
558 [number] => { $crate::syntax::untyped::SyntaxKind::TK_NUMBER };
559 [html escape character] => { $crate::syntax::untyped::SyntaxKind::TK_HTML_ESCAPE_CHARACTER };
560 [unknown] => { $crate::syntax::untyped::SyntaxKind::TK_UNKNOWN };
561 ["."] => { $crate::syntax::untyped::SyntaxKind::TK_DOT };
562 [".."] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_DOT };
563 ["..."] => { $crate::syntax::untyped::SyntaxKind::TK_TRIPLE_DOT };
564 [","] => { $crate::syntax::untyped::SyntaxKind::TK_COMMA };
565 [":"] => { $crate::syntax::untyped::SyntaxKind::TK_COLON };
566 [";"] => { $crate::syntax::untyped::SyntaxKind::TK_SEMICOLON };
567 ["!"] => { $crate::syntax::untyped::SyntaxKind::TK_EXCLAMATION_MARK };
568 ["!="] => { $crate::syntax::untyped::SyntaxKind::TK_EXCLAMATION_MARK_EQUALS };
569 ["!=="] => { $crate::syntax::untyped::SyntaxKind::TK_EXCLAMATION_MARK_DOUBLE_EQUALS };
570 ["?"] => { $crate::syntax::untyped::SyntaxKind::TK_QUESTION_MARK };
571 ["??"] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_QUESTION_MARK };
572 ["%"] => { $crate::syntax::untyped::SyntaxKind::TK_PERCENT };
573 ["~"] => { $crate::syntax::untyped::SyntaxKind::TK_TILDE };
574 ["|"] => { $crate::syntax::untyped::SyntaxKind::TK_SINGLE_PIPE };
575 ["||"] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_PIPE };
576 ["&"] => { $crate::syntax::untyped::SyntaxKind::TK_AMPERSAND };
577 ["&&"] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_AMPERSAND };
578 ["/"] => { $crate::syntax::untyped::SyntaxKind::TK_FORWARD_SLASH };
579 ["//"] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_FORWARD_SLASH };
580 ["\\"] => { $crate::syntax::untyped::SyntaxKind::TK_BACKWARD_SLASH };
581 ["("] => { $crate::syntax::untyped::SyntaxKind::TK_OPEN_PARENTHESIS };
582 [")"] => { $crate::syntax::untyped::SyntaxKind::TK_CLOSE_PARENTHESIS };
583 ["{"] => { $crate::syntax::untyped::SyntaxKind::TK_OPEN_CURLY };
584 ["}"] => { $crate::syntax::untyped::SyntaxKind::TK_CLOSE_CURLY };
585 ["["] => { $crate::syntax::untyped::SyntaxKind::TK_OPEN_SQUARE };
586 ["]"] => { $crate::syntax::untyped::SyntaxKind::TK_CLOSE_SQUARE };
587 ["<"] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN };
588 ["<="] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN_EQUAL };
589 ["<=>"] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN_EQUAL_GREATER_THAN };
590 ["</"] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN_SLASH };
591 ["<!"] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN_EXCLAMATION_MARK };
592 ["DOCTYPE"] => { $crate::syntax::untyped::SyntaxKind::TK_DOCTYPE };
593 [">"] => { $crate::syntax::untyped::SyntaxKind::TK_GREATER_THAN };
594 [">="] => { $crate::syntax::untyped::SyntaxKind::TK_GREATER_THAN_EQUAL };
595 ["=>"] => { $crate::syntax::untyped::SyntaxKind::TK_EQUAL_GREATER_THAN };
596 ["/>"] => { $crate::syntax::untyped::SyntaxKind::TK_SLASH_GREATER_THAN };
597 ["<!--"] => { $crate::syntax::untyped::SyntaxKind::TK_LESS_THAN_EXCLAMATION_MARK_MINUS_MINUS };
598 ["-->"] => { $crate::syntax::untyped::SyntaxKind::TK_MINUS_MINUS_GREATER_THAN };
599 ["="] => { $crate::syntax::untyped::SyntaxKind::TK_EQUAL };
600 ["=="] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_EQUAL };
601 ["==="] => { $crate::syntax::untyped::SyntaxKind::TK_TRIPLE_EQUAL };
602 ["+"] => { $crate::syntax::untyped::SyntaxKind::TK_PLUS };
603 ["-"] => { $crate::syntax::untyped::SyntaxKind::TK_MINUS };
604 ["*"] => { $crate::syntax::untyped::SyntaxKind::TK_STAR };
605 ["**"] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_STAR };
606 ["\""] => { $crate::syntax::untyped::SyntaxKind::TK_DOUBLE_QUOTES };
607 ["'"] => { $crate::syntax::untyped::SyntaxKind::TK_SINGLE_QUOTES };
608 ["`"] => { $crate::syntax::untyped::SyntaxKind::TK_GRAVE_ACCENT_QUOTES };
609 ["{%"] => { $crate::syntax::untyped::SyntaxKind::TK_CURLY_PERCENT };
610 ["%}"] => { $crate::syntax::untyped::SyntaxKind::TK_PERCENT_CURLY };
611 ["{{"] => { $crate::syntax::untyped::SyntaxKind::TK_OPEN_CURLY_CURLY };
612 ["}}"] => { $crate::syntax::untyped::SyntaxKind::TK_CLOSE_CURLY_CURLY };
613 ["{#"] => { $crate::syntax::untyped::SyntaxKind::TK_OPEN_CURLY_HASHTAG };
614 ["#}"] => { $crate::syntax::untyped::SyntaxKind::TK_HASHTAG_CLOSE_CURLY };
615 ["#"] => { $crate::syntax::untyped::SyntaxKind::TK_HASHTAG };
616 ["true"] => { $crate::syntax::untyped::SyntaxKind::TK_TRUE };
617 ["false"] => { $crate::syntax::untyped::SyntaxKind::TK_FALSE };
618 ["block"] => { $crate::syntax::untyped::SyntaxKind::TK_BLOCK };
619 ["endblock"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDBLOCK };
620 ["if"] => { $crate::syntax::untyped::SyntaxKind::TK_IF };
621 ["elseif"] => { $crate::syntax::untyped::SyntaxKind::TK_ELSE_IF };
622 ["else"] => { $crate::syntax::untyped::SyntaxKind::TK_ELSE };
623 ["endif"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDIF };
624 ["apply"] => { $crate::syntax::untyped::SyntaxKind::TK_APPLY };
625 ["endapply"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDAPPLY };
626 ["autoescape"] => { $crate::syntax::untyped::SyntaxKind::TK_AUTOESCAPE };
627 ["endautoescape"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDAUTOESCAPE };
628 ["cache"] => { $crate::syntax::untyped::SyntaxKind::TK_CACHE };
629 ["endcache"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDCACHE };
630 ["deprecated"] => { $crate::syntax::untyped::SyntaxKind::TK_DEPRECATED };
631 ["do"] => { $crate::syntax::untyped::SyntaxKind::TK_DO };
632 ["embed"] => { $crate::syntax::untyped::SyntaxKind::TK_EMBED };
633 ["endembed"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDEMBED };
634 ["extends"] => { $crate::syntax::untyped::SyntaxKind::TK_EXTENDS };
635 ["flush"] => { $crate::syntax::untyped::SyntaxKind::TK_FLUSH };
636 ["for"] => { $crate::syntax::untyped::SyntaxKind::TK_FOR };
637 ["endfor"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDFOR };
638 ["from"] => { $crate::syntax::untyped::SyntaxKind::TK_FROM };
639 ["import"] => { $crate::syntax::untyped::SyntaxKind::TK_IMPORT };
640 ["macro"] => { $crate::syntax::untyped::SyntaxKind::TK_MACRO };
641 ["endmacro"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDMACRO };
642 ["sandbox"] => { $crate::syntax::untyped::SyntaxKind::TK_SANDBOX };
643 ["endsandbox"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDSANDBOX };
644 ["set"] => { $crate::syntax::untyped::SyntaxKind::TK_SET };
645 ["endset"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDSET };
646 ["use"] => { $crate::syntax::untyped::SyntaxKind::TK_USE };
647 ["verbatim"] => { $crate::syntax::untyped::SyntaxKind::TK_VERBATIM };
648 ["endverbatim"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDVERBATIM };
649 ["only"] => { $crate::syntax::untyped::SyntaxKind::TK_ONLY };
650 ["ignore missing"] => { $crate::syntax::untyped::SyntaxKind::TK_IGNORE_MISSING };
651 ["with"] => { $crate::syntax::untyped::SyntaxKind::TK_WITH };
652 ["endwith"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDWITH };
653 ["ttl"] => { $crate::syntax::untyped::SyntaxKind::TK_TTL };
654 ["tags"] => { $crate::syntax::untyped::SyntaxKind::TK_TAGS };
655 ["props"] => { $crate::syntax::untyped::SyntaxKind::TK_PROPS };
656 ["component"] => { $crate::syntax::untyped::SyntaxKind::TK_COMPONENT };
657 ["endcomponent"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDCOMPONENT };
658 ["not"] => { $crate::syntax::untyped::SyntaxKind::TK_NOT };
659 ["not in"] => { $crate::syntax::untyped::SyntaxKind::TK_NOT_IN };
660 ["or"] => { $crate::syntax::untyped::SyntaxKind::TK_OR };
661 ["and"] => { $crate::syntax::untyped::SyntaxKind::TK_AND };
662 ["b-or"] => { $crate::syntax::untyped::SyntaxKind::TK_BINARY_OR };
663 ["b-xor"] => { $crate::syntax::untyped::SyntaxKind::TK_BINARY_XOR };
664 ["b-and"] => { $crate::syntax::untyped::SyntaxKind::TK_BINARY_AND };
665 ["in"] => { $crate::syntax::untyped::SyntaxKind::TK_IN };
666 ["matches"] => { $crate::syntax::untyped::SyntaxKind::TK_MATCHES };
667 ["starts with"] => { $crate::syntax::untyped::SyntaxKind::TK_STARTS_WITH };
668 ["ends with"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDS_WITH };
669 ["is"] => { $crate::syntax::untyped::SyntaxKind::TK_IS };
670 ["is not"] => { $crate::syntax::untyped::SyntaxKind::TK_IS_NOT };
671 ["even"] => { $crate::syntax::untyped::SyntaxKind::TK_EVEN };
672 ["odd"] => { $crate::syntax::untyped::SyntaxKind::TK_ODD };
673 ["defined"] => { $crate::syntax::untyped::SyntaxKind::TK_DEFINED };
674 ["same as"] => { $crate::syntax::untyped::SyntaxKind::TK_SAME_AS };
675 ["as"] => { $crate::syntax::untyped::SyntaxKind::TK_AS };
676 ["none"] => { $crate::syntax::untyped::SyntaxKind::TK_NONE };
677 ["null"] => { $crate::syntax::untyped::SyntaxKind::TK_NULL };
678 ["divisible by"] => { $crate::syntax::untyped::SyntaxKind::TK_DIVISIBLE_BY };
679 ["constant"] => { $crate::syntax::untyped::SyntaxKind::TK_CONSTANT };
680 ["empty"] => { $crate::syntax::untyped::SyntaxKind::TK_EMPTY };
681 ["iterable"] => { $crate::syntax::untyped::SyntaxKind::TK_ITERABLE };
682 ["max"] => { $crate::syntax::untyped::SyntaxKind::TK_MAX };
683 ["min"] => { $crate::syntax::untyped::SyntaxKind::TK_MIN };
684 ["range"] => { $crate::syntax::untyped::SyntaxKind::TK_RANGE };
685 ["cycle"] => { $crate::syntax::untyped::SyntaxKind::TK_CYCLE };
686 ["random"] => { $crate::syntax::untyped::SyntaxKind::TK_RANDOM };
687 ["date"] => { $crate::syntax::untyped::SyntaxKind::TK_DATE };
688 ["include"] => { $crate::syntax::untyped::SyntaxKind::TK_INCLUDE };
689 ["source"] => { $crate::syntax::untyped::SyntaxKind::TK_SOURCE };
690 ["trans"] => { $crate::syntax::untyped::SyntaxKind::TK_TRANS };
691 ["endtrans"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDTRANS };
692 ["sw_extends"] => { $crate::syntax::untyped::SyntaxKind::TK_SW_EXTENDS };
693 ["sw_silent_feature_call"] => { $crate::syntax::untyped::SyntaxKind::TK_SW_SILENT_FEATURE_CALL };
694 ["endsw_silent_feature_call"] => { $crate::syntax::untyped::SyntaxKind::TK_ENDSW_SILENT_FEATURE_CALL };
695 ["sw_include"] => { $crate::syntax::untyped::SyntaxKind::TK_SW_INCLUDE };
696 ["return"] => { $crate::syntax::untyped::SyntaxKind::TK_RETURN };
697 ["sw_icon"] => { $crate::syntax::untyped::SyntaxKind::TK_SW_ICON };
698 ["sw_thumbnails"] => { $crate::syntax::untyped::SyntaxKind::TK_SW_THUMBNAILS };
699 ["style"] => { $crate::syntax::untyped::SyntaxKind::TK_STYLE };
700 ["ludtwig-ignore-file"] => { $crate::syntax::untyped::SyntaxKind::TK_LUDTWIG_IGNORE_FILE };
701 ["ludtwig-ignore"] => { $crate::syntax::untyped::SyntaxKind::TK_LUDTWIG_IGNORE };
702}
703
704impl SyntaxKind {
705 #[must_use]
706 pub fn is_trivia(self) -> bool {
707 matches!(self, T![ws] | T![lb])
709 }
710}
711
712#[allow(clippy::too_many_lines)]
713impl fmt::Display for SyntaxKind {
714 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
715 f.write_str(match self {
716 SyntaxKind::TK_WHITESPACE => "whitespace",
717 SyntaxKind::TK_LINE_BREAK => "line break",
718 SyntaxKind::TK_WORD => "word",
719 SyntaxKind::TK_TWIG_COMPONENT_NAME => "twig component name",
720 SyntaxKind::TK_NUMBER => "number",
721 SyntaxKind::TK_HTML_ESCAPE_CHARACTER => "html escape character",
722 SyntaxKind::TK_DOT => ".",
723 SyntaxKind::TK_DOUBLE_DOT => "..",
724 SyntaxKind::TK_TRIPLE_DOT => "...",
725 SyntaxKind::TK_COMMA => ",",
726 SyntaxKind::TK_COLON => ":",
727 SyntaxKind::TK_SEMICOLON => ";",
728 SyntaxKind::TK_EXCLAMATION_MARK => "!",
729 SyntaxKind::TK_EXCLAMATION_MARK_EQUALS => "!=",
730 SyntaxKind::TK_EXCLAMATION_MARK_DOUBLE_EQUALS => "!==",
731 SyntaxKind::TK_QUESTION_MARK => "?",
732 SyntaxKind::TK_DOUBLE_QUESTION_MARK => "??",
733 SyntaxKind::TK_PERCENT => "%",
734 SyntaxKind::TK_TILDE => "~",
735 SyntaxKind::TK_SINGLE_PIPE => "|",
736 SyntaxKind::TK_DOUBLE_PIPE => "||",
737 SyntaxKind::TK_AMPERSAND => "&",
738 SyntaxKind::TK_DOUBLE_AMPERSAND => "&&",
739 SyntaxKind::TK_FORWARD_SLASH => "/",
740 SyntaxKind::TK_DOUBLE_FORWARD_SLASH => "//",
741 SyntaxKind::TK_BACKWARD_SLASH => "\\",
742 SyntaxKind::TK_OPEN_PARENTHESIS => "(",
743 SyntaxKind::TK_CLOSE_PARENTHESIS => ")",
744 SyntaxKind::TK_OPEN_CURLY => "{",
745 SyntaxKind::TK_CLOSE_CURLY => "}",
746 SyntaxKind::TK_OPEN_SQUARE => "[",
747 SyntaxKind::TK_CLOSE_SQUARE => "]",
748 SyntaxKind::TK_LESS_THAN => "<",
749 SyntaxKind::TK_LESS_THAN_EQUAL => "<=",
750 SyntaxKind::TK_LESS_THAN_EQUAL_GREATER_THAN => "<=>",
751 SyntaxKind::TK_LESS_THAN_SLASH => "</",
752 SyntaxKind::TK_LESS_THAN_EXCLAMATION_MARK => "<!",
753 SyntaxKind::TK_DOCTYPE => "DOCTYPE",
754 SyntaxKind::TK_GREATER_THAN => ">",
755 SyntaxKind::TK_GREATER_THAN_EQUAL => ">=",
756 SyntaxKind::TK_EQUAL_GREATER_THAN => "=>",
757 SyntaxKind::TK_SLASH_GREATER_THAN => "/>",
758 SyntaxKind::TK_LESS_THAN_EXCLAMATION_MARK_MINUS_MINUS => "<!--",
759 SyntaxKind::TK_MINUS_MINUS_GREATER_THAN => "-->",
760 SyntaxKind::TK_EQUAL => "=",
761 SyntaxKind::TK_DOUBLE_EQUAL => "==",
762 SyntaxKind::TK_TRIPLE_EQUAL => "===",
763 SyntaxKind::TK_PLUS => "+",
764 SyntaxKind::TK_MINUS => "-",
765 SyntaxKind::TK_STAR => "*",
766 SyntaxKind::TK_DOUBLE_STAR => "**",
767 SyntaxKind::TK_DOUBLE_QUOTES => "\"",
768 SyntaxKind::TK_SINGLE_QUOTES => "'",
769 SyntaxKind::TK_GRAVE_ACCENT_QUOTES => "`",
770 SyntaxKind::TK_CURLY_PERCENT => "{%",
771 SyntaxKind::TK_PERCENT_CURLY => "%}",
772 SyntaxKind::TK_OPEN_CURLY_CURLY => "{{",
773 SyntaxKind::TK_CLOSE_CURLY_CURLY => "}}",
774 SyntaxKind::TK_OPEN_CURLY_HASHTAG => "{#",
775 SyntaxKind::TK_HASHTAG_CLOSE_CURLY => "#}",
776 SyntaxKind::TK_HASHTAG => "#",
777 SyntaxKind::TK_TRUE => "true",
778 SyntaxKind::TK_FALSE => "false",
779 SyntaxKind::TK_BLOCK => "block",
780 SyntaxKind::TK_ENDBLOCK => "endblock",
781 SyntaxKind::TK_IF => "if",
782 SyntaxKind::TK_ELSE_IF => "elseif",
783 SyntaxKind::TK_ELSE => "else",
784 SyntaxKind::TK_ENDIF => "endif",
785 SyntaxKind::TK_APPLY => "apply",
786 SyntaxKind::TK_ENDAPPLY => "endapply",
787 SyntaxKind::TK_AUTOESCAPE => "autoescape",
788 SyntaxKind::TK_ENDAUTOESCAPE => "endautoescape",
789 SyntaxKind::TK_CACHE => "cache",
790 SyntaxKind::TK_ENDCACHE => "endcache",
791 SyntaxKind::TK_DEPRECATED => "deprecated",
792 SyntaxKind::TK_DO => "do",
793 SyntaxKind::TK_EMBED => "embed",
794 SyntaxKind::TK_ENDEMBED => "endembed",
795 SyntaxKind::TK_EXTENDS => "extends",
796 SyntaxKind::TK_FLUSH => "flush",
797 SyntaxKind::TK_FOR => "for",
798 SyntaxKind::TK_ENDFOR => "endfor",
799 SyntaxKind::TK_FROM => "from",
800 SyntaxKind::TK_IMPORT => "import",
801 SyntaxKind::TK_MACRO => "macro",
802 SyntaxKind::TK_ENDMACRO => "endmacro",
803 SyntaxKind::TK_SANDBOX => "sandbox",
804 SyntaxKind::TK_ENDSANDBOX => "endsandbox",
805 SyntaxKind::TK_SET => "set",
806 SyntaxKind::TK_ENDSET => "endset",
807 SyntaxKind::TK_USE => "use",
808 SyntaxKind::TK_VERBATIM => "verbatim",
809 SyntaxKind::TK_ENDVERBATIM => "endverbatim",
810 SyntaxKind::TK_ONLY => "only",
811 SyntaxKind::TK_IGNORE_MISSING => "ignore missing",
812 SyntaxKind::TK_WITH => "with",
813 SyntaxKind::TK_ENDWITH => "endwith",
814 SyntaxKind::TK_TTL => "ttl",
815 SyntaxKind::TK_TAGS => "tags",
816 SyntaxKind::TK_PROPS => "props",
817 SyntaxKind::TK_COMPONENT => "component",
818 SyntaxKind::TK_ENDCOMPONENT => "endcomponent",
819 SyntaxKind::TK_NOT => "not",
820 SyntaxKind::TK_NOT_IN => "not in",
821 SyntaxKind::TK_OR => "or",
822 SyntaxKind::TK_AND => "and",
823 SyntaxKind::TK_BINARY_OR => "b-or",
824 SyntaxKind::TK_BINARY_XOR => "b-xor",
825 SyntaxKind::TK_BINARY_AND => "b-and",
826 SyntaxKind::TK_IN => "in",
827 SyntaxKind::TK_MATCHES => "matches",
828 SyntaxKind::TK_STARTS_WITH => "starts with",
829 SyntaxKind::TK_ENDS_WITH => "ends with",
830 SyntaxKind::TK_IS => "is",
831 SyntaxKind::TK_IS_NOT => "is not",
832 SyntaxKind::TK_EVEN => "even",
833 SyntaxKind::TK_ODD => "odd",
834 SyntaxKind::TK_DEFINED => "defined",
835 SyntaxKind::TK_SAME_AS => "same as",
836 SyntaxKind::TK_AS => "as",
837 SyntaxKind::TK_NONE => "none",
838 SyntaxKind::TK_NULL => "null",
839 SyntaxKind::TK_DIVISIBLE_BY => "divisible by",
840 SyntaxKind::TK_CONSTANT => "constant",
841 SyntaxKind::TK_EMPTY => "empty",
842 SyntaxKind::TK_ITERABLE => "iterable",
843 SyntaxKind::TK_MAX => "max",
844 SyntaxKind::TK_MIN => "min",
845 SyntaxKind::TK_RANGE => "range",
846 SyntaxKind::TK_CYCLE => "cycle",
847 SyntaxKind::TK_RANDOM => "random",
848 SyntaxKind::TK_DATE => "date",
849 SyntaxKind::TK_INCLUDE => "include",
850 SyntaxKind::TK_SOURCE => "source",
851 SyntaxKind::TK_TRANS => "trans",
852 SyntaxKind::TK_ENDTRANS => "endtrans",
853 SyntaxKind::TK_SW_EXTENDS => "sw_extends",
854 SyntaxKind::TK_SW_SILENT_FEATURE_CALL => "sw_silent_feature_call",
855 SyntaxKind::TK_ENDSW_SILENT_FEATURE_CALL => "endsw_silent_feature_call",
856 SyntaxKind::TK_SW_INCLUDE => "sw_include",
857 SyntaxKind::TK_RETURN => "return",
858 SyntaxKind::TK_SW_ICON => "sw_icon",
859 SyntaxKind::TK_SW_THUMBNAILS => "sw_thumbnails",
860 SyntaxKind::TK_STYLE => "style",
861 SyntaxKind::TK_LUDTWIG_IGNORE_FILE => "ludtwig-ignore-file",
862 SyntaxKind::TK_LUDTWIG_IGNORE => "ludtwig-ignore",
863 SyntaxKind::TK_UNKNOWN => "unknown",
864 SyntaxKind::ERROR => "error",
865 t => unreachable!("Display not implemented for {:?}", t),
866 })
867 }
868}
869
870impl From<SyntaxKind> for rowan::SyntaxKind {
876 fn from(kind: SyntaxKind) -> Self {
877 Self(kind as u16)
878 }
879}
880
881#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
885pub enum TemplateLanguage {}
886impl Language for TemplateLanguage {
887 type Kind = SyntaxKind;
888 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
889 assert!(raw.0 <= SyntaxKind::ROOT as u16);
890 unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
891 }
892 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
893 kind.into()
894 }
895}
896
897pub type SyntaxNode = rowan::SyntaxNode<TemplateLanguage>;
903pub type SyntaxToken = rowan::SyntaxToken<TemplateLanguage>;
904pub type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
905pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<TemplateLanguage>;
906pub type SyntaxElementChildren = rowan::SyntaxElementChildren<TemplateLanguage>;
907pub type Preorder = rowan::api::Preorder<TemplateLanguage>;
908pub type PreorderWithTokens = rowan::api::PreorderWithTokens<TemplateLanguage>;
909
910#[must_use]
911pub fn debug_tree(syntax_node: &SyntaxNode) -> String {
912 let formatted = format!("{syntax_node:#?}");
913 formatted[0..formatted.len() - 1].to_string()
915}
916
917pub trait SyntaxNodeExt {
918 fn text_range_trimmed_trivia(&self) -> TextRange;
919}
920
921impl SyntaxNodeExt for SyntaxNode {
922 fn text_range_trimmed_trivia(&self) -> TextRange {
924 let mut range = self.text_range();
925
926 for element in self.children_with_tokens() {
927 match element {
928 SyntaxElement::Token(t) if t.kind().is_trivia() => {
929 let new_start = range.start() + t.text_range().len();
930 if new_start < range.end() {
931 range = TextRange::new(new_start, range.end());
932 }
933 }
934 _ => return range,
935 }
936 }
937
938 range
939 }
940}