From 842079a3cd7528282d6ccc2a991f894bcaea4bf2 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Thu, 1 Oct 2020 12:31:16 +0000 Subject: [PATCH] [glsl-in] Handle spacing for preproces directives --- src/front/glsl/lex.rs | 29 ++++++++++++++++++++--------- src/front/glsl/parser_tests.rs | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/front/glsl/lex.rs b/src/front/glsl/lex.rs index 6502bbb5aa..f0b9e6b95a 100644 --- a/src/front/glsl/lex.rs +++ b/src/front/glsl/lex.rs @@ -16,7 +16,7 @@ fn consume_any(input: &str, what: impl Fn(char) -> bool) -> (&str, &str, usize) (o, i, pos) } -pub fn consume_token(mut input: &str) -> (Option, &str) { +pub fn consume_token(mut input: &str, start_of_line: bool) -> (Option, &str) { let start = input .find(|c: char| !c.is_whitespace()) .unwrap_or_else(|| input.chars().count()); @@ -246,13 +246,21 @@ pub fn consume_token(mut input: &str) -> (Option, &str) { } } '#' => { - input = chars.as_str(); - let (word, rest, pos) = consume_any(input, |c| c.is_alphanumeric() || c == '_'); - meta.chars.end = start + 1 + pos; - match word { - "version" => (Some(Token::Version(meta)), rest), - _ => (None, input), - } + if start_of_line { + input = chars.as_str(); + + // skip whitespace + let word_start = input + .find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| input.chars().count()); + input = &input[word_start..]; + + let (word, rest, pos) = consume_any(input, |c| c.is_alphanumeric() || c == '_'); + meta.chars.end = start + word_start + 1 + pos; + match word { + "version" => (Some(Token::Version(meta)), rest), + _ => (None, input), + } //TODO: preprocessor // if chars.next() == Some(cur) { @@ -260,6 +268,9 @@ pub fn consume_token(mut input: &str) -> (Option, &str) { // } else { // (Token::Preprocessor, input, start, start + 1) // } + } else { + (Some(Token::Unknown((meta, '#'))), chars.as_str()) + } } '~' => (Some(Token::Tilde(meta)), chars.as_str()), '?' => (Some(Token::Question(meta)), chars.as_str()), @@ -302,7 +313,7 @@ impl<'a> Lexer<'a> { #[must_use] pub fn next(&mut self) -> Option { - let (token, rest) = consume_token(&self.input); + let (token, rest) = consume_token(&self.input, self.offset == 0); if let Some(mut token) = token { self.input = String::from(rest); diff --git a/src/front/glsl/parser_tests.rs b/src/front/glsl/parser_tests.rs index 14db86fda0..77cdac5571 100644 --- a/src/front/glsl/parser_tests.rs +++ b/src/front/glsl/parser_tests.rs @@ -49,7 +49,23 @@ fn version() { "InvalidProfile(TokenMetadata { line: 0, chars: 13..18 }, \"smart\")" ); + assert_eq!( + format!( + "{:?}", + parse_program("#version 450\nvoid f(){} #version 450", ShaderStage::Vertex) + .err() + .unwrap() + ), + "InvalidToken(Unknown((TokenMetadata { line: 1, chars: 11..12 }, \'#\')))" + ); + // valid versions + let program = parse_program(" # version 450\nvoid main() {}", ShaderStage::Vertex).unwrap(); + assert_eq!( + format!("{:?}", (program.version, program.profile)), + "(450, Core)" + ); + let program = parse_program("#version 450\nvoid main() {}", ShaderStage::Vertex).unwrap(); assert_eq!( format!("{:?}", (program.version, program.profile)),