| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Unit tests for VerilogLexer (from verilog.lex) |
| #include "verilog/parser/verilog_lexer.h" |
| |
| #include <initializer_list> |
| #include <utility> |
| |
| #include "absl/strings/string_view.h" |
| #include "common/lexer/lexer_test_util.h" |
| #include "common/text/token_info.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "verilog/parser/verilog_token_enum.h" |
| |
| namespace verilog { |
| namespace { |
| |
| using testing::ElementsAre; |
| using verible::TokenInfo; |
| |
| // Removes non-essential tokens from token output stream, such as spaces. |
| class FilteredVerilogLexer : public VerilogLexer { |
| public: |
| explicit FilteredVerilogLexer(absl::string_view code) : VerilogLexer(code) {} |
| |
| const TokenInfo& DoNextToken() final { |
| do { |
| VerilogLexer::DoNextToken(); |
| } while (!VerilogLexer::KeepSyntaxTreeTokens(GetLastToken())); |
| return GetLastToken(); |
| } |
| }; |
| |
| // Some tests work on filtered tokens, others check unfiltered tokens. |
| // TODO(b/139743437): Upgrade GenericTestDataSequence to LexerTestData. |
| using verible::GenericTestDataSequence; |
| using verible::SimpleTestData; |
| using LexerTestData = verible::SynthesizedLexerTestData; |
| |
| // Forwarding function to the template test driver function. |
| template <typename... Args> |
| static void TestLexer(Args&&... args) { |
| verible::TestLexer<VerilogLexer>(std::forward<Args>(args)...); |
| } |
| |
| // Forwarding function to the template test driver function. |
| template <typename... Args> |
| static void TestFilteredLexer(Args&&... args) { |
| verible::TestLexer<FilteredVerilogLexer>(std::forward<Args>(args)...); |
| } |
| |
| static std::initializer_list<LexerTestData> kCommentTests = { |
| {{TK_COMMENT_BLOCK, "/**/"}}, |
| {{TK_COMMENT_BLOCK, "/***/"}}, |
| {{TK_COMMENT_BLOCK, "/* */"}}, |
| {{TK_COMMENT_BLOCK, "/* foo */"}}, |
| {{TK_COMMENT_BLOCK, "/* foo\nbar */"}}, |
| {{TK_EOL_COMMENT, "//"}, {TK_NEWLINE, "\n"}}, |
| {{TK_EOL_COMMENT, "//"}, {TK_NEWLINE, "\r"}}, |
| {{TK_EOL_COMMENT, "// foo"}, {TK_NEWLINE, "\n"}}, |
| {{TK_EOL_COMMENT, "// bar"}, {TK_NEWLINE, "\r"}}, |
| {{TK_EOL_COMMENT, "//"}}, // missing \n, but treat as if it were there |
| {{TK_EOL_COMMENT, "//foo"}}, // missing \n, but treat as if it were there |
| }; |
| |
| // treating attributes lists as C-style comments, |
| // except they are not returned as comment blocks. |
| static std::initializer_list<SimpleTestData> kAttributeTests = { |
| {"(**)"}, {"(* *)"}, |
| {"(* x)*)"}, {"(* ** *)"}, |
| {"(***)"}, {"(** **)"}, |
| {"(*\n*)"}, {"(* style=flat *)"}, |
| {"(*foo=bar*)"}, {"(* style=flat, fill=empty *)"}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kAttributeSequenceTests = { |
| {{TK_ATTRIBUTE, "(**)"}, {TK_ATTRIBUTE, "(**)"}}, |
| {{TK_ATTRIBUTE, "(* style=flat,\nfill=empty *)"}, {TK_NEWLINE, "\n"}}, |
| {{TK_ATTRIBUTE, "(*garbage\nGARBAGE*)"}, {TK_NEWLINE, "\n"}}, |
| {{TK_ATTRIBUTE, "(*\ntoken\nsoup\n*)"}, {TK_NEWLINE, "\n"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kMacroCallTests = { |
| {{MacroCallId, "`FOO"}, '(', ')'}, |
| {{MacroCallId, "`FOO1"}, '(', ')', ';'}, |
| {{MacroCallId, "`FOO2"}, '(', ')'}, |
| {{MacroCallId, "`FOO3"}, '(', {MacroCallCloseToEndLine, ")"}, "\n"}, |
| {{MacroCallId, "`FOO4"}, '(', {MacroCallCloseToEndLine, ")"}, "\n", ';'}, |
| {{MacroCallId, "`FOO5"}, '(', {MacroCallCloseToEndLine, ")"}, " ", "\n"}, |
| {{MacroCallId, "`FOO5b"}, '(', {MacroCallCloseToEndLine, ")"}, " \n"}, |
| {{MacroCallId, "`FOO6"}, '(', ')', ';'}, |
| {{MacroCallId, "`FOO7"}, |
| '(', |
| {MacroArg, "BAR"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO8"}, '(', {MacroArg, "BAR"}, ')'}, |
| {{MacroCallId, "`FOO9"}, |
| {TK_SPACE, " "}, |
| '(', |
| {MacroArg, "BAR"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO10"}, " ", '(', {MacroArg, "BAR"}, ')'}, |
| {{MacroCallId, "`FOO11"}, |
| " ", |
| '(', |
| {MacroArg, "\"bar\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO11b"}, |
| " ", |
| '(', |
| {MacroArg, "`\"bar`\""}, // preprocess-evaluated string literal |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO11c"}, |
| " ", |
| '(', |
| {MacroArg, "`\"bar()`\""}, // preprocess-evaluated string literal |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO12"}, |
| '(', |
| {MacroArg, "BAR"}, |
| ',', |
| {MacroArg, "\"bar\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO13"}, |
| " ", |
| '(', |
| {MacroArg, "`BAR"}, |
| ',', |
| {MacroArg, "\"bar\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO14"}, |
| " ", |
| '(', |
| {MacroArg, "`BAR"}, |
| ',', |
| " ", |
| {MacroArg, "\"bar\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO15"}, |
| '(', |
| {MacroArg, "`BAR"}, |
| ',', |
| " ", |
| {MacroArg, "\"bar\""}, |
| ')'}, |
| // macro arg string literals containing balance characters: |
| {{MacroCallId, "`FOO16"}, |
| '(', |
| {MacroArg, "`BAR"}, |
| ',', |
| " ", |
| {MacroArg, "\"bar([{\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| // macro arg string literals containing balance characters: |
| {{MacroCallId, "`FOO17"}, |
| '(', |
| {MacroArg, "`BAR"}, |
| ',', |
| " ", |
| {MacroArg, "\"bar)]}\""}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO18"}, |
| '(', |
| {MacroArg, "{1,2,3}"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO19"}, |
| '(', |
| {MacroArg, "BAR()"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO20"}, |
| '(', |
| {MacroArg, "`BAR()"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO21"}, '(', {MacroArg, "`BAR()"}, ')'}, |
| {{MacroCallId, "`FOO22"}, |
| '(', |
| {MacroArg, "{1,2,3}"}, |
| ',', |
| {TK_SPACE, " "}, |
| {MacroArg, "`BAR()"}, // macro arg without trailing spaces |
| {TK_SPACE, " "}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO22b"}, |
| '(', |
| {MacroArg, "bar"}, |
| {TK_SPACE, " "}, |
| ',', |
| {MacroArg, "none"}, |
| {TK_SPACE, " "}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO23"}, " ", '(', {MacroArg, "{{{}}((){})}"}, ')'}, |
| {{MacroCallId, "`FOO24"}, '(', {MacroArg, "{{{}}((){})}"}, ')'}, |
| {{MacroCallId, "`FOO25"}, |
| '(', |
| {MacroArg, "{{{}}((){})}"}, |
| {MacroCallCloseToEndLine, ")"}, |
| "\n"}, |
| {{MacroCallId, "`FOO26"}, " ", '(', {TK_SPACE, " "}, ')'}, |
| {{MacroCallId, "`FOO27"}, '(', {TK_NEWLINE, "\n"}, ')'}, |
| {{MacroCallId, "`FOO28"}, " ", '(', {TK_SPACE, "\t"}, ')'}, |
| {{MacroCallId, "`FOO29"}, '(', {TK_SPACE, " "}, ',', {TK_SPACE, " "}, ')'}, |
| {{MacroCallId, "`FOO30"}, '(', ',', ')'}, |
| {{MacroCallId, "`FOO30b"}, '(', ',', {TK_SPACE, " "}, ')'}, |
| {{MacroCallId, "`FOO31"}, '(', ',', ',', ',', ')'}, |
| {{MacroCallId, "`FOO32"}, |
| '(', |
| " ", |
| ',', |
| "\n", |
| ',', |
| "\n\n", |
| ',', |
| " ", |
| ')'}, |
| {{MacroCallId, "`FOO33"}, |
| '(', |
| " ", |
| {MacroArg, "abc"}, |
| " ", // trailing spaces separated from preceding macro argument |
| ',', |
| " ", |
| ')'}, |
| {{MacroCallId, "`FOO34"}, |
| '(', |
| " ", |
| ',', |
| " ", |
| {MacroArg, "def"}, |
| " ", |
| ')'}, |
| {{MacroCallId, "`FOO35"}, |
| '(', |
| " ", |
| ',', |
| " ", |
| {MacroArg, "def"}, |
| " ", |
| ',', |
| " ", |
| ')'}, |
| {{MacroCallId, "`FOO36"}, '(', ',', {MacroArg, "def"}, ',', ')'}, |
| {{MacroIdItem, "`uvm_func_new"}, {TK_NEWLINE, "\n"}}, |
| {{MacroIdentifier, "`uvm_func_new"}, ';', {TK_NEWLINE, "\n"}}, |
| {{MacroIdItem, "`uvm_func_new"}, {TK_SPACE, " "}, "\n"}, |
| {{MacroIdItem, "`uvm_func_new"}, |
| " ", |
| {TK_EOL_COMMENT, "// comment"}, |
| "\n"}, |
| {{MacroIdItem, "`uvm_func_new"}, |
| " ", |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| "\n"}, |
| {{MacroIdItem, "`uvm_func_new"}, |
| " ", |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| " \n"}, |
| {{MacroIdItem, "`uvm_func_new"}, |
| {TK_COMMENT_BLOCK, "/*C*/"}, |
| {TK_COMMENT_BLOCK, "/*D*/"}, |
| " ", |
| {TK_EOL_COMMENT, "//E"}, |
| "\n"}, |
| {{MacroIdItem, "`uvm_object_utils_end"}, {TK_NEWLINE, "\n"}}, |
| {{MacroIdItem, "`uvm_func_new"}, |
| {TK_NEWLINE, "\n"}, |
| {MacroIdItem, "`uvm_func_tew"}, |
| {TK_NEWLINE, "\n"}}, |
| {{MacroIdentifier, "`uvm_blah"}, |
| ';', |
| " ", |
| {MacroIdItem, "`uvm_blah"}, |
| "\n"}, |
| {{MacroIdentifier, "`macro"}, |
| " ", |
| '+', |
| " ", |
| {MacroIdentifier, "`schmacro"}, |
| ';'}, |
| {{MacroIdentifier, "`macro"}, '+', {MacroIdentifier, "`schmacro"}, ';'}, |
| {{SymbolIdentifier, "lvalue"}, |
| " ", |
| '=', |
| " ", |
| {MacroIdItem, "`schmacro"}, |
| "\n"}, |
| {{SymbolIdentifier, "lvalue"}, '=', {MacroIdItem, "`schmacro"}, "\n"}, |
| |
| // with escaped identifiers in call args |
| {{MacroCallId, "`FOO"}, '(', {MacroArg, "\\BAR"}, " ", ')'}, |
| {{MacroCallId, "`FOO"}, '(', {MacroArg, "\\BAR"}, "\t", ')'}, |
| {{MacroCallId, "`FOO"}, '(', {MacroArg, "\\BAR"}, "\n", ')'}, |
| |
| // Comments are lexed together with macro arguments |
| {{MacroCallId, "`FOO"}, |
| '(', |
| "\n", |
| {MacroArg, "/*comment*/ bar"}, |
| "\n", |
| ')'}, |
| {{MacroCallId, "`FOO"}, |
| '(', |
| "\n", |
| {MacroArg, "bar /*comment*/"}, |
| "\n", |
| ')'}, |
| {{MacroCallId, "`FOO"}, |
| '(', |
| "\n", |
| {MacroArg, "/*\nmulti\nline\n*/ bar"}, |
| "\n", |
| ')'}, |
| {{MacroCallId, "`FOO"}, |
| '(', |
| "\n", |
| {MacroArg, "//comment\n bar"}, |
| "\n", |
| ')'}, |
| {{MacroCallId, "`FOO"}, |
| '(', |
| "\n", |
| {MacroArg, "//multi\n//line\n//comment\n bar"}, |
| "\n", |
| ')'}, |
| { |
| // fuzzer test case |
| {MacroCallId, "`g"}, |
| '(', |
| {MacroArg, "(\\x\" `g(::\"\n)"}, |
| ',' // unterminated call, unexpected EOF here |
| }, |
| }; |
| |
| static std::initializer_list<LexerTestData> kUnfilteredMacroCallTests = { |
| { |
| {MacroIdItem, "`uvm_func_new"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroIdItem, "`uvm_func_new"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroIdItem, "`uvm_func_new"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_SPACE, " "}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroIdItem, "`uvm_func_new"}, |
| {TK_COMMENT_BLOCK, "/*C*/"}, |
| {TK_COMMENT_BLOCK, "/*D*/"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "//E"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO1"}, |
| '(', |
| {TK_SPACE, " "}, |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO2"}, |
| '(', |
| {TK_SPACE, " "}, |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_SPACE, " "}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO3"}, |
| '(', |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO4"}, |
| '(', |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO5"}, |
| '(', |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_SPACE, " "}, |
| {TK_COMMENT_BLOCK, "/* comment */"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO6"}, |
| '(', |
| {MacroArg, "a"}, |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {MacroCallId, "`FOO7"}, |
| '(', |
| {MacroArg, "a"}, |
| ',', |
| {MacroArg, "b"}, |
| {MacroCallCloseToEndLine, ")"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| }; |
| |
| static std::initializer_list<LexerTestData> kMacroDefineTests = { |
| {{PP_define, "`define"}, |
| {TK_SPACE, " "}, |
| {PP_Identifier, "FOO"}, |
| {PP_define_body, ""}, |
| {TK_NEWLINE, "\n"}}, |
| {{PP_define, "`define"}, |
| {TK_SPACE, " "}, |
| {PP_Identifier, "FOO"}, |
| {PP_define_body, ""}, |
| {TK_NEWLINE, "\n"}}, |
| {{PP_define, "`define"}, |
| {TK_SPACE, " "}, |
| {PP_Identifier, "FOO"}, |
| " ", |
| {PP_define_body, ""}, |
| {TK_NEWLINE, "\n"}}, |
| {{PP_define, "`define"}, |
| {TK_SPACE, "\t"}, |
| {PP_Identifier, "FOO"}, |
| {PP_define_body, ""}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| {TK_SPACE, "\t\t"}, |
| {PP_Identifier, "FOO"}, |
| '(', |
| ')', |
| " ", |
| {PP_define_body, "foo()"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| " ", |
| {PP_define_body, "12"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| "\t", |
| {PP_Identifier, "FOO"}, |
| "\t", |
| {PP_define_body, "13"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| " ", |
| {PP_define_body, "\\\n14"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| {PP_define_body, "\\\n"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| {PP_define_body, "\\\n15"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| ')', |
| " ", |
| {PP_define_body, "bar()"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| ')', |
| " ", |
| {PP_define_body, "bar(x);"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| " ", |
| {PP_define_body, "\"hello\\world\""}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| ')', |
| " ", |
| {PP_define_body, "\"hello\\world\""}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "y"}, |
| ')', |
| " ", |
| {PP_define_body, "\"hello\\world\"\\\n\"goodbye.\""}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| ')', |
| " ", |
| {PP_define_body, "$bar(x, y);"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| ')', |
| " ", |
| {PP_define_body, "\\\n$bar(x, y);"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| ',', |
| " ", |
| {PP_Identifier, "z"}, |
| ')', |
| " ", |
| {PP_define_body, "\\\n$bar(x, y);\\\nzoo();"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "y"}, |
| ',', |
| " ", |
| {PP_Identifier, "z"}, |
| ')', |
| " ", |
| {PP_define_body, "\\\nalways look on\\\n\tthe bright side of life"}, |
| "\n"}, |
| // 2 definitions: |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| " ", |
| {PP_define_body, "12"}, |
| "\n", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "ZOO"}, |
| '(', |
| {PP_Identifier, "a"}, |
| ',', |
| " ", |
| {PP_Identifier, "b"}, |
| ')', |
| " ", |
| {PP_define_body, "b - a"}, |
| "\n"}, |
| // definition with condition definitions inside body: |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "F"}, |
| '(', |
| {PP_Identifier, "z"}, |
| ')', |
| {PP_define_body, |
| "\\\n" |
| "`ifdef Z \\\n" |
| "`define X z\\\n" |
| "`else \\\n" |
| "`define X 2 \\\n" |
| "`endif"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "GOOD"}, |
| " ", |
| {PP_define_body, "EVIL"}, |
| "\n", |
| {TK_static, "static"}, |
| " ", |
| {TK_void, "void"}, |
| " ", |
| {SymbolIdentifier, "tokens"}, |
| "\n"}, |
| // macro parameters with defaults: |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| '=', |
| {PP_default_text, "88"}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| '=', |
| {PP_default_text, "\"abc\""}, |
| ')', |
| " ", |
| {PP_define_body, "\\\n$bar(y, x);"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| '=', |
| {PP_default_text, "\"88\""}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| '=', |
| {PP_default_text, "abc"}, |
| ')', |
| " ", |
| {PP_define_body, "\\\n$bar(y, x);"}, |
| "\n"}, |
| // macro parameters with defaults, padded with spaces |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| " ", |
| '=', |
| {TK_SPACE, " "}, // leading space |
| {PP_default_text, "88"}, |
| {TK_SPACE, " "}, // trailing space |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| " ", |
| '=', |
| {TK_SPACE, " "}, // leading space |
| {PP_default_text, "\"abc\""}, |
| {TK_SPACE, " "}, // trailing space |
| ')', |
| " ", |
| {PP_define_body, "\\\n$bar(y, x);"}, |
| "\n"}, |
| // testing parenthesis balancing in PP_default_text |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| '=', |
| {PP_default_text, "(a,(b,c))"}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| " ", |
| '=', |
| " ", // leading space |
| {PP_default_text, "\"non)},{(sense\""}, |
| " ", // trailing space |
| ')', |
| " ", |
| {PP_define_body, "\\\nbar(y, x);"}, |
| "\n"}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| '(', |
| {PP_Identifier, "x"}, |
| '=', |
| {PP_default_text, "\"\""}, |
| ',', |
| " ", |
| {PP_Identifier, "y"}, |
| " ", |
| '=', |
| {PP_default_text, "(a,\"bc\")"}, |
| ')', |
| " ", |
| {PP_define_body, "\\\nbar(y, x);"}, |
| "\n"}, |
| // no line following continuation: |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "UNFINISHED"}, |
| " ", |
| {PP_define_body, "blah + \\"}, |
| "\n"}, |
| // multiple blank newlines after empty definition body |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "BAR"}, |
| {PP_define_body, ""}, |
| "\n\n\n"}, |
| // conditional define |
| {{PP_ifndef, "`ifndef"}, |
| " ", |
| {PP_Identifier, "FOO"}, |
| "\n", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "BAR"}, |
| {PP_define_body, ""}, |
| "\n\n", |
| {PP_endif, "`endif"}, |
| "\n"}, |
| { |
| {PP_define, "`define"}, " ", {PP_Identifier, "UNFINISHED"}, |
| // No \n before EOF |
| }, |
| { |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "UNFINISHED"}, |
| " ", |
| {PP_define_body, "symphony"}, |
| // No \n before EOF |
| }, |
| { |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "UNFINISHED"}, |
| " ", |
| {PP_define_body, "symphony \\"}, // end with line continuation |
| // No \n before EOF |
| }, |
| { |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "UNFINISHED"}, |
| " ", |
| {PP_define_body, "symphony \\\n number"}, |
| // No \n before EOF |
| }, |
| }; |
| |
| static std::initializer_list<GenericTestDataSequence> kProtectedTests = { |
| // TODO(b/134180314): lexer current drops tokens from protected sections, |
| // but instead emit the tokens and filter them out. |
| {"module foo;\n" |
| "`protected\n" |
| "`endprotected\n" |
| "endmodule\n", |
| {TK_module, TK_SPACE, SymbolIdentifier, ';', TK_NEWLINE, TK_NEWLINE, |
| TK_endmodule, TK_NEWLINE}}, |
| {"abc\n" |
| "`protected\n" |
| "(*&^%$#@!!@#$%^&*(a8sayasd\n" |
| "87y&*H*HYgyGYh@#BH)72361^&*\n" |
| "`endprotected\n" |
| "begin\n", |
| {SymbolIdentifier, TK_NEWLINE, TK_NEWLINE, TK_begin, TK_NEWLINE}}, |
| {"task bar;\n" |
| "// pragma protect begin_protected\n" |
| "// pragma protect end_protected\n" |
| "endtask\n", |
| {TK_task, TK_SPACE, SymbolIdentifier, ';', TK_NEWLINE, TK_NEWLINE, |
| TK_endtask, TK_NEWLINE}}, |
| {"end\n" |
| "//pragma protect begin_protected\n" |
| "(*&^%$#@!!@#$%^&*(a8sayasd\n" |
| "87y&*H*HYgyGYh@#BH)72361^&*\n" |
| "//pragma protect end_protected\n" |
| "always\n", |
| {TK_end, TK_NEWLINE, TK_NEWLINE, TK_always, TK_NEWLINE}}, |
| {"end\n" |
| "`pragma protect begin_protected\n" |
| "(*&^%$#@!!@#$%^&*(a8sayasd\n" |
| "87y&*H*HYgyGYh@#BH)72361^&*\n" |
| "`pragma protect end_protected\n" |
| "begin\n", |
| {TK_end, TK_NEWLINE, TK_NEWLINE, TK_begin, TK_NEWLINE}}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kSymbolIdentifierTests = { |
| {"a"}, {" a"}, {"\t\ta"}, {"\nb"}, {"_"}, {"_987"}, |
| {"_1u"}, {"_$"}, {"_$_"}, {"Foo"}, {"F00"}, {"Foo222"}, |
| {"_Foo"}, {"Foo$"}, {"Foo_Bar"}, {"Foo$Bar"}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kEscapedIdentifierTests = { |
| // escaped identifiers |
| {"\\foo "}, |
| {"\\__ "}, |
| {"\\555 "}, |
| {"\\these.are[really]ugly "}, |
| {"\\5.6.7.8 "}, |
| {"\\)(*&^%$#@! "}, |
| {"\\]fdg[];'[as321=-+/.,>. "}, |
| {"\\..:;;{]{*&!6^$94* "}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kMacroIdentifierTests = { |
| // treat `identifier (macro-constants) like plain identifier |
| {"`foo"}, |
| {"`foo789"}, |
| {"`___"}, |
| {"`_oo00OO"}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kKeywordTests = { |
| {{TK_1step, "1step"}}, |
| {{TK_always, "always"}}, |
| {{TK_and, "and"}}, |
| {{TK_assign, "assign"}}, |
| {{TK_begin, "begin"}}, |
| {{TK_buf, "buf"}}, |
| {{TK_bufif0, "bufif0"}}, |
| {{TK_bufif1, "bufif1"}}, |
| {{TK_case, "case"}}, |
| {{TK_casex, "casex"}}, |
| {{TK_casez, "casez"}}, |
| {{TK_cmos, "cmos"}}, |
| {{TK_deassign, "deassign"}}, |
| {{TK_default, "default"}}, |
| {{TK_defparam, "defparam"}}, |
| {{TK_disable, "disable"}}, |
| {{TK_edge, "edge"}}, |
| {{TK_else, "else"}}, |
| {{TK_end, "end"}}, |
| {{TK_endcase, "endcase"}}, |
| {{TK_endfunction, "endfunction"}}, |
| {{TK_endmodule, "endmodule"}}, |
| {{TK_endprimitive, "endprimitive"}}, |
| {{TK_endspecify, "endspecify"}}, |
| {{SymbolIdentifier, "endtable"}}, // is keyword in table context |
| {{TK_endtask, "endtask"}}, |
| {{TK_event, "event"}}, |
| {{SymbolIdentifier, "find"}}, |
| {{SymbolIdentifier, "find_index"}}, |
| {{SymbolIdentifier, "find_first"}}, |
| {{SymbolIdentifier, "find_first_index"}}, |
| {{SymbolIdentifier, "find_last"}}, |
| {{SymbolIdentifier, "find_last_index"}}, |
| {{TK_for, "for"}}, |
| {{TK_force, "force"}}, |
| {{TK_forever, "forever"}}, |
| {{TK_fork, "fork"}}, |
| {{TK_function, "function"}}, |
| {{TK_highz0, "highz0"}}, |
| {{TK_highz1, "highz1"}}, |
| {{TK_if, "if"}}, |
| {{TK_ifnone, "ifnone"}}, |
| {{TK_initial, "initial"}}, |
| {{TK_inout, "inout"}}, |
| {{TK_input, "input"}}, |
| {{TK_integer, "integer"}}, |
| {{TK_join, "join"}}, |
| {{TK_large, "large"}}, |
| {{TK_macromodule, "macromodule"}}, |
| {{TK_medium, "medium"}}, |
| {{TK_module, "module"}}, |
| {{TK_nand, "nand"}}, |
| {{TK_negedge, "negedge"}}, |
| {{TK_nmos, "nmos"}}, |
| {{TK_nor, "nor"}}, |
| {{TK_not, "not"}}, |
| {{TK_notif0, "notif0"}}, |
| {{TK_notif1, "notif1"}}, |
| {{TK_or, "or"}}, |
| {{TK_output, "output"}}, |
| {{TK_parameter, "parameter"}}, |
| {{TK_pmos, "pmos"}}, |
| {{TK_posedge, "posedge"}}, |
| {{TK_primitive, "primitive"}}, |
| {{TK_pull0, "pull0"}}, |
| {{TK_pull1, "pull1"}}, |
| {{TK_pulldown, "pulldown"}}, |
| {{TK_pullup, "pullup"}}, |
| {{TK_rcmos, "rcmos"}}, |
| {{TK_real, "real"}}, |
| {{TK_realtime, "realtime"}}, |
| {{TK_reg, "reg"}}, |
| {{TK_release, "release"}}, |
| {{TK_repeat, "repeat"}}, |
| {{TK_rnmos, "rnmos"}}, |
| {{TK_rpmos, "rpmos"}}, |
| {{TK_rtran, "rtran"}}, |
| {{TK_rtranif0, "rtranif0"}}, |
| {{TK_rtranif1, "rtranif1"}}, |
| {{TK_scalared, "scalared"}}, |
| {{TK_small, "small"}}, |
| {{TK_specify, "specify"}}, |
| {{TK_specparam, "specparam"}}, |
| {{TK_strong0, "strong0"}}, |
| {{TK_strong1, "strong1"}}, |
| {{TK_supply0, "supply0"}}, |
| {{TK_supply1, "supply1"}}, |
| {{SymbolIdentifier, "table"}}, // is keyword inside primitive context |
| {{TK_task, "task"}}, |
| {{TK_time, "time"}}, |
| {{TK_tran, "tran"}}, |
| {{TK_tranif0, "tranif0"}}, |
| {{TK_tranif1, "tranif1"}}, |
| {{TK_tri, "tri"}}, |
| {{TK_tri0, "tri0"}}, |
| {{TK_tri1, "tri1"}}, |
| {{TK_triand, "triand"}}, |
| {{TK_trior, "trior"}}, |
| {{TK_trireg, "trireg"}}, |
| {{TK_vectored, "vectored"}}, |
| {{TK_wait, "wait"}}, |
| {{TK_wand, "wand"}}, |
| {{TK_weak0, "weak0"}}, |
| {{TK_weak1, "weak1"}}, |
| {{TK_while, "while"}}, |
| {{TK_wire, "wire"}}, |
| {{TK_wor, "wor"}}, |
| {{TK_xnor, "xnor"}}, |
| {{TK_xor, "xor"}}, |
| {{TK_Shold, "$hold"}}, |
| {{TK_Snochange, "$nochange"}}, |
| {{TK_Speriod, "$period"}}, |
| {{TK_Srecovery, "$recovery"}}, |
| {{TK_Ssetup, "$setup"}}, |
| {{TK_Ssetuphold, "$setuphold"}}, |
| {{TK_Sskew, "$skew"}}, |
| {{TK_Swidth, "$width"}}, |
| {{TKK_attribute, "$attribute"}}, |
| {{TK_automatic, "automatic"}}, |
| {{TK_endgenerate, "endgenerate"}}, |
| {{TK_generate, "generate"}}, |
| {{TK_genvar, "genvar"}}, |
| {{TK_localparam, "localparam"}}, |
| {{TK_noshowcancelled, "noshowcancelled"}}, |
| {{TK_pulsestyle_onevent, "pulsestyle_onevent"}}, |
| {{TK_pulsestyle_ondetect, "pulsestyle_ondetect"}}, |
| {{TK_showcancelled, "showcancelled"}}, |
| {{TK_signed, "signed"}}, |
| {{TK_unsigned, "unsigned"}}, |
| {{TK_Sfullskew, "$fullskew"}}, |
| {{TK_Srecrem, "$recrem"}}, |
| {{TK_Sremoval, "$removal"}}, |
| {{TK_Stimeskew, "$timeskew"}}, |
| {{TK_cell, "cell"}}, |
| {{TK_config, "config"}}, |
| {{TK_design, "design"}}, |
| {{TK_endconfig, "endconfig"}}, |
| {{TK_incdir, "incdir"}}, |
| {{TK_include, "include"}}, |
| {{TK_instance, "instance"}}, |
| {{TK_liblist, "liblist"}}, |
| {{TK_library, "library"}}, |
| {{TK_use, "use"}}, |
| {{TK_wone, "wone"}}, |
| {{TK_uwire, "uwire"}}, |
| {{TK_alias, "alias"}}, |
| {{TK_always_comb, "always_comb"}}, |
| {{TK_always_ff, "always_ff"}}, |
| {{TK_always_latch, "always_latch"}}, |
| {{TK_assert, "assert"}}, |
| {{TK_assume, "assume"}}, |
| {{TK_before, "before"}}, |
| {{TK_bind, "bind"}}, |
| {{TK_bins, "bins"}}, |
| {{TK_binsof, "binsof"}}, |
| {{TK_bit, "bit"}}, |
| {{TK_break, "break"}}, |
| {{TK_byte, "byte"}}, |
| {{TK_chandle, "chandle"}}, |
| {{TK_class, "class"}}, |
| {{TK_clocking, "clocking"}}, |
| {{TK_const, "const"}}, |
| {{TK_constraint, "constraint"}}, |
| {{TK_context, "context"}}, |
| {{TK_continue, "continue"}}, |
| {{TK_cover, "cover"}}, |
| {{TK_covergroup, "covergroup"}}, |
| {{TK_coverpoint, "coverpoint"}}, |
| {{TK_cross, "cross"}}, |
| {{TK_dist, "dist"}}, |
| {{TK_do, "do"}}, |
| {{TK_endclass, "endclass"}}, |
| {{TK_endclocking, "endclocking"}}, |
| {{TK_endgroup, "endgroup"}}, |
| {{TK_endinterface, "endinterface"}}, |
| {{TK_endpackage, "endpackage"}}, |
| {{TK_endprogram, "endprogram"}}, |
| {{TK_endproperty, "endproperty"}}, |
| {{TK_endsequence, "endsequence"}}, |
| {{TK_enum, "enum"}}, |
| {{TK_expect, "expect"}}, |
| {{TK_export, "export"}}, |
| {{TK_extends, "extends"}}, |
| {{TK_extern, "extern"}}, |
| {{TK_final, "final"}}, |
| {{TK_first_match, "first_match"}}, |
| {{TK_foreach, "foreach"}}, |
| {{TK_forkjoin, "forkjoin"}}, |
| {{TK_iff, "iff"}}, |
| {{TK_ignore_bins, "ignore_bins"}}, |
| {{TK_illegal_bins, "illegal_bins"}}, |
| {{TK_import, "import"}}, |
| {{TK_inside, "inside"}}, |
| {{TK_int, "int"}}, |
| {{TK_interface, "interface"}}, |
| {{TK_intersect, "intersect"}}, |
| {{TK_join_any, "join_any"}}, |
| {{TK_join_none, "join_none"}}, |
| {{TK_local_SCOPE, "local::"}}, |
| {{TK_local, "local"}}, |
| {{TK_logic, "logic"}}, |
| {{TK_longint, "longint"}}, |
| {{TK_matches, "matches"}}, |
| {{TK_modport, "modport"}}, |
| {{TK_new, "new"}}, |
| {{TK_null, "null"}}, |
| {{TK_package, "package"}}, |
| {{TK_packed, "packed"}}, |
| {{TK_priority, "priority"}}, |
| {{TK_program, "program"}}, |
| {{TK_property, "property"}}, |
| {{TK_protected, "protected"}}, |
| {{TK_pure, "pure"}}, |
| {{TK_rand, "rand"}}, |
| {{TK_randc, "randc"}}, |
| {{TK_randcase, "randcase"}}, |
| {{TK_randsequence, "randsequence"}}, |
| {{TK_randomize, "randomize"}}, |
| {{TK_randomize, "std::randomize"}}, |
| {{TK_ref, "ref"}}, |
| {{TK_return, "return"}}, |
| {{TK_Sroot, "$root"}}, |
| {{TK_sequence, "sequence"}}, |
| {{TK_shortint, "shortint"}}, |
| {{TK_shortreal, "shortreal"}}, |
| {{TK_solve, "solve"}}, |
| {{TK_static, "static"}}, |
| {{TK_string, "string"}}, |
| {{TK_struct, "struct"}}, |
| {{TK_super, "super"}}, |
| {{TK_tagged, "tagged"}}, |
| {{TK_this, "this"}}, |
| {{TK_throughout, "throughout"}}, |
| {{TK_timeprecision, "timeprecision"}}, |
| {{TK_timeunit, "timeunit"}}, |
| {{TK_type, "type"}}, |
| {{TK_typedef, "typedef"}}, |
| {{TK_union, "union"}}, |
| {{TK_unique, "unique"}}, |
| {{TK_Sunit, "$unit"}}, |
| {{TK_var, "var"}}, |
| {{TK_virtual, "virtual"}}, |
| {{TK_void, "void"}}, |
| {{TK_wait_order, "wait_order"}}, |
| {{TK_wildcard, "wildcard"}}, |
| {{TK_with, "with"}}, |
| {{TK_within, "within"}}, |
| {{TK_timeprecision_check, "timeprecision_check"}}, |
| {{TK_timeunit_check, "timeunit_check"}}, |
| {{TK_accept_on, "accept_on"}}, |
| {{TK_checker, "checker"}}, |
| {{TK_endchecker, "endchecker"}}, |
| {{TK_eventually, "eventually"}}, |
| {{TK_global, "global"}}, |
| {{TK_implies, "implies"}}, |
| {{TK_let, "let"}}, |
| {{TK_nexttime, "nexttime"}}, |
| {{TK_reject_on, "reject_on"}}, |
| {{TK_restrict, "restrict"}}, |
| {{TK_s_always, "s_always"}}, |
| {{TK_s_eventually, "s_eventually"}}, |
| {{TK_s_nexttime, "s_nexttime"}}, |
| {{TK_s_until, "s_until"}}, |
| {{TK_s_until_with, "s_until_with"}}, |
| {{TK_strong, "strong"}}, |
| {{TK_sync_accept_on, "sync_accept_on"}}, |
| {{TK_sync_reject_on, "sync_reject_on"}}, |
| {{TK_unique0, "unique0"}}, |
| {{TK_until, "until"}}, |
| {{TK_until_with, "until_with"}}, |
| {{TK_untyped, "untyped"}}, |
| {{TK_weak, "weak"}}, |
| {{TK_implements, "implements"}}, |
| {{TK_interconnect, "interconnect"}}, |
| {{TK_nettype, "nettype"}}, |
| {{TK_soft, "soft"}}, |
| {{TK_absdelay, "absdelay"}}, |
| {{TK_abstol, "abstol"}}, |
| {{TK_access, "access"}}, |
| {{TK_ac_stim, "ac_stim"}}, |
| {{TK_aliasparam, "aliasparam"}}, |
| {{TK_analog, "analog"}}, |
| {{TK_analysis, "analysis"}}, |
| {{TK_connectmodule, "connectmodule"}}, |
| {{TK_connectrules, "connectrules"}}, |
| {{TK_continuous, "continuous"}}, |
| {{TK_ddt_nature, "ddt_nature"}}, |
| {{TK_discipline, "discipline"}}, |
| {{TK_discrete, "discrete"}}, |
| {{SymbolIdentifier, "domain"}}, // is keyword in discipline context |
| {{TK_driver_update, "driver_update"}}, |
| {{TK_endconnectrules, "endconnectrules"}}, |
| {{TK_enddiscipline, "enddiscipline"}}, |
| {{TK_endnature, "endnature"}}, |
| {{TK_endparamset, "endparamset"}}, |
| {{TK_exclude, "exclude"}}, |
| {{TK_flicker_noise, "flicker_noise"}}, |
| {{TK_flow, "flow"}}, |
| {{TK_from, "from"}}, |
| {{TK_idt_nature, "idt_nature"}}, |
| {{TK_inf, "inf"}}, |
| {{TK_infinite, "infinite"}}, |
| {{TK_laplace_nd, "laplace_nd"}}, |
| {{TK_laplace_np, "laplace_np"}}, |
| {{TK_laplace_zd, "laplace_zd"}}, |
| {{TK_laplace_zp, "laplace_zp"}}, |
| {{TK_last_crossing, "last_crossing"}}, |
| {{TK_limexp, "limexp"}}, |
| {{SymbolIdentifier, "max"}}, |
| {{SymbolIdentifier, "min"}}, |
| {{TK_nature, "nature"}}, |
| {{TK_net_resolution, "net_resolution"}}, |
| {{TK_noise_table, "noise_table"}}, |
| {{TK_paramset, "paramset"}}, |
| {{TK_potential, "potential"}}, |
| {{TK_resolveto, "resolveto"}}, |
| {{TK_transition, "transition"}}, |
| {{TK_units, "units"}}, |
| {{TK_white_noise, "white_noise"}}, |
| {{TK_wreal, "wreal"}}, |
| {{TK_zi_nd, "zi_nd"}}, |
| {{TK_zi_np, "zi_np"}}, |
| {{TK_zi_zd, "zi_zd"}}, |
| {{TK_zi_zp, "zi_zp"}}, |
| {{TK_PLUS_EQ, "+="}}, |
| {{TK_MINUS_EQ, "-="}}, |
| {{TK_MUL_EQ, "*="}}, |
| {{TK_DIV_EQ, "/="}}, |
| {{TK_MOD_EQ, "%="}}, |
| {{TK_AND_EQ, "&="}}, |
| {{TK_OR_EQ, "|="}}, |
| {{TK_XOR_EQ, "^="}}, |
| {{TK_INCR, "++"}}, |
| {{TK_DECR, "--"}}, |
| {{TK_LE, "<="}}, |
| {{TK_GE, ">="}}, |
| {{TK_EG, "=>"}}, |
| {{TK_WILDCARD_EQ, "==?"}}, |
| {{TK_EQ, "=="}}, |
| {{TK_WILDCARD_NE, "!=?"}}, |
| {{TK_NE, "!="}}, |
| {{TK_CEQ, "==="}}, |
| {{TK_CNE, "!=="}}, |
| {{TK_LP, "'{"}}, |
| {{TK_LS, "<<"}}, |
| {{TK_RS, ">>"}}, |
| {{TK_RSS, ">>>"}}, |
| {{TK_SG, "*>"}}, |
| {{TK_CONTRIBUTE, "<+"}}, |
| {{TK_PO_POS, "+:"}}, |
| {{TK_PO_NEG, "-:"}}, |
| {{TK_POW, "**"}}, |
| // {{TK_PSTAR , { "(*"}}, // ignored by lexer, treated as comment |
| // {{TK_STARP , { "*)"}}, // ignored by lexer, treated as comment |
| {{TK_DOTSTAR, ".*"}}, |
| {{TK_LOR, "||"}}, |
| {{TK_LAND, "&&"}}, |
| {{TK_TAND, "&&&"}}, |
| {{TK_NAND, "~&"}}, |
| {{TK_NOR, "~|"}}, |
| {{TK_NXOR, "~^"}}, |
| {{TK_NONBLOCKING_TRIGGER, "->>"}}, |
| {{_TK_RARROW, "->"}}, // This can disambiguate to different enums, |
| // depending on context. |
| {{TK_LOGEQUIV, "<->"}}, |
| {{TK_SCOPE_RES, "::"}}, |
| {{TK_COLON_EQ, ":="}}, |
| {{TK_COLON_DIV, ":/"}}, |
| {{TK_POUNDPOUND, "##"}}, |
| {{TK_LBSTAR, "[*"}}, |
| {{TK_LBSTARRB, "[*]"}}, |
| {{TK_LBPLUSRB, "[+]"}}, |
| {{TK_LBEQ, "[="}}, |
| {{TK_LBRARROW, "[->"}}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kSingleCharTokenTests = { |
| {"}"}, {"{"}, {";"}, {":"}, {"["}, {"]"}, {","}, {"("}, {")"}, |
| {"#"}, {"="}, {"."}, {"@"}, {"&"}, {"!"}, {"?"}, {"<"}, {">"}, |
| {"%"}, {"|"}, {"^"}, {"~"}, {"+"}, {"*"}, {"/"}, {"-"}, {"\'"}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kRealTimeTests = { |
| // scientific units |
| {"1e-3"}, |
| {"2e+3"}, |
| {"3e6"}, |
| {"4E6"}, |
| {"5.12e-6"}, |
| {"0e-0"}, |
| {"0e+0"}, |
| {"6e-12"}, |
| {"7e-100"}, |
| {"6.02e-23"}, |
| {"2.9e8"}, |
| // scaled units are for Verilog-AMS |
| {"1u"}, |
| {"2a"}, |
| {"3f"}, |
| {"4m"}, |
| {"5p"}, |
| {"6k"}, |
| {"6K"}, |
| {"7M"}, |
| {"8G"}, |
| {"9T"}, |
| {"2.5n"}, |
| {"100p"}, |
| {"10.0p"}, |
| {"0.01m"}, |
| {"0m"}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kBasedNumberTests = { |
| {{TK_UnBasedNumber, "'0"}}, |
| {{TK_UnBasedNumber, "'1"}}, |
| {{TK_UnBasedNumber, "'x"}}, |
| {{TK_UnBasedNumber, "'X"}}, |
| {{TK_UnBasedNumber, "'z"}}, |
| {{TK_UnBasedNumber, "'Z"}}, |
| {{TK_DecBase, "'d"}, {TK_DecDigits, "0"}}, |
| {{TK_DecBase, "'d"}, {TK_SPACE, " "}, {TK_DecDigits, "0"}}, |
| {{TK_DecBase, "'d"}, {TK_DecDigits, "20"}}, |
| {{TK_DecBase, "'d"}, {TK_DecDigits, "20__"}}, |
| {{TK_DecBase, "'sd"}, {TK_DecDigits, "9"}}, |
| {{TK_DecBase, "'SD"}, {TK_DecDigits, "12"}}, |
| {{TK_DecBase, "'d"}, {TK_XZDigits, "x"}}, |
| {{TK_DecBase, "'d"}, {TK_SPACE, " "}, {TK_XZDigits, "x"}}, |
| {{TK_DecBase, "'d"}, {TK_NEWLINE, "\n"}, {TK_XZDigits, "x"}}, |
| {{TK_DecBase, "'d"}, {TK_XZDigits, "x_"}}, |
| {{TK_DecBase, "'d"}, {TK_XZDigits, "Z"}}, |
| {{TK_DecBase, "'d"}, {TK_XZDigits, "?"}}, |
| {{TK_BinBase, "'B"}, {TK_BinDigits, "0"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "1"}}, |
| {{TK_BinBase, "'b"}, {TK_SPACE, " "}, {TK_BinDigits, "1"}}, |
| {{TK_BinBase, "'b"}, {TK_NEWLINE, "\n"}, {TK_BinDigits, "1"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "x"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "z"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "1100"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "xX10Zz"}}, |
| {{TK_BinBase, "'b"}, {TK_BinDigits, "_x_X_10_Zz"}}, |
| {{TK_OctBase, "'o"}, {TK_OctDigits, "0"}}, |
| {{TK_OctBase, "'o"}, {TK_OctDigits, "000"}}, |
| {{TK_OctBase, "'o"}, {TK_OctDigits, "777"}}, |
| {{TK_OctBase, "'o"}, {TK_SPACE, " "}, {TK_OctDigits, "777"}}, |
| {{TK_OctBase, "'o"}, {TK_NEWLINE, "\n"}, {TK_OctDigits, "777"}}, |
| {{TK_OctBase, "'o"}, {TK_OctDigits, "_007_007_"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "0"}}, |
| {{TK_HexBase, "'h"}, {TK_SPACE, " "}, {TK_HexDigits, "0"}}, |
| {{TK_HexBase, "'h"}, {TK_NEWLINE, "\n"}, {TK_HexDigits, "0"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "a"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "e110"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "_feed_face"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "0_cafebabe_"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "00d_f00d"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "xXXxcaca"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "cacazzZZ"}}, |
| {{TK_HexBase, "'h"}, {TK_HexDigits, "e110???_000"}}, |
| }; |
| |
| static std::initializer_list<SimpleTestData> kTimeLiteralTests = { |
| {"1fs"}, {"2ps"}, {"3ns"}, {"4us"}, {"5ms"}, {"6.6fs"}, |
| {"7.77ps"}, {"88.0ns"}, {"999.99us"}, {"10.0ms"}, {"66s"}, |
| // {"1 ms"}, {"11.0 ms"}, // only allowed in `timescale context |
| }; |
| |
| static std::initializer_list<SimpleTestData> kStringLiteralTests = { |
| {"\"\""}, |
| {"\".\""}, |
| {"\"...\""}, |
| {"\":)\""}, |
| {"\"^ ^\""}, |
| {"\"O_o\""}, |
| {"\"foobar\""}, |
| {"\"foo bar\""}, |
| {"\"the\\\\great\\\\escape\""}, |
| {"\"the\\\"great\\\"escape\""}, |
| {"\"the\\nGREAT\\nescape\""}, // with line continuations |
| {"\"`abc\""}, |
| {"\"`abc()\""}, |
| {"\"`abc(d)\""}, |
| {"\"`abc(d,e)\""}, |
| }; |
| |
| // `"...`" preprocessor-evaluated string literals |
| static std::initializer_list<SimpleTestData> kEvalStringLiteralTests = { |
| {"`\"`\""}, // |
| {"`\" `\""}, // |
| {"`\"123`\""}, // |
| {"`\"abc`\""}, // |
| {"`\"`abc`\""}, // |
| {"`\"`abc()`\""}, // |
| {"`\"`abc(d)`\""}, // |
| {"`\"`abc(d,e)`\""}, // |
| {"`\"```\""}, // token concatenation operator in middle |
| }; |
| |
| // tokens with special handling in lexer |
| static std::initializer_list<LexerTestData> kTrickyTests = { |
| {{'*', "(*)"}}, |
| {{TK_COLON_DIV, ":/"}, {TK_SPACE, " "}}, |
| {{TK_COLON_DIV, ":/"}, {TK_DecNumber, "8"}}, |
| {':', {TK_EOL_COMMENT, "//"}, {TK_NEWLINE, "\n"}}, |
| {':', {TK_COMMENT_BLOCK, "/*ignore*/"}, {TK_NEWLINE, "\n"}}, |
| {{TK_DecNumber, "0"}, |
| ':', |
| {TK_EOL_COMMENT, "// case description"}, |
| {TK_NEWLINE, "\n"}}, |
| {{SymbolIdentifier, "FOO"}, |
| {TK_SPACE, " "}, |
| {TK_LINE_CONT, "\\"}, |
| {TK_NEWLINE, "\n"}, |
| {SymbolIdentifier, "BAR"}, |
| ';'}, |
| { |
| {TK_EOL_COMMENT, "//FOO"}, |
| {TK_LINE_CONT, "\\"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {TK_EOL_COMMENT, "//FOO"}, |
| {TK_LINE_CONT, "\\"}, |
| {TK_NEWLINE, "\n"}, |
| {TK_EOL_COMMENT, "//BAR "}, |
| {TK_LINE_CONT, "\\"}, |
| {TK_NEWLINE, "\n"}, |
| }, |
| }; |
| |
| // make sure these are lexed as separate tokens |
| static std::initializer_list<LexerTestData> kSequenceTests = { |
| {{'+', "+"}, {TK_EG, "=>"}}, |
| {{'-', "-"}, {TK_EG, "=>"}}, |
| {{TK_POUNDPOUND, "##"}, {'#', "#"}}, |
| {{TK_POUNDPOUND, "##"}, {TK_POUNDPOUND, "##"}}, |
| {{'[', "["}, {'-', "-"}, {TK_DecNumber, "12"}, {']', "]"}}, |
| {{TK_LBSTAR, "[*"}, {TK_DecNumber, "12"}, {']', "]"}}, |
| {{'[', "["}, " ", {'*', "*"}, {TK_DecNumber, "3"}, {']', "]"}}, |
| {{TK_LBEQ, "[="}, {TK_DecNumber, "1"}, {']', "]"}}, |
| {{'[', "["}, " ", {'=', "="}, {TK_DecNumber, "1"}, {']', "]"}}, |
| {{TK_LBRARROW, "[->"}, {']', "]"}}, |
| {{'[', "["}, " ", {_TK_RARROW, "->"}, {']', "]"}}, |
| {{MacroNumericWidth, "`WIDTH"}, {TK_DecBase, "'d"}, {TK_DecDigits, "777"}}, |
| {{MacroNumericWidth, "`WIDTH"}, |
| {TK_DecBase, "'d"}, |
| {MacroIdentifier, "`DIGITS"}}, |
| {{MacroNumericWidth, "`WIDTH"}, |
| " ", |
| {TK_HexBase, "'h"}, |
| {TK_HexDigits, "888"}}, |
| {{MacroNumericWidth, "`WIDTH"}, |
| " ", |
| {TK_HexBase, "'h"}, |
| {MacroIdentifier, "`DIGITS"}}, |
| {{MacroNumericWidth, "`WIDTH"}, |
| " \t ", |
| {TK_OctBase, "'o"}, |
| {TK_OctDigits, "654"}}, |
| {{MacroNumericWidth, "`WIDTH"}, {TK_BinBase, "'b"}, {TK_BinDigits, "101"}}, |
| {{MacroNumericWidth, "`WIDTH"}, {TK_BinBase, "'b"}, {TK_BinDigits, "10zx"}}, |
| {{MacroNumericWidth, "`WIDTH"}, |
| {TK_BinBase, "'b"}, |
| {MacroIdentifier, "`DIGITS"}}, |
| {{'*', "(*)"}, {'*', "(*)"}}, |
| {{'*', "(*)"}, " ", {'*', "(*)"}}, |
| {{'*', "(* )"}, {'*', "(* )"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kContextKeywordTests = { |
| {{SymbolIdentifier, "option"}}, |
| {{TK_covergroup, "covergroup"}, |
| " ", |
| {SymbolIdentifier, "blah1"}, |
| " ", |
| {TK_option, "option"}, |
| " ", |
| {SymbolIdentifier, "blah2"}, |
| " ", |
| {TK_endgroup, "endgroup"}, |
| " ", |
| {SymbolIdentifier, "option"}}, |
| {{TK_with, "with"}, |
| " ", |
| {TK_covergroup, "covergroup"}, |
| " ", |
| {TK_with__covergroup, "with"}, |
| " ", |
| {TK_endgroup, "endgroup"}, |
| " ", |
| {TK_with, "with"}}, |
| {{SymbolIdentifier, "domain"}, |
| " ", |
| {TK_discipline, "discipline"}, |
| " ", |
| {TK_domain, "domain"}, |
| " ", |
| {TK_enddiscipline, "enddiscipline"}, |
| " ", |
| {SymbolIdentifier, "domain"}}}; |
| |
| static std::initializer_list<LexerTestData> kBuiltinMethodKeywordTests = { |
| {{'.', "."}, " ", {TK_randomize, "randomize"}, {'(', "("}, {')', ")"}}, |
| {{'.', "."}, {TK_randomize, "randomize"}, " ", {TK_with, "with"}}, |
| {{SymbolIdentifier, "min"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_min, "min"}, |
| " ", |
| {SymbolIdentifier, "min"}}, |
| {{SymbolIdentifier, "min"}, |
| {'.', "."}, |
| {SymbolIdentifier, "minime"}, |
| " ", |
| {SymbolIdentifier, "min"}}, |
| {{SymbolIdentifier, "max"}, |
| {'.', "."}, |
| " ", |
| {TK_max, "max"}, |
| " ", |
| {SymbolIdentifier, "max"}}, |
| {{SymbolIdentifier, "max"}, |
| {'.', "."}, |
| {SymbolIdentifier, "maxime"}, |
| " ", |
| {SymbolIdentifier, "max"}}, |
| {{SymbolIdentifier, "find"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_find, "find"}, |
| " ", |
| {SymbolIdentifier, "find"}}, |
| {{'.', "."}, {SymbolIdentifier, "finder"}}, |
| {{SymbolIdentifier, "find_index"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_find_index, "find_index"}, |
| " ", |
| {SymbolIdentifier, "find_index"}}, |
| {{SymbolIdentifier, "find_first_index"}, |
| {'.', "."}, |
| {TK_find_first_index, "find_first_index"}, |
| " ", |
| {SymbolIdentifier, "find_first_index"}}, |
| {{SymbolIdentifier, "find_last"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_find_last, "find_last"}, |
| " ", |
| {SymbolIdentifier, "find_last"}}, |
| {{SymbolIdentifier, "find_last_index"}, |
| {'.', "."}, |
| {TK_find_last_index, "find_last_index"}, |
| " ", |
| {SymbolIdentifier, "find_last_index"}}, |
| {{TK_unique, "unique"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_unique, "unique"}, |
| " ", |
| {TK_unique, "unique"}}, |
| {{SymbolIdentifier, "uniquely"}, |
| {'.', "."}, |
| {SymbolIdentifier, "uniquely"}, |
| " ", |
| {SymbolIdentifier, "uniquely"}}, |
| {{SymbolIdentifier, "unique_index"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_unique_index, "unique_index"}, |
| " ", |
| {SymbolIdentifier, "unique_index"}}, |
| {{SymbolIdentifier, "sort"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_sort, "sort"}, |
| " ", |
| {SymbolIdentifier, "sort"}}, |
| {{SymbolIdentifier, "rsort"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_rsort, "rsort"}, |
| " ", |
| {SymbolIdentifier, "rsort"}}, |
| {{SymbolIdentifier, "reverse"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_reverse, "reverse"}, |
| " ", |
| {SymbolIdentifier, "reverse"}}, |
| {{SymbolIdentifier, "shuffle"}, |
| " ", |
| {'.', "."}, |
| {TK_shuffle, "shuffle"}, |
| " ", |
| {SymbolIdentifier, "shuffle"}}, |
| {{SymbolIdentifier, "sum"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_sum, "sum"}, |
| " ", |
| {SymbolIdentifier, "sum"}}, |
| {{SymbolIdentifier, "product"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_product, "product"}, |
| " ", |
| {SymbolIdentifier, "product"}}, |
| {{TK_and, "and"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_and, "and"}, |
| " ", |
| {TK_and, "and"}}, |
| {{TK_or, "or"}, " ", {'.', "."}, " ", {TK_or, "or"}, " ", {TK_or, "or"}}, |
| {{TK_xor, "xor"}, |
| " ", |
| {'.', "."}, |
| " ", |
| {TK_xor, "xor"}, |
| " ", |
| {TK_xor, "xor"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kEdgeTests = { |
| {{TK_edge, "edge"}, " ", {'[', "["}, {']', "]"}, " ", {TK_DecNumber, "10"}}, |
| {{TK_edge, "edge"}, |
| "\n", |
| {'[', "["}, |
| {']', "]"}, |
| " ", |
| {SymbolIdentifier, "z0"}}, |
| {{TK_edge, "edge"}, |
| {'[', "["}, |
| {TK_edge_descriptor, "10"}, |
| {']', "]"}, |
| " "}, |
| {{TK_edge, "edge"}, |
| "\n", |
| {'[', "["}, |
| {TK_edge_descriptor, "z0"}, |
| {']', "]"}}, |
| {{TK_edge, "edge"}, |
| "\n", |
| {'[', "["}, |
| {TK_edge_descriptor, "01"}, |
| " ", |
| {TK_edge_descriptor, "0x"}, |
| " ", |
| {TK_edge_descriptor, "1x"}, |
| " ", |
| {TK_edge_descriptor, "x0"}, |
| " ", |
| {TK_edge_descriptor, "z1"}, |
| " ", |
| {']', "]"}, |
| " ", |
| {TK_DecNumber, "10"}}, |
| {{TK_edge, "edge"}, |
| "\n", |
| {'[', "["}, |
| {TK_edge_descriptor, "01"}, |
| " ", |
| {',', ","}, |
| {TK_edge_descriptor, "0x"}, |
| " ", |
| {',', ","}, |
| {TK_edge_descriptor, "1x"}, |
| {',', ","}, |
| {TK_edge_descriptor, "x0"}, |
| {',', ","}, |
| {TK_edge_descriptor, "z1"}, |
| {',', ","}, |
| {']', "]"}, |
| " ", |
| {SymbolIdentifier, "x0"}}, |
| {{TK_edge, "edge"}, " ", {SymbolIdentifier, "x0"}}, |
| {{TK_edge, "edge"}, |
| " ", |
| {SymbolIdentifier, "x0"}, |
| " ", |
| {'[', "["}, |
| " ", |
| {TK_DecNumber, "10"}, |
| " ", |
| {']', "]"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kUDPTests = { |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {TK_endtable, "endtable"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'b', "b"}, |
| {':', ":"}, |
| {'l', "l"}, |
| {';', ";"}, |
| " ", |
| {TK_endtable, "endtable"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'b', "B"}, |
| {':', ":"}, |
| {'l', "L"}, |
| {':', ":"}, |
| {'h', "H"}, |
| {';', ";"}, |
| " ", |
| {TK_endtable, "endtable"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'b', "b"}, |
| " ", |
| {'b', "B"}, |
| " ", |
| {'l', "l"}, |
| " ", |
| {'l', "L"}, |
| " ", |
| {'h', "h"}, |
| " ", |
| {'h', "H"}, |
| " ", |
| {'f', "f"}, |
| " ", |
| {'f', "F"}, |
| " ", |
| {'r', "r"}, |
| " ", |
| {'r', "R"}, |
| " ", |
| {'x', "x"}, |
| " ", |
| {'x', "X"}, |
| " ", |
| {'n', "n"}, |
| " ", |
| {'n', "N"}, |
| " ", |
| {'p', "p"}, |
| " ", |
| {'p', "P"}, |
| " ", |
| {'0', "0"}, |
| " ", |
| {'1', "1"}, |
| " ", |
| {'?', "?"}, |
| " ", |
| {'*', "*"}, |
| " ", |
| {'-', "-"}, |
| " ", |
| {':', ":"}, |
| " ", |
| {';', ";"}, |
| " ", |
| {TK_endtable, "endtable"}, |
| " ", |
| {SymbolIdentifier, "B"}, |
| " ", |
| {SymbolIdentifier, "L"}, |
| " ", |
| {SymbolIdentifier, "F"}, |
| " ", |
| {SymbolIdentifier, "H"}, |
| " ", |
| {SymbolIdentifier, "R"}, |
| " ", |
| {TK_DecNumber, "1"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'_', "(?0)"}, |
| " ", |
| {'+', "(?1)"}, |
| " ", |
| {'%', "(?x)"}, |
| " ", |
| {'%', "(?X)"}, |
| " ", |
| {'*', "(?\?)"}, // Break tri-graph |
| " ", |
| {'r', "(01)"}, |
| " ", |
| {'Q', "(0x)"}, |
| " ", |
| {'Q', "(0X)"}, |
| " ", |
| {'q', "(bx)"}, |
| " ", |
| {'q', "(bX)"}, |
| " ", |
| {'f', "(b0)"}, |
| " ", |
| {'r', "(b1)"}, |
| " ", |
| {'P', "(0?)"}, |
| " ", |
| {'f', "(10)"}, |
| " ", |
| {'M', "(1x)"}, |
| " ", |
| {'M', "(1X)"}, |
| " ", |
| {'N', "(1?)"}, |
| " ", |
| {'F', "(x0)"}, |
| " ", |
| {'F', "(X0)"}, |
| " ", |
| {'R', "(x1)"}, |
| " ", |
| {'R', "(X1)"}, |
| " ", |
| {'B', "(x?)"}, |
| " ", |
| {'B', "(X?)"}, |
| " ", |
| {TK_endtable, "endtable"}, |
| " ", |
| {SymbolIdentifier, "b0"}, |
| " ", |
| {SymbolIdentifier, "bx"}, |
| " ", |
| {SymbolIdentifier, "x1"}, |
| " ", |
| {SymbolIdentifier, "X0"}, |
| " ", |
| {TK_DecNumber, "10"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| // TK_DecNumber inside UDP should be rejected, and will be caught by parser |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {TK_OTHER, "321"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'1', "1"}, |
| {'0', "0"}, |
| {'1', "1"}, |
| {'0', "0"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'1', "1"}, |
| {'0', "0"}, |
| "\t", |
| {'1', "1"}, |
| {'0', "0"}}, |
| {{TK_primitive, "primitive"}, |
| " ", |
| {TK_table, "table"}, |
| " ", |
| {'1', "1"}, |
| {'0', "0"}, |
| "\n", |
| {PP_ifdef, "`ifdef"}, |
| " ", |
| {PP_Identifier, "BLAH"}, |
| "\n", |
| {'1', "1"}, |
| {'0', "0"}}, |
| {// should not crash or stack-underflow |
| {TK_endprimitive, "endprimitive"}}, |
| {// should not crash or stack-underflow |
| {TK_endprimitive, "endprimitive"}, |
| " ", |
| {TK_endprimitive, "endprimitive"}}, |
| {// should not crash or stack-underflow |
| {TK_EOL_COMMENT, "//zzz"}, |
| "\n", |
| {TK_endprimitive, "endprimitive"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kUnfilteredUDPTests = { |
| {{TK_primitive, "primitive"}, |
| {TK_SPACE, " "}, |
| {TK_table, "table"}, |
| {TK_SPACE, " "}, |
| {'1', "1"}, |
| {'0', "0"}, |
| {TK_COMMENT_BLOCK, "/*comment*/"}, |
| {'1', "1"}, |
| {'0', "0"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kTimingCheckTests = { |
| {{TK_Shold, "$hold"}}, {{TK_Snochange, "$nochange"}}, |
| {{TK_Speriod, "$period"}}, {{TK_Srecovery, "$recovery"}}, |
| {{TK_Ssetup, "$setup"}}, {{TK_Ssetuphold, "$setuphold"}}, |
| {{TK_Sskew, "$skew"}}, {{TK_Swidth, "$width"}}, |
| {{TK_Sfullskew, "$fullskew"}}, {{TK_Srecrem, "$recrem"}}, |
| {{TK_Sremoval, "$removal"}}, {{TK_Stimeskew, "$timeskew"}}, |
| {{TKK_attribute, "$attribute"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kSystemTaskFunctionTests = { |
| {{SystemTFIdentifier, "$display"}}, {{SystemTFIdentifier, "$error"}}, |
| {{SystemTFIdentifier, "$info"}}, {{SystemTFIdentifier, "$warning"}}, |
| {{SystemTFIdentifier, "$fatal"}}, {{SystemTFIdentifier, "$finish"}}, |
| {{SystemTFIdentifier, "$stop"}}, {{SystemTFIdentifier, "$hammertime"}}, |
| {{SystemTFIdentifier, "$__MAGIC__"}}, {{SystemTFIdentifier, "$thechosen1"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kPreprocessorTests = { |
| {{}, ""}, |
| {{PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "true"}, |
| " ", |
| {PP_define_body, "false"}, |
| "\n"}, |
| {" ", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "SIMULTION"}, |
| {PP_define_body, ""}, |
| "\n"}, |
| { |
| {PP_elsif, "`elsif"}, |
| "\n", |
| }, |
| {{PP_elsif, "`elsif"}, "\n", {SymbolIdentifier, "foo"}}, |
| {{PP_elsif, "`elsif"}, " ", {PP_Identifier, "foo"}, "\n"}, |
| {{PP_elsif, "`elsif"}, " ", {PP_Identifier, "foo"}, " ", "\n"}, |
| {" ", {PP_elsif, "`elsif"}, " ", {PP_Identifier, "foo"}, " ", "\n"}, |
| {" ", {PP_elsif, "`elsif"}, " ", {PP_Identifier, "foo"}, "\n"}, |
| {" ", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "BAR"}, |
| {PP_define_body, ""}, |
| "\n"}, |
| {"\t\t", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "BEAR"}, |
| {PP_define_body, ""}, |
| "\n"}, |
| {{PP_else, "`else"}, "\n"}, |
| {{PP_else, "`else"}, " ", {SymbolIdentifier, "blah"}, "\n"}, |
| {{PP_endif, "`endif"}, "\n"}, |
| {{PP_endif, "`endif"}, " ", {SymbolIdentifier, "blah"}, "\n"}, |
| {{PP_ifdef, "`ifdef"}, " ", {PP_Identifier, "evil"}, "\n"}, |
| {" ", |
| {PP_ifdef, "`ifdef"}, |
| " ", |
| {PP_Identifier, "dont_be_evil"}, |
| "\n"}, |
| {" ", |
| {PP_undef, "`undef"}, |
| "\t", |
| {PP_Identifier, "dont_be_evil"}, |
| "\t\n"}, |
| {{PP_ifndef, "`ifndef"}, " ", {PP_Identifier, "dont_be_evil"}, "\n"}, |
| {{PP_include, "`include"}, |
| " ", |
| {TK_StringLiteral, "\"lib/standard_cells.v\""}, |
| "\n"}, |
| {{PP_undef, "`undef"}, " ", {PP_Identifier, "behavior"}, "\n"}, |
| {{PP_ifdef, "`ifdef"}, |
| " ", |
| {PP_Identifier, "god_mode"}, |
| "\n", |
| {PP_define, "`define"}, |
| " ", |
| {PP_Identifier, "private"}, |
| " ", |
| {PP_define_body, "public"}, |
| "\n", |
| {PP_elsif, "`elsif"}, |
| " ", |
| {PP_Identifier, "hacker_mode"}, |
| "\n", |
| " ", |
| {PP_elsif, "`elsif"}, |
| " ", |
| {PP_Identifier, "sneaky_mode"}, |
| " \n", |
| " ", |
| {PP_elsif, "`elsif"}, |
| " ", |
| {PP_Identifier, "squeaky_mode"}, |
| "\n", |
| {PP_else, "`else"}, |
| "\n", |
| {PP_endif, "`endif"}, |
| "\n"}, |
| // Token concatenations |
| { |
| {PP_TOKEN_CONCAT, "``"}, |
| }, |
| { |
| {PP_TOKEN_CONCAT, "``"}, |
| "\n", |
| }, |
| { |
| " ", |
| {PP_TOKEN_CONCAT, "``"}, |
| " ", |
| }, |
| { |
| {SymbolIdentifier, "ab"}, |
| {PP_TOKEN_CONCAT, "``"}, |
| {SymbolIdentifier, "cd"}, |
| }, |
| }; |
| |
| static std::initializer_list<LexerTestData> kUnfilteredPreprocessorTests = { |
| {{PP_else, "`else"}, |
| {TK_SPACE, " "}, |
| {TK_EOL_COMMENT, "// comment"}, |
| {TK_NEWLINE, "\n"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kUnfilteredDirectiveTests = { |
| {{DR_timescale, "`timescale"}, |
| {TK_SPACE, " "}, |
| {TK_TimeLiteral, "1ps"}, |
| {'/', "/"}, |
| {TK_TimeLiteral, "1ps"}, |
| {TK_NEWLINE, "\n"}}, |
| // TODO(b/134180314): lexer current drops tokens from pragma sections, |
| // but instead emit the tokens and filter them out. |
| // {{DR_pragma, "`pragma"}, " fragma", {TK_NEWLINE, "\n"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kDirectiveTests = { |
| {{DR_timescale, "`timescale"}}, |
| {{DR_timescale, "`timescale"}, |
| " ", |
| {TK_TimeLiteral, "1ps"}, |
| {'/', "/"}, |
| {TK_TimeLiteral, "1ps"}}, |
| {" ", |
| {DR_timescale, "`timescale"}, |
| " ", |
| {TK_TimeLiteral, "1ps"}, |
| {'/', "/"}, |
| {TK_TimeLiteral, "1ps"}}, |
| {{DR_timescale, "`timescale"}, |
| " ", |
| {TK_TimeLiteral, "1s"}, |
| " ", |
| {'/', "/"}, |
| " ", |
| {TK_TimeLiteral, "1ms"}}, |
| {{DR_timescale, "`timescale"}, |
| " ", |
| {TK_TimeLiteral, "100ps"}, |
| " ", |
| {'/', "/"}, |
| " ", |
| {TK_TimeLiteral, "100ps"}}, |
| {{DR_timescale, "`timescale"}, |
| " ", |
| {TK_DecNumber, "100"}, |
| " ", |
| {TK_timescale_unit, "ps"}, |
| " ", |
| {'/', "/"}, |
| " ", |
| {TK_DecNumber, "100"}, |
| " ", |
| {TK_timescale_unit, "ps"}}, |
| {{DR_celldefine, "`celldefine"}}, |
| {{DR_celldefine, "`celldefine"}, "\n", {TK_module, "module"}}, |
| {{DR_endcelldefine, "`endcelldefine"}}, |
| {{DR_resetall, "`resetall"}}, |
| {{DR_unconnected_drive, "`unconnected_drive"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_nounconnected_drive, "`nounconnected_drive"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_default_decay_time, "`default_decay_time"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_default_decay_time, "`default_decay_time"}, |
| " ", |
| {TK_infinite, "infinite"}}, |
| {{DR_default_trireg_strength, "`default_trireg_strength"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_delay_mode_path, "`delay_mode_path"}, " "}, |
| {{DR_delay_mode_unit, "`delay_mode_unit"}, " ", {SymbolIdentifier, "blah"}}, |
| {{DR_delay_mode_zero, "`delay_mode_zero"}, " ", {SymbolIdentifier, "blah"}}, |
| {{DR_disable_portfaults, "`disable_portfaults"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_enable_portfaults, "`enable_portfaults"}, |
| " ", |
| {SymbolIdentifier, "blah"}}, |
| {{DR_suppress_faults, "`suppress_faults"}, " ", {SymbolIdentifier, "blah"}}, |
| // TODO(b/134180314): lexer current drops tokens from pragma sections, |
| // but instead emit the tokens and filter them out. |
| // {{DR_uselib, "`uselib"}, " lib=schmoozelib\n"}, |
| {{DR_protect, "`protect"}}, |
| {{DR_endprotect, "`endprotect"}}, |
| {{DR_begin_keywords, "`begin_keywords"}, |
| " ", |
| {SymbolIdentifier, "random"}, |
| " ", |
| {TK_StringLiteral, "\"keywords\""}}, |
| {{DR_end_keywords, "`end_keywords"}}, |
| {{DR_default_nettype, "`default_nettype"}, " ", {SymbolIdentifier, "blah"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kLibraryTests = { |
| { |
| {TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "1mylibpath/"}, // not an identifier |
| ';', |
| {SymbolIdentifier, "foo_bar_pkg"}, // not a file-path |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| // with newlines instead of spaces |
| {TK_library, "library"}, |
| {TK_NEWLINE, "\n"}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_NEWLINE, "\n"}, |
| {TK_FILEPATH, "6666/"}, // not a number |
| {TK_NEWLINE, "\n"}, |
| ';', |
| {SymbolIdentifier, "foo_bar_pkg"}, // not a file-path |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| // with comments |
| {TK_library, "library"}, |
| {TK_COMMENT_BLOCK, "/*c1*/"}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "2222"}, // not a number |
| ';', |
| {TK_COMMENT_BLOCK, "/*c3*/"}, |
| {SymbolIdentifier, "foo_bar_pkg"}, // not a file-path |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "_my_lib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "_1my_lib_path/"}, // underscores |
| ';', |
| {SymbolIdentifier, "foo_bar_pkg"}, // not a file-path |
| {TK_NEWLINE, "\n"}, |
| }, |
| { |
| {TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "_my_lib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "1my-lib-path/"}, // dashes |
| ';', |
| {SymbolIdentifier, "foo_bar_pkg"}, // not a file-path |
| {TK_NEWLINE, "\n"}, |
| }, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "/path1"}, // absolute path |
| ',', |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "/path2/path3"}, |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "*.v"}, // * wildcard |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "foo?.v"}, // ? wildcard |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "foo/"}, |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "Foo/*.v"}, |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_library, "library"}, |
| {TK_SPACE, " "}, |
| {SymbolIdentifier, "mylib"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "*.v"}, |
| {TK_SPACE, " "}, |
| '-', |
| {TK_incdir, "incdir"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "/path/to/files"}, // absolute path |
| ',', |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "/path/to/morefiles"}, |
| ';', |
| {TK_NEWLINE, "\n"}, |
| {SymbolIdentifier, "not_a_path"}}, |
| {{TK_include, "include"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "foo/*.v"}, |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_include, "include"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "../../foo/*.v"}, // up-dir, relative |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_include, "include"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "../../foo/..."}, // ... wildcard |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_include, "include"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "../foo/.../*.vg"}, // ... wildcard |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| {{TK_include, "include"}, |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "foo/*.v"}, |
| ',', |
| {TK_SPACE, " "}, |
| {TK_FILEPATH, "bar/*.vg"}, |
| ';', |
| {TK_NEWLINE, "\n"}}, |
| }; |
| |
| static std::initializer_list<LexerTestData> kLexicalErrorTests = { |
| // TODO(fangism): Return different error enums for different errors. |
| {{TK_OTHER, "111wire"}}, |
| {{TK_wire, "wire"}, " ", {TK_OTHER, "111wire"}, {';', ";"}}, |
| {{TK_OTHER, "`111macro"}, "\n"}, |
| {{TK_OTHER, "`111macrocall"}, {'(', "("}, {')', ")"}, "\n"}, |
| {{TK_OTHER, "`"}}, |
| {{TK_OTHER, "`"}, " "}, |
| {{TK_OTHER, "`"}, "\t"}, |
| {{TK_OTHER, "`"}, "\n"}, |
| {{TK_OTHER, "`"}, {TK_EOL_COMMENT, "//"}, "\n"}, |
| {{TK_OTHER, "`"}, {TK_COMMENT_BLOCK, "/* */"}}, |
| {{TK_OTHER, "`"}, {TK_DecNumber, "11"}}, |
| {{TK_OTHER, "`"}, " ", {SymbolIdentifier, "spacebad"}, "\n"}, |
| {{PP_TOKEN_CONCAT, "``"}, {TK_OTHER, "`"}}, // triple-tick breakdown |
| {{TK_OTHER, "\""}, "\n"}, |
| {{TK_OTHER, "\"unterminated string literal"}}, |
| {{TK_OTHER, "\"unterminated string literal"}, "\n"}, |
| {{TK_OTHER, "\"unterminated \\\nstring \\\nliteral"}, "\n"}, |
| {{TK_OTHER, "`\"unterminated eval string literal"}}, |
| {{TK_OTHER, "`\"unterminated eval string literal\n"}}, |
| {{TK_OTHER, "`\"unterminated \"eval\" string literal"}}, |
| {{TK_OTHER, "/*"}}, |
| {{TK_OTHER, "/*\n"}}, |
| {{TK_OTHER, "/* interminated comment"}}, |
| // Unterminated string literal inside macro call args |
| {{MacroCallId, "`b"}, '(', {TK_OTHER, "\");"}}, |
| {{MacroCallId, "`c"}, '(', {TK_OTHER, "/*"}}, |
| // Rejected ACSII characters |
| {{TK_OTHER, "\x7F"}}, |
| {{TK_OTHER, "\x80"}}, |
| {{TK_OTHER, "\xFF"}}, |
| }; |
| |
| TEST(VerilogLexerTest, LexicalErrors) { TestLexer(kLexicalErrorTests); } |
| TEST(VerilogLexerTest, Comments) { TestLexer(kCommentTests); } |
| TEST(VerilogLexerTest, Attributes) { TestLexer(kAttributeTests, TK_ATTRIBUTE); } |
| TEST(VerilogLexerTest, AttributesSequence) { |
| TestLexer(kAttributeSequenceTests); |
| } |
| TEST(VerilogLexerTest, MacroCalls) { TestLexer(kMacroCallTests); } |
| TEST(VerilogLexerTest, MacroCallsUnfiltered) { |
| TestLexer(kUnfilteredMacroCallTests); |
| } |
| TEST(VerilogLexerTest, MacroDefines) { TestLexer(kMacroDefineTests); } |
| TEST(VerilogLexerTest, SymbolIdentifiers) { |
| TestFilteredLexer(kSymbolIdentifierTests, SymbolIdentifier); |
| } |
| TEST(VerilogLexerTest, EscapedIdentifiers) { |
| TestFilteredLexer(kEscapedIdentifierTests, EscapedIdentifier); |
| } |
| TEST(VerilogLexerTest, MacroIdentifiers) { |
| TestLexer(kMacroIdentifierTests, MacroIdentifier); |
| } |
| TEST(VerilogLexerTest, Protected) { TestLexer(kProtectedTests); } |
| TEST(VerilogLexerTest, Keywords) { TestFilteredLexer(kKeywordTests); } |
| TEST(VerilogLexerTest, SingleCharToken) { |
| TestLexer(kSingleCharTokenTests, verible::SingleChar); |
| } |
| TEST(VerilogLexerTest, RealTime) { TestLexer(kRealTimeTests, TK_RealTime); } |
| TEST(VerilogLexerTest, BasedNumbers) { TestLexer(kBasedNumberTests); } |
| TEST(VerilogLexerTest, TimeLiteral) { |
| TestLexer(kTimeLiteralTests, TK_TimeLiteral); |
| } |
| TEST(VerilogLexerTest, Tricky) { TestLexer(kTrickyTests); } |
| TEST(VerilogLexerTest, Sequence) { TestLexer(kSequenceTests); } |
| TEST(VerilogLexerTest, StringLiteral) { |
| TestLexer(kStringLiteralTests, TK_StringLiteral); |
| } |
| TEST(VerilogLexerTest, EvalStringLiteral) { |
| TestLexer(kEvalStringLiteralTests, TK_EvalStringLiteral); |
| } |
| TEST(VerilogLexerTest, Edges) { TestLexer(kEdgeTests); } |
| TEST(VerilogLexerTest, UDP) { TestLexer(kUDPTests); } |
| TEST(VerilogLexerTest, UDPUnfiltered) { TestLexer(kUnfilteredUDPTests); } |
| TEST(VerilogLexerTest, ContextKeywords) { TestLexer(kContextKeywordTests); } |
| TEST(VerilogLexerTest, BuiltinMethods) { |
| TestLexer(kBuiltinMethodKeywordTests); |
| } |
| TEST(VerilogLexerTest, TimingChecks) { TestFilteredLexer(kTimingCheckTests); } |
| TEST(VerilogLexerTest, SystemTaskFunctionChecks) { |
| TestFilteredLexer(kSystemTaskFunctionTests); |
| } |
| TEST(VerilogLexerTest, Preprocessor) { TestLexer(kPreprocessorTests); } |
| TEST(VerilogLexerTest, PreprocessorUnfiltered) { |
| TestLexer(kUnfilteredPreprocessorTests); |
| } |
| TEST(VerilogLexerTest, Directives) { TestLexer(kDirectiveTests); } |
| TEST(VerilogLexerTest, DirectivesUnfiltered) { |
| TestLexer(kUnfilteredDirectiveTests); |
| } |
| TEST(VerilogLexerTest, Library) { TestLexer(kLibraryTests); } |
| |
| TEST(RecursiveLexTextTest, Basic) { |
| constexpr absl::string_view text("hello;"); |
| std::vector<TokenInfo> tokens; |
| RecursiveLexText(text, |
| [&tokens](const TokenInfo& t) { tokens.push_back(t); }); |
| EXPECT_THAT(tokens, |
| ElementsAre(TokenInfo(SymbolIdentifier, text.substr(0, 5)), |
| TokenInfo(';', text.substr(5, 1)))); |
| } |
| |
| } // namespace |
| } // namespace verilog |