1use std::fmt;
22use std::iter::{once, FromIterator};
23use std::ops::{Deref, DerefMut};
24
25#[derive(Clone, Debug, PartialEq)]
27pub struct NonEmpty<T>(pub Vec<T>);
28
29impl<T> NonEmpty<T> {
30 pub fn from_non_empty_iter<I>(iter: I) -> Option<Self>
36 where
37 I: IntoIterator<Item = T>,
38 {
39 let vec: Vec<_> = iter.into_iter().collect();
40
41 if vec.is_empty() {
42 None
43 } else {
44 Some(NonEmpty(vec))
45 }
46 }
47
48 pub fn push(&mut self, item: T) {
50 self.0.push(item);
51 }
52
53 pub fn pop(&mut self) -> Option<T> {
59 if self.0.len() == 1 {
60 None
61 } else {
62 self.0.pop()
63 }
64 }
65}
66
67impl<T> IntoIterator for NonEmpty<T> {
68 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
69 type Item = T;
70
71 fn into_iter(self) -> Self::IntoIter {
72 self.0.into_iter()
73 }
74}
75
76impl<'a, T> IntoIterator for &'a NonEmpty<T> {
77 type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
78 type Item = &'a T;
79
80 fn into_iter(self) -> Self::IntoIter {
81 self.0.iter()
82 }
83}
84
85impl<'a, T> IntoIterator for &'a mut NonEmpty<T> {
86 type IntoIter = <&'a mut Vec<T> as IntoIterator>::IntoIter;
87 type Item = &'a mut T;
88
89 fn into_iter(self) -> Self::IntoIter {
90 self.0.iter_mut()
91 }
92}
93
94impl<T> Extend<T> for NonEmpty<T> {
95 fn extend<I>(&mut self, iter: I)
96 where
97 I: IntoIterator<Item = T>,
98 {
99 self.0.extend(iter);
100 }
101}
102
103#[derive(Clone, Debug, PartialEq)]
105pub enum Path {
106 Absolute(String),
108 Relative(String),
110}
111
112#[derive(Debug)]
114pub enum IdentifierError {
115 StartsWithDigit,
116 ContainsNonASCIIAlphaNum,
117}
118
119impl std::error::Error for IdentifierError {}
120
121impl fmt::Display for IdentifierError {
122 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
123 match *self {
124 IdentifierError::StartsWithDigit => f.write_str("starts starts with a digit"),
125
126 IdentifierError::ContainsNonASCIIAlphaNum => {
127 f.write_str("contains at least one non-alphanumeric ASCII character")
128 }
129 }
130 }
131}
132
133#[derive(Clone, Debug, PartialEq)]
135pub struct Identifier(pub String);
136
137impl Identifier {
138 pub fn new<N>(name: N) -> Result<Self, IdentifierError>
145 where
146 N: Into<String>,
147 {
148 let name = name.into();
149
150 if name
151 .chars()
152 .next()
153 .map(|c| c.is_ascii_alphabetic() || c == '_')
154 == Some(false)
155 {
156 Err(IdentifierError::StartsWithDigit)
158 } else if name.contains(|c: char| !(c.is_ascii_alphanumeric() || c == '_')) {
159 Err(IdentifierError::ContainsNonASCIIAlphaNum)
161 } else {
162 Ok(Identifier(name))
163 }
164 }
165
166 pub fn as_str(&self) -> &str {
168 &self.0
169 }
170}
171
172impl<'a> From<&'a str> for Identifier {
173 fn from(s: &str) -> Self {
174 Identifier(s.to_owned())
175 }
176}
177
178impl From<String> for Identifier {
179 fn from(s: String) -> Self {
180 Identifier(s)
181 }
182}
183
184impl fmt::Display for Identifier {
185 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
186 self.0.fmt(f)
187 }
188}
189
190#[derive(Clone, Debug, PartialEq)]
192pub struct TypeName(pub String);
193
194impl TypeName {
195 pub fn new<N>(name: N) -> Result<Self, IdentifierError>
202 where
203 N: Into<String>,
204 {
205 let Identifier(tn) = Identifier::new(name)?;
207 Ok(TypeName(tn))
208 }
209
210 pub fn as_str(&self) -> &str {
212 &self.0
213 }
214}
215
216impl<'a> From<&'a str> for TypeName {
217 fn from(s: &str) -> Self {
218 TypeName(s.to_owned())
219 }
220}
221
222impl From<String> for TypeName {
223 fn from(s: String) -> Self {
224 TypeName(s)
225 }
226}
227
228impl fmt::Display for TypeName {
229 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
230 self.0.fmt(f)
231 }
232}
233
234#[derive(Clone, Debug, PartialEq)]
236pub enum TypeSpecifierNonArray {
237 Void,
239 Bool,
240 Int,
241 UInt,
242 Float,
243 Double,
244 Vec2,
245 Vec3,
246 Vec4,
247 DVec2,
248 DVec3,
249 DVec4,
250 BVec2,
251 BVec3,
252 BVec4,
253 IVec2,
254 IVec3,
255 IVec4,
256 UVec2,
257 UVec3,
258 UVec4,
259 Mat2,
260 Mat3,
261 Mat4,
262 Mat23,
263 Mat24,
264 Mat32,
265 Mat34,
266 Mat42,
267 Mat43,
268 DMat2,
269 DMat3,
270 DMat4,
271 DMat23,
272 DMat24,
273 DMat32,
274 DMat34,
275 DMat42,
276 DMat43,
277 Sampler1D,
279 Image1D,
280 Sampler2D,
281 Image2D,
282 Sampler3D,
283 Image3D,
284 SamplerCube,
285 ImageCube,
286 Sampler2DRect,
287 Image2DRect,
288 Sampler1DArray,
289 Image1DArray,
290 Sampler2DArray,
291 Image2DArray,
292 SamplerBuffer,
293 ImageBuffer,
294 Sampler2DMS,
295 Image2DMS,
296 Sampler2DMSArray,
297 Image2DMSArray,
298 SamplerCubeArray,
299 ImageCubeArray,
300 Sampler1DShadow,
301 Sampler2DShadow,
302 Sampler2DRectShadow,
303 Sampler1DArrayShadow,
304 Sampler2DArrayShadow,
305 SamplerCubeShadow,
306 SamplerCubeArrayShadow,
307 ISampler1D,
309 IImage1D,
310 ISampler2D,
311 IImage2D,
312 ISampler3D,
313 IImage3D,
314 ISamplerCube,
315 IImageCube,
316 ISampler2DRect,
317 IImage2DRect,
318 ISampler1DArray,
319 IImage1DArray,
320 ISampler2DArray,
321 IImage2DArray,
322 ISamplerBuffer,
323 IImageBuffer,
324 ISampler2DMS,
325 IImage2DMS,
326 ISampler2DMSArray,
327 IImage2DMSArray,
328 ISamplerCubeArray,
329 IImageCubeArray,
330 AtomicUInt,
332 USampler1D,
333 UImage1D,
334 USampler2D,
335 UImage2D,
336 USampler3D,
337 UImage3D,
338 USamplerCube,
339 UImageCube,
340 USampler2DRect,
341 UImage2DRect,
342 USampler1DArray,
343 UImage1DArray,
344 USampler2DArray,
345 UImage2DArray,
346 USamplerBuffer,
347 UImageBuffer,
348 USampler2DMS,
349 UImage2DMS,
350 USampler2DMSArray,
351 UImage2DMSArray,
352 USamplerCubeArray,
353 UImageCubeArray,
354 Struct(StructSpecifier),
355 TypeName(TypeName),
356}
357
358#[derive(Clone, Debug, PartialEq)]
360pub struct TypeSpecifier {
361 pub ty: TypeSpecifierNonArray,
362 pub array_specifier: Option<ArraySpecifier>,
363}
364
365impl TypeSpecifier {
366 pub fn new(ty: TypeSpecifierNonArray) -> Self {
367 TypeSpecifier {
368 ty,
369 array_specifier: None,
370 }
371 }
372}
373
374impl From<TypeSpecifierNonArray> for TypeSpecifier {
375 fn from(ty: TypeSpecifierNonArray) -> Self {
376 TypeSpecifier::new(ty)
377 }
378}
379
380#[derive(Clone, Debug, PartialEq)]
382pub struct StructSpecifier {
383 pub name: Option<TypeName>,
384 pub fields: NonEmpty<StructFieldSpecifier>,
385}
386
387#[derive(Clone, Debug, PartialEq)]
389pub struct StructFieldSpecifier {
390 pub qualifier: Option<TypeQualifier>,
391 pub ty: TypeSpecifier,
392 pub identifiers: NonEmpty<ArrayedIdentifier>, }
394
395impl StructFieldSpecifier {
396 pub fn new<A, T>(identifier: A, ty: T) -> Self
398 where
399 A: Into<ArrayedIdentifier>,
400 T: Into<TypeSpecifier>,
401 {
402 StructFieldSpecifier {
403 qualifier: None,
404 ty: ty.into(),
405 identifiers: NonEmpty(vec![identifier.into()]),
406 }
407 }
408
409 pub fn new_many<I>(identifiers: I, ty: TypeSpecifier) -> Self
411 where
412 I: IntoIterator<Item = ArrayedIdentifier>,
413 {
414 StructFieldSpecifier {
415 qualifier: None,
416 ty,
417 identifiers: NonEmpty(identifiers.into_iter().collect()),
418 }
419 }
420}
421
422#[derive(Clone, Debug, PartialEq)]
424pub struct ArrayedIdentifier {
425 pub ident: Identifier,
426 pub array_spec: Option<ArraySpecifier>,
427}
428
429impl ArrayedIdentifier {
430 pub fn new<I, AS>(ident: I, array_spec: AS) -> Self
431 where
432 I: Into<Identifier>,
433 AS: Into<Option<ArraySpecifier>>,
434 {
435 ArrayedIdentifier {
436 ident: ident.into(),
437 array_spec: array_spec.into(),
438 }
439 }
440}
441
442impl<'a> From<&'a str> for ArrayedIdentifier {
443 fn from(ident: &str) -> Self {
444 ArrayedIdentifier {
445 ident: Identifier(ident.to_owned()),
446 array_spec: None,
447 }
448 }
449}
450
451impl From<Identifier> for ArrayedIdentifier {
452 fn from(ident: Identifier) -> Self {
453 ArrayedIdentifier {
454 ident,
455 array_spec: None,
456 }
457 }
458}
459
460#[derive(Clone, Debug, PartialEq)]
462pub struct TypeQualifier {
463 pub qualifiers: NonEmpty<TypeQualifierSpec>,
464}
465
466#[derive(Clone, Debug, PartialEq)]
468pub enum TypeQualifierSpec {
469 Storage(StorageQualifier),
470 Layout(LayoutQualifier),
471 Precision(PrecisionQualifier),
472 Interpolation(InterpolationQualifier),
473 Invariant,
474 Precise,
475}
476
477#[derive(Clone, Debug, PartialEq)]
479pub enum StorageQualifier {
480 Const,
481 InOut,
482 In,
483 Out,
484 Centroid,
485 Patch,
486 Sample,
487 Uniform,
488 Attribute,
489 Varying,
490 Buffer,
491 Shared,
492 Coherent,
493 Volatile,
494 Restrict,
495 ReadOnly,
496 WriteOnly,
497 Subroutine(Vec<TypeName>),
498}
499
500#[derive(Clone, Debug, PartialEq)]
502pub struct LayoutQualifier {
503 pub ids: NonEmpty<LayoutQualifierSpec>,
504}
505
506#[derive(Clone, Debug, PartialEq)]
508pub enum LayoutQualifierSpec {
509 Identifier(Identifier, Option<Box<Expr>>),
510 Shared,
511}
512
513#[derive(Clone, Debug, PartialEq)]
515pub enum PrecisionQualifier {
516 High,
517 Medium,
518 Low,
519}
520
521#[derive(Clone, Debug, PartialEq)]
523pub enum InterpolationQualifier {
524 Smooth,
525 Flat,
526 NoPerspective,
527}
528
529#[derive(Clone, Debug, PartialEq)]
531pub struct FullySpecifiedType {
532 pub qualifier: Option<TypeQualifier>,
533 pub ty: TypeSpecifier,
534}
535
536impl FullySpecifiedType {
537 pub fn new(ty: TypeSpecifierNonArray) -> Self {
538 FullySpecifiedType {
539 qualifier: None,
540 ty: TypeSpecifier {
541 ty,
542 array_specifier: None,
543 },
544 }
545 }
546}
547
548impl From<TypeSpecifierNonArray> for FullySpecifiedType {
549 fn from(ty: TypeSpecifierNonArray) -> Self {
550 FullySpecifiedType::new(ty)
551 }
552}
553
554#[derive(Clone, Debug, PartialEq)]
556pub struct ArraySpecifier {
557 pub dimensions: NonEmpty<ArraySpecifierDimension>,
559}
560
561#[derive(Clone, Debug, PartialEq)]
563pub enum ArraySpecifierDimension {
564 Unsized,
565 ExplicitlySized(Box<Expr>),
566}
567
568#[derive(Clone, Debug, PartialEq)]
570pub enum Declaration {
571 FunctionPrototype(FunctionPrototype),
572 InitDeclaratorList(InitDeclaratorList),
573 Precision(PrecisionQualifier, TypeSpecifier),
574 Block(Block),
575 Global(TypeQualifier, Vec<Identifier>),
576}
577
578#[derive(Clone, Debug, PartialEq)]
581pub struct Block {
582 pub qualifier: TypeQualifier,
583 pub name: Identifier,
584 pub fields: Vec<StructFieldSpecifier>,
585 pub identifier: Option<ArrayedIdentifier>,
586}
587
588#[derive(Clone, Debug, PartialEq)]
590pub enum FunIdentifier {
591 Identifier(Identifier),
592 Expr(Box<Expr>),
593}
594
595impl FunIdentifier {
596 pub(crate) fn into_expr(self) -> Option<Expr> {
597 match self {
598 FunIdentifier::Identifier(..) => None,
599 FunIdentifier::Expr(expr) => Some(*expr),
600 }
601 }
602}
603
604#[derive(Clone, Debug, PartialEq)]
606pub struct FunctionPrototype {
607 pub ty: FullySpecifiedType,
608 pub name: Identifier,
609 pub parameters: Vec<FunctionParameterDeclaration>,
610}
611
612#[derive(Clone, Debug, PartialEq)]
614pub enum FunctionParameterDeclaration {
615 Named(Option<TypeQualifier>, FunctionParameterDeclarator),
616 Unnamed(Option<TypeQualifier>, TypeSpecifier),
617}
618
619impl FunctionParameterDeclaration {
620 pub fn new_named<I, T>(ident: I, ty: T) -> Self
622 where
623 I: Into<ArrayedIdentifier>,
624 T: Into<TypeSpecifier>,
625 {
626 let declator = FunctionParameterDeclarator {
627 ty: ty.into(),
628 ident: ident.into(),
629 };
630
631 FunctionParameterDeclaration::Named(None, declator)
632 }
633
634 pub fn new_unnamed<T>(ty: T) -> Self
636 where
637 T: Into<TypeSpecifier>,
638 {
639 FunctionParameterDeclaration::Unnamed(None, ty.into())
640 }
641}
642
643#[derive(Clone, Debug, PartialEq)]
645pub struct FunctionParameterDeclarator {
646 pub ty: TypeSpecifier,
647 pub ident: ArrayedIdentifier,
648}
649
650#[derive(Clone, Debug, PartialEq)]
652pub struct InitDeclaratorList {
653 pub head: SingleDeclaration,
654 pub tail: Vec<SingleDeclarationNoType>,
655}
656
657#[derive(Clone, Debug, PartialEq)]
659pub struct SingleDeclaration {
660 pub ty: FullySpecifiedType,
661 pub name: Option<Identifier>,
662 pub array_specifier: Option<ArraySpecifier>,
663 pub initializer: Option<Initializer>,
664}
665
666#[derive(Clone, Debug, PartialEq)]
668pub struct SingleDeclarationNoType {
669 pub ident: ArrayedIdentifier,
670 pub initializer: Option<Initializer>,
671}
672
673#[derive(Clone, Debug, PartialEq)]
675pub enum Initializer {
676 Simple(Box<Expr>),
677 List(NonEmpty<Initializer>),
678}
679
680impl From<Expr> for Initializer {
681 fn from(e: Expr) -> Self {
682 Initializer::Simple(Box::new(e))
683 }
684}
685
686#[derive(Clone, Debug, PartialEq)]
692pub enum Expr {
693 Variable(Identifier),
695 IntConst(i32),
697 UIntConst(u32),
699 BoolConst(bool),
701 FloatConst(f32),
703 DoubleConst(f64),
705 Unary(UnaryOp, Box<Expr>),
707 Binary(BinaryOp, Box<Expr>, Box<Expr>),
709 Ternary(Box<Expr>, Box<Expr>, Box<Expr>),
711 Assignment(Box<Expr>, AssignmentOp, Box<Expr>),
714 Bracket(Box<Expr>, ArraySpecifier),
716 FunCall(FunIdentifier, Vec<Expr>),
718 Dot(Box<Expr>, Identifier),
720 PostInc(Box<Expr>),
722 PostDec(Box<Expr>),
724 Comma(Box<Expr>, Box<Expr>),
726}
727
728impl From<i32> for Expr {
729 fn from(x: i32) -> Expr {
730 Expr::IntConst(x)
731 }
732}
733
734impl From<u32> for Expr {
735 fn from(x: u32) -> Expr {
736 Expr::UIntConst(x)
737 }
738}
739
740impl From<bool> for Expr {
741 fn from(x: bool) -> Expr {
742 Expr::BoolConst(x)
743 }
744}
745
746impl From<f32> for Expr {
747 fn from(x: f32) -> Expr {
748 Expr::FloatConst(x)
749 }
750}
751
752impl From<f64> for Expr {
753 fn from(x: f64) -> Expr {
754 Expr::DoubleConst(x)
755 }
756}
757
758#[derive(Clone, Debug, PartialEq)]
760pub enum UnaryOp {
761 Inc,
762 Dec,
763 Add,
764 Minus,
765 Not,
766 Complement,
767}
768
769#[derive(Clone, Debug, PartialEq)]
771pub enum BinaryOp {
772 Or,
773 Xor,
774 And,
775 BitOr,
776 BitXor,
777 BitAnd,
778 Equal,
779 NonEqual,
780 LT,
781 GT,
782 LTE,
783 GTE,
784 LShift,
785 RShift,
786 Add,
787 Sub,
788 Mult,
789 Div,
790 Mod,
791}
792
793#[derive(Clone, Debug, PartialEq)]
795pub enum AssignmentOp {
796 Equal,
797 Mult,
798 Div,
799 Mod,
800 Add,
801 Sub,
802 LShift,
803 RShift,
804 And,
805 Xor,
806 Or,
807}
808
809#[derive(Clone, Debug, PartialEq)]
811pub struct TranslationUnit(pub NonEmpty<ExternalDeclaration>);
812
813pub type ShaderStage = TranslationUnit;
815
816impl TranslationUnit {
817 pub fn from_non_empty_iter<I>(iter: I) -> Option<Self>
824 where
825 I: IntoIterator<Item = ExternalDeclaration>,
826 {
827 NonEmpty::from_non_empty_iter(iter).map(TranslationUnit)
828 }
829}
830
831impl Deref for TranslationUnit {
832 type Target = NonEmpty<ExternalDeclaration>;
833
834 fn deref(&self) -> &Self::Target {
835 &self.0
836 }
837}
838
839impl DerefMut for TranslationUnit {
840 fn deref_mut(&mut self) -> &mut Self::Target {
841 &mut self.0
842 }
843}
844
845impl IntoIterator for TranslationUnit {
846 type IntoIter = <NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
847 type Item = ExternalDeclaration;
848
849 fn into_iter(self) -> Self::IntoIter {
850 self.0.into_iter()
851 }
852}
853
854impl<'a> IntoIterator for &'a TranslationUnit {
855 type IntoIter = <&'a NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
856 type Item = &'a ExternalDeclaration;
857
858 fn into_iter(self) -> Self::IntoIter {
859 (&self.0).into_iter()
860 }
861}
862
863impl<'a> IntoIterator for &'a mut TranslationUnit {
864 type IntoIter = <&'a mut NonEmpty<ExternalDeclaration> as IntoIterator>::IntoIter;
865 type Item = &'a mut ExternalDeclaration;
866
867 fn into_iter(self) -> Self::IntoIter {
868 (&mut self.0).into_iter()
869 }
870}
871
872#[derive(Clone, Debug, PartialEq)]
874pub enum ExternalDeclaration {
875 Preprocessor(Preprocessor),
876 FunctionDefinition(FunctionDefinition),
877 Declaration(Declaration),
878}
879
880impl ExternalDeclaration {
881 pub fn new_fn<T, N, A, S>(ret_ty: T, name: N, args: A, body: S) -> Self
883 where
884 T: Into<FullySpecifiedType>,
885 N: Into<Identifier>,
886 A: IntoIterator<Item = FunctionParameterDeclaration>,
887 S: IntoIterator<Item = Statement>,
888 {
889 ExternalDeclaration::FunctionDefinition(FunctionDefinition {
890 prototype: FunctionPrototype {
891 ty: ret_ty.into(),
892 name: name.into(),
893 parameters: args.into_iter().collect(),
894 },
895 statement: CompoundStatement {
896 statement_list: body.into_iter().collect(),
897 },
898 })
899 }
900
901 pub fn new_struct<N, F>(name: N, fields: F) -> Option<Self>
907 where
908 N: Into<TypeName>,
909 F: IntoIterator<Item = StructFieldSpecifier>,
910 {
911 let fields: Vec<_> = fields.into_iter().collect();
912
913 if fields.is_empty() {
914 None
915 } else {
916 Some(ExternalDeclaration::Declaration(
917 Declaration::InitDeclaratorList(InitDeclaratorList {
918 head: SingleDeclaration {
919 ty: FullySpecifiedType {
920 qualifier: None,
921 ty: TypeSpecifier {
922 ty: TypeSpecifierNonArray::Struct(StructSpecifier {
923 name: Some(name.into()),
924 fields: NonEmpty(fields.into_iter().collect()),
925 }),
926 array_specifier: None,
927 },
928 },
929 name: None,
930 array_specifier: None,
931 initializer: None,
932 },
933 tail: vec![],
934 }),
935 ))
936 }
937 }
938}
939
940#[derive(Clone, Debug, PartialEq)]
942pub struct FunctionDefinition {
943 pub prototype: FunctionPrototype,
944 pub statement: CompoundStatement,
945}
946
947#[derive(Clone, Debug, PartialEq)]
949pub struct CompoundStatement {
950 pub statement_list: Vec<Statement>,
951}
952
953impl FromIterator<Statement> for CompoundStatement {
954 fn from_iter<T>(iter: T) -> Self
955 where
956 T: IntoIterator<Item = Statement>,
957 {
958 CompoundStatement {
959 statement_list: iter.into_iter().collect(),
960 }
961 }
962}
963
964#[derive(Clone, Debug, PartialEq)]
966pub enum Statement {
967 Compound(Box<CompoundStatement>),
968 Simple(Box<SimpleStatement>),
969}
970
971impl Statement {
972 pub fn new_case<C, S>(case: C, statements: S) -> Self
974 where
975 C: Into<CaseLabel>,
976 S: IntoIterator<Item = Statement>,
977 {
978 let case_stmt = Statement::Simple(Box::new(SimpleStatement::CaseLabel(case.into())));
979
980 Statement::Compound(Box::new(CompoundStatement {
981 statement_list: once(case_stmt).chain(statements.into_iter()).collect(),
982 }))
983 }
984
985 pub fn declare_var<T, N, A, I>(ty: T, name: N, array_specifier: A, initializer: I) -> Self
991 where
992 T: Into<FullySpecifiedType>,
993 N: Into<Identifier>,
994 A: Into<Option<ArraySpecifier>>,
995 I: Into<Option<Initializer>>,
996 {
997 Statement::Simple(Box::new(SimpleStatement::Declaration(
998 Declaration::InitDeclaratorList(InitDeclaratorList {
999 head: SingleDeclaration {
1000 ty: ty.into(),
1001 name: Some(name.into()),
1002 array_specifier: array_specifier.into(),
1003 initializer: initializer.into(),
1004 },
1005 tail: Vec::new(),
1006 }),
1007 )))
1008 }
1009}
1010
1011#[derive(Clone, Debug, PartialEq)]
1013pub enum SimpleStatement {
1014 Declaration(Declaration),
1015 Expression(ExprStatement),
1016 Selection(SelectionStatement),
1017 Switch(SwitchStatement),
1018 CaseLabel(CaseLabel),
1019 Iteration(IterationStatement),
1020 Jump(JumpStatement),
1021}
1022
1023impl SimpleStatement {
1024 pub fn new_expr<E>(expr: E) -> Self
1026 where
1027 E: Into<Expr>,
1028 {
1029 SimpleStatement::Expression(Some(expr.into()))
1030 }
1031
1032 pub fn new_if_else<If, True, False>(ife: If, truee: True, falsee: False) -> Self
1034 where
1035 If: Into<Expr>,
1036 True: Into<Statement>,
1037 False: Into<Statement>,
1038 {
1039 SimpleStatement::Selection(SelectionStatement {
1040 cond: Box::new(ife.into()),
1041 rest: SelectionRestStatement::Else(Box::new(truee.into()), Box::new(falsee.into())),
1042 })
1043 }
1044
1045 pub fn new_switch<H, B>(head: H, body: B) -> Self
1050 where
1051 H: Into<Expr>,
1052 B: IntoIterator<Item = Statement>,
1053 {
1054 SimpleStatement::Switch(SwitchStatement {
1055 head: Box::new(head.into()),
1056 body: body.into_iter().collect(),
1057 })
1058 }
1059
1060 pub fn new_while<C, S>(cond: C, body: S) -> Self
1062 where
1063 C: Into<Condition>,
1064 S: Into<Statement>,
1065 {
1066 SimpleStatement::Iteration(IterationStatement::While(
1067 cond.into(),
1068 Box::new(body.into()),
1069 ))
1070 }
1071
1072 pub fn new_do_while<C, S>(body: S, cond: C) -> Self
1074 where
1075 S: Into<Statement>,
1076 C: Into<Expr>,
1077 {
1078 SimpleStatement::Iteration(IterationStatement::DoWhile(
1079 Box::new(body.into()),
1080 Box::new(cond.into()),
1081 ))
1082 }
1083}
1084
1085pub type ExprStatement = Option<Expr>;
1087
1088#[derive(Clone, Debug, PartialEq)]
1090pub struct SelectionStatement {
1091 pub cond: Box<Expr>,
1092 pub rest: SelectionRestStatement,
1093}
1094
1095#[derive(Clone, Debug, PartialEq)]
1097pub enum Condition {
1098 Expr(Box<Expr>),
1099 Assignment(FullySpecifiedType, Identifier, Initializer),
1100}
1101
1102impl From<Expr> for Condition {
1103 fn from(expr: Expr) -> Self {
1104 Condition::Expr(Box::new(expr))
1105 }
1106}
1107
1108#[derive(Clone, Debug, PartialEq)]
1110pub enum SelectionRestStatement {
1111 Statement(Box<Statement>),
1113 Else(Box<Statement>, Box<Statement>),
1115}
1116
1117#[derive(Clone, Debug, PartialEq)]
1119pub struct SwitchStatement {
1120 pub head: Box<Expr>,
1121 pub body: Vec<Statement>,
1122}
1123
1124#[derive(Clone, Debug, PartialEq)]
1126pub enum CaseLabel {
1127 Case(Box<Expr>),
1128 Def,
1129}
1130
1131#[derive(Clone, Debug, PartialEq)]
1133pub enum IterationStatement {
1134 While(Condition, Box<Statement>),
1135 DoWhile(Box<Statement>, Box<Expr>),
1136 For(ForInitStatement, ForRestStatement, Box<Statement>),
1137}
1138
1139#[derive(Clone, Debug, PartialEq)]
1141pub enum ForInitStatement {
1142 Expression(Option<Expr>),
1143 Declaration(Box<Declaration>),
1144}
1145
1146#[derive(Clone, Debug, PartialEq)]
1148pub struct ForRestStatement {
1149 pub condition: Option<Condition>,
1150 pub post_expr: Option<Box<Expr>>,
1151}
1152
1153#[derive(Clone, Debug, PartialEq)]
1155pub enum JumpStatement {
1156 Continue,
1157 Break,
1158 Return(Option<Box<Expr>>),
1159 Discard,
1160}
1161
1162#[derive(Clone, Debug, PartialEq)]
1168pub enum Preprocessor {
1169 Define(PreprocessorDefine),
1170 Else,
1171 ElIf(PreprocessorElIf),
1172 EndIf,
1173 Error(PreprocessorError),
1174 If(PreprocessorIf),
1175 IfDef(PreprocessorIfDef),
1176 IfNDef(PreprocessorIfNDef),
1177 Include(PreprocessorInclude),
1178 Line(PreprocessorLine),
1179 Pragma(PreprocessorPragma),
1180 Undef(PreprocessorUndef),
1181 Version(PreprocessorVersion),
1182 Extension(PreprocessorExtension),
1183}
1184
1185#[derive(Clone, Debug, PartialEq)]
1189pub enum PreprocessorDefine {
1190 ObjectLike {
1191 ident: Identifier,
1192 value: String,
1193 },
1194
1195 FunctionLike {
1196 ident: Identifier,
1197 args: Vec<Identifier>,
1198 value: String,
1199 },
1200}
1201
1202#[derive(Clone, Debug, PartialEq)]
1204pub struct PreprocessorElIf {
1205 pub condition: String,
1206}
1207
1208#[derive(Clone, Debug, PartialEq)]
1210pub struct PreprocessorError {
1211 pub message: String,
1212}
1213
1214#[derive(Clone, Debug, PartialEq)]
1216pub struct PreprocessorIf {
1217 pub condition: String,
1218}
1219
1220#[derive(Clone, Debug, PartialEq)]
1222pub struct PreprocessorIfDef {
1223 pub ident: Identifier,
1224}
1225
1226#[derive(Clone, Debug, PartialEq)]
1228pub struct PreprocessorIfNDef {
1229 pub ident: Identifier,
1230}
1231
1232#[derive(Clone, Debug, PartialEq)]
1234pub struct PreprocessorInclude {
1235 pub path: Path,
1236}
1237
1238#[derive(Clone, Debug, PartialEq)]
1240pub struct PreprocessorLine {
1241 pub line: u32,
1242 pub source_string_number: Option<u32>,
1243}
1244
1245#[derive(Clone, Debug, PartialEq)]
1248pub struct PreprocessorPragma {
1249 pub command: String,
1250}
1251
1252#[derive(Clone, Debug, PartialEq)]
1254pub struct PreprocessorUndef {
1255 pub name: Identifier,
1256}
1257
1258#[derive(Clone, Debug, PartialEq)]
1260pub struct PreprocessorVersion {
1261 pub version: u16,
1262 pub profile: Option<PreprocessorVersionProfile>,
1263}
1264
1265#[derive(Clone, Debug, PartialEq)]
1267pub enum PreprocessorVersionProfile {
1268 Core,
1269 Compatibility,
1270 ES,
1271}
1272
1273#[derive(Clone, Debug, PartialEq)]
1275pub struct PreprocessorExtension {
1276 pub name: PreprocessorExtensionName,
1277 pub behavior: Option<PreprocessorExtensionBehavior>,
1278}
1279
1280#[derive(Clone, Debug, PartialEq)]
1282pub enum PreprocessorExtensionName {
1283 All,
1285 Specific(String),
1287}
1288
1289#[derive(Clone, Debug, PartialEq)]
1291pub enum PreprocessorExtensionBehavior {
1292 Require,
1293 Enable,
1294 Warn,
1295 Disable,
1296}
1297
1298#[cfg(test)]
1299mod tests {
1300 use super::*;
1301
1302 #[test]
1303 fn create_new_identifier() {
1304 assert!(Identifier::new("foo_bar").is_ok());
1305 assert!(Identifier::new("3foo_bar").is_err());
1306 assert!(Identifier::new("FooBar").is_ok());
1307 assert!(Identifier::new("_FooBar").is_ok());
1308 assert!(Identifier::new("foo3").is_ok());
1309 assert!(Identifier::new("foo3_").is_ok());
1310 assert!(Identifier::new("fδo3_").is_err());
1311 }
1312
1313 #[test]
1314 fn create_new_type_name() {
1315 assert!(TypeName::new("foo_bar").is_ok());
1316 assert!(TypeName::new("FooBar").is_ok());
1317 assert!(TypeName::new("foo3").is_ok());
1318 assert!(TypeName::new("foo3_").is_ok());
1319
1320 assert!(TypeName::new("_FooBar").is_ok());
1321 assert!(TypeName::new("3foo_bar").is_err());
1322 assert!(TypeName::new("fδo3_").is_err());
1323 }
1324
1325 #[test]
1328 fn declare_new_fn() {
1329 let _ = ExternalDeclaration::new_fn(
1330 TypeSpecifierNonArray::Bool,
1331 "predicate",
1332 vec![FunctionParameterDeclaration::new_named(
1333 "x",
1334 TypeSpecifierNonArray::Float,
1335 )],
1336 vec![],
1337 );
1338 }
1339
1340 #[test]
1345 fn declare_struct() {
1346 let point = ExternalDeclaration::new_struct(
1347 "Point2D",
1348 vec![
1349 StructFieldSpecifier::new("x", TypeSpecifierNonArray::Double),
1350 StructFieldSpecifier::new("y", TypeSpecifierNonArray::Double),
1351 ],
1352 );
1353
1354 assert!(point.is_some());
1355 }
1356
1357 #[test]
1359 fn declare_bad_struct() {
1360 let point = ExternalDeclaration::new_struct("Point2D", vec![]);
1361 assert!(point.is_none());
1362 }
1363
1364 #[test]
1365 fn initializer_from_expr() {
1366 let _: Initializer = Expr::from(false).into();
1367 }
1368}