blob: b10c883171bdf9ff2bb5fe110f58e53c32da9491 [file] [log] [blame]
// 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