reader/wgsl: Add support for block comments
Handles nested block comments.
Allow unterminated block comments at EOF, as it is not clear whether
WGSL will allow this or not.
Bug: tint:881
Change-Id: Ieae4e0073dab69f773adb32018a9bdaf4f352116
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59180
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc
index dffed2e..c4eed5f 100644
--- a/src/reader/wgsl/lexer.cc
+++ b/src/reader/wgsl/lexer.cc
@@ -135,13 +135,43 @@
}
void Lexer::skip_comments() {
- if (!matches(pos_, "//")) {
+ if (matches(pos_, "//")) {
+ // Line comment: ignore everything until the end of line.
+ while (!is_eof() && !matches(pos_, "\n")) {
+ pos_++;
+ location_.column++;
+ }
return;
}
- while (!is_eof() && !matches(pos_, "\n")) {
- pos_++;
- location_.column++;
+ if (matches(pos_, "/*")) {
+ // Block comment: ignore everything until the closing '*/' token.
+ pos_ += 2;
+ location_.column += 2;
+
+ int depth = 1;
+ while (!is_eof() && depth > 0) {
+ if (matches(pos_, "/*")) {
+ // Start of block comment: increase nesting depth.
+ pos_ += 2;
+ location_.column += 2;
+ depth++;
+ } else if (matches(pos_, "*/")) {
+ // End of block comment: decrease nesting depth.
+ pos_ += 2;
+ location_.column += 2;
+ depth--;
+ } else if (matches(pos_, "\n")) {
+ // Newline: skip and update source location.
+ pos_++;
+ location_.line++;
+ location_.column = 1;
+ } else {
+ // Anything else: skip and update source location.
+ pos_++;
+ location_.column++;
+ }
+ }
}
}
diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc
index 52a6f1b..b134bc0 100644
--- a/src/reader/wgsl/lexer_test.cc
+++ b/src/reader/wgsl/lexer_test.cc
@@ -48,7 +48,7 @@
EXPECT_TRUE(t.IsEof());
}
-TEST_F(LexerTest, Skips_Comments) {
+TEST_F(LexerTest, Skips_Comments_Line) {
Source::FileContent content(R"(//starts with comment
ident1 //ends with comment
// blank line
@@ -75,6 +75,41 @@
EXPECT_TRUE(t.IsEof());
}
+TEST_F(LexerTest, Skips_Comments_Block) {
+ Source::FileContent content(R"(/* comment
+text */ident)");
+ Lexer l("test.wgsl", &content);
+
+ auto t = l.next();
+ EXPECT_TRUE(t.IsIdentifier());
+ EXPECT_EQ(t.source().range.begin.line, 2u);
+ EXPECT_EQ(t.source().range.begin.column, 8u);
+ EXPECT_EQ(t.source().range.end.line, 2u);
+ EXPECT_EQ(t.source().range.end.column, 13u);
+ EXPECT_EQ(t.to_str(), "ident");
+
+ t = l.next();
+ EXPECT_TRUE(t.IsEof());
+}
+
+TEST_F(LexerTest, Skips_Comments_Block_Nested) {
+ Source::FileContent content(R"(/* comment
+text // nested line comments are ignored /* more text
+/////**/ */*/ident)");
+ Lexer l("test.wgsl", &content);
+
+ auto t = l.next();
+ EXPECT_TRUE(t.IsIdentifier());
+ EXPECT_EQ(t.source().range.begin.line, 3u);
+ EXPECT_EQ(t.source().range.begin.column, 14u);
+ EXPECT_EQ(t.source().range.end.line, 3u);
+ EXPECT_EQ(t.source().range.end.column, 19u);
+ EXPECT_EQ(t.to_str(), "ident");
+
+ t = l.next();
+ EXPECT_TRUE(t.IsEof());
+}
+
struct FloatData {
const char* input;
float result;
diff --git a/src/reader/wgsl/parser_impl_test.cc b/src/reader/wgsl/parser_impl_test.cc
index a7ba36e..588967e 100644
--- a/src/reader/wgsl/parser_impl_test.cc
+++ b/src/reader/wgsl/parser_impl_test.cc
@@ -48,6 +48,26 @@
EXPECT_EQ(p->error(), "2:15: unable to determine function return type");
}
+TEST_F(ParserImplTest, Comments) {
+ auto p = parser(R"(
+/**
+ * Here is my shader.
+ *
+ * /* I can nest /**/ comments. */
+ * // I can nest line comments too.
+ **/
+[[stage(fragment)]] // This is the stage
+fn main(/*
+no
+parameters
+*/) -> [[location(0)]] vec4<f32> {
+ return/*block_comments_delimit_tokens*/vec4<f32>(.4, .2, .3, 1);
+}/* unterminated block comments are OK at EOF...)");
+
+ ASSERT_TRUE(p->Parse()) << p->error();
+ ASSERT_EQ(1u, p->program().AST().Functions().size());
+}
+
TEST_F(ParserImplTest, GetRegisteredType) {
auto p = parser("");
auto* alias = create<ast::Alias>(Sym("my_alias"), ty.i32());