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