diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/ast_src.rs | 417 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 287 |
2 files changed, 284 insertions, 420 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index bb97b13fe..8c0b5f5a8 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -11,7 +11,7 @@ pub(crate) struct KindsSrc<'a> { | |||
11 | 11 | ||
12 | pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | 12 | pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { |
13 | punct: &[ | 13 | punct: &[ |
14 | (";", "SEMI"), | 14 | (";", "SEMICOLON"), |
15 | (",", "COMMA"), | 15 | (",", "COMMA"), |
16 | ("(", "L_PAREN"), | 16 | ("(", "L_PAREN"), |
17 | (")", "R_PAREN"), | 17 | (")", "R_PAREN"), |
@@ -35,15 +35,15 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
35 | ("%", "PERCENT"), | 35 | ("%", "PERCENT"), |
36 | ("_", "UNDERSCORE"), | 36 | ("_", "UNDERSCORE"), |
37 | (".", "DOT"), | 37 | (".", "DOT"), |
38 | ("..", "DOTDOT"), | 38 | ("..", "DOT2"), |
39 | ("...", "DOTDOTDOT"), | 39 | ("...", "DOT3"), |
40 | ("..=", "DOTDOTEQ"), | 40 | ("..=", "DOT2EQ"), |
41 | (":", "COLON"), | 41 | (":", "COLON"), |
42 | ("::", "COLONCOLON"), | 42 | ("::", "COLON2"), |
43 | ("=", "EQ"), | 43 | ("=", "EQ"), |
44 | ("==", "EQEQ"), | 44 | ("==", "EQ2"), |
45 | ("=>", "FAT_ARROW"), | 45 | ("=>", "FAT_ARROW"), |
46 | ("!", "EXCL"), | 46 | ("!", "BANG"), |
47 | ("!=", "NEQ"), | 47 | ("!=", "NEQ"), |
48 | ("-", "MINUS"), | 48 | ("-", "MINUS"), |
49 | ("->", "THIN_ARROW"), | 49 | ("->", "THIN_ARROW"), |
@@ -57,8 +57,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
57 | ("/=", "SLASHEQ"), | 57 | ("/=", "SLASHEQ"), |
58 | ("*=", "STAREQ"), | 58 | ("*=", "STAREQ"), |
59 | ("%=", "PERCENTEQ"), | 59 | ("%=", "PERCENTEQ"), |
60 | ("&&", "AMPAMP"), | 60 | ("&&", "AMP2"), |
61 | ("||", "PIPEPIPE"), | 61 | ("||", "PIPE2"), |
62 | ("<<", "SHL"), | 62 | ("<<", "SHL"), |
63 | (">>", "SHR"), | 63 | (">>", "SHR"), |
64 | ("<<=", "SHLEQ"), | 64 | ("<<=", "SHLEQ"), |
@@ -225,21 +225,26 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
225 | }; | 225 | }; |
226 | 226 | ||
227 | pub(crate) struct AstSrc<'a> { | 227 | pub(crate) struct AstSrc<'a> { |
228 | pub(crate) tokens: &'a [&'a str], | ||
228 | pub(crate) nodes: &'a [AstNodeSrc<'a>], | 229 | pub(crate) nodes: &'a [AstNodeSrc<'a>], |
229 | pub(crate) enums: &'a [AstEnumSrc<'a>], | 230 | pub(crate) enums: &'a [AstEnumSrc<'a>], |
230 | pub(crate) token_enums: &'a [AstEnumSrc<'a>], | ||
231 | } | 231 | } |
232 | 232 | ||
233 | pub(crate) struct AstNodeSrc<'a> { | 233 | pub(crate) struct AstNodeSrc<'a> { |
234 | pub(crate) name: &'a str, | 234 | pub(crate) name: &'a str, |
235 | pub(crate) traits: &'a [&'a str], | 235 | pub(crate) traits: &'a [&'a str], |
236 | pub(crate) fields: &'a [(&'a str, FieldSrc<&'a str>)], | 236 | pub(crate) fields: &'a [Field<'a>], |
237 | } | ||
238 | |||
239 | pub(crate) enum Field<'a> { | ||
240 | Token(&'a str), | ||
241 | Node { name: &'a str, src: FieldSrc<'a> }, | ||
237 | } | 242 | } |
238 | 243 | ||
239 | pub(crate) enum FieldSrc<T> { | 244 | pub(crate) enum FieldSrc<'a> { |
240 | Shorthand, | 245 | Shorthand, |
241 | Optional(T), | 246 | Optional(&'a str), |
242 | Many(T), | 247 | Many(&'a str), |
243 | } | 248 | } |
244 | 249 | ||
245 | pub(crate) struct AstEnumSrc<'a> { | 250 | pub(crate) struct AstEnumSrc<'a> { |
@@ -251,31 +256,34 @@ pub(crate) struct AstEnumSrc<'a> { | |||
251 | macro_rules! ast_nodes { | 256 | macro_rules! ast_nodes { |
252 | ($( | 257 | ($( |
253 | struct $name:ident$(: $($trait:ident),*)? { | 258 | struct $name:ident$(: $($trait:ident),*)? { |
254 | $($field_name:ident $(: $ty:tt)?),*$(,)? | 259 | $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)? |
255 | } | 260 | } |
256 | )*) => { | 261 | )*) => { |
257 | [$( | 262 | [$( |
258 | AstNodeSrc { | 263 | AstNodeSrc { |
259 | name: stringify!($name), | 264 | name: stringify!($name), |
260 | traits: &[$($(stringify!($trait)),*)?], | 265 | traits: &[$($(stringify!($trait)),*)?], |
261 | fields: &[$( | 266 | fields: &[ |
262 | (stringify!($field_name), field_ty!($field_name $($ty)?)) | 267 | $(field!($(T![$token])? $field_name $($ty)?)),* |
263 | ),*], | 268 | ], |
264 | 269 | ||
265 | } | 270 | } |
266 | ),*] | 271 | ),*] |
267 | }; | 272 | }; |
268 | } | 273 | } |
269 | 274 | ||
270 | macro_rules! field_ty { | 275 | macro_rules! field { |
276 | (T![$token:tt] T) => { | ||
277 | Field::Token(stringify!($token)) | ||
278 | }; | ||
271 | ($field_name:ident) => { | 279 | ($field_name:ident) => { |
272 | FieldSrc::Shorthand | 280 | Field::Node { name: stringify!($field_name), src: FieldSrc::Shorthand } |
273 | }; | 281 | }; |
274 | ($field_name:ident [$ty:ident]) => { | 282 | ($field_name:ident [$ty:ident]) => { |
275 | FieldSrc::Many(stringify!($ty)) | 283 | Field::Node { name: stringify!($field_name), src: FieldSrc::Many(stringify!($ty)) } |
276 | }; | 284 | }; |
277 | ($field_name:ident $ty:ident) => { | 285 | ($field_name:ident $ty:ident) => { |
278 | FieldSrc::Optional(stringify!($ty)) | 286 | Field::Node { name: stringify!($field_name), src: FieldSrc::Optional(stringify!($ty)) } |
279 | }; | 287 | }; |
280 | } | 288 | } |
281 | 289 | ||
@@ -290,13 +298,13 @@ macro_rules! ast_enums { | |||
290 | name: stringify!($name), | 298 | name: stringify!($name), |
291 | traits: &[$($(stringify!($trait)),*)?], | 299 | traits: &[$($(stringify!($trait)),*)?], |
292 | variants: &[$(stringify!($variant)),*], | 300 | variants: &[$(stringify!($variant)),*], |
293 | |||
294 | } | 301 | } |
295 | ),*] | 302 | ),*] |
296 | }; | 303 | }; |
297 | } | 304 | } |
298 | 305 | ||
299 | pub(crate) const AST_SRC: AstSrc = AstSrc { | 306 | pub(crate) const AST_SRC: AstSrc = AstSrc { |
307 | tokens: &["Whitespace", "Comment", "String", "RawString"], | ||
300 | nodes: &ast_nodes! { | 308 | nodes: &ast_nodes! { |
301 | struct SourceFile: ModuleItemOwner, AttrsOwner { | 309 | struct SourceFile: ModuleItemOwner, AttrsOwner { |
302 | modules: [Module], | 310 | modules: [Module], |
@@ -304,305 +312,305 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
304 | 312 | ||
305 | struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { | 313 | struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { |
306 | Abi, | 314 | Abi, |
307 | ConstKw, | 315 | T![const], |
308 | DefaultKw, | 316 | T![default], |
309 | AsyncKw, | 317 | T![async], |
310 | UnsafeKw, | 318 | T![unsafe], |
311 | FnKw, | 319 | T![fn], |
312 | ParamList, | 320 | ParamList, |
313 | RetType, | 321 | RetType, |
314 | body: BlockExpr, | 322 | body: BlockExpr, |
315 | Semi | 323 | T![;] |
316 | } | 324 | } |
317 | 325 | ||
318 | struct RetType { ThinArrow, TypeRef } | 326 | struct RetType { T![->], TypeRef } |
319 | 327 | ||
320 | struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 328 | struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
321 | StructKw, | 329 | T![struct], |
322 | FieldDefList, | 330 | FieldDefList, |
323 | Semi | 331 | T![;] |
324 | } | 332 | } |
325 | 333 | ||
326 | struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 334 | struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
327 | UnionKw, | 335 | T![union], |
328 | RecordFieldDefList, | 336 | RecordFieldDefList, |
329 | } | 337 | } |
330 | 338 | ||
331 | struct RecordFieldDefList { LCurly, fields: [RecordFieldDef], RCurly } | 339 | struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] } |
332 | struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } | 340 | struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } |
333 | 341 | ||
334 | struct TupleFieldDefList { LParen, fields: [TupleFieldDef], RParen } | 342 | struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] } |
335 | struct TupleFieldDef: VisibilityOwner, AttrsOwner { | 343 | struct TupleFieldDef: VisibilityOwner, AttrsOwner { |
336 | TypeRef, | 344 | TypeRef, |
337 | } | 345 | } |
338 | 346 | ||
339 | struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 347 | struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
340 | EnumKw, | 348 | T![enum], |
341 | variant_list: EnumVariantList, | 349 | variant_list: EnumVariantList, |
342 | } | 350 | } |
343 | struct EnumVariantList { | 351 | struct EnumVariantList { |
344 | LCurly, | 352 | T!['{'], |
345 | variants: [EnumVariant], | 353 | variants: [EnumVariant], |
346 | RCurly | 354 | T!['}'] |
347 | } | 355 | } |
348 | struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { | 356 | struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { |
349 | FieldDefList, | 357 | FieldDefList, |
350 | Eq, | 358 | T![=], |
351 | Expr | 359 | Expr |
352 | } | 360 | } |
353 | 361 | ||
354 | struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { | 362 | struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { |
355 | UnsafeKw, | 363 | T![unsafe], |
356 | AutoKw, | 364 | T![auto], |
357 | TraitKw, | 365 | T![trait], |
358 | ItemList, | 366 | ItemList, |
359 | } | 367 | } |
360 | 368 | ||
361 | struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { | 369 | struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { |
362 | ModKw, | 370 | T![mod], |
363 | ItemList, | 371 | ItemList, |
364 | Semi | 372 | T![;] |
365 | } | 373 | } |
366 | 374 | ||
367 | struct ItemList: ModuleItemOwner { | 375 | struct ItemList: ModuleItemOwner { |
368 | LCurly, | 376 | T!['{'], |
369 | impl_items: [ImplItem], | 377 | impl_items: [ImplItem], |
370 | RCurly | 378 | T!['}'] |
371 | } | 379 | } |
372 | 380 | ||
373 | struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | 381 | struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { |
374 | DefaultKw, | 382 | T![default], |
375 | ConstKw, | 383 | T![const], |
376 | Eq, | 384 | T![=], |
377 | body: Expr, | 385 | body: Expr, |
378 | Semi | 386 | T![;] |
379 | } | 387 | } |
380 | 388 | ||
381 | struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | 389 | struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { |
382 | StaticKw, | 390 | T![static], |
383 | MutKw, | 391 | T![mut], |
384 | Eq, | 392 | T![=], |
385 | body: Expr, | 393 | body: Expr, |
386 | Semi | 394 | T![;] |
387 | } | 395 | } |
388 | 396 | ||
389 | struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { | 397 | struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { |
390 | DefaultKw, | 398 | T![default], |
391 | TypeKw, | 399 | T![type], |
392 | Eq, | 400 | T![=], |
393 | TypeRef, | 401 | TypeRef, |
394 | Semi | 402 | T![;] |
395 | } | 403 | } |
396 | 404 | ||
397 | struct ImplDef: TypeParamsOwner, AttrsOwner { | 405 | struct ImplDef: TypeParamsOwner, AttrsOwner { |
398 | DefaultKw, | 406 | T![default], |
399 | ConstKw, | 407 | T![const], |
400 | UnsafeKw, | 408 | T![unsafe], |
401 | ImplKw, | 409 | T![impl], |
402 | Excl, | 410 | T![!], |
403 | ForKw, | 411 | T![for], |
404 | ItemList, | 412 | ItemList, |
405 | } | 413 | } |
406 | 414 | ||
407 | struct ParenType { LParen, TypeRef, RParen } | 415 | struct ParenType { T!['('], TypeRef, T![')'] } |
408 | struct TupleType { LParen, fields: [TypeRef], RParen } | 416 | struct TupleType { T!['('], fields: [TypeRef], T![')'] } |
409 | struct NeverType { Excl } | 417 | struct NeverType { T![!] } |
410 | struct PathType { Path } | 418 | struct PathType { Path } |
411 | struct PointerType { Star, ConstKw, MutKw, TypeRef } | 419 | struct PointerType { T![*], T![const], T![mut], TypeRef } |
412 | struct ArrayType { LBrack, TypeRef, Semi, Expr, RBrack } | 420 | struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] } |
413 | struct SliceType { LBrack, TypeRef, RBrack } | 421 | struct SliceType { T!['['], TypeRef, T![']'] } |
414 | struct ReferenceType { Amp, Lifetime, MutKw, TypeRef } | 422 | struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef } |
415 | struct PlaceholderType { Underscore } | 423 | struct PlaceholderType { T![_] } |
416 | struct FnPointerType { Abi, UnsafeKw, FnKw, ParamList, RetType } | 424 | struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType } |
417 | struct ForType { ForKw, TypeParamList, TypeRef } | 425 | struct ForType { T![for], TypeParamList, TypeRef } |
418 | struct ImplTraitType: TypeBoundsOwner { ImplKw } | 426 | struct ImplTraitType: TypeBoundsOwner { T![impl] } |
419 | struct DynTraitType: TypeBoundsOwner { DynKw } | 427 | struct DynTraitType: TypeBoundsOwner { T![dyn] } |
420 | 428 | ||
421 | struct TupleExpr: AttrsOwner { LParen, exprs: [Expr], RParen } | 429 | struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] } |
422 | struct ArrayExpr: AttrsOwner { LBrack, exprs: [Expr], Semi, RBrack } | 430 | struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] } |
423 | struct ParenExpr: AttrsOwner { LParen, Expr, RParen } | 431 | struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] } |
424 | struct PathExpr { Path } | 432 | struct PathExpr { Path } |
425 | struct LambdaExpr: AttrsOwner { | 433 | struct LambdaExpr: AttrsOwner { |
426 | StaticKw, | 434 | T![static], |
427 | AsyncKw, | 435 | T![async], |
428 | MoveKw, | 436 | T![move], |
429 | ParamList, | 437 | ParamList, |
430 | RetType, | 438 | RetType, |
431 | body: Expr, | 439 | body: Expr, |
432 | } | 440 | } |
433 | struct IfExpr: AttrsOwner { IfKw, Condition } | 441 | struct IfExpr: AttrsOwner { T![if], Condition } |
434 | struct LoopExpr: AttrsOwner, LoopBodyOwner { LoopKw } | 442 | struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } |
435 | struct TryBlockExpr: AttrsOwner { TryKw, body: BlockExpr } | 443 | struct TryBlockExpr: AttrsOwner { T![try], body: BlockExpr } |
436 | struct ForExpr: AttrsOwner, LoopBodyOwner { | 444 | struct ForExpr: AttrsOwner, LoopBodyOwner { |
437 | ForKw, | 445 | T![for], |
438 | Pat, | 446 | Pat, |
439 | InKw, | 447 | T![in], |
440 | iterable: Expr, | 448 | iterable: Expr, |
441 | } | 449 | } |
442 | struct WhileExpr: AttrsOwner, LoopBodyOwner { WhileKw, Condition } | 450 | struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition } |
443 | struct ContinueExpr: AttrsOwner { ContinueKw, Lifetime } | 451 | struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } |
444 | struct BreakExpr: AttrsOwner { BreakKw, Lifetime, Expr } | 452 | struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } |
445 | struct Label { Lifetime } | 453 | struct Label { T![lifetime] } |
446 | struct BlockExpr: AttrsOwner { Label, UnsafeKw, Block } | 454 | struct BlockExpr: AttrsOwner { Label, T![unsafe], Block } |
447 | struct ReturnExpr: AttrsOwner { Expr } | 455 | struct ReturnExpr: AttrsOwner { Expr } |
448 | struct CallExpr: ArgListOwner { Expr } | 456 | struct CallExpr: ArgListOwner { Expr } |
449 | struct MethodCallExpr: AttrsOwner, ArgListOwner { | 457 | struct MethodCallExpr: AttrsOwner, ArgListOwner { |
450 | Expr, Dot, NameRef, TypeArgList, | 458 | Expr, T![.], NameRef, TypeArgList, |
451 | } | 459 | } |
452 | struct IndexExpr: AttrsOwner { LBrack, RBrack } | 460 | struct IndexExpr: AttrsOwner { T!['['], T![']'] } |
453 | struct FieldExpr: AttrsOwner { Expr, Dot, NameRef } | 461 | struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } |
454 | struct AwaitExpr: AttrsOwner { Expr, Dot, AwaitKw } | 462 | struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } |
455 | struct TryExpr: AttrsOwner { TryKw, Expr } | 463 | struct TryExpr: AttrsOwner { T![try], Expr } |
456 | struct CastExpr: AttrsOwner { Expr, AsKw, TypeRef } | 464 | struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } |
457 | struct RefExpr: AttrsOwner { Amp, RawKw, MutKw, Expr } | 465 | struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr } |
458 | struct PrefixExpr: AttrsOwner { PrefixOp, Expr } | 466 | struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } |
459 | struct BoxExpr: AttrsOwner { BoxKw, Expr } | 467 | struct BoxExpr: AttrsOwner { T![box], Expr } |
460 | struct RangeExpr: AttrsOwner { RangeOp } | 468 | struct RangeExpr: AttrsOwner { /*RangeOp*/ } |
461 | struct BinExpr: AttrsOwner { BinOp } | 469 | struct BinExpr: AttrsOwner { /*BinOp*/ } |
462 | struct Literal { LiteralToken } | 470 | struct Literal { /*LiteralToken*/ } |
463 | 471 | ||
464 | struct MatchExpr: AttrsOwner { MatchKw, Expr, MatchArmList } | 472 | struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList } |
465 | struct MatchArmList: AttrsOwner { LCurly, arms: [MatchArm], RCurly } | 473 | struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] } |
466 | struct MatchArm: AttrsOwner { | 474 | struct MatchArm: AttrsOwner { |
467 | pat: Pat, | 475 | pat: Pat, |
468 | guard: MatchGuard, | 476 | guard: MatchGuard, |
469 | FatArrow, | 477 | T![=>], |
470 | Expr, | 478 | Expr, |
471 | } | 479 | } |
472 | struct MatchGuard { IfKw, Expr } | 480 | struct MatchGuard { T![if], Expr } |
473 | 481 | ||
474 | struct RecordLit { Path, RecordFieldList} | 482 | struct RecordLit { Path, RecordFieldList} |
475 | struct RecordFieldList { | 483 | struct RecordFieldList { |
476 | LCurly, | 484 | T!['{'], |
477 | fields: [RecordField], | 485 | fields: [RecordField], |
478 | Dotdot, | 486 | T![..], |
479 | spread: Expr, | 487 | spread: Expr, |
480 | RCurly | 488 | T!['}'] |
481 | } | 489 | } |
482 | struct RecordField: AttrsOwner { NameRef, Colon, Expr } | 490 | struct RecordField: AttrsOwner { NameRef, T![:], Expr } |
483 | 491 | ||
484 | struct OrPat { pats: [Pat] } | 492 | struct OrPat { pats: [Pat] } |
485 | struct ParenPat { LParen, Pat, RParen } | 493 | struct ParenPat { T!['('], Pat, T![')'] } |
486 | struct RefPat { Amp, MutKw, Pat } | 494 | struct RefPat { T![&], T![mut], Pat } |
487 | struct BoxPat { BoxKw, Pat } | 495 | struct BoxPat { T![box], Pat } |
488 | struct BindPat: AttrsOwner, NameOwner { RefKw, MutKw, At, Pat } | 496 | struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat } |
489 | struct PlaceholderPat { Underscore } | 497 | struct PlaceholderPat { T![_] } |
490 | struct DotDotPat { Dotdot } | 498 | struct DotDotPat { T![..] } |
491 | struct PathPat { Path } | 499 | struct PathPat { Path } |
492 | struct SlicePat { LBrack, args: [Pat], RBrack } | 500 | struct SlicePat { T!['['], args: [Pat], T![']'] } |
493 | struct RangePat { RangeSeparator } | 501 | struct RangePat { /*RangeSeparator*/ } |
494 | struct LiteralPat { Literal } | 502 | struct LiteralPat { Literal } |
495 | struct MacroPat { MacroCall } | 503 | struct MacroPat { MacroCall } |
496 | 504 | ||
497 | struct RecordPat { RecordFieldPatList, Path } | 505 | struct RecordPat { RecordFieldPatList, Path } |
498 | struct RecordFieldPatList { | 506 | struct RecordFieldPatList { |
499 | LCurly, | 507 | T!['{'], |
500 | pats: [RecordInnerPat], | 508 | pats: [RecordInnerPat], |
501 | record_field_pats: [RecordFieldPat], | 509 | record_field_pats: [RecordFieldPat], |
502 | bind_pats: [BindPat], | 510 | bind_pats: [BindPat], |
503 | Dotdot, | 511 | T![..], |
504 | RCurly | 512 | T!['}'] |
505 | } | 513 | } |
506 | struct RecordFieldPat: AttrsOwner, NameOwner { Colon, Pat } | 514 | struct RecordFieldPat: AttrsOwner, NameOwner { T![:], Pat } |
507 | 515 | ||
508 | struct TupleStructPat { Path, LParen, args: [Pat], RParen } | 516 | struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } |
509 | struct TuplePat { LParen, args: [Pat], RParen } | 517 | struct TuplePat { T!['('], args: [Pat], T![')'] } |
510 | 518 | ||
511 | struct Visibility { PubKw, SuperKw, SelfKw, CrateKw } | 519 | struct Visibility { T![pub], T![super], T![self], T![crate] } |
512 | struct Name { Ident } | 520 | struct Name { T![ident] } |
513 | struct NameRef { NameRefToken } | 521 | struct NameRef { /*NameRefToken*/ } |
514 | 522 | ||
515 | struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { | 523 | struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { |
516 | Path, Excl, TokenTree, Semi | 524 | Path, T![!], TokenTree, T![;] |
517 | } | 525 | } |
518 | struct Attr { Pound, Excl, LBrack, Path, Eq, input: AttrInput, RBrack } | 526 | struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] } |
519 | struct TokenTree {} | 527 | struct TokenTree {} |
520 | struct TypeParamList { | 528 | struct TypeParamList { |
521 | LAngle, | 529 | T![<], |
522 | generic_params: [GenericParam], | 530 | generic_params: [GenericParam], |
523 | type_params: [TypeParam], | 531 | type_params: [TypeParam], |
524 | lifetime_params: [LifetimeParam], | 532 | lifetime_params: [LifetimeParam], |
525 | const_params: [ConstParam], | 533 | const_params: [ConstParam], |
526 | RAngle | 534 | T![>] |
527 | } | 535 | } |
528 | struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { | 536 | struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { |
529 | Eq, | 537 | T![=], |
530 | default_type: TypeRef, | 538 | default_type: TypeRef, |
531 | } | 539 | } |
532 | struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { | 540 | struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { |
533 | Eq, | 541 | T![=], |
534 | default_val: Expr, | 542 | default_val: Expr, |
535 | } | 543 | } |
536 | struct LifetimeParam: AttrsOwner { Lifetime} | 544 | struct LifetimeParam: AttrsOwner { T![lifetime] } |
537 | struct TypeBound { Lifetime, /* Question, */ ConstKw, /* Question, */ TypeRef} | 545 | struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef} |
538 | struct TypeBoundList { bounds: [TypeBound] } | 546 | struct TypeBoundList { bounds: [TypeBound] } |
539 | struct WherePred: TypeBoundsOwner { Lifetime, TypeRef } | 547 | struct WherePred: TypeBoundsOwner { T![lifetime], TypeRef } |
540 | struct WhereClause { WhereKw, predicates: [WherePred] } | 548 | struct WhereClause { T![where], predicates: [WherePred] } |
541 | struct Abi { String } | 549 | struct Abi { /*String*/ } |
542 | struct ExprStmt: AttrsOwner { Expr, Semi } | 550 | struct ExprStmt: AttrsOwner { Expr, T![;] } |
543 | struct LetStmt: AttrsOwner, TypeAscriptionOwner { | 551 | struct LetStmt: AttrsOwner, TypeAscriptionOwner { |
544 | LetKw, | 552 | T![let], |
545 | Pat, | 553 | Pat, |
546 | Eq, | 554 | T![=], |
547 | initializer: Expr, | 555 | initializer: Expr, |
548 | Semi, | 556 | T![;], |
549 | } | 557 | } |
550 | struct Condition { LetKw, Pat, Eq, Expr } | 558 | struct Condition { T![let], Pat, T![=], Expr } |
551 | struct Block: AttrsOwner, ModuleItemOwner { | 559 | struct Block: AttrsOwner, ModuleItemOwner { |
552 | LCurly, | 560 | T!['{'], |
553 | statements: [Stmt], | 561 | statements: [Stmt], |
554 | Expr, | 562 | Expr, |
555 | RCurly, | 563 | T!['}'], |
556 | } | 564 | } |
557 | struct ParamList { | 565 | struct ParamList { |
558 | LParen, | 566 | T!['('], |
559 | SelfParam, | 567 | SelfParam, |
560 | params: [Param], | 568 | params: [Param], |
561 | RParen | 569 | T![')'] |
562 | } | 570 | } |
563 | struct SelfParam: TypeAscriptionOwner, AttrsOwner { Amp, Lifetime, SelfKw } | 571 | struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![lifetime], T![self] } |
564 | struct Param: TypeAscriptionOwner, AttrsOwner { | 572 | struct Param: TypeAscriptionOwner, AttrsOwner { |
565 | Pat, | 573 | Pat, |
566 | Dotdotdot | 574 | T![...] |
567 | } | 575 | } |
568 | struct UseItem: AttrsOwner, VisibilityOwner { | 576 | struct UseItem: AttrsOwner, VisibilityOwner { |
569 | UseKw, | 577 | T![use], |
570 | UseTree, | 578 | UseTree, |
571 | } | 579 | } |
572 | struct UseTree { | 580 | struct UseTree { |
573 | Path, Star, UseTreeList, Alias | 581 | Path, T![*], UseTreeList, Alias |
574 | } | 582 | } |
575 | struct Alias: NameOwner { AsKw } | 583 | struct Alias: NameOwner { T![as] } |
576 | struct UseTreeList { LCurly, use_trees: [UseTree], RCurly } | 584 | struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] } |
577 | struct ExternCrateItem: AttrsOwner, VisibilityOwner { | 585 | struct ExternCrateItem: AttrsOwner, VisibilityOwner { |
578 | ExternKw, CrateKw, NameRef, Alias, | 586 | T![extern], T![crate], NameRef, Alias, |
579 | } | 587 | } |
580 | struct ArgList { | 588 | struct ArgList { |
581 | LParen, | 589 | T!['('], |
582 | args: [Expr], | 590 | args: [Expr], |
583 | RParen | 591 | T![')'] |
584 | } | 592 | } |
585 | struct Path { | 593 | struct Path { |
586 | segment: PathSegment, | 594 | segment: PathSegment, |
587 | qualifier: Path, | 595 | qualifier: Path, |
588 | } | 596 | } |
589 | struct PathSegment { | 597 | struct PathSegment { |
590 | Coloncolon, LAngle, NameRef, TypeArgList, ParamList, RetType, PathType, RAngle | 598 | T![::], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] |
591 | } | 599 | } |
592 | struct TypeArgList { | 600 | struct TypeArgList { |
593 | Coloncolon, | 601 | T![::], |
594 | LAngle, | 602 | T![<], |
595 | generic_args: [GenericArg], | 603 | generic_args: [GenericArg], |
596 | type_args: [TypeArg], | 604 | type_args: [TypeArg], |
597 | lifetime_args: [LifetimeArg], | 605 | lifetime_args: [LifetimeArg], |
598 | assoc_type_args: [AssocTypeArg], | 606 | assoc_type_args: [AssocTypeArg], |
599 | const_args: [ConstArg], | 607 | const_args: [ConstArg], |
600 | RAngle | 608 | T![>] |
601 | } | 609 | } |
602 | struct TypeArg { TypeRef } | 610 | struct TypeArg { TypeRef } |
603 | struct AssocTypeArg : TypeBoundsOwner { NameRef, Eq, TypeRef } | 611 | struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef } |
604 | struct LifetimeArg { Lifetime } | 612 | struct LifetimeArg { T![lifetime] } |
605 | struct ConstArg { Literal, Eq, BlockExpr } | 613 | struct ConstArg { Literal, T![=], BlockExpr } |
606 | 614 | ||
607 | struct MacroItems: ModuleItemOwner{ } | 615 | struct MacroItems: ModuleItemOwner{ } |
608 | 616 | ||
@@ -612,9 +620,9 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
612 | } | 620 | } |
613 | 621 | ||
614 | struct ExternItemList: ModuleItemOwner { | 622 | struct ExternItemList: ModuleItemOwner { |
615 | LCurly, | 623 | T!['{'], |
616 | extern_items: [ExternItem], | 624 | extern_items: [ExternItem], |
617 | RCurly | 625 | T!['}'] |
618 | } | 626 | } |
619 | 627 | ||
620 | struct ExternBlock { | 628 | struct ExternBlock { |
@@ -623,7 +631,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
623 | } | 631 | } |
624 | 632 | ||
625 | struct MetaItem { | 633 | struct MetaItem { |
626 | Path, Eq, AttrInput, nested_meta_items: [MetaItem] | 634 | Path, T![=], AttrInput, nested_meta_items: [MetaItem] |
627 | } | 635 | } |
628 | 636 | ||
629 | struct MacroDef { | 637 | struct MacroDef { |
@@ -760,71 +768,4 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
760 | TupleFieldDefList, | 768 | TupleFieldDefList, |
761 | } | 769 | } |
762 | }, | 770 | }, |
763 | |||
764 | token_enums: &ast_enums! { | ||
765 | enum LeftDelimiter { LParen, LBrack, LCurly } | ||
766 | enum RightDelimiter { RParen, RBrack, RCurly } | ||
767 | enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq} | ||
768 | |||
769 | enum BinOp { | ||
770 | Pipepipe, | ||
771 | Ampamp, | ||
772 | Eqeq, | ||
773 | Neq, | ||
774 | Lteq, | ||
775 | Gteq, | ||
776 | LAngle, | ||
777 | RAngle, | ||
778 | Plus, | ||
779 | Star, | ||
780 | Minus, | ||
781 | Slash, | ||
782 | Percent, | ||
783 | Shl, | ||
784 | Shr, | ||
785 | Caret, | ||
786 | Pipe, | ||
787 | Amp, | ||
788 | Eq, | ||
789 | Pluseq, | ||
790 | Slasheq, | ||
791 | Stareq, | ||
792 | Percenteq, | ||
793 | Shreq, | ||
794 | Shleq, | ||
795 | Minuseq, | ||
796 | Pipeeq, | ||
797 | Ampeq, | ||
798 | Careteq, | ||
799 | } | ||
800 | |||
801 | enum PrefixOp { | ||
802 | Minus, | ||
803 | Excl, | ||
804 | Star | ||
805 | } | ||
806 | |||
807 | enum RangeOp { | ||
808 | Dotdot, | ||
809 | Dotdoteq | ||
810 | } | ||
811 | |||
812 | enum LiteralToken { | ||
813 | IntNumber, | ||
814 | FloatNumber, | ||
815 | String, | ||
816 | RawString, | ||
817 | // TrueKw, | ||
818 | // FalseKw, | ||
819 | ByteString, | ||
820 | RawByteString, | ||
821 | Char, | ||
822 | Byte | ||
823 | } | ||
824 | |||
825 | enum NameRefToken { | ||
826 | Ident, | ||
827 | IntNumber | ||
828 | } | ||
829 | }, | ||
830 | }; | 771 | }; |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index cc98802f6..ec1f6ad8a 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -3,16 +3,13 @@ | |||
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 | ||
6 | use std::{ | 6 | use std::collections::HashSet; |
7 | borrow::Cow, | ||
8 | collections::{BTreeSet, HashSet}, | ||
9 | }; | ||
10 | 7 | ||
11 | use proc_macro2::{Punct, Spacing}; | 8 | use proc_macro2::{Punct, Spacing}; |
12 | use quote::{format_ident, quote}; | 9 | use quote::{format_ident, quote}; |
13 | 10 | ||
14 | use crate::{ | 11 | use crate::{ |
15 | ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, | 12 | ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, |
16 | codegen::{self, update, Mode}, | 13 | codegen::{self, update, Mode}, |
17 | project_root, Result, | 14 | project_root, Result, |
18 | }; | 15 | }; |
@@ -22,61 +19,31 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { | |||
22 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; | 19 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; |
23 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; | 20 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; |
24 | 21 | ||
22 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | ||
23 | let contents = generate_tokens(AST_SRC)?; | ||
24 | update(ast_tokens_file.as_path(), &contents, mode)?; | ||
25 | |||
25 | let ast_nodes_file = project_root().join(codegen::AST_NODES); | 26 | let ast_nodes_file = project_root().join(codegen::AST_NODES); |
26 | let contents = generate_nodes(KINDS_SRC, AST_SRC)?; | 27 | let contents = generate_nodes(KINDS_SRC, AST_SRC)?; |
27 | update(ast_nodes_file.as_path(), &contents, mode)?; | 28 | update(ast_nodes_file.as_path(), &contents, mode)?; |
28 | 29 | ||
29 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | ||
30 | let contents = generate_tokens(KINDS_SRC, AST_SRC)?; | ||
31 | update(ast_tokens_file.as_path(), &contents, mode)?; | ||
32 | |||
33 | Ok(()) | 30 | Ok(()) |
34 | } | 31 | } |
35 | 32 | ||
36 | #[derive(Debug, Default, Clone)] | 33 | fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { |
37 | struct ElementKinds { | 34 | let tokens = grammar.tokens.iter().map(|token| { |
38 | kinds: BTreeSet<proc_macro2::Ident>, | 35 | let name = format_ident!("{}", token); |
39 | has_nodes: bool, | 36 | let kind = format_ident!("{}", to_upper_snake_case(token)); |
40 | has_tokens: bool, | 37 | quote! { |
41 | } | ||
42 | |||
43 | fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | ||
44 | let all_token_kinds: Vec<_> = kinds | ||
45 | .punct | ||
46 | .into_iter() | ||
47 | .map(|(_, kind)| kind) | ||
48 | .copied() | ||
49 | .map(|x| x.into()) | ||
50 | .chain( | ||
51 | kinds | ||
52 | .keywords | ||
53 | .into_iter() | ||
54 | .chain(kinds.contextual_keywords.into_iter()) | ||
55 | .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), | ||
56 | ) | ||
57 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | ||
58 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | ||
59 | .collect(); | ||
60 | |||
61 | let tokens = all_token_kinds.iter().filter_map(|kind_str| { | ||
62 | if kind_str.ends_with("_KW") { | ||
63 | return None; | ||
64 | } | ||
65 | let kind_str = &**kind_str; | ||
66 | let kind = format_ident!("{}", kind_str); | ||
67 | let name = format_ident!("{}", to_pascal_case(kind_str)); | ||
68 | let res = quote! { | ||
69 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 38 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
70 | pub struct #name { | 39 | pub struct #name { |
71 | pub(crate) syntax: SyntaxToken, | 40 | pub(crate) syntax: SyntaxToken, |
72 | } | 41 | } |
73 | |||
74 | impl std::fmt::Display for #name { | 42 | impl std::fmt::Display for #name { |
75 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 43 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
76 | std::fmt::Display::fmt(&self.syntax, f) | 44 | std::fmt::Display::fmt(&self.syntax, f) |
77 | } | 45 | } |
78 | } | 46 | } |
79 | |||
80 | impl AstToken for #name { | 47 | impl AstToken for #name { |
81 | fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } | 48 | fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } |
82 | fn cast(syntax: SyntaxToken) -> Option<Self> { | 49 | fn cast(syntax: SyntaxToken) -> Option<Self> { |
@@ -84,103 +51,18 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
84 | } | 51 | } |
85 | fn syntax(&self) -> &SyntaxToken { &self.syntax } | 52 | fn syntax(&self) -> &SyntaxToken { &self.syntax } |
86 | } | 53 | } |
87 | }; | ||
88 | Some(res) | ||
89 | }); | ||
90 | |||
91 | let enums = grammar.token_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 | assert!(en.traits.is_empty()); | ||
99 | |||
100 | quote! { | ||
101 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
102 | pub enum #name { | ||
103 | #(#variants(#variants),)* | ||
104 | } | ||
105 | |||
106 | #( | ||
107 | impl From<#variants> for #name { | ||
108 | fn from(node: #variants) -> #name { | ||
109 | #name::#variants(node) | ||
110 | } | ||
111 | } | ||
112 | )* | ||
113 | |||
114 | impl std::fmt::Display for #name { | ||
115 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
116 | std::fmt::Display::fmt(self.syntax(), f) | ||
117 | } | ||
118 | } | ||
119 | |||
120 | impl AstToken for #name { | ||
121 | fn can_cast(kind: SyntaxKind) -> bool { | ||
122 | match kind { | ||
123 | #(#kinds)|* => true, | ||
124 | _ => false, | ||
125 | } | ||
126 | } | ||
127 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
128 | let res = match syntax.kind() { | ||
129 | #( | ||
130 | #kinds => #name::#variants(#variants { syntax }), | ||
131 | )* | ||
132 | _ => return None, | ||
133 | }; | ||
134 | Some(res) | ||
135 | } | ||
136 | fn syntax(&self) -> &SyntaxToken { | ||
137 | match self { | ||
138 | #( | ||
139 | #name::#variants(it) => &it.syntax, | ||
140 | )* | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | } | 54 | } |
145 | }); | 55 | }); |
146 | 56 | ||
147 | crate::reformat(quote! { | 57 | let pretty = crate::reformat(quote! { |
148 | use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; | 58 | use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; |
149 | |||
150 | #(#tokens)* | 59 | #(#tokens)* |
151 | #(#enums)* | 60 | })? |
152 | }) | 61 | .replace("#[derive", "\n#[derive"); |
62 | Ok(pretty) | ||
153 | } | 63 | } |
154 | 64 | ||
155 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | 65 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { |
156 | let all_token_kinds: Vec<_> = kinds | ||
157 | .punct | ||
158 | .into_iter() | ||
159 | .map(|(_, kind)| kind) | ||
160 | .copied() | ||
161 | .map(|x| x.into()) | ||
162 | .chain( | ||
163 | kinds | ||
164 | .keywords | ||
165 | .into_iter() | ||
166 | .chain(kinds.contextual_keywords.into_iter()) | ||
167 | .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), | ||
168 | ) | ||
169 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | ||
170 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | ||
171 | .collect(); | ||
172 | |||
173 | let mut token_kinds = HashSet::new(); | ||
174 | for kind in &all_token_kinds { | ||
175 | let kind = &**kind; | ||
176 | let name = to_pascal_case(kind); | ||
177 | token_kinds.insert(name); | ||
178 | } | ||
179 | |||
180 | for en in grammar.token_enums { | ||
181 | token_kinds.insert(en.name.to_string()); | ||
182 | } | ||
183 | |||
184 | let nodes = grammar.nodes.iter().map(|node| { | 66 | let nodes = grammar.nodes.iter().map(|node| { |
185 | let name = format_ident!("{}", node.name); | 67 | let name = format_ident!("{}", node.name); |
186 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); | 68 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); |
@@ -189,53 +71,27 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
189 | quote!(impl ast::#trait_name for #name {}) | 71 | quote!(impl ast::#trait_name for #name {}) |
190 | }); | 72 | }); |
191 | 73 | ||
192 | let methods = node.fields.iter().map(|(name, field)| { | 74 | let methods = node.fields.iter().map(|field| { |
193 | let is_kw = name.ends_with("Kw"); | 75 | let method_name = field.method_name(); |
194 | let method_name = match field { | 76 | let ty = field.ty(); |
195 | FieldSrc::Shorthand => { | ||
196 | let name = if is_kw { &name[..name.len() - 2] } else { &name }; | ||
197 | format_ident!("{}", to_lower_snake_case(name)) | ||
198 | } | ||
199 | _ => format_ident!("{}", name), | ||
200 | }; | ||
201 | let ty = match field { | ||
202 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, | ||
203 | FieldSrc::Shorthand => name, | ||
204 | }; | ||
205 | 77 | ||
206 | let ty = format_ident!("{}", ty); | 78 | if field.is_many() { |
207 | 79 | quote! { | |
208 | match field { | 80 | pub fn #method_name(&self) -> AstChildren<#ty> { |
209 | FieldSrc::Many(_) => { | 81 | support::children(&self.syntax) |
210 | quote! { | ||
211 | pub fn #method_name(&self) -> AstChildren<#ty> { | ||
212 | support::children(&self.syntax) | ||
213 | } | ||
214 | } | 82 | } |
215 | } | 83 | } |
216 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { | 84 | } else { |
217 | let is_token = token_kinds.contains(&ty.to_string()); | 85 | if let Some(token_kind) = field.token_kind() { |
218 | if is_token { | 86 | quote! { |
219 | let method_name = format_ident!("{}_token", method_name); | 87 | pub fn #method_name(&self) -> Option<#ty> { |
220 | if is_kw { | 88 | support::token(&self.syntax, #token_kind) |
221 | let token_kind = format_ident!("{}", to_upper_snake_case(name)); | ||
222 | quote! { | ||
223 | pub fn #method_name(&self) -> Option<SyntaxToken> { | ||
224 | support::token2(&self.syntax, #token_kind) | ||
225 | } | ||
226 | } | ||
227 | } else { | ||
228 | quote! { | ||
229 | pub fn #method_name(&self) -> Option<#ty> { | ||
230 | support::token(&self.syntax) | ||
231 | } | ||
232 | } | ||
233 | } | 89 | } |
234 | } else { | 90 | } |
235 | quote! { | 91 | } else { |
236 | pub fn #method_name(&self) -> Option<#ty> { | 92 | quote! { |
237 | support::child(&self.syntax) | 93 | pub fn #method_name(&self) -> Option<#ty> { |
238 | } | 94 | support::child(&self.syntax) |
239 | } | 95 | } |
240 | } | 96 | } |
241 | } | 97 | } |
@@ -351,16 +207,16 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
351 | use crate::{ | 207 | use crate::{ |
352 | SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, | 208 | SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, |
353 | ast::{self, AstNode, AstChildren, support}, | 209 | ast::{self, AstNode, AstChildren, support}, |
210 | T, | ||
354 | }; | 211 | }; |
355 | 212 | ||
356 | use super::tokens::*; | ||
357 | |||
358 | #(#nodes)* | 213 | #(#nodes)* |
359 | #(#enums)* | 214 | #(#enums)* |
360 | #(#displays)* | 215 | #(#displays)* |
361 | }; | 216 | }; |
362 | 217 | ||
363 | let pretty = crate::reformat(ast)?; | 218 | let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])"); |
219 | let pretty = crate::reformat(ast)?.replace("#[derive", "\n#[derive"); | ||
364 | Ok(pretty) | 220 | Ok(pretty) |
365 | } | 221 | } |
366 | 222 | ||
@@ -468,8 +324,10 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
468 | 324 | ||
469 | #[macro_export] | 325 | #[macro_export] |
470 | macro_rules! T { | 326 | macro_rules! T { |
471 | #((#punctuation_values) => { $crate::SyntaxKind::#punctuation };)* | 327 | #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)* |
472 | #((#all_keywords_idents) => { $crate::SyntaxKind::#all_keywords };)* | 328 | #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)* |
329 | [lifetime] => { $crate::SyntaxKind::LIFETIME }; | ||
330 | [ident] => { $crate::SyntaxKind::IDENT }; | ||
473 | } | 331 | } |
474 | }; | 332 | }; |
475 | 333 | ||
@@ -519,3 +377,68 @@ fn to_pascal_case(s: &str) -> String { | |||
519 | } | 377 | } |
520 | buf | 378 | buf |
521 | } | 379 | } |
380 | |||
381 | impl Field<'_> { | ||
382 | fn is_many(&self) -> bool { | ||
383 | match self { | ||
384 | Field::Node { src: FieldSrc::Many(_), .. } => true, | ||
385 | _ => false, | ||
386 | } | ||
387 | } | ||
388 | fn token_kind(&self) -> Option<proc_macro2::TokenStream> { | ||
389 | let res = match self { | ||
390 | Field::Token(token) => { | ||
391 | let token: proc_macro2::TokenStream = token.parse().unwrap(); | ||
392 | quote! { T![#token] } | ||
393 | } | ||
394 | _ => return None, | ||
395 | }; | ||
396 | Some(res) | ||
397 | } | ||
398 | fn method_name(&self) -> proc_macro2::Ident { | ||
399 | match self { | ||
400 | Field::Token(name) => { | ||
401 | let name = match *name { | ||
402 | ";" => "semicolon", | ||
403 | "->" => "thin_arrow", | ||
404 | "'{'" => "l_curly", | ||
405 | "'}'" => "r_curly", | ||
406 | "'('" => "l_paren", | ||
407 | "')'" => "r_paren", | ||
408 | "'['" => "l_brack", | ||
409 | "']'" => "r_brack", | ||
410 | "<" => "l_angle", | ||
411 | ">" => "r_angle", | ||
412 | "=" => "eq", | ||
413 | "!" => "excl", | ||
414 | "*" => "star", | ||
415 | "&" => "amp", | ||
416 | "_" => "underscore", | ||
417 | "." => "dot", | ||
418 | ".." => "dotdot", | ||
419 | "..." => "dotdotdot", | ||
420 | "=>" => "fat_arrow", | ||
421 | "@" => "at", | ||
422 | ":" => "colon", | ||
423 | "::" => "coloncolon", | ||
424 | "#" => "pound", | ||
425 | _ => name, | ||
426 | }; | ||
427 | format_ident!("{}_token", name) | ||
428 | } | ||
429 | Field::Node { name, src } => match src { | ||
430 | FieldSrc::Shorthand => format_ident!("{}", to_lower_snake_case(name)), | ||
431 | _ => format_ident!("{}", name), | ||
432 | }, | ||
433 | } | ||
434 | } | ||
435 | fn ty(&self) -> proc_macro2::Ident { | ||
436 | match self { | ||
437 | Field::Token(_) => format_ident!("SyntaxToken"), | ||
438 | Field::Node { name, src } => match src { | ||
439 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => format_ident!("{}", ty), | ||
440 | FieldSrc::Shorthand => format_ident!("{}", name), | ||
441 | }, | ||
442 | } | ||
443 | } | ||
444 | } | ||