From 74ccde2448711de113a7eaab75b8272a3298059a Mon Sep 17 00:00:00 2001
From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com>
Date: Tue, 9 Aug 2022 12:51:12 +0200
Subject: [PATCH] Deny WATCH statements. (#1942)

Throw error if WATCH encountered in NMODL.
---
 modcc/parser.cpp                | 16 ++++++++++++++++
 modcc/parser.hpp                |  1 +
 modcc/token.cpp                 |  2 ++
 modcc/token.hpp                 |  3 +++
 test/unit-modcc/test_parser.cpp |  4 ++++
 5 files changed, 26 insertions(+)

diff --git a/modcc/parser.cpp b/modcc/parser.cpp
index 75bf1a57..965e4946 100644
--- a/modcc/parser.cpp
+++ b/modcc/parser.cpp
@@ -1008,6 +1008,8 @@ expression_ptr Parser::parse_statement() {
         return parse_solve();
     case tok::local:
         return parse_local();
+    case tok::watch:
+        return parse_watch();
     case tok::identifier:
         return parse_line_expression();
     case tok::conserve:
@@ -1399,6 +1401,7 @@ expression_ptr Parser::parse_unaryop() {
 /// expects one of :
 ///  ::  number
 ///  ::  identifier
+///  ::  watch
 ///  ::  call
 ///  ::  parenthesis expression (parsed recursively)
 ///  ::  prefix binary operators
@@ -1656,6 +1659,19 @@ conductance_statement_error:
     return nullptr;
 }
 
+// WATCH (cond) flag
+expression_ptr Parser::parse_watch() {
+    Location loc = location_; // solve location for expression
+    get_token();              // consume keyword
+
+    parse_parenthesis_expression();
+    parse_expression();
+
+    error("WATCH statements are not supported in modcc.", loc);
+    return nullptr;
+}
+
+
 expression_ptr Parser::parse_if() {
     Token if_token = token_;
     get_token(); // consume 'if'
diff --git a/modcc/parser.hpp b/modcc/parser.hpp
index 84e56316..bf82af8d 100644
--- a/modcc/parser.hpp
+++ b/modcc/parser.hpp
@@ -36,6 +36,7 @@ public:
     expression_ptr parse_local();
     expression_ptr parse_solve();
     expression_ptr parse_conductance();
+    expression_ptr parse_watch();
     expression_ptr parse_block(bool);
     expression_ptr parse_initial();
     expression_ptr parse_compartment_statement();
diff --git a/modcc/token.cpp b/modcc/token.cpp
index 7ba2f71b..db338d16 100644
--- a/modcc/token.cpp
+++ b/modcc/token.cpp
@@ -74,6 +74,7 @@ static Keyword keywords[] = {
     {"exprelr",     tok::exprelr},
     {"safeinv",     tok::safeinv},
     {"CONDUCTANCE", tok::conductance},
+    {"WATCH",       tok::watch},
     {nullptr,       tok::reserved},
 };
 
@@ -152,6 +153,7 @@ static TokenString token_strings[] = {
     {"sin",         tok::sin},
     {"cnexp",       tok::cnexp},
     {"CONDUCTANCE", tok::conductance},
+    {"WATCH",       tok::watch},
     {"error",       tok::reserved},
 };
 
diff --git a/modcc/token.hpp b/modcc/token.hpp
index 0e09c385..a953ae2e 100644
--- a/modcc/token.hpp
+++ b/modcc/token.hpp
@@ -83,6 +83,9 @@ enum class tok {
 
     conductance,
 
+    // trap unsupported keywords
+    watch,
+
     reserved, // placeholder for generating keyword lookup
 };
 
diff --git a/test/unit-modcc/test_parser.cpp b/test/unit-modcc/test_parser.cpp
index 5916704c..18d3e19c 100644
--- a/test/unit-modcc/test_parser.cpp
+++ b/test/unit-modcc/test_parser.cpp
@@ -279,6 +279,10 @@ TEST(Parser, parse_conductance) {
     }
 }
 
+TEST(Parser, parse_watch) {
+    EXPECT_TRUE(check_parse_fail(&Parser::parse_watch, "WATCH( 0 < 1) 42"));
+}
+
 TEST(Parser, parse_if) {
     std::unique_ptr<IfExpression> s;
 
-- 
GitLab