├── .gitignore ├── Cargo.toml ├── bless.nu ├── examples ├── item.expanded.rs ├── item.rs ├── punct.expanded.rs ├── punct.rs ├── unit_struct.expanded.rs └── unit_struct.rs ├── src └── lib.rs └── tests └── examples.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pegcel" 3 | version = "0.2.0" 4 | edition = "2021" 5 | 6 | autoexamples = false 7 | 8 | [features] 9 | default = ["clone-impls", "printing"] 10 | 11 | clone-impls = ["syn/clone-impls"] 12 | extra-traits = ["syn/extra-traits"] 13 | printing = ["syn/printing", "dep:quote"] 14 | 15 | [[example]] 16 | name = "item" 17 | 18 | [[example]] 19 | name = "punct" 20 | 21 | [[example]] 22 | name = "unit_struct" 23 | 24 | [dependencies] 25 | paste = { version = "1.0.12", default-features = false } 26 | proc-macro2 = { version = "1.0.60", default-features = false } 27 | quote = { version = "1.0.28", default-features = false, optional = true } 28 | syn = { version = "2.0.18", default-features = false, features = ["parsing"] } 29 | 30 | [dev-dependencies] 31 | macrotest = "1.0.9" 32 | syn = { version = "2.0.18", features = ["full"] } 33 | -------------------------------------------------------------------------------- /bless.nu: -------------------------------------------------------------------------------- 1 | with-env [MACROTEST "overwrite"] { 2 | cargo +nightly test --test examples -- expand 3 | } 4 | -------------------------------------------------------------------------------- /examples/item.expanded.rs: -------------------------------------------------------------------------------- 1 | //! syn::Item 2 | use syn::{ 3 | ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, 4 | ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, 5 | ItemUse, 6 | }; 7 | enum Item { 8 | Const(ItemConst), 9 | Enum(ItemEnum), 10 | ExternCrate(ItemExternCrate), 11 | Fn(ItemFn), 12 | ForeignMod(ItemForeignMod), 13 | Impl(ItemImpl), 14 | Macro(ItemMacro), 15 | Mod(ItemMod), 16 | Static(ItemStatic), 17 | Struct(ItemStruct), 18 | Trait(ItemTrait), 19 | TraitAlias(ItemTraitAlias), 20 | Type(ItemType), 21 | Union(ItemUnion), 22 | Use(ItemUse), 23 | } 24 | #[automatically_derived] 25 | impl ::pegcel::std::clone::Clone for Item { 26 | fn clone(&self) -> Self { 27 | match self { 28 | Item::Const(v) => Item::Const(v.clone()), 29 | Item::Enum(v) => Item::Enum(v.clone()), 30 | Item::ExternCrate(v) => Item::ExternCrate(v.clone()), 31 | Item::Fn(v) => Item::Fn(v.clone()), 32 | Item::ForeignMod(v) => Item::ForeignMod(v.clone()), 33 | Item::Impl(v) => Item::Impl(v.clone()), 34 | Item::Macro(v) => Item::Macro(v.clone()), 35 | Item::Mod(v) => Item::Mod(v.clone()), 36 | Item::Static(v) => Item::Static(v.clone()), 37 | Item::Struct(v) => Item::Struct(v.clone()), 38 | Item::Trait(v) => Item::Trait(v.clone()), 39 | Item::TraitAlias(v) => Item::TraitAlias(v.clone()), 40 | Item::Type(v) => Item::Type(v.clone()), 41 | Item::Union(v) => Item::Union(v.clone()), 42 | Item::Use(v) => Item::Use(v.clone()), 43 | } 44 | } 45 | } 46 | #[automatically_derived] 47 | impl ::pegcel::std::fmt::Debug for Item { 48 | fn fmt( 49 | &self, 50 | f: &mut ::pegcel::std::fmt::Formatter<'_>, 51 | ) -> ::pegcel::std::fmt::Result { 52 | match self { 53 | Item::Const(v) => f.debug_tuple("Const").field(v).finish(), 54 | Item::Enum(v) => f.debug_tuple("Enum").field(v).finish(), 55 | Item::ExternCrate(v) => f.debug_tuple("ExternCrate").field(v).finish(), 56 | Item::Fn(v) => f.debug_tuple("Fn").field(v).finish(), 57 | Item::ForeignMod(v) => f.debug_tuple("ForeignMod").field(v).finish(), 58 | Item::Impl(v) => f.debug_tuple("Impl").field(v).finish(), 59 | Item::Macro(v) => f.debug_tuple("Macro").field(v).finish(), 60 | Item::Mod(v) => f.debug_tuple("Mod").field(v).finish(), 61 | Item::Static(v) => f.debug_tuple("Static").field(v).finish(), 62 | Item::Struct(v) => f.debug_tuple("Struct").field(v).finish(), 63 | Item::Trait(v) => f.debug_tuple("Trait").field(v).finish(), 64 | Item::TraitAlias(v) => f.debug_tuple("TraitAlias").field(v).finish(), 65 | Item::Type(v) => f.debug_tuple("Type").field(v).finish(), 66 | Item::Union(v) => f.debug_tuple("Union").field(v).finish(), 67 | Item::Use(v) => f.debug_tuple("Use").field(v).finish(), 68 | } 69 | } 70 | } 71 | #[automatically_derived] 72 | impl ::pegcel::std::hash::Hash for Item { 73 | fn hash(&self, state: &mut H) { 74 | match self { 75 | Item::Const(v) => { 76 | ::pegcel::std::mem::discriminant(self).hash(state); 77 | v.hash(state); 78 | } 79 | Item::Enum(v) => { 80 | ::pegcel::std::mem::discriminant(self).hash(state); 81 | v.hash(state); 82 | } 83 | Item::ExternCrate(v) => { 84 | ::pegcel::std::mem::discriminant(self).hash(state); 85 | v.hash(state); 86 | } 87 | Item::Fn(v) => { 88 | ::pegcel::std::mem::discriminant(self).hash(state); 89 | v.hash(state); 90 | } 91 | Item::ForeignMod(v) => { 92 | ::pegcel::std::mem::discriminant(self).hash(state); 93 | v.hash(state); 94 | } 95 | Item::Impl(v) => { 96 | ::pegcel::std::mem::discriminant(self).hash(state); 97 | v.hash(state); 98 | } 99 | Item::Macro(v) => { 100 | ::pegcel::std::mem::discriminant(self).hash(state); 101 | v.hash(state); 102 | } 103 | Item::Mod(v) => { 104 | ::pegcel::std::mem::discriminant(self).hash(state); 105 | v.hash(state); 106 | } 107 | Item::Static(v) => { 108 | ::pegcel::std::mem::discriminant(self).hash(state); 109 | v.hash(state); 110 | } 111 | Item::Struct(v) => { 112 | ::pegcel::std::mem::discriminant(self).hash(state); 113 | v.hash(state); 114 | } 115 | Item::Trait(v) => { 116 | ::pegcel::std::mem::discriminant(self).hash(state); 117 | v.hash(state); 118 | } 119 | Item::TraitAlias(v) => { 120 | ::pegcel::std::mem::discriminant(self).hash(state); 121 | v.hash(state); 122 | } 123 | Item::Type(v) => { 124 | ::pegcel::std::mem::discriminant(self).hash(state); 125 | v.hash(state); 126 | } 127 | Item::Union(v) => { 128 | ::pegcel::std::mem::discriminant(self).hash(state); 129 | v.hash(state); 130 | } 131 | Item::Use(v) => { 132 | ::pegcel::std::mem::discriminant(self).hash(state); 133 | v.hash(state); 134 | } 135 | } 136 | } 137 | } 138 | #[automatically_derived] 139 | impl ::pegcel::std::cmp::PartialEq for Item { 140 | fn eq(&self, other: &Self) -> bool { 141 | match (self, other) { 142 | (Item::Const(lhs), Item::Const(rhs)) => lhs == rhs, 143 | (Item::Enum(lhs), Item::Enum(rhs)) => lhs == rhs, 144 | (Item::ExternCrate(lhs), Item::ExternCrate(rhs)) => lhs == rhs, 145 | (Item::Fn(lhs), Item::Fn(rhs)) => lhs == rhs, 146 | (Item::ForeignMod(lhs), Item::ForeignMod(rhs)) => lhs == rhs, 147 | (Item::Impl(lhs), Item::Impl(rhs)) => lhs == rhs, 148 | (Item::Macro(lhs), Item::Macro(rhs)) => lhs == rhs, 149 | (Item::Mod(lhs), Item::Mod(rhs)) => lhs == rhs, 150 | (Item::Static(lhs), Item::Static(rhs)) => lhs == rhs, 151 | (Item::Struct(lhs), Item::Struct(rhs)) => lhs == rhs, 152 | (Item::Trait(lhs), Item::Trait(rhs)) => lhs == rhs, 153 | (Item::TraitAlias(lhs), Item::TraitAlias(rhs)) => lhs == rhs, 154 | (Item::Type(lhs), Item::Type(rhs)) => lhs == rhs, 155 | (Item::Union(lhs), Item::Union(rhs)) => lhs == rhs, 156 | (Item::Use(lhs), Item::Use(rhs)) => lhs == rhs, 157 | _ => false, 158 | } 159 | } 160 | } 161 | #[automatically_derived] 162 | impl ::pegcel::std::cmp::Eq for Item {} 163 | #[automatically_derived] 164 | impl From for Item { 165 | fn from(v: ItemConst) -> Self { 166 | Item::Const(v) 167 | } 168 | } 169 | #[automatically_derived] 170 | impl From for Item { 171 | fn from(v: ItemEnum) -> Self { 172 | Item::Enum(v) 173 | } 174 | } 175 | #[automatically_derived] 176 | impl From for Item { 177 | fn from(v: ItemExternCrate) -> Self { 178 | Item::ExternCrate(v) 179 | } 180 | } 181 | #[automatically_derived] 182 | impl From for Item { 183 | fn from(v: ItemFn) -> Self { 184 | Item::Fn(v) 185 | } 186 | } 187 | #[automatically_derived] 188 | impl From for Item { 189 | fn from(v: ItemForeignMod) -> Self { 190 | Item::ForeignMod(v) 191 | } 192 | } 193 | #[automatically_derived] 194 | impl From for Item { 195 | fn from(v: ItemImpl) -> Self { 196 | Item::Impl(v) 197 | } 198 | } 199 | #[automatically_derived] 200 | impl From for Item { 201 | fn from(v: ItemMacro) -> Self { 202 | Item::Macro(v) 203 | } 204 | } 205 | #[automatically_derived] 206 | impl From for Item { 207 | fn from(v: ItemMod) -> Self { 208 | Item::Mod(v) 209 | } 210 | } 211 | #[automatically_derived] 212 | impl From for Item { 213 | fn from(v: ItemStatic) -> Self { 214 | Item::Static(v) 215 | } 216 | } 217 | #[automatically_derived] 218 | impl From for Item { 219 | fn from(v: ItemStruct) -> Self { 220 | Item::Struct(v) 221 | } 222 | } 223 | #[automatically_derived] 224 | impl From for Item { 225 | fn from(v: ItemTrait) -> Self { 226 | Item::Trait(v) 227 | } 228 | } 229 | #[automatically_derived] 230 | impl From for Item { 231 | fn from(v: ItemTraitAlias) -> Self { 232 | Item::TraitAlias(v) 233 | } 234 | } 235 | #[automatically_derived] 236 | impl From for Item { 237 | fn from(v: ItemType) -> Self { 238 | Item::Type(v) 239 | } 240 | } 241 | #[automatically_derived] 242 | impl From for Item { 243 | fn from(v: ItemUnion) -> Self { 244 | Item::Union(v) 245 | } 246 | } 247 | #[automatically_derived] 248 | impl From for Item { 249 | fn from(v: ItemUse) -> Self { 250 | Item::Use(v) 251 | } 252 | } 253 | #[automatically_derived] 254 | impl ::pegcel::syn::parse::Parse for Item { 255 | fn parse( 256 | input: ::pegcel::syn::parse::ParseStream, 257 | ) -> ::pegcel::syn::parse::Result { 258 | use ::pegcel::syn::parse::discouraged::Speculative; 259 | let mut best_guess = ::pegcel::std::option::Option::None; 260 | let mut best_guess_cursor = input.cursor(); 261 | let mut best_guess_variant = ""; 262 | { 263 | let fork = input.fork(); 264 | match fork.parse::() { 265 | ::pegcel::std::result::Result::Ok(v) => { 266 | input.advance_to(&fork); 267 | return ::pegcel::std::result::Result::Ok(Item::Const(v)); 268 | } 269 | ::pegcel::std::result::Result::Err(e) => { 270 | let this_guess_cursor = fork.cursor(); 271 | if this_guess_cursor > best_guess_cursor { 272 | best_guess = ::pegcel::std::option::Option::Some(e); 273 | best_guess_variant = "Const"; 274 | best_guess_cursor = this_guess_cursor; 275 | } else if this_guess_cursor == best_guess_cursor { 276 | if let ::pegcel::std::option::Option::Some(existing) 277 | = &mut best_guess { 278 | existing.combine(e); 279 | } else { 280 | best_guess = ::pegcel::std::option::Option::Some(e); 281 | } 282 | } 283 | } 284 | } 285 | } 286 | { 287 | let fork = input.fork(); 288 | match fork.parse::() { 289 | ::pegcel::std::result::Result::Ok(v) => { 290 | input.advance_to(&fork); 291 | return ::pegcel::std::result::Result::Ok(Item::Enum(v)); 292 | } 293 | ::pegcel::std::result::Result::Err(e) => { 294 | let this_guess_cursor = fork.cursor(); 295 | if this_guess_cursor > best_guess_cursor { 296 | best_guess = ::pegcel::std::option::Option::Some(e); 297 | best_guess_variant = "Enum"; 298 | best_guess_cursor = this_guess_cursor; 299 | } else if this_guess_cursor == best_guess_cursor { 300 | if let ::pegcel::std::option::Option::Some(existing) 301 | = &mut best_guess { 302 | existing.combine(e); 303 | } else { 304 | best_guess = ::pegcel::std::option::Option::Some(e); 305 | } 306 | } 307 | } 308 | } 309 | } 310 | { 311 | let fork = input.fork(); 312 | match fork.parse::() { 313 | ::pegcel::std::result::Result::Ok(v) => { 314 | input.advance_to(&fork); 315 | return ::pegcel::std::result::Result::Ok(Item::ExternCrate(v)); 316 | } 317 | ::pegcel::std::result::Result::Err(e) => { 318 | let this_guess_cursor = fork.cursor(); 319 | if this_guess_cursor > best_guess_cursor { 320 | best_guess = ::pegcel::std::option::Option::Some(e); 321 | best_guess_variant = "ExternCrate"; 322 | best_guess_cursor = this_guess_cursor; 323 | } else if this_guess_cursor == best_guess_cursor { 324 | if let ::pegcel::std::option::Option::Some(existing) 325 | = &mut best_guess { 326 | existing.combine(e); 327 | } else { 328 | best_guess = ::pegcel::std::option::Option::Some(e); 329 | } 330 | } 331 | } 332 | } 333 | } 334 | { 335 | let fork = input.fork(); 336 | match fork.parse::() { 337 | ::pegcel::std::result::Result::Ok(v) => { 338 | input.advance_to(&fork); 339 | return ::pegcel::std::result::Result::Ok(Item::Fn(v)); 340 | } 341 | ::pegcel::std::result::Result::Err(e) => { 342 | let this_guess_cursor = fork.cursor(); 343 | if this_guess_cursor > best_guess_cursor { 344 | best_guess = ::pegcel::std::option::Option::Some(e); 345 | best_guess_variant = "Fn"; 346 | best_guess_cursor = this_guess_cursor; 347 | } else if this_guess_cursor == best_guess_cursor { 348 | if let ::pegcel::std::option::Option::Some(existing) 349 | = &mut best_guess { 350 | existing.combine(e); 351 | } else { 352 | best_guess = ::pegcel::std::option::Option::Some(e); 353 | } 354 | } 355 | } 356 | } 357 | } 358 | { 359 | let fork = input.fork(); 360 | match fork.parse::() { 361 | ::pegcel::std::result::Result::Ok(v) => { 362 | input.advance_to(&fork); 363 | return ::pegcel::std::result::Result::Ok(Item::ForeignMod(v)); 364 | } 365 | ::pegcel::std::result::Result::Err(e) => { 366 | let this_guess_cursor = fork.cursor(); 367 | if this_guess_cursor > best_guess_cursor { 368 | best_guess = ::pegcel::std::option::Option::Some(e); 369 | best_guess_variant = "ForeignMod"; 370 | best_guess_cursor = this_guess_cursor; 371 | } else if this_guess_cursor == best_guess_cursor { 372 | if let ::pegcel::std::option::Option::Some(existing) 373 | = &mut best_guess { 374 | existing.combine(e); 375 | } else { 376 | best_guess = ::pegcel::std::option::Option::Some(e); 377 | } 378 | } 379 | } 380 | } 381 | } 382 | { 383 | let fork = input.fork(); 384 | match fork.parse::() { 385 | ::pegcel::std::result::Result::Ok(v) => { 386 | input.advance_to(&fork); 387 | return ::pegcel::std::result::Result::Ok(Item::Impl(v)); 388 | } 389 | ::pegcel::std::result::Result::Err(e) => { 390 | let this_guess_cursor = fork.cursor(); 391 | if this_guess_cursor > best_guess_cursor { 392 | best_guess = ::pegcel::std::option::Option::Some(e); 393 | best_guess_variant = "Impl"; 394 | best_guess_cursor = this_guess_cursor; 395 | } else if this_guess_cursor == best_guess_cursor { 396 | if let ::pegcel::std::option::Option::Some(existing) 397 | = &mut best_guess { 398 | existing.combine(e); 399 | } else { 400 | best_guess = ::pegcel::std::option::Option::Some(e); 401 | } 402 | } 403 | } 404 | } 405 | } 406 | { 407 | let fork = input.fork(); 408 | match fork.parse::() { 409 | ::pegcel::std::result::Result::Ok(v) => { 410 | input.advance_to(&fork); 411 | return ::pegcel::std::result::Result::Ok(Item::Macro(v)); 412 | } 413 | ::pegcel::std::result::Result::Err(e) => { 414 | let this_guess_cursor = fork.cursor(); 415 | if this_guess_cursor > best_guess_cursor { 416 | best_guess = ::pegcel::std::option::Option::Some(e); 417 | best_guess_variant = "Macro"; 418 | best_guess_cursor = this_guess_cursor; 419 | } else if this_guess_cursor == best_guess_cursor { 420 | if let ::pegcel::std::option::Option::Some(existing) 421 | = &mut best_guess { 422 | existing.combine(e); 423 | } else { 424 | best_guess = ::pegcel::std::option::Option::Some(e); 425 | } 426 | } 427 | } 428 | } 429 | } 430 | { 431 | let fork = input.fork(); 432 | match fork.parse::() { 433 | ::pegcel::std::result::Result::Ok(v) => { 434 | input.advance_to(&fork); 435 | return ::pegcel::std::result::Result::Ok(Item::Mod(v)); 436 | } 437 | ::pegcel::std::result::Result::Err(e) => { 438 | let this_guess_cursor = fork.cursor(); 439 | if this_guess_cursor > best_guess_cursor { 440 | best_guess = ::pegcel::std::option::Option::Some(e); 441 | best_guess_variant = "Mod"; 442 | best_guess_cursor = this_guess_cursor; 443 | } else if this_guess_cursor == best_guess_cursor { 444 | if let ::pegcel::std::option::Option::Some(existing) 445 | = &mut best_guess { 446 | existing.combine(e); 447 | } else { 448 | best_guess = ::pegcel::std::option::Option::Some(e); 449 | } 450 | } 451 | } 452 | } 453 | } 454 | { 455 | let fork = input.fork(); 456 | match fork.parse::() { 457 | ::pegcel::std::result::Result::Ok(v) => { 458 | input.advance_to(&fork); 459 | return ::pegcel::std::result::Result::Ok(Item::Static(v)); 460 | } 461 | ::pegcel::std::result::Result::Err(e) => { 462 | let this_guess_cursor = fork.cursor(); 463 | if this_guess_cursor > best_guess_cursor { 464 | best_guess = ::pegcel::std::option::Option::Some(e); 465 | best_guess_variant = "Static"; 466 | best_guess_cursor = this_guess_cursor; 467 | } else if this_guess_cursor == best_guess_cursor { 468 | if let ::pegcel::std::option::Option::Some(existing) 469 | = &mut best_guess { 470 | existing.combine(e); 471 | } else { 472 | best_guess = ::pegcel::std::option::Option::Some(e); 473 | } 474 | } 475 | } 476 | } 477 | } 478 | { 479 | let fork = input.fork(); 480 | match fork.parse::() { 481 | ::pegcel::std::result::Result::Ok(v) => { 482 | input.advance_to(&fork); 483 | return ::pegcel::std::result::Result::Ok(Item::Struct(v)); 484 | } 485 | ::pegcel::std::result::Result::Err(e) => { 486 | let this_guess_cursor = fork.cursor(); 487 | if this_guess_cursor > best_guess_cursor { 488 | best_guess = ::pegcel::std::option::Option::Some(e); 489 | best_guess_variant = "Struct"; 490 | best_guess_cursor = this_guess_cursor; 491 | } else if this_guess_cursor == best_guess_cursor { 492 | if let ::pegcel::std::option::Option::Some(existing) 493 | = &mut best_guess { 494 | existing.combine(e); 495 | } else { 496 | best_guess = ::pegcel::std::option::Option::Some(e); 497 | } 498 | } 499 | } 500 | } 501 | } 502 | { 503 | let fork = input.fork(); 504 | match fork.parse::() { 505 | ::pegcel::std::result::Result::Ok(v) => { 506 | input.advance_to(&fork); 507 | return ::pegcel::std::result::Result::Ok(Item::Trait(v)); 508 | } 509 | ::pegcel::std::result::Result::Err(e) => { 510 | let this_guess_cursor = fork.cursor(); 511 | if this_guess_cursor > best_guess_cursor { 512 | best_guess = ::pegcel::std::option::Option::Some(e); 513 | best_guess_variant = "Trait"; 514 | best_guess_cursor = this_guess_cursor; 515 | } else if this_guess_cursor == best_guess_cursor { 516 | if let ::pegcel::std::option::Option::Some(existing) 517 | = &mut best_guess { 518 | existing.combine(e); 519 | } else { 520 | best_guess = ::pegcel::std::option::Option::Some(e); 521 | } 522 | } 523 | } 524 | } 525 | } 526 | { 527 | let fork = input.fork(); 528 | match fork.parse::() { 529 | ::pegcel::std::result::Result::Ok(v) => { 530 | input.advance_to(&fork); 531 | return ::pegcel::std::result::Result::Ok(Item::TraitAlias(v)); 532 | } 533 | ::pegcel::std::result::Result::Err(e) => { 534 | let this_guess_cursor = fork.cursor(); 535 | if this_guess_cursor > best_guess_cursor { 536 | best_guess = ::pegcel::std::option::Option::Some(e); 537 | best_guess_variant = "TraitAlias"; 538 | best_guess_cursor = this_guess_cursor; 539 | } else if this_guess_cursor == best_guess_cursor { 540 | if let ::pegcel::std::option::Option::Some(existing) 541 | = &mut best_guess { 542 | existing.combine(e); 543 | } else { 544 | best_guess = ::pegcel::std::option::Option::Some(e); 545 | } 546 | } 547 | } 548 | } 549 | } 550 | { 551 | let fork = input.fork(); 552 | match fork.parse::() { 553 | ::pegcel::std::result::Result::Ok(v) => { 554 | input.advance_to(&fork); 555 | return ::pegcel::std::result::Result::Ok(Item::Type(v)); 556 | } 557 | ::pegcel::std::result::Result::Err(e) => { 558 | let this_guess_cursor = fork.cursor(); 559 | if this_guess_cursor > best_guess_cursor { 560 | best_guess = ::pegcel::std::option::Option::Some(e); 561 | best_guess_variant = "Type"; 562 | best_guess_cursor = this_guess_cursor; 563 | } else if this_guess_cursor == best_guess_cursor { 564 | if let ::pegcel::std::option::Option::Some(existing) 565 | = &mut best_guess { 566 | existing.combine(e); 567 | } else { 568 | best_guess = ::pegcel::std::option::Option::Some(e); 569 | } 570 | } 571 | } 572 | } 573 | } 574 | { 575 | let fork = input.fork(); 576 | match fork.parse::() { 577 | ::pegcel::std::result::Result::Ok(v) => { 578 | input.advance_to(&fork); 579 | return ::pegcel::std::result::Result::Ok(Item::Union(v)); 580 | } 581 | ::pegcel::std::result::Result::Err(e) => { 582 | let this_guess_cursor = fork.cursor(); 583 | if this_guess_cursor > best_guess_cursor { 584 | best_guess = ::pegcel::std::option::Option::Some(e); 585 | best_guess_variant = "Union"; 586 | best_guess_cursor = this_guess_cursor; 587 | } else if this_guess_cursor == best_guess_cursor { 588 | if let ::pegcel::std::option::Option::Some(existing) 589 | = &mut best_guess { 590 | existing.combine(e); 591 | } else { 592 | best_guess = ::pegcel::std::option::Option::Some(e); 593 | } 594 | } 595 | } 596 | } 597 | } 598 | { 599 | let fork = input.fork(); 600 | match fork.parse::() { 601 | ::pegcel::std::result::Result::Ok(v) => { 602 | input.advance_to(&fork); 603 | return ::pegcel::std::result::Result::Ok(Item::Use(v)); 604 | } 605 | ::pegcel::std::result::Result::Err(e) => { 606 | let this_guess_cursor = fork.cursor(); 607 | if this_guess_cursor > best_guess_cursor { 608 | best_guess = ::pegcel::std::option::Option::Some(e); 609 | best_guess_variant = "Use"; 610 | best_guess_cursor = this_guess_cursor; 611 | } else if this_guess_cursor == best_guess_cursor { 612 | if let ::pegcel::std::option::Option::Some(existing) 613 | = &mut best_guess { 614 | existing.combine(e); 615 | } else { 616 | best_guess = ::pegcel::std::option::Option::Some(e); 617 | } 618 | } 619 | } 620 | } 621 | } 622 | ::pegcel::std::result::Result::Err( 623 | input 624 | .error( 625 | format_args!( 626 | "expected {0} but failed to parse any variant; best attempt was {1} with {2}", 627 | "Item", best_guess_variant, best_guess.unwrap() 628 | ), 629 | ), 630 | ) 631 | } 632 | } 633 | impl ::pegcel::quote::ToTokens for Item { 634 | fn to_tokens(&self, tokens: &mut ::pegcel::proc_macro2::TokenStream) { 635 | match self { 636 | Item::Const(v) => (&v).to_tokens(tokens), 637 | Item::Enum(v) => (&v).to_tokens(tokens), 638 | Item::ExternCrate(v) => (&v).to_tokens(tokens), 639 | Item::Fn(v) => (&v).to_tokens(tokens), 640 | Item::ForeignMod(v) => (&v).to_tokens(tokens), 641 | Item::Impl(v) => (&v).to_tokens(tokens), 642 | Item::Macro(v) => (&v).to_tokens(tokens), 643 | Item::Mod(v) => (&v).to_tokens(tokens), 644 | Item::Static(v) => (&v).to_tokens(tokens), 645 | Item::Struct(v) => (&v).to_tokens(tokens), 646 | Item::Trait(v) => (&v).to_tokens(tokens), 647 | Item::TraitAlias(v) => (&v).to_tokens(tokens), 648 | Item::Type(v) => (&v).to_tokens(tokens), 649 | Item::Union(v) => (&v).to_tokens(tokens), 650 | Item::Use(v) => (&v).to_tokens(tokens), 651 | } 652 | } 653 | } 654 | fn main() {} 655 | -------------------------------------------------------------------------------- /examples/item.rs: -------------------------------------------------------------------------------- 1 | //! syn::Item 2 | 3 | use syn::{ 4 | ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, 5 | ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, 6 | }; 7 | 8 | pegcel::define_syntax! { 9 | enum Item { 10 | Const, 11 | Enum, 12 | ExternCrate, 13 | Fn, 14 | ForeignMod, 15 | Impl, 16 | Macro, 17 | Mod, 18 | Static, 19 | Struct, 20 | Trait, 21 | TraitAlias, 22 | Type, 23 | Union, 24 | Use, 25 | } 26 | } 27 | 28 | fn main() {} 29 | -------------------------------------------------------------------------------- /examples/punct.expanded.rs: -------------------------------------------------------------------------------- 1 | mod syntax { 2 | pub mod kw { 3 | #[allow(non_camel_case_types)] 4 | pub struct yeet { 5 | pub span: ::syn::__private::Span, 6 | } 7 | #[doc(hidden)] 8 | #[allow(dead_code, non_snake_case)] 9 | pub fn yeet<__S: ::syn::__private::IntoSpans<::syn::__private::Span>>( 10 | span: __S, 11 | ) -> yeet { 12 | yeet { 13 | span: ::syn::__private::IntoSpans::into_spans(span), 14 | } 15 | } 16 | const _: () = { 17 | impl ::syn::__private::Default for yeet { 18 | fn default() -> Self { 19 | yeet { 20 | span: ::syn::__private::Span::call_site(), 21 | } 22 | } 23 | } 24 | impl ::syn::token::CustomToken for yeet { 25 | fn peek(cursor: ::syn::buffer::Cursor) -> ::syn::__private::bool { 26 | if let ::syn::__private::Some((ident, _rest)) = cursor.ident() { 27 | ident == "yeet" 28 | } else { 29 | false 30 | } 31 | } 32 | fn display() -> &'static ::syn::__private::str { 33 | "`yeet`" 34 | } 35 | } 36 | impl ::syn::parse::Parse for yeet { 37 | fn parse( 38 | input: ::syn::parse::ParseStream, 39 | ) -> ::syn::parse::Result { 40 | input 41 | .step(|cursor| { 42 | if let ::syn::__private::Some((ident, rest)) = cursor.ident() 43 | { 44 | if ident == "yeet" { 45 | return ::syn::__private::Ok(( 46 | yeet { span: ident.span() }, 47 | rest, 48 | )); 49 | } 50 | } 51 | ::syn::__private::Err(cursor.error("expected `yeet`")) 52 | }) 53 | } 54 | } 55 | impl ::syn::__private::ToTokens for yeet { 56 | fn to_tokens(&self, tokens: &mut ::syn::__private::TokenStream2) { 57 | let ident = ::syn::Ident::new("yeet", self.span); 58 | ::syn::__private::TokenStreamExt::append(tokens, ident); 59 | } 60 | } 61 | impl ::syn::__private::Copy for yeet {} 62 | #[allow(clippy::expl_impl_clone_on_copy)] 63 | impl ::syn::__private::Clone for yeet { 64 | fn clone(&self) -> Self { 65 | *self 66 | } 67 | } 68 | impl ::syn::__private::Debug for yeet { 69 | fn fmt( 70 | &self, 71 | f: &mut ::syn::__private::Formatter, 72 | ) -> ::syn::__private::fmt::Result { 73 | ::syn::__private::Formatter::write_str(f, "Keyword [yeet]") 74 | } 75 | } 76 | impl ::syn::__private::Eq for yeet {} 77 | impl ::syn::__private::PartialEq for yeet { 78 | fn eq(&self, _other: &Self) -> ::syn::__private::bool { 79 | true 80 | } 81 | } 82 | impl ::syn::__private::Hash for yeet { 83 | fn hash<__H: ::syn::__private::Hasher>(&self, _state: &mut __H) {} 84 | } 85 | }; 86 | } 87 | pub mod punct { 88 | pub struct Elvis { 89 | pub spans: [::syn::__private::Span; 0 + 1 + 1], 90 | } 91 | #[doc(hidden)] 92 | #[allow(dead_code, non_snake_case)] 93 | pub fn Elvis< 94 | __S: ::syn::__private::IntoSpans<[::syn::__private::Span; 0 + 1 + 1]>, 95 | >(spans: __S) -> Elvis { 96 | let _validate_len = 0 + 1 + 1; 97 | Elvis { 98 | spans: ::syn::__private::IntoSpans::into_spans(spans), 99 | } 100 | } 101 | const _: () = { 102 | impl ::syn::__private::Default for Elvis { 103 | fn default() -> Self { 104 | Elvis(::syn::__private::Span::call_site()) 105 | } 106 | } 107 | impl ::syn::token::CustomToken for Elvis { 108 | fn peek(cursor: ::syn::buffer::Cursor) -> bool { 109 | ::syn::__private::peek_punct(cursor, "?:") 110 | } 111 | fn display() -> &'static ::syn::__private::str { 112 | "`?:`" 113 | } 114 | } 115 | impl ::syn::parse::Parse for Elvis { 116 | fn parse( 117 | input: ::syn::parse::ParseStream, 118 | ) -> ::syn::parse::Result { 119 | let spans: [::syn::__private::Span; 0 + 1 + 1] = ::syn::__private::parse_punct( 120 | input, 121 | "?:", 122 | )?; 123 | Ok(Elvis(spans)) 124 | } 125 | } 126 | impl ::syn::__private::ToTokens for Elvis { 127 | fn to_tokens(&self, tokens: &mut ::syn::__private::TokenStream2) { 128 | ::syn::__private::print_punct("?:", &self.spans, tokens) 129 | } 130 | } 131 | impl ::syn::__private::Copy for Elvis {} 132 | #[allow(clippy::expl_impl_clone_on_copy)] 133 | impl ::syn::__private::Clone for Elvis { 134 | fn clone(&self) -> Self { 135 | *self 136 | } 137 | } 138 | impl ::syn::__private::Debug for Elvis { 139 | fn fmt( 140 | &self, 141 | f: &mut ::syn::__private::Formatter, 142 | ) -> ::syn::__private::fmt::Result { 143 | ::syn::__private::Formatter::write_str(f, "Elvis") 144 | } 145 | } 146 | impl ::syn::__private::Eq for Elvis {} 147 | impl ::syn::__private::PartialEq for Elvis { 148 | fn eq(&self, _other: &Self) -> ::syn::__private::bool { 149 | true 150 | } 151 | } 152 | impl ::syn::__private::Hash for Elvis { 153 | fn hash<__H: ::syn::__private::Hasher>(&self, _state: &mut __H) {} 154 | } 155 | }; 156 | } 157 | pub use __pegcel_generated_token_macro__Token as Token; 158 | } 159 | fn main() { 160 | let _ = ::default(); 161 | let _ = ::default(); 162 | let _ = <::syn::token::Do>::default(); 163 | let _ = <::syn::token::PathSep>::default(); 164 | } 165 | -------------------------------------------------------------------------------- /examples/punct.rs: -------------------------------------------------------------------------------- 1 | mod syntax { 2 | pegcel::define_syntax! { 3 | pub macro_rules! Token; 4 | mod self = crate::syntax; 5 | 6 | mod kw { 7 | yeet; 8 | } 9 | 10 | mod punct { 11 | Elvis(?:); 12 | } 13 | } 14 | } 15 | 16 | fn main() { 17 | // macros don't show up in the expansion, so here's an example: 18 | let _ = ::default(); 19 | let _ = ::default(); 20 | // and syn tokens are still available: 21 | let _ = ::default(); 22 | let _ = ::default(); 23 | } 24 | -------------------------------------------------------------------------------- /examples/unit_struct.expanded.rs: -------------------------------------------------------------------------------- 1 | //! A unit struct with attributes. 2 | //! 3 | //! ```no_compile 4 | //! #[path = "s.tmpl"] 5 | //! struct S; 6 | //! ``` 7 | use syn::{Attribute, Ident, Token}; 8 | struct UnitStruct { 9 | attrs: Vec, 10 | struct_token: (), 11 | name: Ident, 12 | semi_token: (), 13 | } 14 | #[automatically_derived] 15 | impl ::pegcel::std::clone::Clone for UnitStruct { 16 | fn clone(&self) -> Self { 17 | Self { 18 | attrs: self.attrs.clone(), 19 | struct_token: self.struct_token.clone(), 20 | name: self.name.clone(), 21 | semi_token: self.semi_token.clone(), 22 | } 23 | } 24 | } 25 | #[automatically_derived] 26 | impl ::pegcel::std::fmt::Debug for UnitStruct { 27 | fn fmt( 28 | &self, 29 | f: &mut ::pegcel::std::fmt::Formatter<'_>, 30 | ) -> ::pegcel::std::fmt::Result { 31 | f.debug_struct("UnitStruct") 32 | .field("attrs", &self.attrs) 33 | .field("struct_token", &self.struct_token) 34 | .field("name", &self.name) 35 | .field("semi_token", &self.semi_token) 36 | .finish() 37 | } 38 | } 39 | #[automatically_derived] 40 | impl ::pegcel::std::hash::Hash for UnitStruct { 41 | fn hash(&self, state: &mut H) { 42 | self.attrs.hash(state); 43 | self.struct_token.hash(state); 44 | self.name.hash(state); 45 | self.semi_token.hash(state); 46 | } 47 | } 48 | #[automatically_derived] 49 | impl ::pegcel::std::cmp::PartialEq for UnitStruct { 50 | fn eq(&self, other: &Self) -> bool { 51 | self.attrs == other.attrs && self.struct_token == other.struct_token 52 | && self.name == other.name && self.semi_token == other.semi_token 53 | } 54 | } 55 | #[automatically_derived] 56 | impl ::pegcel::std::cmp::Eq for UnitStruct {} 57 | #[automatically_derived] 58 | impl ::pegcel::syn::parse::Parse for UnitStruct { 59 | fn parse( 60 | input: ::pegcel::syn::parse::ParseStream, 61 | ) -> ::pegcel::syn::parse::Result { 62 | ::pegcel::std::result::Result::Ok(Self { 63 | attrs: input.call(Attribute::parse_outer)?, 64 | struct_token: input.parse()?, 65 | name: input.parse()?, 66 | semi_token: input.parse()?, 67 | }) 68 | } 69 | } 70 | impl ::pegcel::quote::ToTokens for UnitStruct { 71 | fn to_tokens(&self, tokens: &mut ::pegcel::proc_macro2::TokenStream) { 72 | use ::pegcel::__IterableToTokens; 73 | (&self.attrs).to_tokens(tokens); 74 | (&self.struct_token).to_tokens(tokens); 75 | (&self.name).to_tokens(tokens); 76 | (&self.semi_token).to_tokens(tokens); 77 | } 78 | } 79 | fn main() {} 80 | -------------------------------------------------------------------------------- /examples/unit_struct.rs: -------------------------------------------------------------------------------- 1 | //! A unit struct with attributes. 2 | //! 3 | //! ```no_compile 4 | //! #[path = "s.tmpl"] 5 | //! struct S; 6 | //! ``` 7 | 8 | use syn::{Attribute, Ident, Token}; 9 | 10 | pegcel::define_syntax! { 11 | struct UnitStruct { 12 | attrs: Vec as Attribute::parse_outer, 13 | struct_token: Token![struct], 14 | name: Ident, 15 | semi_token: Token![;], 16 | } 17 | } 18 | 19 | fn main() {} 20 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[doc(hidden)] 2 | #[cfg(feature = "printing")] 3 | pub use quote; 4 | #[doc(hidden)] 5 | pub use {paste::paste, proc_macro2, std, syn}; 6 | 7 | #[macro_export] 8 | macro_rules! define_syntax { 9 | { 10 | $(#[$struct_attr:meta])* 11 | $struct_vis:vis struct $Name:ident { 12 | $( 13 | $(#[$field_attr:meta])* 14 | $field_vis:vis $field:ident: $ty:ty 15 | $(as $parse_fn:expr)? 16 | ),* $(,)? 17 | } 18 | } => { 19 | $(#[$struct_attr])* 20 | $struct_vis struct $Name { 21 | $( 22 | $(#[$field_attr])* 23 | $field_vis $field: $ty 24 | ),* 25 | } 26 | 27 | $crate::__clone_impls! { 28 | #[automatically_derived] 29 | impl $crate::std::clone::Clone for $Name { 30 | fn clone(&self) -> Self { 31 | Self { 32 | $( 33 | $field: self.$field.clone(), 34 | )* 35 | } 36 | } 37 | } 38 | } 39 | 40 | $crate::__extra_traits! { 41 | #[automatically_derived] 42 | impl $crate::std::fmt::Debug for $Name { 43 | fn fmt(&self, f: &mut $crate::std::fmt::Formatter<'_>) -> $crate::std::fmt::Result { 44 | f.debug_struct(::std::stringify!($Name)) 45 | $( 46 | .field(::std::stringify!($field), &self.$field) 47 | )* 48 | .finish() 49 | } 50 | } 51 | 52 | #[automatically_derived] 53 | impl $crate::std::hash::Hash for $Name { 54 | fn hash(&self, state: &mut H) { 55 | $( 56 | self.$field.hash(state); 57 | )* 58 | } 59 | } 60 | 61 | #[automatically_derived] 62 | impl $crate::std::cmp::PartialEq for $Name { 63 | fn eq(&self, other: &Self) -> bool { 64 | $( 65 | self.$field == other.$field 66 | )&&* 67 | } 68 | } 69 | 70 | #[automatically_derived] 71 | impl $crate::std::cmp::Eq for $Name { 72 | } 73 | } 74 | 75 | #[automatically_derived] 76 | impl $crate::syn::parse::Parse for $Name { 77 | fn parse(input: $crate::syn::parse::ParseStream) -> $crate::syn::parse::Result { 78 | $crate::std::result::Result::Ok(Self { 79 | $( 80 | $field: $crate::__switch! { 81 | if { $($parse_fn)? } 82 | do { input.call($($parse_fn)?)? } 83 | else { input.parse()? } 84 | }, 85 | )* 86 | }) 87 | } 88 | } 89 | 90 | $crate::__printing! { 91 | impl $crate::quote::ToTokens for $Name { 92 | fn to_tokens(&self, tokens: &mut $crate::proc_macro2::TokenStream) { 93 | use $crate::__IterableToTokens; 94 | $( 95 | (&self.$field).to_tokens(tokens); 96 | )* 97 | } 98 | } 99 | } 100 | }; 101 | 102 | { 103 | $(#[$enum_attr:meta])* 104 | $enum_vis:vis enum $Name:ident { 105 | $($Variant:ident $(($NameVariant:ty))?),+ $(,)? 106 | } 107 | } => { 108 | $crate::paste! { 109 | $(#[$enum_attr])* 110 | $enum_vis enum $Name { 111 | $($Variant($crate::__switch!{ 112 | if { $($NameVariant)? } 113 | do { $($NameVariant)? } 114 | else { [<$Name $Variant>] } 115 | })),* 116 | } 117 | 118 | $crate::__clone_impls! { 119 | #[automatically_derived] 120 | impl $crate::std::clone::Clone for $Name { 121 | fn clone(&self) -> Self { 122 | match self { 123 | $( 124 | $Name::$Variant(v) => $Name::$Variant(v.clone()), 125 | )* 126 | } 127 | } 128 | } 129 | } 130 | 131 | $crate::__extra_traits! { 132 | #[automatically_derived] 133 | impl $crate::std::fmt::Debug for $Name { 134 | fn fmt(&self, f: &mut $crate::std::fmt::Formatter<'_>) -> $crate::std::fmt::Result { 135 | match self { 136 | $( 137 | $Name::$Variant(v) => 138 | f.debug_tuple(::std::stringify!($Variant)) 139 | .field(v) 140 | .finish(), 141 | )* 142 | } 143 | } 144 | } 145 | 146 | #[automatically_derived] 147 | impl $crate::std::hash::Hash for $Name { 148 | fn hash(&self, state: &mut H) { 149 | match self { 150 | $( 151 | $Name::$Variant(v) => { 152 | $crate::std::mem::discriminant(self).hash(state); 153 | v.hash(state); 154 | }, 155 | )* 156 | } 157 | } 158 | } 159 | 160 | #[automatically_derived] 161 | impl $crate::std::cmp::PartialEq for $Name { 162 | fn eq(&self, other: &Self) -> bool { 163 | match (self, other) { 164 | $( 165 | ($Name::$Variant(lhs), $Name::$Variant(rhs)) => lhs == rhs, 166 | )* 167 | _ => false, 168 | } 169 | } 170 | } 171 | 172 | #[automatically_derived] 173 | impl $crate::std::cmp::Eq for $Name {} 174 | } 175 | 176 | $( 177 | #[automatically_derived] 178 | impl From<$crate::__switch! { 179 | if { $($NameVariant)? } 180 | do { $($NameVariant)? } 181 | else { [<$Name $Variant>] } 182 | }> for $Name { 183 | fn from( 184 | v: $crate::__switch! { 185 | if { $($NameVariant)? } 186 | do { $($NameVariant)? } 187 | else { [<$Name $Variant>] } 188 | }, 189 | ) -> Self { 190 | $Name::$Variant(v) 191 | } 192 | } 193 | )* 194 | 195 | #[automatically_derived] 196 | impl $crate::syn::parse::Parse for $Name { 197 | fn parse(input: $crate::syn::parse::ParseStream) -> $crate::syn::parse::Result { 198 | use $crate::syn::parse::discouraged::Speculative; 199 | let mut best_guess = $crate::std::option::Option::None; 200 | let mut best_guess_cursor = input.cursor(); 201 | let mut best_guess_variant = ""; 202 | $({ 203 | let fork = input.fork(); 204 | match fork.parse::<$crate::__switch! { 205 | if { $($NameVariant)? } 206 | do { $($NameVariant)? } 207 | else { [<$Name $Variant>] } 208 | }>() { 209 | $crate::std::result::Result::Ok(v) => { 210 | input.advance_to(&fork); 211 | return $crate::std::result::Result::Ok($Name::$Variant(v)); 212 | } 213 | $crate::std::result::Result::Err(e) => { 214 | let this_guess_cursor = fork.cursor(); 215 | if this_guess_cursor > best_guess_cursor { 216 | // If the cursor is further along, then this error occurred 217 | // later in the input. Use it instead of the previous error, 218 | // as the more successful parse is likely to be intended. 219 | best_guess = $crate::std::option::Option::Some(e); 220 | best_guess_variant = $crate::std::stringify!($Variant); 221 | best_guess_cursor = this_guess_cursor; 222 | } else if this_guess_cursor == best_guess_cursor { 223 | // If the cursor is the same, then both errors occurred at the 224 | // "same" position. Combine the errors to avoid losing information. 225 | if let $crate::std::option::Option::Some(existing) = &mut best_guess { 226 | existing.combine(e); 227 | } else { 228 | // There's no existing error, so just use the new one. 229 | best_guess = $crate::std::option::Option::Some(e); 230 | } 231 | } 232 | }, 233 | } 234 | })* 235 | $crate::std::result::Result::Err(input.error(format_args!( 236 | "expected {} but failed to parse any variant; best attempt was {} with {}", 237 | $crate::std::stringify!($Name), 238 | best_guess_variant, 239 | best_guess.unwrap(), 240 | ))) 241 | } 242 | } 243 | 244 | $crate::__printing! { 245 | impl $crate::quote::ToTokens for $Name { 246 | fn to_tokens(&self, tokens: &mut $crate::proc_macro2::TokenStream) { 247 | match self { 248 | $( 249 | $Name::$Variant(v) => (&v).to_tokens(tokens), 250 | )* 251 | } 252 | } 253 | } 254 | } 255 | } 256 | }; 257 | 258 | { 259 | $vis:vis macro_rules! $Macro:ident; 260 | mod self = $krate:tt $(::$self_path:ident)*; 261 | $( 262 | mod kw { 263 | $($keyword:ident;)* 264 | } 265 | )? 266 | $( 267 | mod punct { 268 | $($punct:ident($($tt:tt)+);)* 269 | } 270 | )? 271 | } => { 272 | $crate::define_syntax! { 273 | (@$) $vis macro_rules! $Macro; 274 | mod self = $krate $(::$self_path)*; 275 | $( 276 | mod kw { 277 | $($keyword;)* 278 | } 279 | )? 280 | $( 281 | mod punct { 282 | $($punct($($tt)+);)* 283 | } 284 | )? 285 | } 286 | }; 287 | { 288 | (@$d:tt) $vis:vis macro_rules! $Macro:ident; 289 | mod self = $krate:tt $(::$self_path:ident)*; 290 | $( 291 | mod kw { 292 | $($keyword:ident;)* 293 | } 294 | )? 295 | $( 296 | mod punct { 297 | $($punct:ident($($tt:tt)+);)* 298 | } 299 | )? 300 | } => { 301 | $($vis mod kw { 302 | $($crate::syn::custom_keyword!($keyword);)* 303 | })? 304 | $($vis mod punct { 305 | $($crate::syn::custom_punctuation!($punct, $($tt)+);)* 306 | })? 307 | 308 | $crate::paste! { 309 | // this is a macro generated macro generated macro; my head hurts 310 | macro_rules! [< __pegcel_generate_token_macro__ $Macro >] { 311 | (($d d:tt) macro = $d macro:path) => { 312 | // NB: avoid using $$crate: rust-lang/rust#99035 313 | #[macro_export] 314 | macro_rules! [< __pegcel_generated_token_macro__ $Macro >] { 315 | { __pegcel_generated_token_macro__ kw $d d keyword:ident } => { $d $krate $(:: $self_path)* :: kw :: $d d keyword }; 316 | { __pegcel_generated_token_macro__ punct $d d punct:ident } => { $d $krate $(:: $self_path)* :: punct :: $d d punct }; 317 | 318 | $($( [$keyword] => { $d macro ! { __pegcel_generated_token_macro__ kw $keyword } }; )*)? 319 | $($( [$($tt)+] => { $d macro ! { __pegcel_generated_token_macro__ punct $punct } }; )*)? 320 | [$d d ( $d d fallback:tt )*] => { $crate::syn::Token! { $d d ( $d d fallback )* } }; 321 | } 322 | } 323 | } 324 | 325 | [< __pegcel_generate_token_macro__ $Macro >]!(($) macro = $krate $(:: $self_path)* :: $Macro); 326 | $vis use [< __pegcel_generated_token_macro__ $Macro >] as $Macro; 327 | } 328 | }; 329 | } 330 | 331 | #[doc(hidden)] 332 | #[cfg(feature = "printing")] 333 | /// Used to "specialize" `$field.to_tokens()` for iterables quoted with `#()*`. 334 | pub trait __IterableToTokens { 335 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream); 336 | } 337 | 338 | #[cfg(feature = "printing")] 339 | impl<'a, T> __IterableToTokens for &'a T 340 | where 341 | &'a T: IntoIterator, 342 | <&'a T as IntoIterator>::Item: quote::ToTokens, 343 | { 344 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { 345 | use quote::TokenStreamExt; 346 | tokens.append_all(*self) 347 | } 348 | } 349 | 350 | #[doc(hidden)] 351 | #[macro_export] 352 | macro_rules! __switch { 353 | { 354 | if { 355 | } 356 | do { 357 | $($do:tt)* 358 | } 359 | $(else { 360 | $($else:tt)* 361 | })? 362 | } => { 363 | $($($else)*)? 364 | }; 365 | { 366 | if { 367 | $($cond:tt)+ 368 | } 369 | do { 370 | $($do:tt)* 371 | } 372 | $(else { 373 | $($else:tt)* 374 | })? 375 | } => { 376 | $($do)* 377 | }; 378 | } 379 | 380 | #[doc(hidden)] 381 | #[macro_export] 382 | #[cfg(feature = "clone-impls")] 383 | macro_rules! __clone_impls { 384 | ($($tt:tt)*) => ($($tt)*); 385 | } 386 | 387 | #[doc(hidden)] 388 | #[macro_export] 389 | #[cfg(not(feature = "clone-impls"))] 390 | macro_rules! __clone_impls { 391 | ($($tt:tt)*) => {}; 392 | } 393 | 394 | #[doc(hidden)] 395 | #[macro_export] 396 | #[cfg(feature = "extra-traits")] 397 | macro_rules! __extra_traits { 398 | ($($tt:tt)*) => ($($tt)*); 399 | } 400 | 401 | #[doc(hidden)] 402 | #[macro_export] 403 | #[cfg(not(feature = "extra-traits"))] 404 | macro_rules! __extra_traits { 405 | ($($tt:tt)*) => {}; 406 | } 407 | 408 | #[doc(hidden)] 409 | #[macro_export] 410 | #[cfg(feature = "printing")] 411 | macro_rules! __printing { 412 | ($($tt:tt)*) => ($($tt)*); 413 | } 414 | 415 | #[doc(hidden)] 416 | #[macro_export] 417 | #[cfg(not(feature = "printing"))] 418 | macro_rules! __printing { 419 | ($($tt:tt)*) => {}; 420 | } 421 | -------------------------------------------------------------------------------- /tests/examples.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn expand() { 3 | macrotest::expand_args( 4 | "examples/*.rs", 5 | &[ 6 | "--features", 7 | "pegcel/clone-impls,pegcel/extra-traits,pegcel/printing", 8 | ], 9 | ); 10 | } 11 | --------------------------------------------------------------------------------