Skip to content

Commit

Permalink
Merge pull request #2 from xtofalex/error_testing
Browse files Browse the repository at this point in the history
error testing
  • Loading branch information
xtofalex authored May 11, 2023
2 parents 33bf6af + d95cf3b commit eeab5f4
Show file tree
Hide file tree
Showing 16 changed files with 260 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/VerilogConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ void VerilogConstructor::parse(const std::filesystem::path& path) {
}
currentPath_ = path;
std::ifstream inFile(path);
//LCOV_EXCL_START
if (not inFile.good()) {
std::string reason(path.string() + " is not a readable file");
throw VerilogException(reason);
}
//LCOV_EXCL_STOP
internalParse(inFile);
}

Expand Down
23 changes: 18 additions & 5 deletions src/VerilogParser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -233,18 +233,31 @@ list_of_module_instances: module_instance
number
: CONSTVAL_TK BASE_TK BASED_CONSTVAL_TK {
if ($2.size() == 2) {
if ($2[0] == 's' || $2[0] == 'S') {
//LCOV_EXCL_START
if (not ($2[0] == 's' || $2[0] == 'S')) {
//Following should not happen as long as lexer is correct
//should this be replaced by an assertion ?
std::ostringstream reason;
reason << "Parser error: "
<< $1 << $2 << $3 << " is not a valid number: wrong size character.\n"
<< " begin at line " << @$.begin.line << " col " << @$.begin.column << '\n'
<< " end at line " << @$.end.line << " col " << @$.end.column << "\n";
throw VerilogException(reason.str());
}
//LCOV_EXCL_STOP
$$ = Number($1, true, $2[1], $3);
} else if ($2.size() == 1) {
$$ = Number($1, false, $2[0], $3);
} else {
//LCOV_EXCL_START
//Same as previously: should not be accessible, as this is filtered by lexer.
std::ostringstream reason;
reason << "Parser error: "
<< $1 << $2 << $3 << " is not a valid number\n"
<< " begin at line " << @$.begin.line << " col " << @$.begin.column << '\n'
<< " end at line " << @$.end.line << " col " << @$.end.column << "\n";
<< $1 << $2 << $3 << " is not a valid number\n"
<< " begin at line " << @$.begin.line << " col " << @$.begin.column << '\n'
<< " end at line " << @$.end.line << " col " << @$.end.column << "\n";
throw VerilogException(reason.str());
//LCOV_EXCL_STOP
}
}
| CONSTVAL_TK {
Expand Down Expand Up @@ -389,4 +402,4 @@ void naja::verilog::VerilogParser::error(
<< " begin at line " << l.begin.line << " col " << l.begin.column << '\n'
<< " end at line " << l.end.line << " col " << l.end.column << "\n";
throw VerilogException(reason.str());
}
}
34 changes: 24 additions & 10 deletions src/VerilogScanner.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
%{
/* C++ string header, for string ops below */
#include <string>
#include <sstream>

#include "VerilogException.h"

/* Implementation of yyFlexScanner */
#include "VerilogScanner.h"
Expand Down Expand Up @@ -88,20 +91,26 @@ ESCAPED_IDENTIFIER \\[\\^!"#$%&',()*+\-.a-zA-Z0-9/{|}~[\]_:;<=>?@]+[\t\f ]
{COMMENT_BEGIN} { BEGIN(in_comment); }
<in_comment><<EOF>> {
BEGIN(INITIAL);
std::cerr << "Unclosed comment at line " << loc->end.line << " col " << loc->end.column << '\n';
yyterminate();
}
BEGIN(INITIAL);
std::ostringstream reason;
reason << "Unclosed comment at line "
<< loc->end.line << " col " << loc->end.column;
throw VerilogException(reason.str());
}
<in_comment>{NEWLINE} { loc->lines(); }
<in_comment>. { /* ignore characters in comment */ }
<in_comment>{COMMENT_END} { BEGIN(INITIAL); }
{ATTRIBUTE_BEGIN} { BEGIN(in_attribute); }
<in_attribute><<EOF>> {
BEGIN(INITIAL);
std::cerr << "Unclosed attribute at line " << loc->end.line << " col " << loc->end.column << '\n';
yyterminate();
}
BEGIN(INITIAL);
std::ostringstream reason;
reason << "Unclosed attribute at line "
<< loc->end.line << " col " << loc->end.column;
throw VerilogException(reason.str());
}
<in_attribute>{NEWLINE} { loc->lines(); }
<in_attribute>. { /* ignore characters in comment */ }
<in_attribute>{ATTRIBUTE_END} { BEGIN(INITIAL); }
Expand Down Expand Up @@ -134,6 +143,7 @@ assign { return token::ASSIGN_KW; }
\'[sS]?[bodhBODH] {
BEGIN(based_const);
//we don't need the "'" first character and we are sure that yytext is 's?b|o|...
std::cerr << "LEX: " << std::string(yytext+1) << std::endl;
yylval->build<std::string>(yytext+1);
return token::BASE_TK;
}
Expand All @@ -145,9 +155,13 @@ assign { return token::ASSIGN_KW; }
}

/* Last rule catches everything */
/* LCOV_EXCL_START */
. {
std::cerr << "Failed to match : " << yytext << '\n';
yyterminate();
std::ostringstream reason;
reason << "Failed to match: " << yytext << " at line "
<< loc->end.line << " col " << loc->end.column;
throw VerilogException(reason.str());
}
/* LCOV_EXCL_STOP */

%%
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(tests
NajaVerilogTest5.cpp
NajaVerilogTest6.cpp
NajaVerilogTest7.cpp
NajaVerilogTestMultipleFiles.cpp
NajaVerilogTestErrors.cpp
)

Expand Down
94 changes: 93 additions & 1 deletion test/NajaVerilogTest6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,99 @@ TEST(NajaVerilogTest6, test) {
ASSERT_EQ(1, constructor.modules_.size());
auto test = constructor.modules_[0];
EXPECT_EQ("test", test->name_);
EXPECT_EQ(1, constructor.modules_.size());
{
auto mod = constructor.modules_[0];
EXPECT_TRUE(mod->assigns_.empty());
}

constructor.setFirstPass(false);
constructor.parse(test6Path);
}
EXPECT_EQ(1, constructor.modules_.size());
auto mod = constructor.modules_[0];
EXPECT_FALSE(mod->assigns_.empty());
EXPECT_EQ(4, mod->assigns_.size());

{
auto assign = mod->assigns_[0];
EXPECT_EQ(1, assign.identifiers_.size());
auto identifier = assign.identifiers_[0];
EXPECT_EQ("n0", identifier.name_);
EXPECT_FALSE(identifier.range_.valid_);
auto expression = assign.expression_;
EXPECT_TRUE(expression.valid_);
EXPECT_EQ(naja::verilog::Expression::Type::IDENTIFIER, expression.value_.index());
auto leftId = std::get<naja::verilog::Expression::Type::IDENTIFIER>(expression.value_);
EXPECT_EQ("n1", leftId.name_);
EXPECT_FALSE(leftId.range_.valid_);
}

{
auto assign = mod->assigns_[1];
EXPECT_EQ(1, assign.identifiers_.size());
auto identifier = assign.identifiers_[0];
EXPECT_EQ("n1", identifier.name_);
EXPECT_FALSE(identifier.range_.valid_);
auto expression = assign.expression_;
EXPECT_TRUE(expression.valid_);
EXPECT_EQ(naja::verilog::Expression::Type::NUMBER, expression.value_.index());
auto leftId = std::get<naja::verilog::Expression::Type::NUMBER>(expression.value_);
EXPECT_TRUE(leftId.sign_);
EXPECT_EQ(naja::verilog::Number::BASED, leftId.value_.index());
auto leftBaseNumber = std::get<naja::verilog::Number::BASED>(leftId.value_);
EXPECT_FALSE(leftBaseNumber.signed_);
EXPECT_EQ(naja::verilog::BasedNumber::BINARY, leftBaseNumber.base_);
EXPECT_EQ(1, leftBaseNumber.size_);
EXPECT_EQ("0", leftBaseNumber.digits_);
}

{
auto assign = mod->assigns_[2];
EXPECT_EQ(2, assign.identifiers_.size());
auto id0 = assign.identifiers_[0];
EXPECT_EQ("n2", id0.name_);
EXPECT_TRUE(id0.range_.valid_);
EXPECT_EQ(3, id0.range_.msb_);
EXPECT_EQ(2, id0.range_.lsb_);
auto id1 = assign.identifiers_[1];
EXPECT_EQ("n2", id1.name_);
EXPECT_TRUE(id1.range_.valid_);
EXPECT_EQ(1, id1.range_.msb_);
EXPECT_EQ(0, id1.range_.lsb_);
auto expression = assign.expression_;
EXPECT_TRUE(expression.valid_);
EXPECT_EQ(naja::verilog::Expression::Type::CONCATENATION, expression.value_.index());
auto concatenation = std::get<naja::verilog::Expression::Type::CONCATENATION>(expression.value_);
EXPECT_EQ(3, concatenation.expressions_.size());
EXPECT_TRUE(concatenation.expressions_[2].valid_);
auto constant = concatenation.expressions_[2];
EXPECT_EQ(naja::verilog::Expression::NUMBER, constant.value_.index());
auto constantValue = std::get<naja::verilog::Expression::NUMBER>(constant.value_);
EXPECT_TRUE(constantValue.sign_);
EXPECT_EQ(naja::verilog::Number::BASED, constantValue.value_.index());
auto constantNumber = std::get<naja::verilog::Number::BASED>(constantValue.value_);
EXPECT_FALSE(constantNumber.signed_);
EXPECT_EQ(naja::verilog::BasedNumber::HEX, constantNumber.base_);
EXPECT_EQ(2, constantNumber.size_);
EXPECT_EQ("2", constantNumber.digits_);
}

{
auto assign = mod->assigns_[3];
EXPECT_EQ(1, assign.identifiers_.size());
auto identifier = assign.identifiers_[0];
EXPECT_EQ("n3", identifier.name_);
EXPECT_FALSE(identifier.range_.valid_);
auto expression = assign.expression_;
EXPECT_TRUE(expression.valid_);
EXPECT_EQ(naja::verilog::Expression::Type::NUMBER, expression.value_.index());
auto leftId = std::get<naja::verilog::Expression::Type::NUMBER>(expression.value_);
EXPECT_TRUE(leftId.sign_);
EXPECT_EQ(naja::verilog::Number::BASED, leftId.value_.index());
auto leftBaseNumber = std::get<naja::verilog::Number::BASED>(leftId.value_);
EXPECT_TRUE(leftBaseNumber.signed_);
EXPECT_EQ(naja::verilog::BasedNumber::HEX, leftBaseNumber.base_);
EXPECT_EQ(4, leftBaseNumber.size_);
EXPECT_EQ("F", leftBaseNumber.digits_);
}
}
32 changes: 31 additions & 1 deletion test/NajaVerilogTestErrors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,38 @@ using namespace naja::verilog;
#define NAJA_VERILOG_BENCHMARKS "Undefined"
#endif

TEST(NajaVerilogTestErrors, test) {
TEST(NajaVerilogTestErrors, testErrorPath) {
VerilogConstructorTest constructor;
std::filesystem::path errorPath("does_not_exist.v");
EXPECT_THROW(constructor.parse(errorPath), VerilogException);
}

TEST(NajaVerilogTestErrors, test0) {
std::filesystem::path error0Path(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("errors")
/ std::filesystem::path("error0.v"));
VerilogConstructorTest constructor;
EXPECT_THROW(constructor.parse(error0Path), VerilogException);
}

TEST(NajaVerilogTestErrors, test1) {
std::filesystem::path error1Path(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("errors")
/ std::filesystem::path("error1.v"));
VerilogConstructorTest constructor;
EXPECT_THROW(constructor.parse(error1Path), VerilogException);
}

TEST(NajaVerilogTestErrors, test2) {
std::filesystem::path error2Path(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("errors")
/ std::filesystem::path("error2.v"));
VerilogConstructorTest constructor;
EXPECT_THROW(constructor.parse(error2Path), VerilogException);
}
48 changes: 48 additions & 0 deletions test/NajaVerilogTestMultipleFiles.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "gtest/gtest.h"

#include <filesystem>
#include <fstream>

#include "VerilogConstructor.h"

using namespace naja::verilog;

#include "VerilogConstructorTest.h"

#ifndef NAJA_VERILOG_BENCHMARKS
#define NAJA_VERILOG_BENCHMARKS "Undefined"
#endif

TEST(NajaVerilogTestMultipleFiles, test) {
VerilogConstructorTest constructor;
std::filesystem::path multipleFilesPath(
std::filesystem::path(NAJA_VERILOG_BENCHMARKS)
/ std::filesystem::path("benchmarks")
/ std::filesystem::path("multifiles"));
VerilogConstructor::Paths paths;
paths.push_back(multipleFilesPath / std::filesystem::path("mod0.v"));
paths.push_back(multipleFilesPath / std::filesystem::path("mod1.v"));
paths.push_back(multipleFilesPath / std::filesystem::path("top.v"));
constructor.parse(paths);
ASSERT_EQ(3, constructor.modules_.size());
EXPECT_EQ("mod0", constructor.modules_[0]->name_);
EXPECT_EQ("mod1", constructor.modules_[1]->name_);
EXPECT_EQ("top", constructor.modules_[2]->name_);
ASSERT_EQ(2, constructor.modules_[0]->ports_.size());
ASSERT_EQ(2, constructor.modules_[1]->ports_.size());
ASSERT_EQ(2, constructor.modules_[2]->ports_.size());

constructor.setFirstPass(false);
constructor.parse(paths);


EXPECT_TRUE(constructor.modules_[0]->instances_.empty());
EXPECT_TRUE(constructor.modules_[1]->instances_.empty());
ASSERT_EQ(2, constructor.modules_[2]->instances_.size());
auto ins0 = constructor.modules_[2]->instances_[0];
EXPECT_EQ("ins0", ins0.name_);
EXPECT_EQ("mod0", ins0.model_);
auto ins1 = constructor.modules_[2]->instances_[1];
EXPECT_EQ("ins1", ins1.name_);
EXPECT_EQ("mod1", ins1.model_);
}
8 changes: 1 addition & 7 deletions test/VerilogConstructorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@ void VerilogConstructorTest::addAssign(
const naja::verilog::Identifiers& identifiers,
const naja::verilog::Expression& expression) {
if (not inFirstPass()) {
std::cerr << "Add assign: ";
for (auto identifier: identifiers) {
std::cerr << identifier.getDescription() << std::endl;
}
std::cerr << expression.getDescription() << std::endl;
//currentModule_->assigns_.push_back(
// Assign(naja::verilog::Identifier(parameterName), expression)
currentModule_->assigns_.push_back(Assign(identifiers, expression));
}
}
7 changes: 7 additions & 0 deletions test/VerilogConstructorTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,14 @@ class VerilogConstructorTest: public naja::verilog::VerilogConstructor {
};

struct Assign {
Assign(
const naja::verilog::Identifiers& identifiers,
const naja::verilog::Expression& expression):
identifiers_(identifiers),
expression_(expression)
{}
naja::verilog::Identifiers identifiers_ {};
naja::verilog::Expression expression_ {};
};

struct Module {
Expand Down
9 changes: 9 additions & 0 deletions test/benchmarks/errors/error0.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
Unterminated comment
*/

module test();
endmodule

/*
This is not terminated
7 changes: 7 additions & 0 deletions test/benchmarks/errors/error1.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
Unterminated pragma
*/

(* src = "/home/source/test.v"
module test();
endmodule
8 changes: 8 additions & 0 deletions test/benchmarks/errors/error2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Syntax error
*/

module test();
//Missing ";"
model ins
endmodule
2 changes: 2 additions & 0 deletions test/benchmarks/multifiles/mod0.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module mod0(input i, output o);
endmodule
2 changes: 2 additions & 0 deletions test/benchmarks/multifiles/mod1.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module mod1(input a, output b);
endmodule
Loading

0 comments on commit eeab5f4

Please sign in to comment.