Give a more useful parse error message for "undeclared variable -1".
authorMorgan Deters <mdeters@cs.nyu.edu>
Wed, 19 Jun 2013 15:09:49 +0000 (11:09 -0400)
committerMorgan Deters <mdeters@cs.nyu.edu>
Wed, 19 Jun 2013 15:09:49 +0000 (11:09 -0400)
Indeed, "-1" is a valid user symbol in SMT-LIB; this commit makes a small
change to the parser to detect when something like "-1" is used but
undeclared, and adds a note to the error message giving the syntax for
unary minus.

src/parser/parser.cpp
src/parser/parser.h
src/parser/smt2/smt2.h

index fa2a1e744c00d919ab869716ec8d547ed7f498d8..a7834a5aaf096c166723fc847680d774b79837f5 100644 (file)
@@ -374,7 +374,8 @@ void Parser::reserveSymbolAtAssertionLevel(const std::string& varName) {
 
 void Parser::checkDeclaration(const std::string& varName,
                               DeclarationCheck check,
-                              SymbolType type)
+                              SymbolType type,
+                              std::string notes)
     throw(ParserException) {
   if(!d_checksEnabled) {
     return;
@@ -384,14 +385,16 @@ void Parser::checkDeclaration(const std::string& varName,
   case CHECK_DECLARED:
     if( !isDeclared(varName, type) ) {
       parseError("Symbol " + varName + " not declared as a " +
-                 (type == SYM_VARIABLE ? "variable" : "type"));
+                 (type == SYM_VARIABLE ? "variable" : "type") +
+                 (notes.size() == 0 ? notes : "\n" + notes));
     }
     break;
 
   case CHECK_UNDECLARED:
     if( isDeclared(varName, type) ) {
       parseError("Symbol " + varName + " previously declared as a " +
-                 (type == SYM_VARIABLE ? "variable" : "type"));
+                 (type == SYM_VARIABLE ? "variable" : "type") +
+                 (notes.size() == 0 ? notes : "\n" + notes));
     }
     break;
 
index b4e79b427df7c5320de6033635a5a6834d9b4e7c..883f1f12b56e6fad8dd14774cf349584885c8da9 100644 (file)
@@ -312,7 +312,8 @@ public:
    * @throws ParserException if checks are enabled and the check fails
    */
   void checkDeclaration(const std::string& name, DeclarationCheck check,
-                        SymbolType type = SYM_VARIABLE) throw(ParserException);
+                        SymbolType type = SYM_VARIABLE,
+                        std::string notes = "") throw(ParserException);
 
   /**
    * Reserve a symbol at the assertion level.
index c50a0972b15a30344993c5b80c3188b523708476..3f1d3b087ba866d5d397d520efaecd6c927aa738 100644 (file)
@@ -97,6 +97,30 @@ public:
     return getExprManager()->mkConst(AbstractValue(Integer(name.substr(1))));
   }
 
+  /**
+   * Smt2 parser provides its own checkDeclaration, which does the
+   * same as the base, but with some more helpful errors.
+   */
+  void checkDeclaration(const std::string& name, DeclarationCheck check,
+                        SymbolType type = SYM_VARIABLE,
+                        std::string notes = "") throw(ParserException) {
+    // if the symbol is something like "-1", we'll give the user a helpful
+    // syntax hint.  (-1 is a valid identifier in SMT-LIB, NOT unary minus.)
+    if( check != CHECK_DECLARED ||
+        name[0] != '-' ||
+        name.find_first_not_of("0123456789", 1) != std::string::npos ) {
+      this->Parser::checkDeclaration(name, check, type, notes);
+      return;
+    }
+
+    std::stringstream ss;
+    ss << notes
+       << "You may have intended to apply unary minus: `(- "
+       << name.substr(1)
+       << ")'\n";
+    this->Parser::checkDeclaration(name, check, type, ss.str());
+  }
+
 private:
 
   void addArithmeticOperators();