aboutsummaryrefslogtreecommitdiff
path: root/xtask/src
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src')
-rw-r--r--xtask/src/ast_src.rs621
-rw-r--r--xtask/src/boilerplate_gen.rs0
-rw-r--r--xtask/src/codegen.rs1
-rw-r--r--xtask/src/codegen/gen_syntax.rs234
-rw-r--r--xtask/src/lib.rs1
5 files changed, 720 insertions, 137 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
new file mode 100644
index 000000000..67d1f41bc
--- /dev/null
+++ b/xtask/src/ast_src.rs
@@ -0,0 +1,621 @@
1pub(crate) struct KindsSrc<'a> {
2 pub(crate) punct: &'a [(&'a str, &'a str)],
3 pub(crate) keywords: &'a [&'a str],
4 pub(crate) contextual_keywords: &'a [&'a str],
5 pub(crate) literals: &'a [&'a str],
6 pub(crate) tokens: &'a [&'a str],
7 pub(crate) nodes: &'a [&'a str],
8}
9
10pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
11 punct: &[
12 (";", "SEMI"),
13 (",", "COMMA"),
14 ("(", "L_PAREN"),
15 (")", "R_PAREN"),
16 ("{", "L_CURLY"),
17 ("}", "R_CURLY"),
18 ("[", "L_BRACK"),
19 ("]", "R_BRACK"),
20 ("<", "L_ANGLE"),
21 (">", "R_ANGLE"),
22 ("@", "AT"),
23 ("#", "POUND"),
24 ("~", "TILDE"),
25 ("?", "QUESTION"),
26 ("$", "DOLLAR"),
27 ("&", "AMP"),
28 ("|", "PIPE"),
29 ("+", "PLUS"),
30 ("*", "STAR"),
31 ("/", "SLASH"),
32 ("^", "CARET"),
33 ("%", "PERCENT"),
34 ("_", "UNDERSCORE"),
35 (".", "DOT"),
36 ("..", "DOTDOT"),
37 ("...", "DOTDOTDOT"),
38 ("..=", "DOTDOTEQ"),
39 (":", "COLON"),
40 ("::", "COLONCOLON"),
41 ("=", "EQ"),
42 ("==", "EQEQ"),
43 ("=>", "FAT_ARROW"),
44 ("!", "EXCL"),
45 ("!=", "NEQ"),
46 ("-", "MINUS"),
47 ("->", "THIN_ARROW"),
48 ("<=", "LTEQ"),
49 (">=", "GTEQ"),
50 ("+=", "PLUSEQ"),
51 ("-=", "MINUSEQ"),
52 ("|=", "PIPEEQ"),
53 ("&=", "AMPEQ"),
54 ("^=", "CARETEQ"),
55 ("/=", "SLASHEQ"),
56 ("*=", "STAREQ"),
57 ("%=", "PERCENTEQ"),
58 ("&&", "AMPAMP"),
59 ("||", "PIPEPIPE"),
60 ("<<", "SHL"),
61 (">>", "SHR"),
62 ("<<=", "SHLEQ"),
63 (">>=", "SHREQ"),
64 ],
65 keywords: &[
66 "as", "async", "await", "box", "break", "const", "continue", "crate", "dyn", "else",
67 "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro",
68 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
69 "trait", "true", "try", "type", "unsafe", "use", "where", "while",
70 ],
71 contextual_keywords: &["auto", "default", "existential", "union"],
72 literals: &[
73 "INT_NUMBER",
74 "FLOAT_NUMBER",
75 "CHAR",
76 "BYTE",
77 "STRING",
78 "RAW_STRING",
79 "BYTE_STRING",
80 "RAW_BYTE_STRING",
81 ],
82 tokens: &[
83 "ERROR",
84 "IDENT",
85 "WHITESPACE",
86 "LIFETIME",
87 "COMMENT",
88 "SHEBANG",
89 "L_DOLLAR",
90 "R_DOLLAR",
91 ],
92 nodes: &[
93 "SOURCE_FILE",
94 "STRUCT_DEF",
95 "UNION_DEF",
96 "ENUM_DEF",
97 "FN_DEF",
98 "RET_TYPE",
99 "EXTERN_CRATE_ITEM",
100 "MODULE",
101 "USE_ITEM",
102 "STATIC_DEF",
103 "CONST_DEF",
104 "TRAIT_DEF",
105 "IMPL_BLOCK",
106 "TYPE_ALIAS_DEF",
107 "MACRO_CALL",
108 "TOKEN_TREE",
109 "MACRO_DEF",
110 "PAREN_TYPE",
111 "TUPLE_TYPE",
112 "NEVER_TYPE",
113 "PATH_TYPE",
114 "POINTER_TYPE",
115 "ARRAY_TYPE",
116 "SLICE_TYPE",
117 "REFERENCE_TYPE",
118 "PLACEHOLDER_TYPE",
119 "FN_POINTER_TYPE",
120 "FOR_TYPE",
121 "IMPL_TRAIT_TYPE",
122 "DYN_TRAIT_TYPE",
123 "REF_PAT",
124 "BOX_PAT",
125 "BIND_PAT",
126 "PLACEHOLDER_PAT",
127 "DOT_DOT_PAT",
128 "PATH_PAT",
129 "RECORD_PAT",
130 "RECORD_FIELD_PAT_LIST",
131 "RECORD_FIELD_PAT",
132 "TUPLE_STRUCT_PAT",
133 "TUPLE_PAT",
134 "SLICE_PAT",
135 "RANGE_PAT",
136 "LITERAL_PAT",
137 // atoms
138 "TUPLE_EXPR",
139 "ARRAY_EXPR",
140 "PAREN_EXPR",
141 "PATH_EXPR",
142 "LAMBDA_EXPR",
143 "IF_EXPR",
144 "WHILE_EXPR",
145 "CONDITION",
146 "LOOP_EXPR",
147 "FOR_EXPR",
148 "CONTINUE_EXPR",
149 "BREAK_EXPR",
150 "LABEL",
151 "BLOCK_EXPR",
152 "RETURN_EXPR",
153 "MATCH_EXPR",
154 "MATCH_ARM_LIST",
155 "MATCH_ARM",
156 "MATCH_GUARD",
157 "RECORD_LIT",
158 "RECORD_FIELD_LIST",
159 "RECORD_FIELD",
160 "TRY_BLOCK_EXPR",
161 "BOX_EXPR",
162 // postfix
163 "CALL_EXPR",
164 "INDEX_EXPR",
165 "METHOD_CALL_EXPR",
166 "FIELD_EXPR",
167 "AWAIT_EXPR",
168 "TRY_EXPR",
169 "CAST_EXPR",
170 // unary
171 "REF_EXPR",
172 "PREFIX_EXPR",
173 "RANGE_EXPR", // just weird
174 "BIN_EXPR",
175 "BLOCK",
176 "EXTERN_BLOCK",
177 "EXTERN_ITEM_LIST",
178 "ENUM_VARIANT",
179 "RECORD_FIELD_DEF_LIST",
180 "RECORD_FIELD_DEF",
181 "TUPLE_FIELD_DEF_LIST",
182 "TUPLE_FIELD_DEF",
183 "ENUM_VARIANT_LIST",
184 "ITEM_LIST",
185 "ATTR",
186 "META_ITEM", // not an item actually
187 "USE_TREE",
188 "USE_TREE_LIST",
189 "PATH",
190 "PATH_SEGMENT",
191 "LITERAL",
192 "ALIAS",
193 "VISIBILITY",
194 "WHERE_CLAUSE",
195 "WHERE_PRED",
196 "ABI",
197 "NAME",
198 "NAME_REF",
199 "LET_STMT",
200 "EXPR_STMT",
201 "TYPE_PARAM_LIST",
202 "LIFETIME_PARAM",
203 "TYPE_PARAM",
204 "CONST_PARAM",
205 "TYPE_ARG_LIST",
206 "LIFETIME_ARG",
207 "TYPE_ARG",
208 "ASSOC_TYPE_ARG",
209 "CONST_ARG",
210 "PARAM_LIST",
211 "PARAM",
212 "SELF_PARAM",
213 "ARG_LIST",
214 "TYPE_BOUND",
215 "TYPE_BOUND_LIST",
216 // macro related
217 "MACRO_ITEMS",
218 "MACRO_STMTS",
219 ],
220};
221
222pub(crate) struct AstSrc<'a> {
223 pub(crate) nodes: &'a [AstNodeSrc<'a>],
224 pub(crate) enums: &'a [AstEnumSrc<'a>],
225}
226
227pub(crate) struct AstNodeSrc<'a> {
228 pub(crate) name: &'a str,
229 pub(crate) traits: &'a [&'a str],
230 pub(crate) fields: &'a [(&'a str, FieldSrc<&'a str>)],
231}
232
233pub(crate) enum FieldSrc<T> {
234 Shorthand,
235 Optional(T),
236 Many(T),
237}
238
239pub(crate) struct AstEnumSrc<'a> {
240 pub(crate) name: &'a str,
241 pub(crate) traits: &'a [&'a str],
242 pub(crate) variants: &'a [&'a str],
243}
244
245macro_rules! ast_nodes {
246 ($(
247 struct $name:ident$(: $($trait:ident),*)? {
248 $($field_name:ident $(: $ty:tt)?),*$(,)?
249 }
250 )*) => {
251 [$(
252 AstNodeSrc {
253 name: stringify!($name),
254 traits: &[$($(stringify!($trait)),*)?],
255 fields: &[$(
256 (stringify!($field_name), field_ty!($field_name $($ty)?))
257 ),*],
258
259 }
260 ),*]
261 };
262}
263
264macro_rules! field_ty {
265 ($field_name:ident) => {
266 FieldSrc::Shorthand
267 };
268 ($field_name:ident [$ty:ident]) => {
269 FieldSrc::Many(stringify!($ty))
270 };
271 ($field_name:ident $ty:ident) => {
272 FieldSrc::Optional(stringify!($ty))
273 };
274}
275
276macro_rules! ast_enums {
277 ($(
278 enum $name:ident $(: $($trait:ident),*)? {
279 $($variant:ident),*$(,)?
280 }
281 )*) => {
282 [$(
283 AstEnumSrc {
284 name: stringify!($name),
285 traits: &[$($(stringify!($trait)),*)?],
286 variants: &[$(stringify!($variant)),*],
287
288 }
289 ),*]
290 };
291}
292
293pub(crate) const AST_SRC: AstSrc = AstSrc {
294 nodes: &ast_nodes! {
295 struct SourceFile: ModuleItemOwner, FnDefOwner {
296 modules: [Module],
297 }
298
299 struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
300 ParamList,
301 RetType,
302 body: BlockExpr,
303 }
304
305 struct RetType { TypeRef }
306
307 struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
308 }
309
310 struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
311 RecordFieldDefList,
312 }
313
314 struct RecordFieldDefList { fields: [RecordFieldDef] }
315 struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
316
317 struct TupleFieldDefList { fields: [TupleFieldDef] }
318 struct TupleFieldDef: VisibilityOwner, AttrsOwner {
319 TypeRef,
320 }
321
322 struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
323 variant_list: EnumVariantList,
324 }
325 struct EnumVariantList {
326 variants: [EnumVariant],
327 }
328 struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner {
329 Expr
330 }
331
332 struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
333 ItemList,
334 }
335
336 struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
337 ItemList,
338 }
339
340 struct ItemList: FnDefOwner, ModuleItemOwner {
341 impl_items: [ImplItem],
342 }
343
344 struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
345 body: Expr,
346 }
347
348 struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
349 body: Expr,
350 }
351
352 struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
353 TypeRef,
354 }
355
356 struct ImplBlock: TypeParamsOwner, AttrsOwner {
357 ItemList,
358 }
359
360 struct ParenType { TypeRef }
361 struct TupleType { fields: [TypeRef] }
362 struct NeverType { }
363 struct PathType { Path }
364 struct PointerType { TypeRef }
365 struct ArrayType { TypeRef, Expr }
366 struct SliceType { TypeRef }
367 struct ReferenceType { TypeRef }
368 struct PlaceholderType { }
369 struct FnPointerType { ParamList, RetType }
370 struct ForType { TypeRef }
371 struct ImplTraitType: TypeBoundsOwner {}
372 struct DynTraitType: TypeBoundsOwner {}
373
374 struct TupleExpr { exprs: [Expr] }
375 struct ArrayExpr { exprs: [Expr] }
376 struct ParenExpr { Expr }
377 struct PathExpr { Path }
378 struct LambdaExpr {
379 ParamList,
380 RetType,
381 body: Expr,
382 }
383 struct IfExpr { Condition }
384 struct LoopExpr: LoopBodyOwner { }
385 struct TryBlockExpr { body: BlockExpr }
386 struct ForExpr: LoopBodyOwner {
387 Pat,
388 iterable: Expr,
389 }
390 struct WhileExpr: LoopBodyOwner { Condition }
391 struct ContinueExpr {}
392 struct BreakExpr { Expr }
393 struct Label {}
394 struct BlockExpr { Block }
395 struct ReturnExpr { Expr }
396 struct CallExpr: ArgListOwner { Expr }
397 struct MethodCallExpr: ArgListOwner {
398 Expr, NameRef, TypeArgList,
399 }
400 struct IndexExpr {}
401 struct FieldExpr { Expr, NameRef }
402 struct AwaitExpr { Expr }
403 struct TryExpr { Expr }
404 struct CastExpr { Expr, TypeRef }
405 struct RefExpr { Expr }
406 struct PrefixExpr { Expr }
407 struct BoxExpr { Expr }
408 struct RangeExpr {}
409 struct BinExpr {}
410 struct Literal {}
411
412 struct MatchExpr { Expr, MatchArmList }
413 struct MatchArmList: AttrsOwner { arms: [MatchArm] }
414 struct MatchArm: AttrsOwner {
415 pats: [Pat],
416 guard: MatchGuard,
417 Expr,
418 }
419 struct MatchGuard { Expr }
420
421 struct RecordLit { Path, RecordFieldList }
422 struct RecordFieldList {
423 fields: [RecordField],
424 spread: Expr,
425 }
426 struct RecordField { NameRef, Expr }
427
428 struct RefPat { Pat }
429 struct BoxPat { Pat }
430 struct BindPat: NameOwner { Pat }
431 struct PlaceholderPat { }
432 struct DotDotPat { }
433 struct PathPat { Path }
434 struct SlicePat {}
435 struct RangePat {}
436 struct LiteralPat { Literal }
437
438 struct RecordPat { RecordFieldPatList, Path }
439 struct RecordFieldPatList {
440 record_field_pats: [RecordFieldPat],
441 bind_pats: [BindPat],
442 }
443 struct RecordFieldPat: NameOwner { Pat }
444
445 struct TupleStructPat { Path, args: [Pat] }
446 struct TuplePat { args: [Pat] }
447
448 struct Visibility {}
449 struct Name {}
450 struct NameRef {}
451
452 struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner {
453 TokenTree, Path
454 }
455 struct Attr { Path, input: AttrInput }
456 struct TokenTree {}
457 struct TypeParamList {
458 type_params: [TypeParam],
459 lifetime_params: [LifetimeParam],
460 }
461 struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
462 default_type: TypeRef,
463 }
464 struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
465 default_val: Expr,
466 }
467 struct LifetimeParam: AttrsOwner { }
468 struct TypeBound { TypeRef}
469 struct TypeBoundList { bounds: [TypeBound] }
470 struct WherePred: TypeBoundsOwner { TypeRef }
471 struct WhereClause { predicates: [WherePred] }
472 struct ExprStmt { Expr }
473 struct LetStmt: TypeAscriptionOwner {
474 Pat,
475 initializer: Expr,
476 }
477 struct Condition { Pat, Expr }
478 struct Block: AttrsOwner, ModuleItemOwner {
479 statements: [Stmt],
480 Expr,
481 }
482 struct ParamList {
483 SelfParam,
484 params: [Param],
485 }
486 struct SelfParam: TypeAscriptionOwner, AttrsOwner { }
487 struct Param: TypeAscriptionOwner, AttrsOwner {
488 Pat,
489 }
490 struct UseItem: AttrsOwner, VisibilityOwner {
491 UseTree,
492 }
493 struct UseTree {
494 Path, UseTreeList, Alias
495 }
496 struct Alias: NameOwner { }
497 struct UseTreeList { use_trees: [UseTree] }
498 struct ExternCrateItem: AttrsOwner, VisibilityOwner {
499 NameRef, Alias,
500 }
501 struct ArgList {
502 args: [Expr],
503 }
504 struct Path {
505 segment: PathSegment,
506 qualifier: Path,
507 }
508 struct PathSegment {
509 NameRef, TypeArgList, ParamList, RetType, PathType,
510 }
511 struct TypeArgList {
512 type_args: [TypeArg],
513 lifetime_args: [LifetimeArg],
514 assoc_type_args: [AssocTypeArg],
515 const_arg: [ConstArg],
516 }
517 struct TypeArg { TypeRef }
518 struct AssocTypeArg { NameRef, TypeRef }
519 struct LifetimeArg {}
520 struct ConstArg { Literal, BlockExpr }
521
522 struct MacroItems: ModuleItemOwner, FnDefOwner { }
523
524 struct MacroStmts {
525 statements: [Stmt],
526 Expr,
527 }
528 },
529 enums: &ast_enums! {
530 enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
531 StructDef, EnumDef, UnionDef,
532 }
533
534 enum TypeRef {
535 ParenType,
536 TupleType,
537 NeverType,
538 PathType,
539 PointerType,
540 ArrayType,
541 SliceType,
542 ReferenceType,
543 PlaceholderType,
544 FnPointerType,
545 ForType,
546 ImplTraitType,
547 DynTraitType,
548 }
549
550 enum ModuleItem: AttrsOwner, VisibilityOwner {
551 StructDef,
552 UnionDef,
553 EnumDef,
554 FnDef,
555 TraitDef,
556 TypeAliasDef,
557 ImplBlock,
558 UseItem,
559 ExternCrateItem,
560 ConstDef,
561 StaticDef,
562 Module,
563 }
564
565 enum ImplItem: AttrsOwner {
566 FnDef, TypeAliasDef, ConstDef,
567 }
568
569 enum Expr {
570 TupleExpr,
571 ArrayExpr,
572 ParenExpr,
573 PathExpr,
574 LambdaExpr,
575 IfExpr,
576 LoopExpr,
577 ForExpr,
578 WhileExpr,
579 ContinueExpr,
580 BreakExpr,
581 Label,
582 BlockExpr,
583 ReturnExpr,
584 MatchExpr,
585 RecordLit,
586 CallExpr,
587 IndexExpr,
588 MethodCallExpr,
589 FieldExpr,
590 AwaitExpr,
591 TryExpr,
592 TryBlockExpr,
593 CastExpr,
594 RefExpr,
595 PrefixExpr,
596 RangeExpr,
597 BinExpr,
598 Literal,
599 MacroCall,
600 BoxExpr,
601 }
602
603 enum Pat {
604 RefPat,
605 BoxPat,
606 BindPat,
607 PlaceholderPat,
608 DotDotPat,
609 PathPat,
610 RecordPat,
611 TupleStructPat,
612 TuplePat,
613 SlicePat,
614 RangePat,
615 LiteralPat,
616 }
617
618 enum AttrInput { Literal, TokenTree }
619 enum Stmt { ExprStmt, LetStmt }
620 },
621};
diff --git a/xtask/src/boilerplate_gen.rs b/xtask/src/boilerplate_gen.rs
deleted file mode 100644
index e69de29bb..000000000
--- a/xtask/src/boilerplate_gen.rs
+++ /dev/null
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 53f524f42..158cfc2d6 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -24,7 +24,6 @@ pub use self::{
24 gen_syntax::generate_syntax, 24 gen_syntax::generate_syntax,
25}; 25};
26 26
27pub const GRAMMAR: &str = "crates/ra_syntax/src/grammar.ron";
28const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; 27const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
29const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok"; 28const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
30const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err"; 29const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index 88f2ac0e3..0f50ca569 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -3,149 +3,142 @@
3//! Specifically, it generates the `SyntaxKind` enum and a number of newtype 3//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
4//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. 4//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`.
5 5
6use std::{collections::BTreeMap, fs};
7
8use proc_macro2::{Punct, Spacing}; 6use proc_macro2::{Punct, Spacing};
9use quote::{format_ident, quote}; 7use quote::{format_ident, quote};
10use ron;
11use serde::Deserialize;
12 8
13use crate::{ 9use crate::{
10 ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
14 codegen::{self, update, Mode}, 11 codegen::{self, update, Mode},
15 project_root, Result, 12 project_root, Result,
16}; 13};
17 14
18pub fn generate_syntax(mode: Mode) -> Result<()> { 15pub fn generate_syntax(mode: Mode) -> Result<()> {
19 let grammar = project_root().join(codegen::GRAMMAR);
20 let grammar: Grammar = {
21 let text = fs::read_to_string(grammar)?;
22 ron::de::from_str(&text)?
23 };
24
25 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); 16 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS);
26 let syntax_kinds = generate_syntax_kinds(&grammar)?; 17 let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
27 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; 18 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
28 19
29 let ast_file = project_root().join(codegen::AST); 20 let ast_file = project_root().join(codegen::AST);
30 let ast = generate_ast(&grammar)?; 21 let ast = generate_ast(AST_SRC)?;
31 update(ast_file.as_path(), &ast, mode)?; 22 update(ast_file.as_path(), &ast, mode)?;
32 23
33 Ok(()) 24 Ok(())
34} 25}
35 26
36fn generate_ast(grammar: &Grammar) -> Result<String> { 27fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
37 let nodes = grammar.ast.iter().map(|(name, ast_node)| { 28 let nodes = grammar.nodes.iter().map(|node| {
38 let variants = 29 let name = format_ident!("{}", node.name);
39 ast_node.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); 30 let kind = format_ident!("{}", to_upper_snake_case(&name.to_string()));
40 let name = format_ident!("{}", name); 31 let traits = node.traits.iter().map(|trait_name| {
41 32 let trait_name = format_ident!("{}", trait_name);
42 let adt = if variants.is_empty() { 33 quote!(impl ast::#trait_name for #name {})
43 let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); 34 });
44 quote! {
45 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
46 pub struct #name {
47 pub(crate) syntax: SyntaxNode,
48 }
49 35
50 impl AstNode for #name { 36 let methods = node.fields.iter().map(|(name, field)| {
51 fn can_cast(kind: SyntaxKind) -> bool { 37 let method_name = match field {
52 match kind { 38 FieldSrc::Shorthand => format_ident!("{}", to_lower_snake_case(&name)),
53 #kind => true, 39 _ => format_ident!("{}", name),
54 _ => false, 40 };
41 let ty = match field {
42 FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty,
43 FieldSrc::Shorthand => name,
44 };
45 let ty = format_ident!("{}", ty);
46
47 match field {
48 FieldSrc::Many(_) => {
49 quote! {
50 pub fn #method_name(&self) -> AstChildren<#ty> {
51 AstChildren::new(&self.syntax)
55 } 52 }
56 } 53 }
57 fn cast(syntax: SyntaxNode) -> Option<Self> { 54 }
58 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } 55 FieldSrc::Optional(_) | FieldSrc::Shorthand => {
56 quote! {
57 pub fn #method_name(&self) -> Option<#ty> {
58 AstChildren::new(&self.syntax).next()
59 }
59 } 60 }
60 fn syntax(&self) -> &SyntaxNode { &self.syntax }
61 } 61 }
62 } 62 }
63 } else { 63 });
64 let kinds = variants
65 .iter()
66 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
67 .collect::<Vec<_>>();
68
69 quote! {
70 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
71 pub enum #name {
72 #(#variants(#variants),)*
73 }
74 64
75 #( 65 quote! {
76 impl From<#variants> for #name { 66 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
77 fn from(node: #variants) -> #name { 67 pub struct #name {
78 #name::#variants(node) 68 pub(crate) syntax: SyntaxNode,
79 } 69 }
80 }
81 )*
82 70
83 impl AstNode for #name { 71 impl AstNode for #name {
84 fn can_cast(kind: SyntaxKind) -> bool { 72 fn can_cast(kind: SyntaxKind) -> bool {
85 match kind { 73 match kind {
86 #(#kinds)|* => true, 74 #kind => true,
87 _ => false, 75 _ => false,
88 }
89 }
90 fn cast(syntax: SyntaxNode) -> Option<Self> {
91 let res = match syntax.kind() {
92 #(
93 #kinds => #name::#variants(#variants { syntax }),
94 )*
95 _ => return None,
96 };
97 Some(res)
98 }
99 fn syntax(&self) -> &SyntaxNode {
100 match self {
101 #(
102 #name::#variants(it) => &it.syntax,
103 )*
104 }
105 } 76 }
106 } 77 }
78 fn cast(syntax: SyntaxNode) -> Option<Self> {
79 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
80 }
81 fn syntax(&self) -> &SyntaxNode { &self.syntax }
107 } 82 }
108 }; 83 #(#traits)*
84
85 impl #name {
86 #(#methods)*
87 }
88 }
89 });
109 90
110 let traits = ast_node.traits.iter().map(|trait_name| { 91 let enums = grammar.enums.iter().map(|en| {
92 let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
93 let name = format_ident!("{}", en.name);
94 let kinds = variants
95 .iter()
96 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
97 .collect::<Vec<_>>();
98 let traits = en.traits.iter().map(|trait_name| {
111 let trait_name = format_ident!("{}", trait_name); 99 let trait_name = format_ident!("{}", trait_name);
112 quote!(impl ast::#trait_name for #name {}) 100 quote!(impl ast::#trait_name for #name {})
113 }); 101 });
114 102
115 let collections = ast_node.collections.iter().map(|(name, kind)| { 103 quote! {
116 let method_name = format_ident!("{}", name); 104 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
117 let kind = format_ident!("{}", kind); 105 pub enum #name {
118 quote! { 106 #(#variants(#variants),)*
119 pub fn #method_name(&self) -> AstChildren<#kind> {
120 AstChildren::new(&self.syntax)
121 }
122 } 107 }
123 });
124 108
125 let options = ast_node.options.iter().map(|attr| { 109 #(
126 let method_name = match attr { 110 impl From<#variants> for #name {
127 Attr::Type(t) => format_ident!("{}", to_lower_snake_case(&t)), 111 fn from(node: #variants) -> #name {
128 Attr::NameType(n, _) => format_ident!("{}", n), 112 #name::#variants(node)
129 };
130 let ty = match attr {
131 Attr::Type(t) | Attr::NameType(_, t) => format_ident!("{}", t),
132 };
133 quote! {
134 pub fn #method_name(&self) -> Option<#ty> {
135 AstChildren::new(&self.syntax).next()
136 } 113 }
137 } 114 }
138 }); 115 )*
139
140 quote! {
141 #adt
142
143 #(#traits)*
144 116
145 impl #name { 117 impl AstNode for #name {
146 #(#collections)* 118 fn can_cast(kind: SyntaxKind) -> bool {
147 #(#options)* 119 match kind {
120 #(#kinds)|* => true,
121 _ => false,
122 }
123 }
124 fn cast(syntax: SyntaxNode) -> Option<Self> {
125 let res = match syntax.kind() {
126 #(
127 #kinds => #name::#variants(#variants { syntax }),
128 )*
129 _ => return None,
130 };
131 Some(res)
132 }
133 fn syntax(&self) -> &SyntaxNode {
134 match self {
135 #(
136 #name::#variants(it) => &it.syntax,
137 )*
138 }
139 }
148 } 140 }
141 #(#traits)*
149 } 142 }
150 }); 143 });
151 144
@@ -156,13 +149,14 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
156 }; 149 };
157 150
158 #(#nodes)* 151 #(#nodes)*
152 #(#enums)*
159 }; 153 };
160 154
161 let pretty = codegen::reformat(ast)?; 155 let pretty = codegen::reformat(ast)?;
162 Ok(pretty) 156 Ok(pretty)
163} 157}
164 158
165fn generate_syntax_kinds(grammar: &Grammar) -> Result<String> { 159fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> {
166 let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar 160 let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
167 .punct 161 .punct
168 .iter() 162 .iter()
@@ -274,38 +268,6 @@ fn generate_syntax_kinds(grammar: &Grammar) -> Result<String> {
274 codegen::reformat(ast) 268 codegen::reformat(ast)
275} 269}
276 270
277#[derive(Deserialize, Debug)]
278struct Grammar {
279 punct: Vec<(String, String)>,
280 keywords: Vec<String>,
281 contextual_keywords: Vec<String>,
282 literals: Vec<String>,
283 tokens: Vec<String>,
284 nodes: Vec<String>,
285 ast: BTreeMap<String, AstNode>,
286}
287
288#[derive(Deserialize, Debug)]
289struct AstNode {
290 #[serde(default)]
291 #[serde(rename = "enum")]
292 variants: Vec<String>,
293
294 #[serde(default)]
295 traits: Vec<String>,
296 #[serde(default)]
297 collections: Vec<(String, String)>,
298 #[serde(default)]
299 options: Vec<Attr>,
300}
301
302#[derive(Deserialize, Debug)]
303#[serde(untagged)]
304enum Attr {
305 Type(String),
306 NameType(String, String),
307}
308
309fn to_upper_snake_case(s: &str) -> String { 271fn to_upper_snake_case(s: &str) -> String {
310 let mut buf = String::with_capacity(s.len()); 272 let mut buf = String::with_capacity(s.len());
311 let mut prev_is_upper = None; 273 let mut prev_is_upper = None;
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index 40a6682be..51a868dee 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -1,6 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3pub mod codegen; 3pub mod codegen;
4mod ast_src;
4 5
5use anyhow::Context; 6use anyhow::Context;
6pub use anyhow::Result; 7pub use anyhow::Result;