3 //! The more general parser is `translation_unit`, that recognizes the most external form of a GLSL
4 //! source (a shader, basically).
6 //! Other parsers are exported if you want more control on how you want to parse your source.
11 use nom::bytes::complete::{tag, take_until, take_while1};
12 use nom::character::complete::{anychar, char, digit1, space0, space1};
13 use nom::character::{is_hex_digit, is_oct_digit};
14 use nom::combinator::{cut, map, not, opt, peek, recognize, value, verify};
15 use nom::error::{ErrorKind, ParseError as _, VerboseError, VerboseErrorKind};
16 use nom::multi::{fold_many0, many0, many1, separated_list0};
17 use nom::sequence::{delimited, pair, preceded, separated_pair, terminated, tuple};
18 use nom::{Err as NomErr, ParseTo};
19 use std::num::ParseIntError;
21 pub use self::nom_helpers::ParserResult;
22 use self::nom_helpers::{blank_space, cnst, eol, many0_, str_till_eol};
25 // Parse a keyword. A keyword is just a regular string that must be followed by punctuation.
26 fn keyword<'a>(kwd: &'a str) -> impl FnMut(&'a str) -> ParserResult<'a, &'a str> {
29 not(verify(peek(anychar), |&c| identifier_pred(c))),
33 /// Parse a single comment.
34 pub fn comment(i: &str) -> ParserResult<&str> {
38 preceded(char('/'), cut(str_till_eol)),
39 preceded(char('*'), cut(terminated(take_until("*/"), tag("*/")))),
44 /// Parse several comments.
45 pub fn comments(i: &str) -> ParserResult<&str> {
46 recognize(many0_(terminated(comment, blank_space)))(i)
49 /// In-between token parser (spaces and comments).
51 /// This parser also allows to break a line into two by finishing the line with a backslack ('\').
52 fn blank(i: &str) -> ParserResult<()> {
53 value((), preceded(blank_space, comments))(i)
57 fn identifier_pred(ch: char) -> bool {
58 ch.is_alphanumeric() || ch == '_'
62 fn verify_identifier(s: &str) -> bool {
63 !char::from(s.as_bytes()[0]).is_digit(10)
66 /// Parse an identifier (raw version).
67 fn identifier_str(i: &str) -> ParserResult<&str> {
68 verify(take_while1(identifier_pred), verify_identifier)(i)
71 /// Parse a string that could be used as an identifier.
72 pub fn string(i: &str) -> ParserResult<String> {
73 map(identifier_str, String::from)(i)
76 /// Parse an identifier.
77 pub fn identifier(i: &str) -> ParserResult<syntax::Identifier> {
78 map(string, syntax::Identifier)(i)
81 /// Parse a type name.
82 pub fn type_name(i: &str) -> ParserResult<syntax::TypeName> {
83 map(string, syntax::TypeName)(i)
86 /// Parse a non-empty list of type names, delimited by comma (,).
87 fn nonempty_type_names(i: &str) -> ParserResult<Vec<syntax::TypeName>> {
88 separated_list0(terminated(char(','), blank), terminated(type_name, blank))(i)
91 /// Parse a type specifier non struct.
92 pub fn type_specifier_non_struct(i: &str) -> ParserResult<syntax::TypeSpecifierNonArray> {
93 let (i1, t) = identifier_str(i)?;
96 "void" => Ok((i1, syntax::TypeSpecifierNonArray::Void)),
97 "bool" => Ok((i1, syntax::TypeSpecifierNonArray::Bool)),
98 "int" => Ok((i1, syntax::TypeSpecifierNonArray::Int)),
99 "uint" => Ok((i1, syntax::TypeSpecifierNonArray::UInt)),
100 "float" => Ok((i1, syntax::TypeSpecifierNonArray::Float)),
101 "double" => Ok((i1, syntax::TypeSpecifierNonArray::Double)),
102 "vec2" => Ok((i1, syntax::TypeSpecifierNonArray::Vec2)),
103 "vec3" => Ok((i1, syntax::TypeSpecifierNonArray::Vec3)),
104 "vec4" => Ok((i1, syntax::TypeSpecifierNonArray::Vec4)),
105 "dvec2" => Ok((i1, syntax::TypeSpecifierNonArray::DVec2)),
106 "dvec3" => Ok((i1, syntax::TypeSpecifierNonArray::DVec3)),
107 "dvec4" => Ok((i1, syntax::TypeSpecifierNonArray::DVec4)),
108 "bvec2" => Ok((i1, syntax::TypeSpecifierNonArray::BVec2)),
109 "bvec3" => Ok((i1, syntax::TypeSpecifierNonArray::BVec3)),
110 "bvec4" => Ok((i1, syntax::TypeSpecifierNonArray::BVec4)),
111 "ivec2" => Ok((i1, syntax::TypeSpecifierNonArray::IVec2)),
112 "ivec3" => Ok((i1, syntax::TypeSpecifierNonArray::IVec3)),
113 "ivec4" => Ok((i1, syntax::TypeSpecifierNonArray::IVec4)),
114 "uvec2" => Ok((i1, syntax::TypeSpecifierNonArray::UVec2)),
115 "uvec3" => Ok((i1, syntax::TypeSpecifierNonArray::UVec3)),
116 "uvec4" => Ok((i1, syntax::TypeSpecifierNonArray::UVec4)),
117 "mat2" => Ok((i1, syntax::TypeSpecifierNonArray::Mat2)),
118 "mat3" => Ok((i1, syntax::TypeSpecifierNonArray::Mat3)),
119 "mat4" => Ok((i1, syntax::TypeSpecifierNonArray::Mat4)),
120 "mat2x2" => Ok((i1, syntax::TypeSpecifierNonArray::Mat2)),
121 "mat2x3" => Ok((i1, syntax::TypeSpecifierNonArray::Mat23)),
122 "mat2x4" => Ok((i1, syntax::TypeSpecifierNonArray::Mat24)),
123 "mat3x2" => Ok((i1, syntax::TypeSpecifierNonArray::Mat32)),
124 "mat3x3" => Ok((i1, syntax::TypeSpecifierNonArray::Mat3)),
125 "mat3x4" => Ok((i1, syntax::TypeSpecifierNonArray::Mat34)),
126 "mat4x2" => Ok((i1, syntax::TypeSpecifierNonArray::Mat42)),
127 "mat4x3" => Ok((i1, syntax::TypeSpecifierNonArray::Mat43)),
128 "mat4x4" => Ok((i1, syntax::TypeSpecifierNonArray::Mat4)),
129 "dmat2" => Ok((i1, syntax::TypeSpecifierNonArray::DMat2)),
130 "dmat3" => Ok((i1, syntax::TypeSpecifierNonArray::DMat3)),
131 "dmat4" => Ok((i1, syntax::TypeSpecifierNonArray::DMat4)),
132 "dmat2x2" => Ok((i1, syntax::TypeSpecifierNonArray::DMat2)),
133 "dmat2x3" => Ok((i1, syntax::TypeSpecifierNonArray::DMat23)),
134 "dmat2x4" => Ok((i1, syntax::TypeSpecifierNonArray::DMat24)),
135 "dmat3x2" => Ok((i1, syntax::TypeSpecifierNonArray::DMat32)),
136 "dmat3x3" => Ok((i1, syntax::TypeSpecifierNonArray::DMat3)),
137 "dmat3x4" => Ok((i1, syntax::TypeSpecifierNonArray::DMat34)),
138 "dmat4x2" => Ok((i1, syntax::TypeSpecifierNonArray::DMat42)),
139 "dmat4x3" => Ok((i1, syntax::TypeSpecifierNonArray::DMat43)),
140 "dmat4x4" => Ok((i1, syntax::TypeSpecifierNonArray::DMat4)),
141 "sampler1D" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler1D)),
142 "image1D" => Ok((i1, syntax::TypeSpecifierNonArray::Image1D)),
143 "sampler2D" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2D)),
144 "image2D" => Ok((i1, syntax::TypeSpecifierNonArray::Image2D)),
145 "sampler3D" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler3D)),
146 "image3D" => Ok((i1, syntax::TypeSpecifierNonArray::Image3D)),
147 "samplerCube" => Ok((i1, syntax::TypeSpecifierNonArray::SamplerCube)),
148 "imageCube" => Ok((i1, syntax::TypeSpecifierNonArray::ImageCube)),
149 "sampler2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DRect)),
150 "image2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::Image2DRect)),
151 "sampler1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler1DArray)),
152 "image1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::Image1DArray)),
153 "sampler2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DArray)),
154 "image2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::Image2DArray)),
155 "samplerBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::SamplerBuffer)),
156 "imageBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::ImageBuffer)),
157 "sampler2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DMS)),
158 "image2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::Image2DMS)),
159 "sampler2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DMSArray)),
160 "image2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::Image2DMSArray)),
161 "samplerCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::SamplerCubeArray)),
162 "imageCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::ImageCubeArray)),
163 "sampler1DShadow" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler1DShadow)),
164 "sampler2DShadow" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DShadow)),
165 "sampler2DRectShadow" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DRectShadow)),
166 "sampler1DArrayShadow" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler1DArrayShadow)),
167 "sampler2DArrayShadow" => Ok((i1, syntax::TypeSpecifierNonArray::Sampler2DArrayShadow)),
168 "samplerCubeShadow" => Ok((i1, syntax::TypeSpecifierNonArray::SamplerCubeShadow)),
169 "samplerCubeArrayShadow" => Ok((i1, syntax::TypeSpecifierNonArray::SamplerCubeArrayShadow)),
170 "isampler1D" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler1D)),
171 "iimage1D" => Ok((i1, syntax::TypeSpecifierNonArray::IImage1D)),
172 "isampler2D" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler2D)),
173 "iimage2D" => Ok((i1, syntax::TypeSpecifierNonArray::IImage2D)),
174 "isampler3D" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler3D)),
175 "iimage3D" => Ok((i1, syntax::TypeSpecifierNonArray::IImage3D)),
176 "isamplerCube" => Ok((i1, syntax::TypeSpecifierNonArray::ISamplerCube)),
177 "iimageCube" => Ok((i1, syntax::TypeSpecifierNonArray::IImageCube)),
178 "isampler2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler2DRect)),
179 "iimage2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::IImage2DRect)),
180 "isampler1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler1DArray)),
181 "iimage1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::IImage1DArray)),
182 "isampler2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler2DArray)),
183 "iimage2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::IImage2DArray)),
184 "isamplerBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::ISamplerBuffer)),
185 "iimageBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::IImageBuffer)),
186 "isampler2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler2DMS)),
187 "iimage2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::IImage2DMS)),
188 "isampler2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::ISampler2DMSArray)),
189 "iimage2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::IImage2DMSArray)),
190 "isamplerCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::ISamplerCubeArray)),
191 "iimageCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::IImageCubeArray)),
192 "atomic_uint" => Ok((i1, syntax::TypeSpecifierNonArray::AtomicUInt)),
193 "usampler1D" => Ok((i1, syntax::TypeSpecifierNonArray::USampler1D)),
194 "uimage1D" => Ok((i1, syntax::TypeSpecifierNonArray::UImage1D)),
195 "usampler2D" => Ok((i1, syntax::TypeSpecifierNonArray::USampler2D)),
196 "uimage2D" => Ok((i1, syntax::TypeSpecifierNonArray::UImage2D)),
197 "usampler3D" => Ok((i1, syntax::TypeSpecifierNonArray::USampler3D)),
198 "uimage3D" => Ok((i1, syntax::TypeSpecifierNonArray::UImage3D)),
199 "usamplerCube" => Ok((i1, syntax::TypeSpecifierNonArray::USamplerCube)),
200 "uimageCube" => Ok((i1, syntax::TypeSpecifierNonArray::UImageCube)),
201 "usampler2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::USampler2DRect)),
202 "uimage2DRect" => Ok((i1, syntax::TypeSpecifierNonArray::UImage2DRect)),
203 "usampler1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::USampler1DArray)),
204 "uimage1DArray" => Ok((i1, syntax::TypeSpecifierNonArray::UImage1DArray)),
205 "usampler2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::USampler2DArray)),
206 "uimage2DArray" => Ok((i1, syntax::TypeSpecifierNonArray::UImage2DArray)),
207 "usamplerBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::USamplerBuffer)),
208 "uimageBuffer" => Ok((i1, syntax::TypeSpecifierNonArray::UImageBuffer)),
209 "usampler2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::USampler2DMS)),
210 "uimage2DMS" => Ok((i1, syntax::TypeSpecifierNonArray::UImage2DMS)),
211 "usampler2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::USampler2DMSArray)),
212 "uimage2DMSArray" => Ok((i1, syntax::TypeSpecifierNonArray::UImage2DMSArray)),
213 "usamplerCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::USamplerCubeArray)),
214 "uimageCubeArray" => Ok((i1, syntax::TypeSpecifierNonArray::UImageCubeArray)),
216 let vek = VerboseErrorKind::Context("unknown type specifier non array");
217 let ve = VerboseError {
218 errors: vec![(i1, vek)],
220 Err(NomErr::Error(ve))
225 /// Parse a type specifier (non-array version).
226 pub fn type_specifier_non_array(i: &str) -> ParserResult<syntax::TypeSpecifierNonArray> {
228 type_specifier_non_struct,
229 map(struct_specifier, syntax::TypeSpecifierNonArray::Struct),
230 map(type_name, syntax::TypeSpecifierNonArray::TypeName),
234 /// Parse a type specifier.
235 pub fn type_specifier(i: &str) -> ParserResult<syntax::TypeSpecifier> {
238 type_specifier_non_array,
239 opt(preceded(blank, array_specifier)),
241 |(ty, array_specifier)| syntax::TypeSpecifier {
248 /// Parse the void type.
249 pub fn void(i: &str) -> ParserResult<()> {
250 value((), keyword("void"))(i)
253 /// Parse a digit that precludes a leading 0.
254 pub(crate) fn nonzero_digits(i: &str) -> ParserResult<&str> {
255 verify(digit1, |s: &str| s.as_bytes()[0] != b'0')(i)
259 fn is_octal(s: &str) -> bool {
260 s.as_bytes()[0] == b'0' && s.bytes().all(is_oct_digit)
264 fn all_hexa(s: &str) -> bool {
265 s.bytes().all(is_hex_digit)
269 fn alphanumeric_no_u(c: char) -> bool {
270 c.is_alphanumeric() && c != 'u' && c != 'U'
273 /// Parse an hexadecimal literal.
274 pub(crate) fn hexadecimal_lit(i: &str) -> ParserResult<Result<u32, ParseIntError>> {
276 preceded(char('0'), cut(alt((char('x'), char('X'))))), // 0x | 0X
277 cut(map(verify(take_while1(alphanumeric_no_u), all_hexa), |i| {
278 u32::from_str_radix(i, 16)
283 /// Parse an octal literal.
284 pub(crate) fn octal_lit(i: &str) -> ParserResult<Result<u32, ParseIntError>> {
285 map(verify(take_while1(alphanumeric_no_u), is_octal), |i| {
286 u32::from_str_radix(i, 8)
290 /// Parse a decimal literal.
291 pub(crate) fn decimal_lit(i: &str) -> ParserResult<Result<u32, ParseIntError>> {
292 map(nonzero_digits, |i| i.parse())(i)
295 /// Parse a literal integral string.
297 /// From the GLSL 4.30 spec:
299 /// > No white space is allowed between the digits of an integer
300 /// > constant, including after the leading 0 or after the leading
301 /// > 0x or 0X of a constant, or before the suffix u or U. When
302 /// > tokenizing, the maximal token matching the above will be
303 /// > recognized before a new token is started. When the suffix u or
304 /// > U is present, the literal has type uint, otherwise the type is
305 /// > int. A leading unary minus sign (-) is interpreted as an
306 /// > arithmetic unary negation, not as part of the constant. Hence,
307 /// > literals themselves are always expressed with non-negative
308 /// > syntax, though they could result in a negative value.
310 /// > It is a compile-time error to provide a literal integer whose
311 /// > bit pattern cannot fit in 32 bits. The bit pattern of the
312 /// > literal is always used unmodified. So a signed literal whose
313 /// > bit pattern includes a set sign bit creates a negative value.
314 pub fn integral_lit_try(i: &str) -> ParserResult<Result<i32, ParseIntError>> {
315 let (i, sign) = opt(char('-'))(i)?;
317 map(alt((octal_lit, hexadecimal_lit, decimal_lit)), move |lit| {
330 pub fn integral_lit(i: &str) -> ParserResult<i32> {
331 match integral_lit_try(i) {
332 Ok((i, v)) => match v {
334 _ => Err(NomErr::Failure(VerboseError::from_error_kind(
336 ErrorKind::AlphaNumeric,
340 Err(NomErr::Failure(x)) | Err(NomErr::Error(x)) => Err(NomErr::Error(x)),
342 Err(NomErr::Incomplete(n)) => Err(NomErr::Incomplete(n)),
346 /// Parse the unsigned suffix.
347 pub(crate) fn unsigned_suffix(i: &str) -> ParserResult<char> {
348 alt((char('u'), char('U')))(i)
351 /// Parse a literal unsigned string.
352 pub fn unsigned_lit(i: &str) -> ParserResult<u32> {
353 map(terminated(integral_lit, unsigned_suffix), |lit| lit as u32)(i)
356 /// Parse a floating point suffix.
357 fn float_suffix(i: &str) -> ParserResult<&str> {
358 alt((keyword("f"), keyword("F")))(i)
361 /// Parse a double point suffix.
362 fn double_suffix(i: &str) -> ParserResult<&str> {
363 alt((keyword("lf"), keyword("LF")))(i)
366 /// Parse the exponent part of a floating point literal.
367 fn floating_exponent(i: &str) -> ParserResult<()> {
371 alt((char('e'), char('E'))),
372 preceded(opt(alt((char('+'), char('-')))), digit1),
377 /// Parse the fractional constant part of a floating point literal.
378 fn floating_frac(i: &str) -> ParserResult<()> {
380 value((), preceded(char('.'), digit1)),
381 value((), delimited(digit1, char('.'), opt(digit1))),
385 /// Parse the « middle » part of a floating value – i.e. fractional and exponential parts.
386 fn floating_middle(i: &str) -> ParserResult<&str> {
388 value((), preceded(floating_frac, opt(floating_exponent))),
389 value((), preceded(nonzero_digits, floating_exponent)),
393 /// Parse a float literal string.
394 pub fn float_lit(i: &str) -> ParserResult<f32> {
395 let (i, (sign, f)) = tuple((
397 terminated(floating_middle, pair(opt(float_suffix), not(double_suffix))),
400 // if the parsed data is in the accepted form ".394634…", we parse it as if it was < 0
401 let n: f32 = if f.as_bytes()[0] == b'.' {
402 let mut f_ = f.to_owned();
410 // handle the sign and return
411 let r = if sign.is_some() { -n } else { n };
415 /// Parse a double literal string.
416 pub fn double_lit(i: &str) -> ParserResult<f64> {
417 let (i, (sign, f)) = tuple((
419 terminated(floating_middle, pair(not(float_suffix), opt(double_suffix))),
422 // if the parsed data is in the accepted form ".394634…", we parse it as if it was < 0
423 let n: f64 = if f.as_bytes()[0] == b'.' {
424 let mut f_ = f.to_owned();
431 // handle the sign and return
432 let r = if sign.is_some() { -n } else { n };
436 /// Parse a constant boolean.
437 pub fn bool_lit(i: &str) -> ParserResult<bool> {
438 alt((value(true, keyword("true")), value(false, keyword("false"))))(i)
441 /// Parse a path literal.
442 pub fn path_lit(i: &str) -> ParserResult<syntax::Path> {
444 map(path_lit_absolute, syntax::Path::Absolute),
445 map(path_lit_relative, syntax::Path::Relative),
449 /// Parse a path literal with angle brackets.
450 pub fn path_lit_absolute(i: &str) -> ParserResult<String> {
452 delimited(char('<'), cut(take_until(">")), cut(char('>'))),
453 |s: &str| s.to_owned(),
457 /// Parse a path literal with double quotes.
458 pub fn path_lit_relative(i: &str) -> ParserResult<String> {
460 delimited(char('"'), cut(take_until("\"")), cut(char('"'))),
461 |s: &str| s.to_owned(),
465 /// Parse a unary operator.
466 pub fn unary_op(i: &str) -> ParserResult<syntax::UnaryOp> {
468 value(syntax::UnaryOp::Inc, tag("++")),
469 value(syntax::UnaryOp::Dec, tag("--")),
470 value(syntax::UnaryOp::Add, char('+')),
471 value(syntax::UnaryOp::Minus, char('-')),
472 value(syntax::UnaryOp::Not, char('!')),
473 value(syntax::UnaryOp::Complement, char('~')),
477 /// Parse an identifier with an optional array specifier.
478 pub fn arrayed_identifier(i: &str) -> ParserResult<syntax::ArrayedIdentifier> {
480 pair(identifier, opt(preceded(blank, array_specifier))),
481 |(i, a)| syntax::ArrayedIdentifier::new(i, a),
485 /// Parse a struct field declaration.
486 pub fn struct_field_specifier(i: &str) -> ParserResult<syntax::StructFieldSpecifier> {
487 let (i, (qualifier, ty, identifiers, _)) = tuple((
488 opt(terminated(type_qualifier, blank)),
489 terminated(type_specifier, blank),
491 terminated(char(','), blank),
492 terminated(arrayed_identifier, blank),
497 let r = syntax::StructFieldSpecifier {
500 identifiers: syntax::NonEmpty(identifiers),
507 pub fn struct_specifier(i: &str) -> ParserResult<syntax::StructSpecifier> {
509 terminated(keyword("struct"), blank),
512 opt(terminated(type_name, blank)),
514 terminated(char('{'), blank),
515 many1(terminated(struct_field_specifier, blank)),
519 |(name, fields)| syntax::StructSpecifier {
521 fields: syntax::NonEmpty(fields),
527 /// Parse a storage qualifier subroutine rule with a list of type names.
528 pub fn storage_qualifier_subroutine_list(i: &str) -> ParserResult<syntax::StorageQualifier> {
531 terminated(keyword("subroutine"), blank),
533 terminated(char('('), blank),
534 cut(terminated(nonempty_type_names, blank)),
538 syntax::StorageQualifier::Subroutine,
542 /// Parse a storage qualifier subroutine rule.
543 pub fn storage_qualifier_subroutine(i: &str) -> ParserResult<syntax::StorageQualifier> {
545 storage_qualifier_subroutine_list,
547 syntax::StorageQualifier::Subroutine(Vec::new()),
548 keyword("subroutine"),
553 /// Parse a storage qualifier.
554 pub fn storage_qualifier(i: &str) -> ParserResult<syntax::StorageQualifier> {
556 value(syntax::StorageQualifier::Const, keyword("const")),
557 value(syntax::StorageQualifier::InOut, keyword("inout")),
558 value(syntax::StorageQualifier::In, keyword("in")),
559 value(syntax::StorageQualifier::Out, keyword("out")),
560 value(syntax::StorageQualifier::Centroid, keyword("centroid")),
561 value(syntax::StorageQualifier::Patch, keyword("patch")),
562 value(syntax::StorageQualifier::Sample, keyword("sample")),
563 value(syntax::StorageQualifier::Uniform, keyword("uniform")),
564 value(syntax::StorageQualifier::Attribute, keyword("attribute")),
565 value(syntax::StorageQualifier::Varying, keyword("varying")),
566 value(syntax::StorageQualifier::Buffer, keyword("buffer")),
567 value(syntax::StorageQualifier::Shared, keyword("shared")),
568 value(syntax::StorageQualifier::Coherent, keyword("coherent")),
569 value(syntax::StorageQualifier::Volatile, keyword("volatile")),
570 value(syntax::StorageQualifier::Restrict, keyword("restrict")),
571 value(syntax::StorageQualifier::ReadOnly, keyword("readonly")),
572 value(syntax::StorageQualifier::WriteOnly, keyword("writeonly")),
573 storage_qualifier_subroutine,
577 /// Parse a layout qualifier.
578 pub fn layout_qualifier(i: &str) -> ParserResult<syntax::LayoutQualifier> {
580 terminated(keyword("layout"), blank),
582 terminated(char('('), blank),
583 cut(layout_qualifier_inner),
589 fn layout_qualifier_inner(i: &str) -> ParserResult<syntax::LayoutQualifier> {
592 terminated(char(','), blank),
593 terminated(layout_qualifier_spec, blank),
595 |ids| syntax::LayoutQualifier {
596 ids: syntax::NonEmpty(ids),
601 fn layout_qualifier_spec(i: &str) -> ParserResult<syntax::LayoutQualifierSpec> {
603 value(syntax::LayoutQualifierSpec::Shared, keyword("shared")),
606 terminated(identifier, blank),
607 terminated(char('='), blank),
610 |(i, e)| syntax::LayoutQualifierSpec::Identifier(i, Some(Box::new(e))),
612 map(identifier, |i| {
613 syntax::LayoutQualifierSpec::Identifier(i, None)
618 /// Parse a precision qualifier.
619 pub fn precision_qualifier(i: &str) -> ParserResult<syntax::PrecisionQualifier> {
621 value(syntax::PrecisionQualifier::High, keyword("highp")),
622 value(syntax::PrecisionQualifier::Medium, keyword("mediump")),
623 value(syntax::PrecisionQualifier::Low, keyword("lowp")),
627 /// Parse an interpolation qualifier.
628 pub fn interpolation_qualifier(i: &str) -> ParserResult<syntax::InterpolationQualifier> {
630 value(syntax::InterpolationQualifier::Smooth, keyword("smooth")),
631 value(syntax::InterpolationQualifier::Flat, keyword("flat")),
633 syntax::InterpolationQualifier::NoPerspective,
634 keyword("noperspective"),
639 /// Parse an invariant qualifier.
640 pub fn invariant_qualifier(i: &str) -> ParserResult<()> {
641 value((), keyword("invariant"))(i)
644 /// Parse a precise qualifier.
645 pub fn precise_qualifier(i: &str) -> ParserResult<()> {
646 value((), keyword("precise"))(i)
649 /// Parse a type qualifier.
650 pub fn type_qualifier(i: &str) -> ParserResult<syntax::TypeQualifier> {
651 map(many1(terminated(type_qualifier_spec, blank)), |qlfs| {
652 syntax::TypeQualifier {
653 qualifiers: syntax::NonEmpty(qlfs),
658 /// Parse a type qualifier spec.
659 pub fn type_qualifier_spec(i: &str) -> ParserResult<syntax::TypeQualifierSpec> {
661 map(storage_qualifier, syntax::TypeQualifierSpec::Storage),
662 map(layout_qualifier, syntax::TypeQualifierSpec::Layout),
663 map(precision_qualifier, syntax::TypeQualifierSpec::Precision),
665 interpolation_qualifier,
666 syntax::TypeQualifierSpec::Interpolation,
668 value(syntax::TypeQualifierSpec::Invariant, invariant_qualifier),
669 value(syntax::TypeQualifierSpec::Precise, precise_qualifier),
673 /// Parse a fully specified type.
674 pub fn fully_specified_type(i: &str) -> ParserResult<syntax::FullySpecifiedType> {
676 pair(opt(type_qualifier), type_specifier),
677 |(qualifier, ty)| syntax::FullySpecifiedType { qualifier, ty },
681 /// Parse an array specifier
682 pub fn array_specifier(i: &str) -> ParserResult<syntax::ArraySpecifier> {
684 many1(delimited(blank, array_specifier_dimension, blank)),
685 |dimensions| syntax::ArraySpecifier {
686 dimensions: syntax::NonEmpty(dimensions),
691 /// Parse an array specifier dimension.
692 pub fn array_specifier_dimension(i: &str) -> ParserResult<syntax::ArraySpecifierDimension> {
695 syntax::ArraySpecifierDimension::Unsized,
696 delimited(char('['), blank, char(']')),
700 terminated(char('['), blank),
702 preceded(blank, cut(char(']'))),
704 |e| syntax::ArraySpecifierDimension::ExplicitlySized(Box::new(e)),
709 /// Parse a primary expression.
710 pub fn primary_expr(i: &str) -> ParserResult<syntax::Expr> {
713 map(float_lit, syntax::Expr::FloatConst),
714 map(double_lit, syntax::Expr::DoubleConst),
715 map(unsigned_lit, syntax::Expr::UIntConst),
716 map(integral_lit, syntax::Expr::IntConst),
717 map(bool_lit, syntax::Expr::BoolConst),
718 map(identifier, syntax::Expr::Variable),
722 /// Parse a postfix expression.
723 pub fn postfix_expr(i: &str) -> ParserResult<syntax::Expr> {
725 function_call_with_identifier,
726 function_call_with_expr_ident_or_expr,
732 // Parse the postfix part of a primary expression. This function will just parse until it cannot
733 // find any more postfix construct.
734 fn postfix_part(i: &str, e: syntax::Expr) -> ParserResult<syntax::Expr> {
736 map(preceded(blank, array_specifier), |a| {
737 syntax::Expr::Bracket(Box::new(e.clone()), a)
739 map(preceded(blank, dot_field_selection), |i| {
740 syntax::Expr::Dot(Box::new(e.clone()), i)
743 syntax::Expr::PostInc(Box::new(e.clone())),
744 preceded(blank, tag("++")),
747 syntax::Expr::PostDec(Box::new(e.clone())),
748 preceded(blank, tag("--")),
753 Ok((i, e)) => postfix_part(i, e),
754 Err(NomErr::Error(_)) => Ok((i, e)),
759 /// Parse a unary expression.
760 pub fn unary_expr(i: &str) -> ParserResult<syntax::Expr> {
762 map(separated_pair(unary_op, blank, unary_expr), |(op, e)| {
763 syntax::Expr::Unary(op, Box::new(e))
769 /// Parse an expression between parens.
770 pub fn parens_expr(i: &str) -> ParserResult<syntax::Expr> {
772 terminated(char('('), blank),
774 preceded(blank, cut(char(')'))),
778 /// Parse a dot field selection identifier.
779 pub fn dot_field_selection(i: &str) -> ParserResult<syntax::Identifier> {
780 preceded(terminated(char('.'), blank), cut(identifier))(i)
783 /// Parse a declaration.
784 pub fn declaration(i: &str) -> ParserResult<syntax::Declaration> {
787 terminated(function_prototype, terminated(blank, char(';'))),
788 syntax::Declaration::FunctionPrototype,
791 terminated(init_declarator_list, terminated(blank, char(';'))),
792 syntax::Declaration::InitDeclaratorList,
794 precision_declaration,
800 /// Parse a precision declaration.
801 pub fn precision_declaration(i: &str) -> ParserResult<syntax::Declaration> {
803 terminated(keyword("precision"), blank),
806 terminated(precision_qualifier, blank),
807 terminated(type_specifier, blank),
809 |(qual, ty)| syntax::Declaration::Precision(qual, ty),
815 /// Parse a block declaration.
816 pub fn block_declaration(i: &str) -> ParserResult<syntax::Declaration> {
819 terminated(type_qualifier, blank),
820 terminated(identifier, blank),
822 terminated(char('{'), blank),
823 many1(terminated(struct_field_specifier, blank)),
824 cut(terminated(char('}'), blank)),
827 value(None, preceded(blank, char(';'))),
829 opt(preceded(blank, arrayed_identifier)),
830 preceded(blank, cut(char(';'))),
834 |(qualifier, name, fields, identifier)| {
835 syntax::Declaration::Block(syntax::Block {
845 /// Parse a global declaration.
846 pub fn global_declaration(i: &str) -> ParserResult<syntax::Declaration> {
849 terminated(type_qualifier, blank),
850 many0(delimited(terminated(char(','), blank), identifier, blank)),
852 |(qual, idents)| syntax::Declaration::Global(qual, idents),
856 /// Parse a function prototype.
857 pub fn function_prototype(i: &str) -> ParserResult<syntax::FunctionPrototype> {
858 terminated(function_declarator, terminated(blank, cut(char(')'))))(i)
861 /// Parse an init declarator list.
862 pub fn init_declarator_list(i: &str) -> ParserResult<syntax::InitDeclaratorList> {
868 preceded(delimited(blank, char(','), blank), cut(identifier)),
869 opt(preceded(blank, array_specifier)),
870 opt(preceded(delimited(blank, char('='), blank), initializer)),
872 |(name, arr_spec, init)| syntax::SingleDeclarationNoType {
873 ident: syntax::ArrayedIdentifier::new(name, arr_spec),
878 |(head, tail)| syntax::InitDeclaratorList { head, tail },
882 /// Parse a single declaration.
883 pub fn single_declaration(i: &str) -> ParserResult<syntax::SingleDeclaration> {
884 let (i, ty) = fully_specified_type(i)?;
885 let ty_ = ty.clone();
890 preceded(blank, identifier),
891 opt(preceded(blank, array_specifier)),
893 delimited(blank, char('='), blank),
897 move |(name, array_specifier, initializer)| syntax::SingleDeclaration {
904 cnst(syntax::SingleDeclaration {
907 array_specifier: None,
913 /// Parse an initializer.
914 pub fn initializer(i: &str) -> ParserResult<syntax::Initializer> {
916 map(assignment_expr, |e| {
917 syntax::Initializer::Simple(Box::new(e))
921 terminated(char('{'), blank),
923 cut(initializer_list),
924 terminated(blank, opt(terminated(char(','), blank))),
928 |il| syntax::Initializer::List(syntax::NonEmpty(il)),
933 /// Parse an initializer list.
934 pub fn initializer_list(i: &str) -> ParserResult<Vec<syntax::Initializer>> {
935 separated_list0(delimited(blank, char(','), blank), initializer)(i)
938 fn function_declarator(i: &str) -> ParserResult<syntax::FunctionPrototype> {
940 function_header_with_parameters,
941 map(function_header, |(ty, name)| syntax::FunctionPrototype {
944 parameters: Vec::new(),
949 fn function_header(i: &str) -> ParserResult<(syntax::FullySpecifiedType, syntax::Identifier)> {
951 terminated(fully_specified_type, blank),
952 terminated(identifier, terminated(blank, char('('))),
956 fn function_header_with_parameters(i: &str) -> ParserResult<syntax::FunctionPrototype> {
961 preceded(blank, char(',')),
962 preceded(blank, function_parameter_declaration),
965 |(header, parameters)| syntax::FunctionPrototype {
973 fn function_parameter_declaration(i: &str) -> ParserResult<syntax::FunctionParameterDeclaration> {
975 function_parameter_declaration_named,
976 function_parameter_declaration_unnamed,
980 fn function_parameter_declaration_named(
982 ) -> ParserResult<syntax::FunctionParameterDeclaration> {
985 opt(terminated(type_qualifier, blank)),
986 function_parameter_declarator,
988 |(ty_qual, fpd)| syntax::FunctionParameterDeclaration::Named(ty_qual, fpd),
992 fn function_parameter_declaration_unnamed(
994 ) -> ParserResult<syntax::FunctionParameterDeclaration> {
996 pair(opt(terminated(type_qualifier, blank)), type_specifier),
997 |(ty_qual, ty_spec)| syntax::FunctionParameterDeclaration::Unnamed(ty_qual, ty_spec),
1001 fn function_parameter_declarator(i: &str) -> ParserResult<syntax::FunctionParameterDeclarator> {
1004 terminated(type_specifier, blank),
1005 terminated(identifier, blank),
1006 opt(array_specifier),
1008 |(ty, name, a)| syntax::FunctionParameterDeclarator {
1010 ident: syntax::ArrayedIdentifier::new(name, a),
1015 fn function_call_with_identifier(i: &str) -> ParserResult<syntax::Expr> {
1017 tuple((function_identifier_identifier, function_call_args)),
1018 |(fi, args)| syntax::Expr::FunCall(fi, args),
1022 fn function_call_with_expr_ident_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1024 tuple((function_identifier_expr, opt(function_call_args))),
1025 |(expr, args)| match args {
1026 Some(args) => syntax::Expr::FunCall(expr, args),
1027 None => expr.into_expr().unwrap(),
1032 fn function_call_args(i: &str) -> ParserResult<Vec<syntax::Expr>> {
1034 terminated(terminated(blank, char('(')), blank),
1037 terminated(blank, terminated(opt(void), terminated(blank, char(')')))),
1042 terminated(char(','), blank),
1043 cut(terminated(assignment_expr, blank)),
1051 fn function_identifier_identifier(i: &str) -> ParserResult<syntax::FunIdentifier> {
1053 terminated(identifier, terminated(blank, peek(char('(')))),
1054 syntax::FunIdentifier::Identifier,
1058 fn function_identifier_expr(i: &str) -> ParserResult<syntax::FunIdentifier> {
1060 let (i, e) = primary_expr(i)?;
1061 postfix_part(i, e).map(|(i, pfe)| (i, syntax::FunIdentifier::Expr(Box::new(pfe))))
1065 /// Parse a function identifier just behind a function list argument.
1066 pub fn function_identifier(i: &str) -> ParserResult<syntax::FunIdentifier> {
1067 alt((function_identifier_identifier, function_identifier_expr))(i)
1070 /// Parse the most general expression.
1071 pub fn expr(i: &str) -> ParserResult<syntax::Expr> {
1072 let (i, first) = assignment_expr(i)?;
1073 let first_ = first.clone();
1076 map(preceded(terminated(char(','), blank), expr), move |next| {
1077 syntax::Expr::Comma(Box::new(first_.clone()), Box::new(next))
1083 /// Parse an assignment expression.
1084 pub fn assignment_expr(i: &str) -> ParserResult<syntax::Expr> {
1088 terminated(unary_expr, blank),
1089 terminated(assignment_op, blank),
1092 |(e, o, v)| syntax::Expr::Assignment(Box::new(e), o, Box::new(v)),
1098 /// Parse an assignment operator.
1099 pub fn assignment_op(i: &str) -> ParserResult<syntax::AssignmentOp> {
1101 value(syntax::AssignmentOp::Equal, char('=')),
1102 value(syntax::AssignmentOp::Mult, tag("*=")),
1103 value(syntax::AssignmentOp::Div, tag("/=")),
1104 value(syntax::AssignmentOp::Mod, tag("%=")),
1105 value(syntax::AssignmentOp::Add, tag("+=")),
1106 value(syntax::AssignmentOp::Sub, tag("-=")),
1107 value(syntax::AssignmentOp::LShift, tag("<<=")),
1108 value(syntax::AssignmentOp::RShift, tag(">>=")),
1109 value(syntax::AssignmentOp::And, tag("&=")),
1110 value(syntax::AssignmentOp::Xor, tag("^=")),
1111 value(syntax::AssignmentOp::Or, tag("|=")),
1115 /// Parse a conditional expression.
1116 pub fn cond_expr(i: &str) -> ParserResult<syntax::Expr> {
1117 let (i, a) = logical_or_expr(i)?;
1121 delimited(blank, char('?'), blank),
1122 cut(terminated(expr, blank)),
1123 cut(terminated(char(':'), blank)),
1124 cut(assignment_expr),
1127 move |acc, (_, b, _, c)| syntax::Expr::Ternary(Box::new(acc), Box::new(b), Box::new(c)),
1131 /// Parse a logical OR expression.
1132 pub fn logical_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1133 let (i, a) = logical_xor_expr(i)?;
1136 preceded(delimited(blank, tag("||"), blank), logical_xor_expr),
1138 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::Or, Box::new(acc), Box::new(b)),
1142 /// Parse a logical XOR expression.
1143 pub fn logical_xor_expr(i: &str) -> ParserResult<syntax::Expr> {
1144 let (i, a) = logical_and_expr(i)?;
1147 preceded(delimited(blank, tag("^^"), blank), logical_and_expr),
1149 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::Xor, Box::new(acc), Box::new(b)),
1153 /// Parse a logical AND expression.
1154 pub fn logical_and_expr(i: &str) -> ParserResult<syntax::Expr> {
1155 let (i, a) = inclusive_or_expr(i)?;
1158 preceded(delimited(blank, tag("&&"), blank), inclusive_or_expr),
1160 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::And, Box::new(acc), Box::new(b)),
1164 /// Parse a bitwise OR expression.
1165 pub fn inclusive_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1166 let (i, a) = exclusive_or_expr(i)?;
1169 preceded(delimited(blank, char('|'), blank), inclusive_or_expr),
1171 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitOr, Box::new(acc), Box::new(b)),
1175 /// Parse a bitwise XOR expression.
1176 pub fn exclusive_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1177 let (i, a) = and_expr(i)?;
1180 preceded(delimited(blank, char('^'), blank), exclusive_or_expr),
1182 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitXor, Box::new(acc), Box::new(b)),
1186 /// Parse a bitwise AND expression.
1187 pub fn and_expr(i: &str) -> ParserResult<syntax::Expr> {
1188 let (i, a) = equality_expr(i)?;
1191 preceded(delimited(blank, char('&'), blank), and_expr),
1193 move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitAnd, Box::new(acc), Box::new(b)),
1197 /// Parse an equality expression.
1198 pub fn equality_expr(i: &str) -> ParserResult<syntax::Expr> {
1199 let (i, a) = rel_expr(i)?;
1206 value(syntax::BinaryOp::Equal, tag("==")),
1207 value(syntax::BinaryOp::NonEqual, tag("!=")),
1214 move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1218 /// Parse a relational expression.
1219 pub fn rel_expr(i: &str) -> ParserResult<syntax::Expr> {
1220 let (i, a) = shift_expr(i)?;
1227 value(syntax::BinaryOp::LTE, tag("<=")),
1228 value(syntax::BinaryOp::GTE, tag(">=")),
1229 value(syntax::BinaryOp::LT, char('<')),
1230 value(syntax::BinaryOp::GT, char('>')),
1237 move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1241 /// Parse a shift expression.
1242 pub fn shift_expr(i: &str) -> ParserResult<syntax::Expr> {
1243 let (i, a) = additive_expr(i)?;
1250 value(syntax::BinaryOp::LShift, tag("<<")),
1251 value(syntax::BinaryOp::RShift, tag(">>")),
1258 move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1262 /// Parse an additive expression.
1263 pub fn additive_expr(i: &str) -> ParserResult<syntax::Expr> {
1264 let (i, a) = multiplicative_expr(i)?;
1271 value(syntax::BinaryOp::Add, char('+')),
1272 value(syntax::BinaryOp::Sub, char('-')),
1276 multiplicative_expr,
1279 move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1283 /// Parse a multiplicative expression.
1284 pub fn multiplicative_expr(i: &str) -> ParserResult<syntax::Expr> {
1285 let (i, a) = unary_expr(i)?;
1292 value(syntax::BinaryOp::Mult, char('*')),
1293 value(syntax::BinaryOp::Div, char('/')),
1294 value(syntax::BinaryOp::Mod, char('%')),
1301 move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1305 /// Parse a simple statement.
1306 pub fn simple_statement(i: &str) -> ParserResult<syntax::SimpleStatement> {
1308 map(jump_statement, syntax::SimpleStatement::Jump),
1309 map(iteration_statement, syntax::SimpleStatement::Iteration),
1310 map(case_label, syntax::SimpleStatement::CaseLabel),
1311 map(switch_statement, syntax::SimpleStatement::Switch),
1312 map(selection_statement, syntax::SimpleStatement::Selection),
1313 map(declaration, syntax::SimpleStatement::Declaration),
1314 map(expr_statement, syntax::SimpleStatement::Expression),
1318 /// Parse an expression statement.
1319 pub fn expr_statement(i: &str) -> ParserResult<syntax::ExprStatement> {
1320 terminated(terminated(opt(expr), blank), char(';'))(i)
1323 /// Parse a selection statement.
1324 pub fn selection_statement(i: &str) -> ParserResult<syntax::SelectionStatement> {
1327 terminated(keyword("if"), blank),
1328 cut(terminated(char('('), blank)),
1329 cut(terminated(expr, blank)),
1330 cut(terminated(char(')'), blank)),
1331 cut(selection_rest_statement),
1333 |(_, _, cond_expr, _, rest)| syntax::SelectionStatement {
1334 cond: Box::new(cond_expr),
1340 fn selection_rest_statement(i: &str) -> ParserResult<syntax::SelectionRestStatement> {
1341 let (i, st) = statement(i)?;
1342 let st_ = st.clone();
1346 preceded(delimited(blank, keyword("else"), blank), cut(statement)),
1347 move |rest| syntax::SelectionRestStatement::Else(Box::new(st_.clone()), Box::new(rest)),
1349 cnst(syntax::SelectionRestStatement::Statement(Box::new(st))),
1353 /// Parse a switch statement.
1354 pub fn switch_statement(i: &str) -> ParserResult<syntax::SwitchStatement> {
1357 terminated(keyword("switch"), blank),
1358 cut(terminated(char('('), blank)),
1359 cut(terminated(expr, blank)),
1360 cut(terminated(char(')'), blank)),
1361 cut(terminated(char('{'), blank)),
1362 cut(many0(terminated(statement, blank))),
1365 |(_, _, head, _, _, body, _)| syntax::SwitchStatement {
1366 head: Box::new(head),
1372 /// Parse a case label.
1373 pub fn case_label(i: &str) -> ParserResult<syntax::CaseLabel> {
1377 terminated(keyword("case"), blank),
1378 cut(terminated(expr, blank)),
1381 |e| syntax::CaseLabel::Case(Box::new(e)),
1384 syntax::CaseLabel::Def,
1385 preceded(terminated(keyword("default"), blank), char(':')),
1390 /// Parse an iteration statement.
1391 pub fn iteration_statement(i: &str) -> ParserResult<syntax::IterationStatement> {
1393 iteration_statement_while,
1394 iteration_statement_do_while,
1395 iteration_statement_for,
1399 /// Parse a while statement.
1400 pub fn iteration_statement_while(i: &str) -> ParserResult<syntax::IterationStatement> {
1403 terminated(keyword("while"), blank),
1404 cut(terminated(char('('), blank)),
1405 cut(terminated(condition, blank)),
1406 cut(terminated(char(')'), blank)),
1409 |(_, _, cond, _, st)| syntax::IterationStatement::While(cond, Box::new(st)),
1413 /// Parse a while statement.
1414 pub fn iteration_statement_do_while(i: &str) -> ParserResult<syntax::IterationStatement> {
1417 terminated(keyword("do"), blank),
1418 cut(terminated(statement, blank)),
1419 cut(terminated(keyword("while"), blank)),
1420 cut(terminated(char('('), blank)),
1421 cut(terminated(expr, blank)),
1422 cut(terminated(char(')'), blank)),
1425 |(_, st, _, _, e, _, _)| syntax::IterationStatement::DoWhile(Box::new(st), Box::new(e)),
1429 // Parse a for statement.
1430 pub fn iteration_statement_for(i: &str) -> ParserResult<syntax::IterationStatement> {
1433 terminated(keyword("for"), blank),
1434 cut(terminated(char('('), blank)),
1435 cut(terminated(iteration_statement_for_init_statement, blank)),
1436 cut(terminated(iteration_statement_for_rest_statement, blank)),
1437 cut(terminated(char(')'), blank)),
1440 |(_, _, head, rest, _, body)| syntax::IterationStatement::For(head, rest, Box::new(body)),
1444 fn iteration_statement_for_init_statement(i: &str) -> ParserResult<syntax::ForInitStatement> {
1446 map(expr_statement, syntax::ForInitStatement::Expression),
1447 map(declaration, |d| {
1448 syntax::ForInitStatement::Declaration(Box::new(d))
1453 fn iteration_statement_for_rest_statement(i: &str) -> ParserResult<syntax::ForRestStatement> {
1456 opt(terminated(condition, blank)),
1457 terminated(char(';'), blank),
1460 |(condition, e)| syntax::ForRestStatement {
1462 post_expr: e.map(Box::new),
1467 /// Parse a jump statement.
1468 pub fn jump_statement(i: &str) -> ParserResult<syntax::JumpStatement> {
1470 jump_statement_continue,
1471 jump_statement_break,
1472 jump_statement_return,
1473 jump_statement_discard,
1477 // Parse a continue statement.
1478 pub fn jump_statement_continue(i: &str) -> ParserResult<syntax::JumpStatement> {
1480 syntax::JumpStatement::Continue,
1481 terminated(keyword("continue"), cut(terminated(blank, char(';')))),
1485 // Parse a break statement.
1486 pub fn jump_statement_break(i: &str) -> ParserResult<syntax::JumpStatement> {
1488 syntax::JumpStatement::Break,
1489 terminated(keyword("break"), cut(terminated(blank, char(';')))),
1493 // Parse a discard statement.
1494 pub fn jump_statement_discard(i: &str) -> ParserResult<syntax::JumpStatement> {
1496 syntax::JumpStatement::Discard,
1497 terminated(keyword("discard"), cut(terminated(blank, char(';')))),
1501 // Parse a return statement.
1502 pub fn jump_statement_return(i: &str) -> ParserResult<syntax::JumpStatement> {
1505 terminated(keyword("return"), blank),
1506 opt(terminated(expr, blank)),
1509 |e| syntax::JumpStatement::Return(e.map(|e| Box::new(e))),
1513 /// Parse a condition.
1514 pub fn condition(i: &str) -> ParserResult<syntax::Condition> {
1516 map(expr, |e| syntax::Condition::Expr(Box::new(e))),
1517 condition_assignment,
1521 fn condition_assignment(i: &str) -> ParserResult<syntax::Condition> {
1524 terminated(fully_specified_type, blank),
1525 terminated(identifier, blank),
1526 terminated(char('='), blank),
1529 |(ty, id, _, ini)| syntax::Condition::Assignment(ty, id, ini),
1533 /// Parse a statement.
1534 pub fn statement(i: &str) -> ParserResult<syntax::Statement> {
1536 map(compound_statement, |c| {
1537 syntax::Statement::Compound(Box::new(c))
1539 map(simple_statement, |s| syntax::Statement::Simple(Box::new(s))),
1543 /// Parse a compound statement.
1544 pub fn compound_statement(i: &str) -> ParserResult<syntax::CompoundStatement> {
1547 terminated(char('{'), blank),
1548 many0(terminated(statement, blank)),
1551 |statement_list| syntax::CompoundStatement { statement_list },
1555 /// Parse a function definition.
1556 pub fn function_definition(i: &str) -> ParserResult<syntax::FunctionDefinition> {
1558 pair(terminated(function_prototype, blank), compound_statement),
1559 |(prototype, statement)| syntax::FunctionDefinition {
1566 /// Parse an external declaration.
1567 pub fn external_declaration(i: &str) -> ParserResult<syntax::ExternalDeclaration> {
1569 map(preprocessor, syntax::ExternalDeclaration::Preprocessor),
1571 function_definition,
1572 syntax::ExternalDeclaration::FunctionDefinition,
1574 map(declaration, syntax::ExternalDeclaration::Declaration),
1576 delimited(blank, char(';'), blank),
1577 cut(external_declaration),
1582 /// Parse a translation unit (entry point).
1583 pub fn translation_unit(i: &str) -> ParserResult<syntax::TranslationUnit> {
1585 many1(delimited(blank, external_declaration, blank)),
1586 |eds| syntax::TranslationUnit(syntax::NonEmpty(eds)),
1590 /// Parse a preprocessor directive.
1591 pub fn preprocessor(i: &str) -> ParserResult<syntax::Preprocessor> {
1593 terminated(char('#'), pp_space0),
1595 map(pp_define, syntax::Preprocessor::Define),
1596 value(syntax::Preprocessor::Else, pp_else),
1597 map(pp_elseif, syntax::Preprocessor::ElseIf),
1598 value(syntax::Preprocessor::EndIf, pp_endif),
1599 map(pp_error, syntax::Preprocessor::Error),
1600 map(pp_if, syntax::Preprocessor::If),
1601 map(pp_ifdef, syntax::Preprocessor::IfDef),
1602 map(pp_ifndef, syntax::Preprocessor::IfNDef),
1603 map(pp_include, syntax::Preprocessor::Include),
1604 map(pp_line, syntax::Preprocessor::Line),
1605 map(pp_pragma, syntax::Preprocessor::Pragma),
1606 map(pp_undef, syntax::Preprocessor::Undef),
1607 map(pp_version, syntax::Preprocessor::Version),
1608 map(pp_extension, syntax::Preprocessor::Extension),
1613 /// Parse a preprocessor version number.
1614 pub(crate) fn pp_version_number(i: &str) -> ParserResult<u16> {
1615 map(digit1, |x: &str| x.parse_to().unwrap())(i)
1618 /// Parse a preprocessor version profile.
1619 pub(crate) fn pp_version_profile(i: &str) -> ParserResult<syntax::PreprocessorVersionProfile> {
1621 value(syntax::PreprocessorVersionProfile::Core, keyword("core")),
1623 syntax::PreprocessorVersionProfile::Compatibility,
1624 keyword("compatibility"),
1626 value(syntax::PreprocessorVersionProfile::ES, keyword("es")),
1630 /// The space parser in preprocessor directives.
1632 /// This parser is needed to authorize breaking a line with the multiline annotation (\).
1633 pub(crate) fn pp_space0(i: &str) -> ParserResult<&str> {
1634 recognize(many0_(alt((space1, tag("\\\n")))))(i)
1637 /// Parse a preprocessor define.
1638 pub(crate) fn pp_define(i: &str) -> ParserResult<syntax::PreprocessorDefine> {
1639 let (i, ident) = map(
1640 tuple((terminated(keyword("define"), pp_space0), cut(identifier))),
1645 pp_define_function_like(ident.clone()),
1646 pp_define_object_like(ident),
1650 // Parse an object-like #define content.
1651 pub(crate) fn pp_define_object_like<'a>(
1652 ident: syntax::Identifier,
1653 ) -> impl Fn(&'a str) -> ParserResult<'a, syntax::PreprocessorDefine> {
1655 map(preceded(pp_space0, cut(str_till_eol)), |value| {
1656 syntax::PreprocessorDefine::ObjectLike {
1657 ident: ident.clone(),
1658 value: value.to_owned(),
1664 // Parse a function-like #define content.
1665 pub(crate) fn pp_define_function_like<'a>(
1666 ident: syntax::Identifier,
1667 ) -> impl Fn(&'a str) -> ParserResult<'a, syntax::PreprocessorDefine> {
1671 terminated(char('('), pp_space0),
1673 terminated(char(','), pp_space0),
1674 cut(terminated(identifier, pp_space0)),
1676 cut(terminated(char(')'), pp_space0)),
1677 cut(map(str_till_eol, String::from)),
1679 |(_, args, _, value)| syntax::PreprocessorDefine::FunctionLike {
1680 ident: ident.clone(),
1688 /// Parse a preprocessor else.
1689 pub(crate) fn pp_else(i: &str) -> ParserResult<syntax::Preprocessor> {
1691 syntax::Preprocessor::Else,
1692 tuple((terminated(keyword("else"), pp_space0), cut(eol))),
1696 /// Parse a preprocessor elseif.
1697 pub(crate) fn pp_elseif(i: &str) -> ParserResult<syntax::PreprocessorElseIf> {
1700 terminated(keyword("elseif"), pp_space0),
1701 cut(map(str_till_eol, String::from)),
1703 |(_, condition)| syntax::PreprocessorElseIf { condition },
1707 /// Parse a preprocessor endif.
1708 pub(crate) fn pp_endif(i: &str) -> ParserResult<syntax::Preprocessor> {
1710 tuple((terminated(keyword("endif"), space0), cut(eol))),
1711 |(_, _)| syntax::Preprocessor::EndIf,
1715 /// Parse a preprocessor error.
1716 pub(crate) fn pp_error(i: &str) -> ParserResult<syntax::PreprocessorError> {
1718 tuple((terminated(keyword("error"), pp_space0), cut(str_till_eol))),
1719 |(_, message)| syntax::PreprocessorError {
1720 message: message.to_owned(),
1725 /// Parse a preprocessor if.
1726 pub(crate) fn pp_if(i: &str) -> ParserResult<syntax::PreprocessorIf> {
1729 terminated(keyword("if"), pp_space0),
1730 cut(map(str_till_eol, String::from)),
1732 |(_, condition)| syntax::PreprocessorIf { condition },
1736 /// Parse a preprocessor ifdef.
1737 pub(crate) fn pp_ifdef(i: &str) -> ParserResult<syntax::PreprocessorIfDef> {
1740 terminated(keyword("ifdef"), pp_space0),
1741 cut(terminated(identifier, pp_space0)),
1744 |(_, ident, _)| syntax::PreprocessorIfDef { ident },
1748 /// Parse a preprocessor ifndef.
1749 pub(crate) fn pp_ifndef(i: &str) -> ParserResult<syntax::PreprocessorIfNDef> {
1752 terminated(keyword("ifndef"), pp_space0),
1753 cut(terminated(identifier, pp_space0)),
1756 |(_, ident, _)| syntax::PreprocessorIfNDef { ident },
1760 /// Parse a preprocessor include.
1761 pub(crate) fn pp_include(i: &str) -> ParserResult<syntax::PreprocessorInclude> {
1764 terminated(keyword("include"), pp_space0),
1765 cut(terminated(path_lit, pp_space0)),
1768 |(_, path, _)| syntax::PreprocessorInclude { path },
1772 /// Parse a preprocessor line.
1773 pub(crate) fn pp_line(i: &str) -> ParserResult<syntax::PreprocessorLine> {
1776 terminated(keyword("line"), pp_space0),
1777 cut(terminated(integral_lit, pp_space0)),
1778 opt(terminated(integral_lit, pp_space0)),
1781 |(_, line, source_string_number, _)| syntax::PreprocessorLine {
1783 source_string_number: source_string_number.map(|n| n as u32),
1788 /// Parse a preprocessor pragma.
1789 pub(crate) fn pp_pragma(i: &str) -> ParserResult<syntax::PreprocessorPragma> {
1791 tuple((terminated(keyword("pragma"), pp_space0), cut(str_till_eol))),
1792 |(_, command)| syntax::PreprocessorPragma {
1793 command: command.to_owned(),
1798 /// Parse a preprocessor undef.
1799 pub(crate) fn pp_undef(i: &str) -> ParserResult<syntax::PreprocessorUndef> {
1802 terminated(keyword("undef"), pp_space0),
1803 cut(terminated(identifier, pp_space0)),
1806 |(_, name, _)| syntax::PreprocessorUndef { name },
1810 /// Parse a preprocessor version.
1811 pub(crate) fn pp_version(i: &str) -> ParserResult<syntax::PreprocessorVersion> {
1814 terminated(keyword("version"), pp_space0),
1815 cut(terminated(pp_version_number, pp_space0)),
1816 opt(terminated(pp_version_profile, pp_space0)),
1819 |(_, version, profile, _)| syntax::PreprocessorVersion { version, profile },
1823 /// Parse a preprocessor extension name.
1824 pub(crate) fn pp_extension_name(i: &str) -> ParserResult<syntax::PreprocessorExtensionName> {
1826 value(syntax::PreprocessorExtensionName::All, keyword("all")),
1827 map(string, syntax::PreprocessorExtensionName::Specific),
1831 /// Parse a preprocessor extension behavior.
1832 pub(crate) fn pp_extension_behavior(
1834 ) -> ParserResult<syntax::PreprocessorExtensionBehavior> {
1837 syntax::PreprocessorExtensionBehavior::Require,
1841 syntax::PreprocessorExtensionBehavior::Enable,
1844 value(syntax::PreprocessorExtensionBehavior::Warn, keyword("warn")),
1846 syntax::PreprocessorExtensionBehavior::Disable,
1852 /// Parse a preprocessor extension.
1853 pub(crate) fn pp_extension(i: &str) -> ParserResult<syntax::PreprocessorExtension> {
1856 terminated(keyword("extension"), pp_space0),
1857 cut(terminated(pp_extension_name, pp_space0)),
1859 terminated(char(':'), pp_space0),
1860 cut(terminated(pp_extension_behavior, pp_space0)),
1864 |(_, name, behavior, _)| syntax::PreprocessorExtension { name, behavior },