diff --git a/src/front/glsl/lex.rs b/src/front/glsl/lex.rs index ecbd4f0828..e5412c8a8d 100644 --- a/src/front/glsl/lex.rs +++ b/src/front/glsl/lex.rs @@ -93,8 +93,20 @@ impl<'a> Lexer<'a> { } } '0'..='9' => { - let (number, remainder, pos) = - consume_any(input, |c| (('0'..='9').contains(&c) || c == '.')); + let next = chars.next().and_then(|c| c.to_lowercase().next()); + + let hexadecimal = cur == '0' && next.map_or(false, |c| c == 'x'); + + let (number, remainder, pos) = if hexadecimal { + consume_any(&input[2..], |c| { + ('0'..='9').contains(&c) + || ('a'..='f').contains(&c) + || ('A'..='F').contains(&c) + }) + } else { + consume_any(input, |c| (('0'..='9').contains(&c) || c == '.')) + }; + let mut remainder_chars = remainder.chars(); let first = remainder_chars.next().and_then(|c| c.to_lowercase().next()); @@ -109,8 +121,22 @@ impl<'a> Lexer<'a> { Some(Token::FloatConstant((meta, number.parse().unwrap()))) } } else if first == Some('u') { - meta.chars.end = start + pos + 1; - Some(Token::UintConstant((meta, number.parse().unwrap()))) + if hexadecimal { + meta.chars.end = start + pos + 3; + Some(Token::UintConstant(( + meta, + u64::from_str_radix(number, 16).unwrap(), + ))) + } else { + meta.chars.end = start + pos + 1; + Some(Token::UintConstant((meta, number.parse().unwrap()))) + } + } else if hexadecimal { + meta.chars.end = start + pos + 2; + Some(Token::IntConstant(( + meta, + i64::from_str_radix(number, 16).unwrap(), + ))) } else { meta.chars.end = start + pos; Some(Token::IntConstant((meta, number.parse().unwrap()))) diff --git a/src/front/glsl/lex_tests.rs b/src/front/glsl/lex_tests.rs index 74bc4a0ed0..7a4e15f52e 100644 --- a/src/front/glsl/lex_tests.rs +++ b/src/front/glsl/lex_tests.rs @@ -389,7 +389,7 @@ fn tokens() { assert_eq!(lex.next(), None); // Integer constants - let mut lex = Lexer::new("120 130u 140U 150"); + let mut lex = Lexer::new("120 130u 140U 150 0x1f 0xf2U 0xF1u"); assert_eq!( lex.next().unwrap(), IntConstant(( @@ -430,5 +430,35 @@ fn tokens() { 150, )) ); + assert_eq!( + lex.next().unwrap(), + IntConstant(( + TokenMetadata { + line: 0, + chars: 18..22 + }, + 31, + )) + ); + assert_eq!( + lex.next().unwrap(), + UintConstant(( + TokenMetadata { + line: 0, + chars: 23..28 + }, + 242, + )) + ); + assert_eq!( + lex.next().unwrap(), + UintConstant(( + TokenMetadata { + line: 0, + chars: 29..34 + }, + 241, + )) + ); assert_eq!(lex.next(), None); }