Bug 1880927 - Use YouTube channel news to ensure DRM-free content r=mboldan
[gecko.git] / third_party / rust / glsl / src / parsers.rs
blob824f7bbba3d424fde61f2a8ffdc974de9766f6c9
1 //! GLSL parsers.
2 //!
3 //! The more general parser is `translation_unit`, that recognizes the most external form of a GLSL
4 //! source (a shader, basically).
5 //!
6 //! Other parsers are exported if you want more control on how you want to parse your source.
8 mod nom_helpers;
10 use nom::branch::alt;
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};
23 use crate::syntax;
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> {
27   terminated(
28     tag(kwd),
29     not(verify(peek(anychar), |&c| identifier_pred(c))),
30   )
33 /// Parse a single comment.
34 pub fn comment(i: &str) -> ParserResult<&str> {
35   preceded(
36     char('/'),
37     alt((
38       preceded(char('/'), cut(str_till_eol)),
39       preceded(char('*'), cut(terminated(take_until("*/"), tag("*/")))),
40     )),
41   )(i)
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).
50 ///
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)
56 #[inline]
57 fn identifier_pred(ch: char) -> bool {
58   ch.is_alphanumeric() || ch == '_'
61 #[inline]
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)?;
95   match t {
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)),
215     _ => {
216       let vek = VerboseErrorKind::Context("unknown type specifier non array");
217       let ve = VerboseError {
218         errors: vec![(i1, vek)],
219       };
220       Err(NomErr::Error(ve))
221     }
222   }
225 /// Parse a type specifier (non-array version).
226 pub fn type_specifier_non_array(i: &str) -> ParserResult<syntax::TypeSpecifierNonArray> {
227   alt((
228     type_specifier_non_struct,
229     map(struct_specifier, syntax::TypeSpecifierNonArray::Struct),
230     map(type_name, syntax::TypeSpecifierNonArray::TypeName),
231   ))(i)
234 /// Parse a type specifier.
235 pub fn type_specifier(i: &str) -> ParserResult<syntax::TypeSpecifier> {
236   map(
237     pair(
238       type_specifier_non_array,
239       opt(preceded(blank, array_specifier)),
240     ),
241     |(ty, array_specifier)| syntax::TypeSpecifier {
242       ty,
243       array_specifier,
244     },
245   )(i)
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)
258 #[inline]
259 fn is_octal(s: &str) -> bool {
260   s.as_bytes()[0] == b'0' && s.bytes().all(is_oct_digit)
263 #[inline]
264 fn all_hexa(s: &str) -> bool {
265   s.bytes().all(is_hex_digit)
268 #[inline]
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>> {
275   preceded(
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)
279     })),
280   )(i)
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)
287   })(i)
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| {
318     lit.map(|v| {
319       let v = v as i32;
321       if sign.is_some() {
322         -v
323       } else {
324         v
325       }
326     })
327   })(i)
330 pub fn integral_lit(i: &str) -> ParserResult<i32> {
331   match integral_lit_try(i) {
332     Ok((i, v)) => match v {
333       Ok(v) => Ok((i, v)),
334       _ => Err(NomErr::Failure(VerboseError::from_error_kind(
335         i,
336         ErrorKind::AlphaNumeric,
337       ))),
338     },
340     Err(NomErr::Failure(x)) | Err(NomErr::Error(x)) => Err(NomErr::Error(x)),
342     Err(NomErr::Incomplete(n)) => Err(NomErr::Incomplete(n)),
343   }
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<()> {
368   value(
369     (),
370     preceded(
371       alt((char('e'), char('E'))),
372       preceded(opt(alt((char('+'), char('-')))), digit1),
373     ),
374   )(i)
377 /// Parse the fractional constant part of a floating point literal.
378 fn floating_frac(i: &str) -> ParserResult<()> {
379   alt((
380     value((), preceded(char('.'), digit1)),
381     value((), delimited(digit1, char('.'), opt(digit1))),
382   ))(i)
385 /// Parse the Â« middle Â» part of a floating value â€“ i.e. fractional and exponential parts.
386 fn floating_middle(i: &str) -> ParserResult<&str> {
387   recognize(alt((
388     value((), preceded(floating_frac, opt(floating_exponent))),
389     value((), preceded(nonzero_digits, floating_exponent)),
390   )))(i)
393 /// Parse a float literal string.
394 pub fn float_lit(i: &str) -> ParserResult<f32> {
395   let (i, (sign, f)) = tuple((
396     opt(char('-')),
397     terminated(floating_middle, pair(opt(float_suffix), not(double_suffix))),
398   ))(i)?;
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();
403     f_.insert(0, '0');
405     f_.parse().unwrap()
406   } else {
407     f.parse().unwrap()
408   };
410   // handle the sign and return
411   let r = if sign.is_some() { -n } else { n };
412   Ok((i, r))
415 /// Parse a double literal string.
416 pub fn double_lit(i: &str) -> ParserResult<f64> {
417   let (i, (sign, f)) = tuple((
418     opt(char('-')),
419     terminated(floating_middle, pair(not(float_suffix), opt(double_suffix))),
420   ))(i)?;
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();
425     f_.insert(0, '0');
426     f_.parse().unwrap()
427   } else {
428     f.parse().unwrap()
429   };
431   // handle the sign and return
432   let r = if sign.is_some() { -n } else { n };
433   Ok((i, r))
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> {
443   alt((
444     map(path_lit_absolute, syntax::Path::Absolute),
445     map(path_lit_relative, syntax::Path::Relative),
446   ))(i)
449 /// Parse a path literal with angle brackets.
450 pub fn path_lit_absolute(i: &str) -> ParserResult<String> {
451   map(
452     delimited(char('<'), cut(take_until(">")), cut(char('>'))),
453     |s: &str| s.to_owned(),
454   )(i)
457 /// Parse a path literal with double quotes.
458 pub fn path_lit_relative(i: &str) -> ParserResult<String> {
459   map(
460     delimited(char('"'), cut(take_until("\"")), cut(char('"'))),
461     |s: &str| s.to_owned(),
462   )(i)
465 /// Parse a unary operator.
466 pub fn unary_op(i: &str) -> ParserResult<syntax::UnaryOp> {
467   alt((
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('~')),
474   ))(i)
477 /// Parse an identifier with an optional array specifier.
478 pub fn arrayed_identifier(i: &str) -> ParserResult<syntax::ArrayedIdentifier> {
479   map(
480     pair(identifier, opt(preceded(blank, array_specifier))),
481     |(i, a)| syntax::ArrayedIdentifier::new(i, a),
482   )(i)
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),
490     cut(separated_list0(
491       terminated(char(','), blank),
492       terminated(arrayed_identifier, blank),
493     )),
494     cut(char(';')),
495   ))(i)?;
497   let r = syntax::StructFieldSpecifier {
498     qualifier,
499     ty,
500     identifiers: syntax::NonEmpty(identifiers),
501   };
503   Ok((i, r))
506 /// Parse a struct.
507 pub fn struct_specifier(i: &str) -> ParserResult<syntax::StructSpecifier> {
508   preceded(
509     terminated(keyword("struct"), blank),
510     map(
511       pair(
512         opt(terminated(type_name, blank)),
513         cut(delimited(
514           terminated(char('{'), blank),
515           many1(terminated(struct_field_specifier, blank)),
516           char('}'),
517         )),
518       ),
519       |(name, fields)| syntax::StructSpecifier {
520         name,
521         fields: syntax::NonEmpty(fields),
522       },
523     ),
524   )(i)
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> {
529   map(
530     preceded(
531       terminated(keyword("subroutine"), blank),
532       delimited(
533         terminated(char('('), blank),
534         cut(terminated(nonempty_type_names, blank)),
535         cut(char(')')),
536       ),
537     ),
538     syntax::StorageQualifier::Subroutine,
539   )(i)
542 /// Parse a storage qualifier subroutine rule.
543 pub fn storage_qualifier_subroutine(i: &str) -> ParserResult<syntax::StorageQualifier> {
544   alt((
545     storage_qualifier_subroutine_list,
546     value(
547       syntax::StorageQualifier::Subroutine(Vec::new()),
548       keyword("subroutine"),
549     ),
550   ))(i)
553 /// Parse a storage qualifier.
554 pub fn storage_qualifier(i: &str) -> ParserResult<syntax::StorageQualifier> {
555   alt((
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,
574   ))(i)
577 /// Parse a layout qualifier.
578 pub fn layout_qualifier(i: &str) -> ParserResult<syntax::LayoutQualifier> {
579   preceded(
580     terminated(keyword("layout"), blank),
581     delimited(
582       terminated(char('('), blank),
583       cut(layout_qualifier_inner),
584       cut(char(')')),
585     ),
586   )(i)
589 fn layout_qualifier_inner(i: &str) -> ParserResult<syntax::LayoutQualifier> {
590   map(
591     separated_list0(
592       terminated(char(','), blank),
593       terminated(layout_qualifier_spec, blank),
594     ),
595     |ids| syntax::LayoutQualifier {
596       ids: syntax::NonEmpty(ids),
597     },
598   )(i)
601 fn layout_qualifier_spec(i: &str) -> ParserResult<syntax::LayoutQualifierSpec> {
602   alt((
603     value(syntax::LayoutQualifierSpec::Shared, keyword("shared")),
604     map(
605       separated_pair(
606         terminated(identifier, blank),
607         terminated(char('='), blank),
608         cond_expr,
609       ),
610       |(i, e)| syntax::LayoutQualifierSpec::Identifier(i, Some(Box::new(e))),
611     ),
612     map(identifier, |i| {
613       syntax::LayoutQualifierSpec::Identifier(i, None)
614     }),
615   ))(i)
618 /// Parse a precision qualifier.
619 pub fn precision_qualifier(i: &str) -> ParserResult<syntax::PrecisionQualifier> {
620   alt((
621     value(syntax::PrecisionQualifier::High, keyword("highp")),
622     value(syntax::PrecisionQualifier::Medium, keyword("mediump")),
623     value(syntax::PrecisionQualifier::Low, keyword("lowp")),
624   ))(i)
627 /// Parse an interpolation qualifier.
628 pub fn interpolation_qualifier(i: &str) -> ParserResult<syntax::InterpolationQualifier> {
629   alt((
630     value(syntax::InterpolationQualifier::Smooth, keyword("smooth")),
631     value(syntax::InterpolationQualifier::Flat, keyword("flat")),
632     value(
633       syntax::InterpolationQualifier::NoPerspective,
634       keyword("noperspective"),
635     ),
636   ))(i)
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),
654     }
655   })(i)
658 /// Parse a type qualifier spec.
659 pub fn type_qualifier_spec(i: &str) -> ParserResult<syntax::TypeQualifierSpec> {
660   alt((
661     map(storage_qualifier, syntax::TypeQualifierSpec::Storage),
662     map(layout_qualifier, syntax::TypeQualifierSpec::Layout),
663     map(precision_qualifier, syntax::TypeQualifierSpec::Precision),
664     map(
665       interpolation_qualifier,
666       syntax::TypeQualifierSpec::Interpolation,
667     ),
668     value(syntax::TypeQualifierSpec::Invariant, invariant_qualifier),
669     value(syntax::TypeQualifierSpec::Precise, precise_qualifier),
670   ))(i)
673 /// Parse a fully specified type.
674 pub fn fully_specified_type(i: &str) -> ParserResult<syntax::FullySpecifiedType> {
675   map(
676     pair(opt(type_qualifier), type_specifier),
677     |(qualifier, ty)| syntax::FullySpecifiedType { qualifier, ty },
678   )(i)
681 /// Parse an array specifier
682 pub fn array_specifier(i: &str) -> ParserResult<syntax::ArraySpecifier> {
683   map(
684     many1(delimited(blank, array_specifier_dimension, blank)),
685     |dimensions| syntax::ArraySpecifier {
686       dimensions: syntax::NonEmpty(dimensions),
687     },
688   )(i)
691 /// Parse an array specifier dimension.
692 pub fn array_specifier_dimension(i: &str) -> ParserResult<syntax::ArraySpecifierDimension> {
693   alt((
694     value(
695       syntax::ArraySpecifierDimension::Unsized,
696       delimited(char('['), blank, char(']')),
697     ),
698     map(
699       delimited(
700         terminated(char('['), blank),
701         cut(cond_expr),
702         preceded(blank, cut(char(']'))),
703       ),
704       |e| syntax::ArraySpecifierDimension::ExplicitlySized(Box::new(e)),
705     ),
706   ))(i)
709 /// Parse a primary expression.
710 pub fn primary_expr(i: &str) -> ParserResult<syntax::Expr> {
711   alt((
712     parens_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),
719   ))(i)
722 /// Parse a postfix expression.
723 pub fn postfix_expr(i: &str) -> ParserResult<syntax::Expr> {
724   let (i, e) = alt((
725     function_call_with_identifier,
726     function_call_with_expr_ident_or_expr,
727   ))(i)?;
729   postfix_part(i, e)
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> {
735   let r = alt((
736     map(preceded(blank, array_specifier), |a| {
737       syntax::Expr::Bracket(Box::new(e.clone()), a)
738     }),
739     map(preceded(blank, dot_field_selection), |i| {
740       syntax::Expr::Dot(Box::new(e.clone()), i)
741     }),
742     value(
743       syntax::Expr::PostInc(Box::new(e.clone())),
744       preceded(blank, tag("++")),
745     ),
746     value(
747       syntax::Expr::PostDec(Box::new(e.clone())),
748       preceded(blank, tag("--")),
749     ),
750   ))(i);
752   match r {
753     Ok((i, e)) => postfix_part(i, e),
754     Err(NomErr::Error(_)) => Ok((i, e)),
755     _ => r,
756   }
759 /// Parse a unary expression.
760 pub fn unary_expr(i: &str) -> ParserResult<syntax::Expr> {
761   alt((
762     map(separated_pair(unary_op, blank, unary_expr), |(op, e)| {
763       syntax::Expr::Unary(op, Box::new(e))
764     }),
765     postfix_expr,
766   ))(i)
769 /// Parse an expression between parens.
770 pub fn parens_expr(i: &str) -> ParserResult<syntax::Expr> {
771   delimited(
772     terminated(char('('), blank),
773     expr,
774     preceded(blank, cut(char(')'))),
775   )(i)
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> {
785   alt((
786     map(
787       terminated(function_prototype, terminated(blank, char(';'))),
788       syntax::Declaration::FunctionPrototype,
789     ),
790     map(
791       terminated(init_declarator_list, terminated(blank, char(';'))),
792       syntax::Declaration::InitDeclaratorList,
793     ),
794     precision_declaration,
795     block_declaration,
796     global_declaration,
797   ))(i)
800 /// Parse a precision declaration.
801 pub fn precision_declaration(i: &str) -> ParserResult<syntax::Declaration> {
802   delimited(
803     terminated(keyword("precision"), blank),
804     map(
805       cut(pair(
806         terminated(precision_qualifier, blank),
807         terminated(type_specifier, blank),
808       )),
809       |(qual, ty)| syntax::Declaration::Precision(qual, ty),
810     ),
811     char(';'),
812   )(i)
815 /// Parse a block declaration.
816 pub fn block_declaration(i: &str) -> ParserResult<syntax::Declaration> {
817   map(
818     tuple((
819       terminated(type_qualifier, blank),
820       terminated(identifier, blank),
821       delimited(
822         terminated(char('{'), blank),
823         many1(terminated(struct_field_specifier, blank)),
824         cut(terminated(char('}'), blank)),
825       ),
826       alt((
827         value(None, preceded(blank, char(';'))),
828         terminated(
829           opt(preceded(blank, arrayed_identifier)),
830           preceded(blank, cut(char(';'))),
831         ),
832       )),
833     )),
834     |(qualifier, name, fields, identifier)| {
835       syntax::Declaration::Block(syntax::Block {
836         qualifier,
837         name,
838         fields,
839         identifier,
840       })
841     },
842   )(i)
845 /// Parse a global declaration.
846 pub fn global_declaration(i: &str) -> ParserResult<syntax::Declaration> {
847   map(
848     pair(
849       terminated(type_qualifier, blank),
850       many0(delimited(terminated(char(','), blank), identifier, blank)),
851     ),
852     |(qual, idents)| syntax::Declaration::Global(qual, idents),
853   )(i)
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> {
863   map(
864     pair(
865       single_declaration,
866       many0(map(
867         tuple((
868           preceded(delimited(blank, char(','), blank), cut(identifier)),
869           opt(preceded(blank, array_specifier)),
870           opt(preceded(delimited(blank, char('='), blank), initializer)),
871         )),
872         |(name, arr_spec, init)| syntax::SingleDeclarationNoType {
873           ident: syntax::ArrayedIdentifier::new(name, arr_spec),
874           initializer: init,
875         },
876       )),
877     ),
878     |(head, tail)| syntax::InitDeclaratorList { head, tail },
879   )(i)
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();
887   alt((
888     map(
889       tuple((
890         preceded(blank, identifier),
891         opt(preceded(blank, array_specifier)),
892         opt(preceded(
893           delimited(blank, char('='), blank),
894           cut(initializer),
895         )),
896       )),
897       move |(name, array_specifier, initializer)| syntax::SingleDeclaration {
898         ty: ty_.clone(),
899         name: Some(name),
900         array_specifier,
901         initializer,
902       },
903     ),
904     cnst(syntax::SingleDeclaration {
905       ty,
906       name: None,
907       array_specifier: None,
908       initializer: None,
909     }),
910   ))(i)
913 /// Parse an initializer.
914 pub fn initializer(i: &str) -> ParserResult<syntax::Initializer> {
915   alt((
916     map(assignment_expr, |e| {
917       syntax::Initializer::Simple(Box::new(e))
918     }),
919     map(
920       delimited(
921         terminated(char('{'), blank),
922         terminated(
923           cut(initializer_list),
924           terminated(blank, opt(terminated(char(','), blank))),
925         ),
926         cut(char('}')),
927       ),
928       |il| syntax::Initializer::List(syntax::NonEmpty(il)),
929     ),
930   ))(i)
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> {
939   alt((
940     function_header_with_parameters,
941     map(function_header, |(ty, name)| syntax::FunctionPrototype {
942       ty,
943       name,
944       parameters: Vec::new(),
945     }),
946   ))(i)
949 fn function_header(i: &str) -> ParserResult<(syntax::FullySpecifiedType, syntax::Identifier)> {
950   pair(
951     terminated(fully_specified_type, blank),
952     terminated(identifier, terminated(blank, char('('))),
953   )(i)
956 fn function_header_with_parameters(i: &str) -> ParserResult<syntax::FunctionPrototype> {
957   map(
958     pair(
959       function_header,
960       separated_list0(
961         preceded(blank, char(',')),
962         preceded(blank, function_parameter_declaration),
963       ),
964     ),
965     |(header, parameters)| syntax::FunctionPrototype {
966       ty: header.0,
967       name: header.1,
968       parameters,
969     },
970   )(i)
973 fn function_parameter_declaration(i: &str) -> ParserResult<syntax::FunctionParameterDeclaration> {
974   alt((
975     function_parameter_declaration_named,
976     function_parameter_declaration_unnamed,
977   ))(i)
980 fn function_parameter_declaration_named(
981   i: &str,
982 ) -> ParserResult<syntax::FunctionParameterDeclaration> {
983   map(
984     pair(
985       opt(terminated(type_qualifier, blank)),
986       function_parameter_declarator,
987     ),
988     |(ty_qual, fpd)| syntax::FunctionParameterDeclaration::Named(ty_qual, fpd),
989   )(i)
992 fn function_parameter_declaration_unnamed(
993   i: &str,
994 ) -> ParserResult<syntax::FunctionParameterDeclaration> {
995   map(
996     pair(opt(terminated(type_qualifier, blank)), type_specifier),
997     |(ty_qual, ty_spec)| syntax::FunctionParameterDeclaration::Unnamed(ty_qual, ty_spec),
998   )(i)
1001 fn function_parameter_declarator(i: &str) -> ParserResult<syntax::FunctionParameterDeclarator> {
1002   map(
1003     tuple((
1004       terminated(type_specifier, blank),
1005       terminated(identifier, blank),
1006       opt(array_specifier),
1007     )),
1008     |(ty, name, a)| syntax::FunctionParameterDeclarator {
1009       ty,
1010       ident: syntax::ArrayedIdentifier::new(name, a),
1011     },
1012   )(i)
1015 fn function_call_with_identifier(i: &str) -> ParserResult<syntax::Expr> {
1016   map(
1017     tuple((function_identifier_identifier, function_call_args)),
1018     |(fi, args)| syntax::Expr::FunCall(fi, args),
1019   )(i)
1022 fn function_call_with_expr_ident_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1023   map(
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(),
1028     },
1029   )(i)
1032 fn function_call_args(i: &str) -> ParserResult<Vec<syntax::Expr>> {
1033   preceded(
1034     terminated(terminated(blank, char('(')), blank),
1035     alt((
1036       map(
1037         terminated(blank, terminated(opt(void), terminated(blank, char(')')))),
1038         |_| vec![],
1039       ),
1040       terminated(
1041         separated_list0(
1042           terminated(char(','), blank),
1043           cut(terminated(assignment_expr, blank)),
1044         ),
1045         cut(char(')')),
1046       ),
1047     )),
1048   )(i)
1051 fn function_identifier_identifier(i: &str) -> ParserResult<syntax::FunIdentifier> {
1052   map(
1053     terminated(identifier, terminated(blank, peek(char('(')))),
1054     syntax::FunIdentifier::Identifier,
1055   )(i)
1058 fn function_identifier_expr(i: &str) -> ParserResult<syntax::FunIdentifier> {
1059   (|i| {
1060     let (i, e) = primary_expr(i)?;
1061     postfix_part(i, e).map(|(i, pfe)| (i, syntax::FunIdentifier::Expr(Box::new(pfe))))
1062   })(i)
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();
1075   alt((
1076     map(preceded(terminated(char(','), blank), expr), move |next| {
1077       syntax::Expr::Comma(Box::new(first_.clone()), Box::new(next))
1078     }),
1079     cnst(first),
1080   ))(i)
1083 /// Parse an assignment expression.
1084 pub fn assignment_expr(i: &str) -> ParserResult<syntax::Expr> {
1085   alt((
1086     map(
1087       tuple((
1088         terminated(unary_expr, blank),
1089         terminated(assignment_op, blank),
1090         assignment_expr,
1091       )),
1092       |(e, o, v)| syntax::Expr::Assignment(Box::new(e), o, Box::new(v)),
1093     ),
1094     cond_expr,
1095   ))(i)
1098 /// Parse an assignment operator.
1099 pub fn assignment_op(i: &str) -> ParserResult<syntax::AssignmentOp> {
1100   alt((
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("|=")),
1112   ))(i)
1115 /// Parse a conditional expression.
1116 pub fn cond_expr(i: &str) -> ParserResult<syntax::Expr> {
1117   let (i, a) = logical_or_expr(i)?;
1119   fold_many0(
1120     tuple((
1121       delimited(blank, char('?'), blank),
1122       cut(terminated(expr, blank)),
1123       cut(terminated(char(':'), blank)),
1124       cut(assignment_expr),
1125     )),
1126     move || a.clone(),
1127     move |acc, (_, b, _, c)| syntax::Expr::Ternary(Box::new(acc), Box::new(b), Box::new(c)),
1128   )(i)
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)?;
1135   fold_many0(
1136     preceded(delimited(blank, tag("||"), blank), logical_xor_expr),
1137     move || a.clone(),
1138     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::Or, Box::new(acc), Box::new(b)),
1139   )(i)
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)?;
1146   fold_many0(
1147     preceded(delimited(blank, tag("^^"), blank), logical_and_expr),
1148     move || a.clone(),
1149     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::Xor, Box::new(acc), Box::new(b)),
1150   )(i)
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)?;
1157   fold_many0(
1158     preceded(delimited(blank, tag("&&"), blank), inclusive_or_expr),
1159     move || a.clone(),
1160     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::And, Box::new(acc), Box::new(b)),
1161   )(i)
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)?;
1168   fold_many0(
1169     preceded(delimited(blank, char('|'), blank), inclusive_or_expr),
1170     move || a.clone(),
1171     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitOr, Box::new(acc), Box::new(b)),
1172   )(i)
1175 /// Parse a bitwise XOR expression.
1176 pub fn exclusive_or_expr(i: &str) -> ParserResult<syntax::Expr> {
1177   let (i, a) = and_expr(i)?;
1179   fold_many0(
1180     preceded(delimited(blank, char('^'), blank), exclusive_or_expr),
1181     move || a.clone(),
1182     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitXor, Box::new(acc), Box::new(b)),
1183   )(i)
1186 /// Parse a bitwise AND expression.
1187 pub fn and_expr(i: &str) -> ParserResult<syntax::Expr> {
1188   let (i, a) = equality_expr(i)?;
1190   fold_many0(
1191     preceded(delimited(blank, char('&'), blank), and_expr),
1192     move || a.clone(),
1193     move |acc, b| syntax::Expr::Binary(syntax::BinaryOp::BitAnd, Box::new(acc), Box::new(b)),
1194   )(i)
1197 /// Parse an equality expression.
1198 pub fn equality_expr(i: &str) -> ParserResult<syntax::Expr> {
1199   let (i, a) = rel_expr(i)?;
1201   fold_many0(
1202     pair(
1203       delimited(
1204         blank,
1205         alt((
1206           value(syntax::BinaryOp::Equal, tag("==")),
1207           value(syntax::BinaryOp::NonEqual, tag("!=")),
1208         )),
1209         blank,
1210       ),
1211       rel_expr,
1212     ),
1213     move || a.clone(),
1214     move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1215   )(i)
1218 /// Parse a relational expression.
1219 pub fn rel_expr(i: &str) -> ParserResult<syntax::Expr> {
1220   let (i, a) = shift_expr(i)?;
1222   fold_many0(
1223     pair(
1224       delimited(
1225         blank,
1226         alt((
1227           value(syntax::BinaryOp::LTE, tag("<=")),
1228           value(syntax::BinaryOp::GTE, tag(">=")),
1229           value(syntax::BinaryOp::LT, char('<')),
1230           value(syntax::BinaryOp::GT, char('>')),
1231         )),
1232         blank,
1233       ),
1234       shift_expr,
1235     ),
1236     move || a.clone(),
1237     move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1238   )(i)
1241 /// Parse a shift expression.
1242 pub fn shift_expr(i: &str) -> ParserResult<syntax::Expr> {
1243   let (i, a) = additive_expr(i)?;
1245   fold_many0(
1246     pair(
1247       delimited(
1248         blank,
1249         alt((
1250           value(syntax::BinaryOp::LShift, tag("<<")),
1251           value(syntax::BinaryOp::RShift, tag(">>")),
1252         )),
1253         blank,
1254       ),
1255       additive_expr,
1256     ),
1257     move || a.clone(),
1258     move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1259   )(i)
1262 /// Parse an additive expression.
1263 pub fn additive_expr(i: &str) -> ParserResult<syntax::Expr> {
1264   let (i, a) = multiplicative_expr(i)?;
1266   fold_many0(
1267     pair(
1268       delimited(
1269         blank,
1270         alt((
1271           value(syntax::BinaryOp::Add, char('+')),
1272           value(syntax::BinaryOp::Sub, char('-')),
1273         )),
1274         blank,
1275       ),
1276       multiplicative_expr,
1277     ),
1278     move || a.clone(),
1279     move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1280   )(i)
1283 /// Parse a multiplicative expression.
1284 pub fn multiplicative_expr(i: &str) -> ParserResult<syntax::Expr> {
1285   let (i, a) = unary_expr(i)?;
1287   fold_many0(
1288     pair(
1289       delimited(
1290         blank,
1291         alt((
1292           value(syntax::BinaryOp::Mult, char('*')),
1293           value(syntax::BinaryOp::Div, char('/')),
1294           value(syntax::BinaryOp::Mod, char('%')),
1295         )),
1296         blank,
1297       ),
1298       unary_expr,
1299     ),
1300     move || a.clone(),
1301     move |acc, (op, b)| syntax::Expr::Binary(op, Box::new(acc), Box::new(b)),
1302   )(i)
1305 /// Parse a simple statement.
1306 pub fn simple_statement(i: &str) -> ParserResult<syntax::SimpleStatement> {
1307   alt((
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),
1315   ))(i)
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> {
1325   map(
1326     tuple((
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),
1332     )),
1333     |(_, _, cond_expr, _, rest)| syntax::SelectionStatement {
1334       cond: Box::new(cond_expr),
1335       rest,
1336     },
1337   )(i)
1340 fn selection_rest_statement(i: &str) -> ParserResult<syntax::SelectionRestStatement> {
1341   let (i, st) = statement(i)?;
1342   let st_ = st.clone();
1344   alt((
1345     map(
1346       preceded(delimited(blank, keyword("else"), blank), cut(statement)),
1347       move |rest| syntax::SelectionRestStatement::Else(Box::new(st_.clone()), Box::new(rest)),
1348     ),
1349     cnst(syntax::SelectionRestStatement::Statement(Box::new(st))),
1350   ))(i)
1353 /// Parse a switch statement.
1354 pub fn switch_statement(i: &str) -> ParserResult<syntax::SwitchStatement> {
1355   map(
1356     tuple((
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))),
1363       cut(char('}')),
1364     )),
1365     |(_, _, head, _, _, body, _)| syntax::SwitchStatement {
1366       head: Box::new(head),
1367       body,
1368     },
1369   )(i)
1372 /// Parse a case label.
1373 pub fn case_label(i: &str) -> ParserResult<syntax::CaseLabel> {
1374   alt((
1375     map(
1376       delimited(
1377         terminated(keyword("case"), blank),
1378         cut(terminated(expr, blank)),
1379         cut(char(':')),
1380       ),
1381       |e| syntax::CaseLabel::Case(Box::new(e)),
1382     ),
1383     value(
1384       syntax::CaseLabel::Def,
1385       preceded(terminated(keyword("default"), blank), char(':')),
1386     ),
1387   ))(i)
1390 /// Parse an iteration statement.
1391 pub fn iteration_statement(i: &str) -> ParserResult<syntax::IterationStatement> {
1392   alt((
1393     iteration_statement_while,
1394     iteration_statement_do_while,
1395     iteration_statement_for,
1396   ))(i)
1399 /// Parse a while statement.
1400 pub fn iteration_statement_while(i: &str) -> ParserResult<syntax::IterationStatement> {
1401   map(
1402     tuple((
1403       terminated(keyword("while"), blank),
1404       cut(terminated(char('('), blank)),
1405       cut(terminated(condition, blank)),
1406       cut(terminated(char(')'), blank)),
1407       cut(statement),
1408     )),
1409     |(_, _, cond, _, st)| syntax::IterationStatement::While(cond, Box::new(st)),
1410   )(i)
1413 /// Parse a while statement.
1414 pub fn iteration_statement_do_while(i: &str) -> ParserResult<syntax::IterationStatement> {
1415   map(
1416     tuple((
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)),
1423       cut(char(';')),
1424     )),
1425     |(_, st, _, _, e, _, _)| syntax::IterationStatement::DoWhile(Box::new(st), Box::new(e)),
1426   )(i)
1429 // Parse a for statement.
1430 pub fn iteration_statement_for(i: &str) -> ParserResult<syntax::IterationStatement> {
1431   map(
1432     tuple((
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)),
1438       cut(statement),
1439     )),
1440     |(_, _, head, rest, _, body)| syntax::IterationStatement::For(head, rest, Box::new(body)),
1441   )(i)
1444 fn iteration_statement_for_init_statement(i: &str) -> ParserResult<syntax::ForInitStatement> {
1445   alt((
1446     map(expr_statement, syntax::ForInitStatement::Expression),
1447     map(declaration, |d| {
1448       syntax::ForInitStatement::Declaration(Box::new(d))
1449     }),
1450   ))(i)
1453 fn iteration_statement_for_rest_statement(i: &str) -> ParserResult<syntax::ForRestStatement> {
1454   map(
1455     separated_pair(
1456       opt(terminated(condition, blank)),
1457       terminated(char(';'), blank),
1458       opt(expr),
1459     ),
1460     |(condition, e)| syntax::ForRestStatement {
1461       condition,
1462       post_expr: e.map(Box::new),
1463     },
1464   )(i)
1467 /// Parse a jump statement.
1468 pub fn jump_statement(i: &str) -> ParserResult<syntax::JumpStatement> {
1469   alt((
1470     jump_statement_continue,
1471     jump_statement_break,
1472     jump_statement_return,
1473     jump_statement_discard,
1474   ))(i)
1477 // Parse a continue statement.
1478 pub fn jump_statement_continue(i: &str) -> ParserResult<syntax::JumpStatement> {
1479   value(
1480     syntax::JumpStatement::Continue,
1481     terminated(keyword("continue"), cut(terminated(blank, char(';')))),
1482   )(i)
1485 // Parse a break statement.
1486 pub fn jump_statement_break(i: &str) -> ParserResult<syntax::JumpStatement> {
1487   value(
1488     syntax::JumpStatement::Break,
1489     terminated(keyword("break"), cut(terminated(blank, char(';')))),
1490   )(i)
1493 // Parse a discard statement.
1494 pub fn jump_statement_discard(i: &str) -> ParserResult<syntax::JumpStatement> {
1495   value(
1496     syntax::JumpStatement::Discard,
1497     terminated(keyword("discard"), cut(terminated(blank, char(';')))),
1498   )(i)
1501 // Parse a return statement.
1502 pub fn jump_statement_return(i: &str) -> ParserResult<syntax::JumpStatement> {
1503   map(
1504     delimited(
1505       terminated(keyword("return"), blank),
1506       opt(terminated(expr, blank)),
1507       cut(char(';')),
1508     ),
1509     |e| syntax::JumpStatement::Return(e.map(|e| Box::new(e))),
1510   )(i)
1513 /// Parse a condition.
1514 pub fn condition(i: &str) -> ParserResult<syntax::Condition> {
1515   alt((
1516     map(expr, |e| syntax::Condition::Expr(Box::new(e))),
1517     condition_assignment,
1518   ))(i)
1521 fn condition_assignment(i: &str) -> ParserResult<syntax::Condition> {
1522   map(
1523     tuple((
1524       terminated(fully_specified_type, blank),
1525       terminated(identifier, blank),
1526       terminated(char('='), blank),
1527       cut(initializer),
1528     )),
1529     |(ty, id, _, ini)| syntax::Condition::Assignment(ty, id, ini),
1530   )(i)
1533 /// Parse a statement.
1534 pub fn statement(i: &str) -> ParserResult<syntax::Statement> {
1535   alt((
1536     map(compound_statement, |c| {
1537       syntax::Statement::Compound(Box::new(c))
1538     }),
1539     map(simple_statement, |s| syntax::Statement::Simple(Box::new(s))),
1540   ))(i)
1543 /// Parse a compound statement.
1544 pub fn compound_statement(i: &str) -> ParserResult<syntax::CompoundStatement> {
1545   map(
1546     delimited(
1547       terminated(char('{'), blank),
1548       many0(terminated(statement, blank)),
1549       cut(char('}')),
1550     ),
1551     |statement_list| syntax::CompoundStatement { statement_list },
1552   )(i)
1555 /// Parse a function definition.
1556 pub fn function_definition(i: &str) -> ParserResult<syntax::FunctionDefinition> {
1557   map(
1558     pair(terminated(function_prototype, blank), compound_statement),
1559     |(prototype, statement)| syntax::FunctionDefinition {
1560       prototype,
1561       statement,
1562     },
1563   )(i)
1566 /// Parse an external declaration.
1567 pub fn external_declaration(i: &str) -> ParserResult<syntax::ExternalDeclaration> {
1568   alt((
1569     map(preprocessor, syntax::ExternalDeclaration::Preprocessor),
1570     map(
1571       function_definition,
1572       syntax::ExternalDeclaration::FunctionDefinition,
1573     ),
1574     map(declaration, syntax::ExternalDeclaration::Declaration),
1575     preceded(
1576       delimited(blank, char(';'), blank),
1577       cut(external_declaration),
1578     ),
1579   ))(i)
1582 /// Parse a translation unit (entry point).
1583 pub fn translation_unit(i: &str) -> ParserResult<syntax::TranslationUnit> {
1584   map(
1585     many1(delimited(blank, external_declaration, blank)),
1586     |eds| syntax::TranslationUnit(syntax::NonEmpty(eds)),
1587   )(i)
1590 /// Parse a preprocessor directive.
1591 pub fn preprocessor(i: &str) -> ParserResult<syntax::Preprocessor> {
1592   preceded(
1593     terminated(char('#'), pp_space0),
1594     cut(alt((
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),
1609     ))),
1610   )(i)
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> {
1620   alt((
1621     value(syntax::PreprocessorVersionProfile::Core, keyword("core")),
1622     value(
1623       syntax::PreprocessorVersionProfile::Compatibility,
1624       keyword("compatibility"),
1625     ),
1626     value(syntax::PreprocessorVersionProfile::ES, keyword("es")),
1627   ))(i)
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))),
1641     |(_, ident)| ident,
1642   )(i)?;
1644   alt((
1645     pp_define_function_like(ident.clone()),
1646     pp_define_object_like(ident),
1647   ))(i)
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> {
1654   move |i| {
1655     map(preceded(pp_space0, cut(str_till_eol)), |value| {
1656       syntax::PreprocessorDefine::ObjectLike {
1657         ident: ident.clone(),
1658         value: value.to_owned(),
1659       }
1660     })(i)
1661   }
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> {
1668   move |i| {
1669     map(
1670       tuple((
1671         terminated(char('('), pp_space0),
1672         separated_list0(
1673           terminated(char(','), pp_space0),
1674           cut(terminated(identifier, pp_space0)),
1675         ),
1676         cut(terminated(char(')'), pp_space0)),
1677         cut(map(str_till_eol, String::from)),
1678       )),
1679       |(_, args, _, value)| syntax::PreprocessorDefine::FunctionLike {
1680         ident: ident.clone(),
1681         args,
1682         value,
1683       },
1684     )(i)
1685   }
1688 /// Parse a preprocessor else.
1689 pub(crate) fn pp_else(i: &str) -> ParserResult<syntax::Preprocessor> {
1690   value(
1691     syntax::Preprocessor::Else,
1692     tuple((terminated(keyword("else"), pp_space0), cut(eol))),
1693   )(i)
1696 /// Parse a preprocessor elseif.
1697 pub(crate) fn pp_elseif(i: &str) -> ParserResult<syntax::PreprocessorElseIf> {
1698   map(
1699     tuple((
1700       terminated(keyword("elseif"), pp_space0),
1701       cut(map(str_till_eol, String::from)),
1702     )),
1703     |(_, condition)| syntax::PreprocessorElseIf { condition },
1704   )(i)
1707 /// Parse a preprocessor endif.
1708 pub(crate) fn pp_endif(i: &str) -> ParserResult<syntax::Preprocessor> {
1709   map(
1710     tuple((terminated(keyword("endif"), space0), cut(eol))),
1711     |(_, _)| syntax::Preprocessor::EndIf,
1712   )(i)
1715 /// Parse a preprocessor error.
1716 pub(crate) fn pp_error(i: &str) -> ParserResult<syntax::PreprocessorError> {
1717   map(
1718     tuple((terminated(keyword("error"), pp_space0), cut(str_till_eol))),
1719     |(_, message)| syntax::PreprocessorError {
1720       message: message.to_owned(),
1721     },
1722   )(i)
1725 /// Parse a preprocessor if.
1726 pub(crate) fn pp_if(i: &str) -> ParserResult<syntax::PreprocessorIf> {
1727   map(
1728     tuple((
1729       terminated(keyword("if"), pp_space0),
1730       cut(map(str_till_eol, String::from)),
1731     )),
1732     |(_, condition)| syntax::PreprocessorIf { condition },
1733   )(i)
1736 /// Parse a preprocessor ifdef.
1737 pub(crate) fn pp_ifdef(i: &str) -> ParserResult<syntax::PreprocessorIfDef> {
1738   map(
1739     tuple((
1740       terminated(keyword("ifdef"), pp_space0),
1741       cut(terminated(identifier, pp_space0)),
1742       eol,
1743     )),
1744     |(_, ident, _)| syntax::PreprocessorIfDef { ident },
1745   )(i)
1748 /// Parse a preprocessor ifndef.
1749 pub(crate) fn pp_ifndef(i: &str) -> ParserResult<syntax::PreprocessorIfNDef> {
1750   map(
1751     tuple((
1752       terminated(keyword("ifndef"), pp_space0),
1753       cut(terminated(identifier, pp_space0)),
1754       eol,
1755     )),
1756     |(_, ident, _)| syntax::PreprocessorIfNDef { ident },
1757   )(i)
1760 /// Parse a preprocessor include.
1761 pub(crate) fn pp_include(i: &str) -> ParserResult<syntax::PreprocessorInclude> {
1762   map(
1763     tuple((
1764       terminated(keyword("include"), pp_space0),
1765       cut(terminated(path_lit, pp_space0)),
1766       cut(eol),
1767     )),
1768     |(_, path, _)| syntax::PreprocessorInclude { path },
1769   )(i)
1772 /// Parse a preprocessor line.
1773 pub(crate) fn pp_line(i: &str) -> ParserResult<syntax::PreprocessorLine> {
1774   map(
1775     tuple((
1776       terminated(keyword("line"), pp_space0),
1777       cut(terminated(integral_lit, pp_space0)),
1778       opt(terminated(integral_lit, pp_space0)),
1779       cut(eol),
1780     )),
1781     |(_, line, source_string_number, _)| syntax::PreprocessorLine {
1782       line: line as u32,
1783       source_string_number: source_string_number.map(|n| n as u32),
1784     },
1785   )(i)
1788 /// Parse a preprocessor pragma.
1789 pub(crate) fn pp_pragma(i: &str) -> ParserResult<syntax::PreprocessorPragma> {
1790   map(
1791     tuple((terminated(keyword("pragma"), pp_space0), cut(str_till_eol))),
1792     |(_, command)| syntax::PreprocessorPragma {
1793       command: command.to_owned(),
1794     },
1795   )(i)
1798 /// Parse a preprocessor undef.
1799 pub(crate) fn pp_undef(i: &str) -> ParserResult<syntax::PreprocessorUndef> {
1800   map(
1801     tuple((
1802       terminated(keyword("undef"), pp_space0),
1803       cut(terminated(identifier, pp_space0)),
1804       eol,
1805     )),
1806     |(_, name, _)| syntax::PreprocessorUndef { name },
1807   )(i)
1810 /// Parse a preprocessor version.
1811 pub(crate) fn pp_version(i: &str) -> ParserResult<syntax::PreprocessorVersion> {
1812   map(
1813     tuple((
1814       terminated(keyword("version"), pp_space0),
1815       cut(terminated(pp_version_number, pp_space0)),
1816       opt(terminated(pp_version_profile, pp_space0)),
1817       cut(eol),
1818     )),
1819     |(_, version, profile, _)| syntax::PreprocessorVersion { version, profile },
1820   )(i)
1823 /// Parse a preprocessor extension name.
1824 pub(crate) fn pp_extension_name(i: &str) -> ParserResult<syntax::PreprocessorExtensionName> {
1825   alt((
1826     value(syntax::PreprocessorExtensionName::All, keyword("all")),
1827     map(string, syntax::PreprocessorExtensionName::Specific),
1828   ))(i)
1831 /// Parse a preprocessor extension behavior.
1832 pub(crate) fn pp_extension_behavior(
1833   i: &str,
1834 ) -> ParserResult<syntax::PreprocessorExtensionBehavior> {
1835   alt((
1836     value(
1837       syntax::PreprocessorExtensionBehavior::Require,
1838       keyword("require"),
1839     ),
1840     value(
1841       syntax::PreprocessorExtensionBehavior::Enable,
1842       keyword("enable"),
1843     ),
1844     value(syntax::PreprocessorExtensionBehavior::Warn, keyword("warn")),
1845     value(
1846       syntax::PreprocessorExtensionBehavior::Disable,
1847       keyword("disable"),
1848     ),
1849   ))(i)
1852 /// Parse a preprocessor extension.
1853 pub(crate) fn pp_extension(i: &str) -> ParserResult<syntax::PreprocessorExtension> {
1854   map(
1855     tuple((
1856       terminated(keyword("extension"), pp_space0),
1857       cut(terminated(pp_extension_name, pp_space0)),
1858       opt(preceded(
1859         terminated(char(':'), pp_space0),
1860         cut(terminated(pp_extension_behavior, pp_space0)),
1861       )),
1862       cut(eol),
1863     )),
1864     |(_, name, behavior, _)| syntax::PreprocessorExtension { name, behavior },
1865   )(i)