glsl_lang/parse/parsable.rs
1use std::borrow::Cow;
2
3use crate::ast;
4
5use super::{DefaultLexer, HasLexerError, ParseContext, ParseError, ParseOptions};
6
7/// A parsable is something we can parse either directly, or embedded in some other syntax
8/// structure.
9///
10/// This allows us to parse specific AST items even though we don't export a LALR parser for it.
11/// Due to the way it is currently implemented, we have to generate extra code around the input,
12/// thus, if you are matching on span positions, you will get a different result than if using the
13/// parser directly.
14pub trait Parsable: Sized {
15 /// Parse the input source
16 fn parse(source: &str) -> Result<Self, ParseError<<DefaultLexer as HasLexerError>::Error>> {
17 <Self as Parsable>::parse_with_options(source, &Default::default())
18 .map(|(parsed, _names)| parsed)
19 }
20
21 /// Parse the input source with the given options
22 fn parse_with_options<'i>(
23 source: &'i str,
24 opts: &ParseOptions,
25 ) -> Result<(Self, ParseContext), ParseError<<DefaultLexer<'i> as HasLexerError>::Error>>;
26
27 /// Parse the input source with the given context
28 fn parse_with_context<'i>(
29 source: &'i str,
30 ctx: &ParseContext,
31 ) -> Result<(Self, ParseContext), ParseError<<DefaultLexer<'i> as HasLexerError>::Error>>;
32}
33
34impl<T: Extractable<ast::TranslationUnit>> Parsable for T {
35 fn parse_with_options<'i>(
36 source: &'i str,
37 opts: &ParseOptions,
38 ) -> Result<(Self, ParseContext), ParseError<<DefaultLexer<'i> as HasLexerError>::Error>> {
39 <ast::TranslationUnit as super::DefaultParse>::parse_with_options(&Self::wrap(source), opts)
40 .map(|(tu, oo, _lexer)| (Self::extract(tu).expect("invalid parse result"), oo))
41 }
42
43 fn parse_with_context<'i>(
44 source: &'i str,
45 ctx: &ParseContext,
46 ) -> Result<(Self, ParseContext), ParseError<<DefaultLexer<'i> as HasLexerError>::Error>> {
47 <ast::TranslationUnit as super::DefaultParse>::parse_with_context(&Self::wrap(source), ctx)
48 .map(|(tu, oo, _lexer)| (Self::extract(tu).expect("invalid parse result"), oo))
49 }
50}
51
52/// Part of the syntax tree that can be extracted from a parent tree
53pub trait Extractable<R>: Sized {
54 /// Wrap the given source which parses as Self into something that parses as R
55 fn wrap(source: &str) -> Cow<str>;
56 /// Extract the subtree for Self from a parent tree R
57 fn extract(tu: R) -> Option<Self>;
58}
59
60impl Extractable<ast::TranslationUnit> for ast::TranslationUnit {
61 fn wrap(source: &str) -> Cow<str> {
62 source.into()
63 }
64
65 fn extract(tu: ast::TranslationUnit) -> Option<Self> {
66 Some(tu)
67 }
68}
69
70impl Extractable<ast::TranslationUnit> for ast::FunctionDefinition {
71 fn wrap(source: &str) -> Cow<str> {
72 source.into()
73 }
74
75 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
76 if let ast::Node {
77 content: ast::ExternalDeclarationData::FunctionDefinition(fndef),
78 ..
79 } = extdecls.into_iter().next().unwrap()
80 {
81 return Some(fndef);
82 }
83
84 None
85 }
86}
87
88impl Extractable<ast::TranslationUnit> for ast::UnaryOp {
89 fn wrap(source: &str) -> Cow<str> {
90 format!("void main() {{ {}x; }}", source).into()
91 }
92
93 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
94 if let ast::Node {
95 content:
96 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
97 content:
98 ast::FunctionDefinitionData {
99 statement:
100 ast::Node {
101 content: ast::CompoundStatementData { statement_list, .. },
102 ..
103 },
104 ..
105 },
106 ..
107 }),
108 ..
109 } = extdecls.into_iter().next().unwrap()
110 {
111 if let ast::StatementData::Expression(ast::ExprStatement {
112 content:
113 ast::ExprStatementData(Some(ast::Expr {
114 content: ast::ExprData::Unary(u, _),
115 ..
116 })),
117 ..
118 }) = statement_list.into_iter().next().unwrap().into_inner()
119 {
120 return Some(u);
121 }
122 }
123
124 None
125 }
126}
127
128impl Extractable<ast::TranslationUnit> for ast::AssignmentOp {
129 fn wrap(source: &str) -> Cow<str> {
130 format!("void main() {{ x {} 2; }}", source).into()
131 }
132
133 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
134 if let ast::Node {
135 content:
136 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
137 content:
138 ast::FunctionDefinitionData {
139 statement:
140 ast::Node {
141 content: ast::CompoundStatementData { statement_list, .. },
142 ..
143 },
144 ..
145 },
146 ..
147 }),
148 ..
149 } = extdecls.into_iter().next().unwrap()
150 {
151 if let ast::StatementData::Expression(ast::ExprStatement {
152 content:
153 ast::ExprStatementData(Some(ast::Expr {
154 content: ast::ExprData::Assignment(_, o, _),
155 ..
156 })),
157 ..
158 }) = statement_list.into_iter().next().unwrap().into_inner()
159 {
160 return Some(o);
161 }
162 }
163
164 None
165 }
166}
167
168macro_rules! impl_parsable_statement {
169 ($i:ident => $t:ty) => {
170 impl Extractable<ast::TranslationUnit> for $t {
171 fn wrap(source: &str) -> Cow<str> {
172 format!("void main() {{ {} }}", source).into()
173 }
174
175 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
176 if let ast::Node {
177 content:
178 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
179 content:
180 ast::FunctionDefinitionData {
181 statement:
182 ast::Node {
183 content:
184 ast::CompoundStatementData { statement_list, .. },
185 ..
186 },
187 ..
188 },
189 ..
190 }),
191 ..
192 } = extdecls.into_iter().next().unwrap()
193 {
194 if let ast::StatementData::$i(expr) =
195 statement_list.into_iter().next().unwrap().into_inner()
196 {
197 return Some(expr);
198 }
199 }
200
201 None
202 }
203 }
204 };
205}
206
207impl_parsable_statement!(Expression => ast::ExprStatement);
208impl_parsable_statement!(Selection => ast::SelectionStatement);
209impl_parsable_statement!(Switch => ast::SwitchStatement);
210impl_parsable_statement!(CaseLabel => ast::CaseLabel);
211impl_parsable_statement!(Iteration => ast::IterationStatement);
212impl_parsable_statement!(Jump => ast::JumpStatement);
213impl_parsable_statement!(Compound => ast::CompoundStatement);
214
215impl Extractable<ast::TranslationUnit> for ast::ArraySpecifierDimension {
216 fn wrap(source: &str) -> Cow<str> {
217 format!("void main() {{ vec2{}(); }}", source).into()
218 }
219
220 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
221 if let ast::Node {
222 content:
223 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
224 content:
225 ast::FunctionDefinitionData {
226 statement:
227 ast::Node {
228 content: ast::CompoundStatementData { statement_list, .. },
229 ..
230 },
231 ..
232 },
233 ..
234 }),
235 ..
236 } = extdecls.into_iter().next().unwrap()
237 {
238 if let ast::StatementData::Expression(ast::ExprStatement {
239 content:
240 ast::ExprStatementData(Some(ast::Expr {
241 content:
242 ast::ExprData::FunCall(
243 ast::FunIdentifier {
244 content: ast::FunIdentifierData::TypeSpecifier(type_specifier),
245 ..
246 },
247 _,
248 ),
249 ..
250 })),
251 ..
252 }) = statement_list.into_iter().next().unwrap().into_inner()
253 {
254 if let ast::TypeSpecifier {
255 content:
256 ast::TypeSpecifierData {
257 array_specifier: Some(ast::ArraySpecifier { content: array, .. }),
258 ..
259 },
260 ..
261 } = *type_specifier
262 {
263 return array.dimensions.into_iter().next();
264 }
265 }
266 }
267
268 None
269 }
270}
271
272impl Extractable<ast::TranslationUnit> for ast::ArraySpecifier {
273 fn wrap(source: &str) -> Cow<str> {
274 format!("void main() {{ vec2{}(); }}", source).into()
275 }
276
277 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
278 if let ast::Node {
279 content:
280 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
281 content:
282 ast::FunctionDefinitionData {
283 statement:
284 ast::Node {
285 content: ast::CompoundStatementData { statement_list, .. },
286 ..
287 },
288 ..
289 },
290 ..
291 }),
292 ..
293 } = extdecls.into_iter().next().unwrap()
294 {
295 if let ast::StatementData::Expression(ast::ExprStatement {
296 content:
297 ast::ExprStatementData(Some(ast::Expr {
298 content:
299 ast::ExprData::FunCall(
300 ast::FunIdentifier {
301 content: ast::FunIdentifierData::TypeSpecifier(type_specifier),
302 ..
303 },
304 _,
305 ),
306 ..
307 })),
308 ..
309 }) = statement_list.into_iter().next().unwrap().into_inner()
310 {
311 if let ast::TypeSpecifier {
312 content:
313 ast::TypeSpecifierData {
314 array_specifier: Some(array),
315 ..
316 },
317 ..
318 } = *type_specifier
319 {
320 return Some(array);
321 }
322 }
323 }
324
325 None
326 }
327}
328
329impl Extractable<ast::TranslationUnit> for ast::FunIdentifier {
330 fn wrap(source: &str) -> Cow<str> {
331 format!("void main() {{ {}(); }}", source).into()
332 }
333
334 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
335 if let ast::Node {
336 content:
337 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
338 content:
339 ast::FunctionDefinitionData {
340 statement:
341 ast::Node {
342 content: ast::CompoundStatementData { statement_list, .. },
343 ..
344 },
345 ..
346 },
347 ..
348 }),
349 ..
350 } = extdecls.into_iter().next().unwrap()
351 {
352 if let ast::StatementData::Expression(ast::ExprStatement {
353 content:
354 ast::ExprStatementData(Some(ast::Expr {
355 content: ast::ExprData::FunCall(fi, _),
356 ..
357 })),
358 ..
359 }) = statement_list.into_iter().next().unwrap().into_inner()
360 {
361 return Some(fi);
362 }
363 }
364
365 None
366 }
367}
368
369impl Extractable<ast::TranslationUnit> for ast::InterpolationQualifier {
370 fn wrap(source: &str) -> Cow<str> {
371 format!("{} float x;", source).into()
372 }
373
374 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
375 if let ast::Node {
376 content:
377 ast::ExternalDeclarationData::Declaration(ast::Node {
378 content:
379 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
380 content:
381 ast::InitDeclaratorListData {
382 head:
383 ast::SingleDeclaration {
384 content:
385 ast::SingleDeclarationData {
386 ty:
387 ast::FullySpecifiedType {
388 content:
389 ast::FullySpecifiedTypeData {
390 qualifier:
391 Some(ast::TypeQualifier {
392 content:
393 ast::TypeQualifierData {
394 qualifiers,
395 },
396 ..
397 }),
398 ..
399 },
400 ..
401 },
402 ..
403 },
404 ..
405 },
406 ..
407 },
408 ..
409 }),
410 ..
411 }),
412 ..
413 } = extdecls.into_iter().next().unwrap()
414 {
415 if let ast::TypeQualifierSpecData::Interpolation(interp) =
416 qualifiers.into_iter().next().unwrap().content
417 {
418 return Some(interp);
419 }
420 }
421
422 None
423 }
424}
425
426impl Extractable<ast::TranslationUnit> for ast::ArrayedIdentifier {
427 fn wrap(source: &str) -> Cow<str> {
428 format!("uniform Block {{ float x; }} {};", source).into()
429 }
430
431 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
432 if let ast::Node {
433 content:
434 ast::ExternalDeclarationData::Declaration(ast::Node {
435 content:
436 ast::DeclarationData::Block(ast::Block {
437 content:
438 ast::BlockData {
439 identifier: Some(a),
440 ..
441 },
442 ..
443 }),
444 ..
445 }),
446 ..
447 } = extdecls.into_iter().next().unwrap()
448 {
449 return Some(a);
450 }
451
452 None
453 }
454}
455
456impl Extractable<ast::TranslationUnit> for ast::PrecisionQualifier {
457 fn wrap(source: &str) -> Cow<str> {
458 format!("{} float x;", source).into()
459 }
460
461 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
462 if let ast::Node {
463 content:
464 ast::ExternalDeclarationData::Declaration(ast::Node {
465 content:
466 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
467 content:
468 ast::InitDeclaratorListData {
469 head:
470 ast::SingleDeclaration {
471 content:
472 ast::SingleDeclarationData {
473 ty:
474 ast::FullySpecifiedType {
475 content:
476 ast::FullySpecifiedTypeData {
477 qualifier:
478 Some(ast::TypeQualifier {
479 content:
480 ast::TypeQualifierData {
481 qualifiers,
482 },
483 ..
484 }),
485 ..
486 },
487 ..
488 },
489 ..
490 },
491 ..
492 },
493 ..
494 },
495 ..
496 }),
497 ..
498 }),
499 ..
500 } = extdecls.into_iter().next().unwrap()
501 {
502 if let ast::TypeQualifierSpecData::Precision(q) =
503 qualifiers.into_iter().next().unwrap().content
504 {
505 return Some(q);
506 }
507 }
508
509 None
510 }
511}
512
513impl Extractable<ast::TranslationUnit> for ast::StorageQualifier {
514 fn wrap(source: &str) -> Cow<str> {
515 format!("{} float x;", source).into()
516 }
517
518 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
519 if let ast::Node {
520 content:
521 ast::ExternalDeclarationData::Declaration(ast::Node {
522 content:
523 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
524 content:
525 ast::InitDeclaratorListData {
526 head:
527 ast::SingleDeclaration {
528 content:
529 ast::SingleDeclarationData {
530 ty:
531 ast::FullySpecifiedType {
532 content:
533 ast::FullySpecifiedTypeData {
534 qualifier:
535 Some(ast::TypeQualifier {
536 content:
537 ast::TypeQualifierData {
538 qualifiers,
539 },
540 ..
541 }),
542 ..
543 },
544 ..
545 },
546 ..
547 },
548 ..
549 },
550 ..
551 },
552 ..
553 }),
554 ..
555 }),
556 ..
557 } = extdecls.into_iter().next().unwrap()
558 {
559 if let ast::TypeQualifierSpecData::Storage(q) =
560 qualifiers.into_iter().next().unwrap().content
561 {
562 return Some(q);
563 }
564 }
565
566 None
567 }
568}
569
570impl Extractable<ast::TranslationUnit> for ast::LayoutQualifier {
571 fn wrap(source: &str) -> Cow<str> {
572 format!("{} float x;", source).into()
573 }
574
575 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
576 if let ast::Node {
577 content:
578 ast::ExternalDeclarationData::Declaration(ast::Node {
579 content:
580 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
581 content:
582 ast::InitDeclaratorListData {
583 head:
584 ast::SingleDeclaration {
585 content:
586 ast::SingleDeclarationData {
587 ty:
588 ast::FullySpecifiedType {
589 content:
590 ast::FullySpecifiedTypeData {
591 qualifier:
592 Some(ast::TypeQualifier {
593 content:
594 ast::TypeQualifierData {
595 qualifiers,
596 },
597 ..
598 }),
599 ..
600 },
601 ..
602 },
603 ..
604 },
605 ..
606 },
607 ..
608 },
609 ..
610 }),
611 ..
612 }),
613 ..
614 } = extdecls.into_iter().next().unwrap()
615 {
616 if let ast::TypeQualifierSpecData::Layout(q) =
617 qualifiers.into_iter().next().unwrap().content
618 {
619 return Some(q);
620 }
621 }
622
623 None
624 }
625}
626
627impl Extractable<ast::TranslationUnit> for ast::TypeQualifier {
628 fn wrap(source: &str) -> Cow<str> {
629 format!("{} float x;", source).into()
630 }
631
632 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
633 if let ast::Node {
634 content:
635 ast::ExternalDeclarationData::Declaration(ast::Node {
636 content:
637 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
638 content:
639 ast::InitDeclaratorListData {
640 head:
641 ast::SingleDeclaration {
642 content:
643 ast::SingleDeclarationData {
644 ty:
645 ast::FullySpecifiedType {
646 content:
647 ast::FullySpecifiedTypeData {
648 qualifier: Some(q),
649 ..
650 },
651 ..
652 },
653 ..
654 },
655 ..
656 },
657 ..
658 },
659 ..
660 }),
661 ..
662 }),
663 ..
664 } = extdecls.into_iter().next().unwrap()
665 {
666 return Some(q);
667 }
668
669 None
670 }
671}
672
673impl Extractable<ast::TranslationUnit> for ast::TypeSpecifier {
674 fn wrap(source: &str) -> Cow<str> {
675 format!("{} x;", source).into()
676 }
677
678 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
679 if let ast::Node {
680 content:
681 ast::ExternalDeclarationData::Declaration(ast::Node {
682 content:
683 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
684 content:
685 ast::InitDeclaratorListData {
686 head:
687 ast::SingleDeclaration {
688 content:
689 ast::SingleDeclarationData {
690 ty:
691 ast::FullySpecifiedType {
692 content:
693 ast::FullySpecifiedTypeData {
694 ty, ..
695 },
696 ..
697 },
698 ..
699 },
700 ..
701 },
702 ..
703 },
704 ..
705 }),
706 ..
707 }),
708 ..
709 } = extdecls.into_iter().next().unwrap()
710 {
711 return Some(ty);
712 }
713
714 None
715 }
716}
717
718impl Extractable<ast::TranslationUnit> for ast::TypeSpecifierNonArray {
719 fn wrap(source: &str) -> Cow<str> {
720 format!("{} x;", source).into()
721 }
722
723 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
724 if let ast::Node {
725 content:
726 ast::ExternalDeclarationData::Declaration(ast::Node {
727 content:
728 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
729 content:
730 ast::InitDeclaratorListData {
731 head:
732 ast::SingleDeclaration {
733 content:
734 ast::SingleDeclarationData {
735 ty:
736 ast::FullySpecifiedType {
737 content:
738 ast::FullySpecifiedTypeData {
739 ty:
740 ast::TypeSpecifier {
741 content:
742 ast::TypeSpecifierData {
743 ty,
744 ..
745 },
746 ..
747 },
748 ..
749 },
750 ..
751 },
752 ..
753 },
754 ..
755 },
756 ..
757 },
758 ..
759 }),
760 ..
761 }),
762 ..
763 } = extdecls.into_iter().next().unwrap()
764 {
765 return Some(ty);
766 }
767
768 None
769 }
770}
771
772impl Extractable<ast::TranslationUnit> for ast::FullySpecifiedType {
773 fn wrap(source: &str) -> Cow<str> {
774 format!("{} x;", source).into()
775 }
776
777 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
778 if let ast::Node {
779 content:
780 ast::ExternalDeclarationData::Declaration(ast::Node {
781 content:
782 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
783 content:
784 ast::InitDeclaratorListData {
785 head:
786 ast::SingleDeclaration {
787 content: ast::SingleDeclarationData { ty, .. },
788 ..
789 },
790 ..
791 },
792 ..
793 }),
794 ..
795 }),
796 ..
797 } = extdecls.into_iter().next().unwrap()
798 {
799 return Some(ty);
800 }
801
802 None
803 }
804}
805
806impl Extractable<ast::TranslationUnit> for ast::Declaration {
807 fn wrap(source: &str) -> Cow<str> {
808 format!("{};", source).into()
809 }
810
811 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
812 if let ast::Node {
813 content: ast::ExternalDeclarationData::Declaration(decl),
814 ..
815 } = extdecls.into_iter().next().unwrap()
816 {
817 return Some(decl);
818 }
819
820 None
821 }
822}
823
824impl Extractable<ast::TranslationUnit> for ast::StructFieldSpecifier {
825 fn wrap(source: &str) -> Cow<str> {
826 format!("struct A {{ {} }};", source).into()
827 }
828
829 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
830 if let ast::Node {
831 content:
832 ast::ExternalDeclarationData::Declaration(ast::Node {
833 content:
834 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
835 content: ast::InitDeclaratorListData {
836 head:
837 ast::SingleDeclaration {
838 content: ast::SingleDeclarationData {
839 ty:
840 ast::FullySpecifiedType {
841 content: ast::FullySpecifiedTypeData {
842 ty:
843 ast::TypeSpecifier {
844 content: ast::TypeSpecifierData {
845 ty:
846 ast::TypeSpecifierNonArray {
847 content: ast::TypeSpecifierNonArrayData::Struct(
848 ast::StructSpecifier {
849 content: ast::StructSpecifierData {
850 fields,
851 ..
852 },
853 ..
854 },
855 ),
856 ..
857 },
858 ..
859 },
860 ..
861 },
862 ..
863 },
864 ..
865 },
866 ..
867 },
868 ..
869 },
870 ..
871 },
872 .. }),
873 ..
874 }),
875 ..
876 } = extdecls.into_iter().next().unwrap()
877 {
878 return fields.into_iter().next();
879 }
880
881 None
882 }
883}
884
885impl Extractable<ast::TranslationUnit> for ast::StructSpecifier {
886 fn wrap(source: &str) -> Cow<str> {
887 format!("{};", source).into()
888 }
889
890 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
891 if let ast::Node {
892 content:
893 ast::ExternalDeclarationData::Declaration(ast::Node {
894 content:
895 ast::DeclarationData::InitDeclaratorList(ast::InitDeclaratorList {
896 content: ast::InitDeclaratorListData {
897 head:
898 ast::SingleDeclaration {
899 content: ast::SingleDeclarationData {
900 ty:
901 ast::FullySpecifiedType {
902 content: ast::FullySpecifiedTypeData {
903 ty:
904 ast::TypeSpecifier {
905 content: ast::TypeSpecifierData {
906 ty:
907 ast::TypeSpecifierNonArray {
908 content: ast::TypeSpecifierNonArrayData::Struct(s),
909 ..
910 },
911 ..
912 },
913 ..
914 },
915 ..
916 },
917 ..
918 },
919 ..
920 },
921 ..
922 },
923 ..
924 },
925 .. }),
926 ..
927 }),
928 ..
929 } = extdecls.into_iter().next().unwrap()
930 {
931 return Some(s);
932 }
933
934 None
935 }
936}
937
938impl Extractable<ast::TranslationUnit> for ast::Expr {
939 fn wrap(source: &str) -> Cow<str> {
940 format!("void main() {{ {}; }}", source).into()
941 }
942
943 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
944 if let ast::Node {
945 content:
946 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
947 content:
948 ast::FunctionDefinitionData {
949 statement:
950 ast::Node {
951 content: ast::CompoundStatementData { statement_list, .. },
952 ..
953 },
954 ..
955 },
956 ..
957 }),
958 ..
959 } = extdecls.into_iter().next().unwrap()
960 {
961 if let ast::StatementData::Expression(ast::ExprStatement {
962 content: ast::ExprStatementData(Some(expr)),
963 ..
964 }) = statement_list.into_iter().next().unwrap().into_inner()
965 {
966 return Some(expr);
967 }
968 }
969
970 None
971 }
972}
973
974impl Extractable<ast::TranslationUnit> for ast::Preprocessor {
975 fn wrap(source: &str) -> Cow<str> {
976 source.into()
977 }
978
979 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
980 if let ast::Node {
981 content: ast::ExternalDeclarationData::Preprocessor(pp),
982 ..
983 } = extdecls.into_iter().next().unwrap()
984 {
985 return Some(pp);
986 }
987
988 None
989 }
990}
991
992impl Extractable<ast::TranslationUnit> for ast::Statement {
993 fn wrap(source: &str) -> Cow<str> {
994 format!("void main() {{ {} }}", source).into()
995 }
996
997 fn extract(ast::TranslationUnit(extdecls): ast::TranslationUnit) -> Option<Self> {
998 if let ast::Node {
999 content:
1000 ast::ExternalDeclarationData::FunctionDefinition(ast::Node {
1001 content:
1002 ast::FunctionDefinitionData {
1003 statement:
1004 ast::Node {
1005 content: ast::CompoundStatementData { statement_list, .. },
1006 ..
1007 },
1008 ..
1009 },
1010 ..
1011 }),
1012 ..
1013 } = extdecls.into_iter().next().unwrap()
1014 {
1015 return statement_list.into_iter().next();
1016 }
1017
1018 None
1019 }
1020}