aboutsummaryrefslogtreecommitdiff
path: root/xtask
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-01-03 19:37:02 +0000
committerAleksey Kladov <[email protected]>2020-01-03 20:54:10 +0000
commit084bd304f304e674fc3d5b132daf8a9f975064c9 (patch)
tree1715adcc8ef9cb9bc48e73e6708f9452854c947f /xtask
parent67922a029a42e11a76711f9a2c71ca542973042c (diff)
Switch ast declaration from ron to a macro
Diffstat (limited to 'xtask')
-rw-r--r--xtask/Cargo.toml2
-rw-r--r--xtask/src/ast_src.rs618
-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, 717 insertions, 139 deletions
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 65cabf005..72dd5e581 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -13,6 +13,4 @@ walkdir = "2.1.3"
13pico-args = "0.3.0" 13pico-args = "0.3.0"
14quote = "1.0.2" 14quote = "1.0.2"
15proc-macro2 = "1.0.1" 15proc-macro2 = "1.0.1"
16ron = "0.5.1"
17serde = { version = "1.0.0", features = ["derive"] }
18anyhow = "1.0.19" 16anyhow = "1.0.19"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
new file mode 100644
index 000000000..d494a4a38
--- /dev/null
+++ b/xtask/src/ast_src.rs
@@ -0,0 +1,618 @@
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 "PARAM_LIST",
210 "PARAM",
211 "SELF_PARAM",
212 "ARG_LIST",
213 "TYPE_BOUND",
214 "TYPE_BOUND_LIST",
215 // macro related
216 "MACRO_ITEMS",
217 "MACRO_STMTS",
218 ],
219};
220
221pub(crate) struct AstSrc<'a> {
222 pub(crate) nodes: &'a [AstNodeSrc<'a>],
223 pub(crate) enums: &'a [AstEnumSrc<'a>],
224}
225
226pub(crate) struct AstNodeSrc<'a> {
227 pub(crate) name: &'a str,
228 pub(crate) traits: &'a [&'a str],
229 pub(crate) fields: &'a [(&'a str, FieldSrc<&'a str>)],
230}
231
232pub(crate) enum FieldSrc<T> {
233 Shorthand,
234 Optional(T),
235 Many(T),
236}
237
238pub(crate) struct AstEnumSrc<'a> {
239 pub(crate) name: &'a str,
240 pub(crate) traits: &'a [&'a str],
241 pub(crate) variants: &'a [&'a str],
242}
243
244macro_rules! ast_nodes {
245 ($(
246 struct $name:ident$(: $($trait:ident),*)? {
247 $($field_name:ident $(: $ty:tt)?),*$(,)?
248 }
249 )*) => {
250 [$(
251 AstNodeSrc {
252 name: stringify!($name),
253 traits: &[$($(stringify!($trait)),*)?],
254 fields: &[$(
255 (stringify!($field_name), field_ty!($field_name $($ty)?))
256 ),*],
257
258 }
259 ),*]
260 };
261}
262
263macro_rules! field_ty {
264 ($field_name:ident) => {
265 FieldSrc::Shorthand
266 };
267 ($field_name:ident [$ty:ident]) => {
268 FieldSrc::Many(stringify!($ty))
269 };
270 ($field_name:ident $ty:ident) => {
271 FieldSrc::Optional(stringify!($ty))
272 };
273}
274
275macro_rules! ast_enums {
276 ($(
277 enum $name:ident $(: $($trait:ident),*)? {
278 $($variant:ident),*$(,)?
279 }
280 )*) => {
281 [$(
282 AstEnumSrc {
283 name: stringify!($name),
284 traits: &[$($(stringify!($trait)),*)?],
285 variants: &[$(stringify!($variant)),*],
286
287 }
288 ),*]
289 };
290}
291
292pub(crate) const AST_SRC: AstSrc = AstSrc {
293 nodes: &ast_nodes! {
294 struct SourceFile: ModuleItemOwner, FnDefOwner {
295 modules: [Module],
296 }
297
298 struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
299 ParamList,
300 RetType,
301 body: BlockExpr,
302 }
303
304 struct RetType { TypeRef }
305
306 struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
307 }
308
309 struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
310 RecordFieldDefList,
311 }
312
313 struct RecordFieldDefList { fields: [RecordFieldDef] }
314 struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
315
316 struct TupleFieldDefList { fields: [TupleFieldDef] }
317 struct TupleFieldDef: VisibilityOwner, AttrsOwner {
318 TypeRef,
319 }
320
321 struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
322 variant_list: EnumVariantList,
323 }
324 struct EnumVariantList {
325 variants: [EnumVariant],
326 }
327 struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner {
328 Expr
329 }
330
331 struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
332 ItemList,
333 }
334
335 struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
336 ItemList,
337 }
338
339 struct ItemList: FnDefOwner, ModuleItemOwner {
340 impl_items: [ImplItem],
341 }
342
343 struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
344 body: Expr,
345 }
346
347 struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
348 body: Expr,
349 }
350
351 struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
352 TypeRef,
353 }
354
355 struct ImplBlock: TypeParamsOwner, AttrsOwner {
356 ItemList,
357 }
358
359 struct ParenType { TypeRef }
360 struct TupleType { fields: [TypeRef] }
361 struct NeverType { }
362 struct PathType { Path }
363 struct PointerType { TypeRef }
364 struct ArrayType { TypeRef, Expr }
365 struct SliceType { TypeRef }
366 struct ReferenceType { TypeRef }
367 struct PlaceholderType { }
368 struct FnPointerType { ParamList, RetType }
369 struct ForType { TypeRef }
370 struct ImplTraitType: TypeBoundsOwner {}
371 struct DynTraitType: TypeBoundsOwner {}
372
373 struct TupleExpr { exprs: [Expr] }
374 struct ArrayExpr { exprs: [Expr] }
375 struct ParenExpr { Expr }
376 struct PathExpr { Path }
377 struct LambdaExpr {
378 ParamList,
379 RetType,
380 body: Expr,
381 }
382 struct IfExpr { Condition }
383 struct LoopExpr: LoopBodyOwner { }
384 struct TryBlockExpr { body: BlockExpr }
385 struct ForExpr: LoopBodyOwner {
386 Pat,
387 iterable: Expr,
388 }
389 struct WhileExpr: LoopBodyOwner { Condition }
390 struct ContinueExpr {}
391 struct BreakExpr { Expr }
392 struct Label {}
393 struct BlockExpr { Block }
394 struct ReturnExpr { Expr }
395 struct CallExpr: ArgListOwner { Expr }
396 struct MethodCallExpr: ArgListOwner {
397 Expr, NameRef, TypeArgList,
398 }
399 struct IndexExpr {}
400 struct FieldExpr { Expr, NameRef }
401 struct AwaitExpr { Expr }
402 struct TryExpr { Expr }
403 struct CastExpr { Expr, TypeRef }
404 struct RefExpr { Expr }
405 struct PrefixExpr { Expr }
406 struct BoxExpr { Expr }
407 struct RangeExpr {}
408 struct BinExpr {}
409 struct Literal {}
410
411 struct MatchExpr { Expr, MatchArmList }
412 struct MatchArmList: AttrsOwner { arms: [MatchArm] }
413 struct MatchArm: AttrsOwner {
414 pats: [Pat],
415 guard: MatchGuard,
416 Expr,
417 }
418 struct MatchGuard { Expr }
419
420 struct RecordLit { Path, RecordFieldList }
421 struct RecordFieldList {
422 fields: [RecordField],
423 spread: Expr,
424 }
425 struct RecordField { NameRef, Expr }
426
427 struct RefPat { Pat }
428 struct BoxPat { Pat }
429 struct BindPat: NameOwner { Pat }
430 struct PlaceholderPat { }
431 struct DotDotPat { }
432 struct PathPat { Path }
433 struct SlicePat {}
434 struct RangePat {}
435 struct LiteralPat { Literal }
436
437 struct RecordPat { RecordFieldPatList, Path }
438 struct RecordFieldPatList {
439 record_field_pats: [RecordFieldPat],
440 bind_pats: [BindPat],
441 }
442 struct RecordFieldPat: NameOwner { Pat }
443
444 struct TupleStructPat { Path, args: [Pat] }
445 struct TuplePat { args: [Pat] }
446
447 struct Visibility {}
448 struct Name {}
449 struct NameRef {}
450
451 struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner {
452 TokenTree, Path
453 }
454 struct Attr { Path, input: AttrInput }
455 struct TokenTree {}
456 struct TypeParamList {
457 type_params: [TypeParam],
458 lifetime_params: [LifetimeParam],
459 }
460 struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
461 default_type: TypeRef,
462 }
463 struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
464 default_val: Expr,
465 }
466 struct LifetimeParam: AttrsOwner { }
467 struct TypeBound { TypeRef}
468 struct TypeBoundList { bounds: [TypeBound] }
469 struct WherePred: TypeBoundsOwner { TypeRef }
470 struct WhereClause { predicates: [WherePred] }
471 struct ExprStmt { Expr }
472 struct LetStmt: TypeAscriptionOwner {
473 Pat,
474 initializer: Expr,
475 }
476 struct Condition { Pat, Expr }
477 struct Block: AttrsOwner, ModuleItemOwner {
478 statements: [Stmt],
479 Expr,
480 }
481 struct ParamList {
482 SelfParam,
483 params: [Param],
484 }
485 struct SelfParam: TypeAscriptionOwner, AttrsOwner { }
486 struct Param: TypeAscriptionOwner, AttrsOwner {
487 Pat,
488 }
489 struct UseItem: AttrsOwner, VisibilityOwner {
490 UseTree,
491 }
492 struct UseTree {
493 Path, UseTreeList, Alias
494 }
495 struct Alias: NameOwner { }
496 struct UseTreeList { use_trees: [UseTree] }
497 struct ExternCrateItem: AttrsOwner, VisibilityOwner {
498 NameRef, Alias,
499 }
500 struct ArgList {
501 args: [Expr],
502 }
503 struct Path {
504 segment: PathSegment,
505 qualifier: Path,
506 }
507 struct PathSegment {
508 NameRef, TypeArgList, ParamList, RetType, PathType,
509 }
510 struct TypeArgList {
511 type_args: [TypeArg],
512 lifetime_args: [LifetimeArg],
513 assoc_type_args: [AssocTypeArg],
514 }
515 struct TypeArg { TypeRef }
516 struct AssocTypeArg { NameRef, TypeRef }
517 struct LifetimeArg {}
518
519 struct MacroItems: ModuleItemOwner, FnDefOwner { }
520
521 struct MacroStmts {
522 statements: [Stmt],
523 Expr,
524 }
525 },
526 enums: &ast_enums! {
527 enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
528 StructDef, EnumDef, UnionDef,
529 }
530
531 enum TypeRef {
532 ParenType,
533 TupleType,
534 NeverType,
535 PathType,
536 PointerType,
537 ArrayType,
538 SliceType,
539 ReferenceType,
540 PlaceholderType,
541 FnPointerType,
542 ForType,
543 ImplTraitType,
544 DynTraitType,
545 }
546
547 enum ModuleItem: AttrsOwner, VisibilityOwner {
548 StructDef,
549 UnionDef,
550 EnumDef,
551 FnDef,
552 TraitDef,
553 TypeAliasDef,
554 ImplBlock,
555 UseItem,
556 ExternCrateItem,
557 ConstDef,
558 StaticDef,
559 Module,
560 }
561
562 enum ImplItem: AttrsOwner {
563 FnDef, TypeAliasDef, ConstDef,
564 }
565
566 enum Expr {
567 TupleExpr,
568 ArrayExpr,
569 ParenExpr,
570 PathExpr,
571 LambdaExpr,
572 IfExpr,
573 LoopExpr,
574 ForExpr,
575 WhileExpr,
576 ContinueExpr,
577 BreakExpr,
578 Label,
579 BlockExpr,
580 ReturnExpr,
581 MatchExpr,
582 RecordLit,
583 CallExpr,
584 IndexExpr,
585 MethodCallExpr,
586 FieldExpr,
587 AwaitExpr,
588 TryExpr,
589 TryBlockExpr,
590 CastExpr,
591 RefExpr,
592 PrefixExpr,
593 RangeExpr,
594 BinExpr,
595 Literal,
596 MacroCall,
597 BoxExpr,
598 }
599
600 enum Pat {
601 RefPat,
602 BoxPat,
603 BindPat,
604 PlaceholderPat,
605 DotDotPat,
606 PathPat,
607 RecordPat,
608 TupleStructPat,
609 TuplePat,
610 SlicePat,
611 RangePat,
612 LiteralPat,
613 }
614
615 enum AttrInput { Literal, TokenTree }
616 enum Stmt { ExprStmt, LetStmt }
617 },
618};
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;