From 6d98823b46eda1db1de8bdf01dd538e513ef2cab Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 15 Jun 2022 19:12:48 +0200 Subject: [PATCH 1/4] Add semantic check for empty unit name --- src/parser/nmodl.yy | 1 - src/visitors/semantic_analysis_visitor.cpp | 11 +++++++++++ src/visitors/semantic_analysis_visitor.hpp | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/parser/nmodl.yy b/src/parser/nmodl.yy index 5867f396d2..7d37328d90 100644 --- a/src/parser/nmodl.yy +++ b/src/parser/nmodl.yy @@ -618,7 +618,6 @@ units : { unit : "(" { scanner.scan_unit(); } ")" { - // @todo Empty units should be handled in semantic analysis auto unit = scanner.get_unit(); auto text = unit->eval(); $$ = new ast::Unit(unit); diff --git a/src/visitors/semantic_analysis_visitor.cpp b/src/visitors/semantic_analysis_visitor.cpp index eecfb74262..3af41ed196 100644 --- a/src/visitors/semantic_analysis_visitor.cpp +++ b/src/visitors/semantic_analysis_visitor.cpp @@ -2,8 +2,10 @@ #include "ast/function_block.hpp" #include "ast/procedure_block.hpp" #include "ast/program.hpp" +#include "ast/string.hpp" #include "ast/suffix.hpp" #include "ast/table_statement.hpp" +#include "ast/unit.hpp" #include "utils/logger.hpp" #include "visitors/visitor_utils.hpp" @@ -66,5 +68,14 @@ void SemanticAnalysisVisitor::visit_destructor_block(const ast::DestructorBlock& /// --> } +void SemanticAnalysisVisitor::visit_unit(const ast::Unit& node) { + /// <-- This code is for check 3 + if (node.get_name()->get_value().empty()) { + logger->warn("SemanticAnalysisVisitor:: An unit cannot be created without name."); + check_fail = true; + } + /// --> +} + } // namespace visitor } // namespace nmodl diff --git a/src/visitors/semantic_analysis_visitor.hpp b/src/visitors/semantic_analysis_visitor.hpp index 54574f584b..92cdb0e641 100644 --- a/src/visitors/semantic_analysis_visitor.hpp +++ b/src/visitors/semantic_analysis_visitor.hpp @@ -26,6 +26,7 @@ * 1. Check that a function or a procedure containing a TABLE statement contains only one argument * (mandatory in mod2c). * 2. Check that destructor blocks are only inside mod file that are point_process + * 3. Check that unit always have a name */ #include "ast/ast.hpp" #include "visitors/ast_visitor.hpp" @@ -56,6 +57,9 @@ class SemanticAnalysisVisitor: public ConstAstVisitor { /// Visit destructor and check that the file is of type POINT_PROCESS or ARTIFICIAL_CELL void visit_destructor_block(const ast::DestructorBlock& node) override; + /// Visit an unit and check that name is not empty + void visit_unit(const ast::Unit& node) override; + public: SemanticAnalysisVisitor() = default; From 30cd3868501e2059ff17e6b5e118959e1fbfaa3d Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 16 Jun 2022 11:39:44 +0200 Subject: [PATCH 2/4] error instead of warning --- src/visitors/semantic_analysis_visitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visitors/semantic_analysis_visitor.cpp b/src/visitors/semantic_analysis_visitor.cpp index 3af41ed196..eb46067cb8 100644 --- a/src/visitors/semantic_analysis_visitor.cpp +++ b/src/visitors/semantic_analysis_visitor.cpp @@ -71,7 +71,7 @@ void SemanticAnalysisVisitor::visit_destructor_block(const ast::DestructorBlock& void SemanticAnalysisVisitor::visit_unit(const ast::Unit& node) { /// <-- This code is for check 3 if (node.get_name()->get_value().empty()) { - logger->warn("SemanticAnalysisVisitor:: An unit cannot be created without name."); + logger->error("SemanticAnalysisVisitor:: An unit cannot be created without name."); check_fail = true; } /// --> From b511a608b45f97027c09eeaca22ddbd4091551d4 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 13 Feb 2023 14:28:28 +0100 Subject: [PATCH 3/4] Fix merge --- src/visitors/semantic_analysis_visitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visitors/semantic_analysis_visitor.cpp b/src/visitors/semantic_analysis_visitor.cpp index d1d820b4fe..1b47e9c14b 100644 --- a/src/visitors/semantic_analysis_visitor.cpp +++ b/src/visitors/semantic_analysis_visitor.cpp @@ -168,8 +168,8 @@ void SemanticAnalysisVisitor::visit_unit(const ast::Unit& node) { /// <-- This code is for check 8 if (node.get_name()->get_value().empty()) { logger->error("SemanticAnalysisVisitor:: An unit cannot be created without name."); + check_fail = true; } - check_fail = true; } } // namespace visitor From 60f1c0ee4a4d966aeb4850d06636a5ed494c97ac Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 13 Feb 2023 17:04:21 +0100 Subject: [PATCH 4/4] Add unit tests --- test/unit/visitor/semantic_analysis.cpp | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/unit/visitor/semantic_analysis.cpp b/test/unit/visitor/semantic_analysis.cpp index 5dc5f1a44f..5d208e22dd 100644 --- a/test/unit/visitor/semantic_analysis.cpp +++ b/test/unit/visitor/semantic_analysis.cpp @@ -165,3 +165,34 @@ SCENARIO("FUNCTION_TABLE block", "[visitor][semantic_analysis]") { } } } + +SCENARIO("UNITS block", "[visitor][semantic_analysis]") { + GIVEN("A mod file with UNITS empty") { + std::string nmodl_text = R"( + UNITS {} + )"; + THEN("Semantic analysis should success") { + REQUIRE_FALSE(run_semantic_analysis_visitor(nmodl_text)); + } + } + GIVEN("A mod file with UNITS with space as name") { + std::string nmodl_text = R"( + UNITS { + ( ) = (millivolt) + } + )"; + THEN("Semantic analysis should success") { + REQUIRE_FALSE(run_semantic_analysis_visitor(nmodl_text)); + } + } + GIVEN("A mod file with UNITS with no name") { + std::string nmodl_text = R"( + UNITS { + () = (millivolt) + } + )"; + THEN("Semantic analysis should fail") { + REQUIRE(run_semantic_analysis_visitor(nmodl_text)); + } + } +}