LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/parser - parser_state.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 338 432 78.2 %
Date: 2026-09-28 09:33:01 Functions: 41 49 83.7 %
Branches: 192 296 64.9 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Parser state implementation.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "parser/parser_state.h"
      14                 :            : 
      15                 :            : #include <cvc5/cvc5.h>
      16                 :            : 
      17                 :            : #include <clocale>
      18                 :            : #include <fstream>
      19                 :            : #include <iostream>
      20                 :            : #include <iterator>
      21                 :            : #include <limits>
      22                 :            : #include <sstream>
      23                 :            : #include <unordered_set>
      24                 :            : 
      25                 :            : #include "base/check.h"
      26                 :            : #include "base/output.h"
      27                 :            : #include "expr/kind.h"
      28                 :            : #include "parser/commands.h"
      29                 :            : 
      30                 :            : using namespace std;
      31                 :            : 
      32                 :            : namespace cvc5 {
      33                 :            : namespace parser {
      34                 :            : 
      35                 :      23526 : ParserState::ParserState(ParserStateCallback* psc,
      36                 :            :                          Solver* solver,
      37                 :            :                          SymManager* sm,
      38                 :      23526 :                          ParsingMode parsingMode)
      39                 :      23526 :     : d_solver(solver),
      40                 :      47052 :       d_tm(d_solver->getTermManager()),
      41                 :      23526 :       d_psc(psc),
      42                 :      23526 :       d_symman(sm),
      43                 :      23526 :       d_symtab(sm->getSymbolTable()),
      44                 :      23526 :       d_checksEnabled(true),
      45                 :      23526 :       d_parsingMode(parsingMode),
      46                 :      47052 :       d_parseOnly(d_solver->getOptionInfo("parse-only").boolValue())
      47                 :            : {
      48                 :      23526 : }
      49                 :            : 
      50                 :      23526 : ParserState::~ParserState() {}
      51                 :            : 
      52                 :     254835 : Solver* ParserState::getSolver() const { return d_solver; }
      53                 :            : 
      54                 :    5589888 : Term ParserState::getVariable(const std::string& name)
      55                 :            : {
      56                 :    5589888 :   Term ret = d_symtab->lookup(name);
      57                 :            :   // if the lookup failed, throw an error
      58         [ +  + ]:    5589888 :   if (ret.isNull())
      59                 :            :   {
      60                 :       2126 :     checkDeclaration(name, CHECK_DECLARED, SYM_VARIABLE);
      61                 :            :   }
      62                 :    5589879 :   return ret;
      63                 :          9 : }
      64                 :            : 
      65                 :       5332 : Term ParserState::getExpressionForNameAndType(const std::string& name, Sort t)
      66                 :            : {
      67 [ -  + ][ -  + ]:       5332 :   Assert(isDeclared(name));
                 [ -  - ]
      68                 :            :   // first check if the variable is declared and not overloaded
      69                 :       5332 :   Term expr = getVariable(name);
      70         [ +  + ]:       5332 :   if (expr.isNull())
      71                 :            :   {
      72                 :            :     // the variable is overloaded, try with type if the type exists
      73         [ +  - ]:          6 :     if (!t.isNull())
      74                 :            :     {
      75                 :            :       // if we decide later to support annotations for function types, this will
      76                 :            :       // update to separate t into ( argument types, return type )
      77                 :          6 :       expr = getOverloadedConstantForType(name, t);
      78         [ -  + ]:          6 :       if (expr.isNull())
      79                 :            :       {
      80                 :          0 :         parseError("Cannot get overloaded constant for type ascription.");
      81                 :            :       }
      82                 :            :     }
      83                 :            :     else
      84                 :            :     {
      85                 :          0 :       parseError("Overloaded constants must be type cast.");
      86                 :            :     }
      87                 :            :   }
      88 [ -  + ][ -  + ]:       5332 :   Assert(!expr.isNull());
                 [ -  - ]
      89                 :       5332 :   return expr;
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : bool ParserState::getTesterName(CVC5_UNUSED Term cons,
      93                 :            :                                 CVC5_UNUSED std::string& name)
      94                 :            : {
      95                 :          0 :   return false;
      96                 :            : }
      97                 :            : 
      98                 :     704672 : Kind ParserState::getKindForFunction(Term fun)
      99                 :            : {
     100                 :     704672 :   Sort t = fun.getSort();
     101         [ +  + ]:     704672 :   if (t.isFunction())
     102                 :            :   {
     103                 :     668693 :     return Kind::APPLY_UF;
     104                 :            :   }
     105         [ +  + ]:      35979 :   else if (t.isDatatypeConstructor())
     106                 :            :   {
     107                 :      12780 :     return Kind::APPLY_CONSTRUCTOR;
     108                 :            :   }
     109         [ +  + ]:      23199 :   else if (t.isDatatypeSelector())
     110                 :            :   {
     111                 :      22831 :     return Kind::APPLY_SELECTOR;
     112                 :            :   }
     113         [ +  - ]:        368 :   else if (t.isDatatypeTester())
     114                 :            :   {
     115                 :        368 :     return Kind::APPLY_TESTER;
     116                 :            :   }
     117         [ -  - ]:          0 :   else if (t.isDatatypeUpdater())
     118                 :            :   {
     119                 :          0 :     return Kind::APPLY_UPDATER;
     120                 :            :   }
     121                 :          0 :   return Kind::UNDEFINED_KIND;
     122                 :     704672 : }
     123                 :            : 
     124                 :     539228 : Sort ParserState::getSort(const std::string& name)
     125                 :            : {
     126                 :     539228 :   Sort t = d_symtab->lookupType(name);
     127                 :            :   // if we fail, throw an error
     128         [ +  + ]:     539228 :   if (t.isNull())
     129                 :            :   {
     130                 :          3 :     checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
     131                 :            :   }
     132                 :     539227 :   return t;
     133                 :          1 : }
     134                 :            : 
     135                 :       1568 : Sort ParserState::getParametricSort(const std::string& name,
     136                 :            :                                     const std::vector<Sort>& params)
     137                 :            : {
     138                 :       1568 :   Sort t = d_symtab->lookupType(name, params);
     139                 :            :   // if we fail, throw an error
     140         [ +  + ]:       1567 :   if (t.isNull())
     141                 :            :   {
     142                 :          6 :     checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
     143                 :            :   }
     144                 :       1565 :   return t;
     145                 :          2 : }
     146                 :            : 
     147                 :     704643 : bool ParserState::isFunctionLike(Term fun)
     148                 :            : {
     149         [ -  + ]:     704643 :   if (fun.isNull())
     150                 :            :   {
     151                 :          0 :     return false;
     152                 :            :   }
     153                 :     704643 :   Sort type = fun.getSort();
     154         [ +  + ]:     740596 :   return type.isFunction() || type.isDatatypeConstructor()
     155 [ +  + ][ +  + ]:     740596 :          || type.isDatatypeTester() || type.isDatatypeSelector();
                 [ +  + ]
     156                 :     704643 : }
     157                 :            : 
     158                 :        705 : Term ParserState::bindVar(const std::string& name,
     159                 :            :                           const Sort& type,
     160                 :            :                           bool doOverload)
     161                 :            : {
     162         [ +  - ]:        705 :   Trace("parser") << "bindVar(" << name << ", " << type << ")" << std::endl;
     163                 :        705 :   Term expr = d_tm.mkConst(type, name);
     164                 :        705 :   defineVar(name, expr, doOverload);
     165                 :        705 :   return expr;
     166                 :          0 : }
     167                 :            : 
     168                 :     157909 : Term ParserState::bindBoundVar(const std::string& name,
     169                 :            :                                const Sort& type,
     170                 :            :                                bool fresh)
     171                 :            : {
     172         [ +  - ]:     315818 :   Trace("parser") << "bindBoundVar(" << name << ", " << type << ")"
     173                 :     157909 :                   << std::endl;
     174                 :     157909 :   std::pair<std::string, Sort> key(name, type);
     175                 :     157909 :   Term expr;
     176         [ +  + ]:     157909 :   if (fresh)
     177                 :            :   {
     178                 :       5711 :     expr = d_tm.mkVar(type, name);
     179                 :            :   }
     180                 :            :   else
     181                 :            :   {
     182                 :            :     std::map<std::pair<std::string, Sort>, Term>::iterator itv =
     183                 :     152198 :         d_varCache.find(key);
     184         [ +  + ]:     152198 :     if (itv != d_varCache.end())
     185                 :            :     {
     186                 :      89202 :       expr = itv->second;
     187                 :            :     }
     188                 :            :     else
     189                 :            :     {
     190                 :      62996 :       expr = d_tm.mkVar(type, name);
     191                 :      62996 :       d_varCache[key] = expr;
     192                 :            :     }
     193                 :            :   }
     194                 :     157909 :   defineVar(name, expr);
     195                 :     315818 :   return expr;
     196                 :     157909 : }
     197                 :            : 
     198                 :      79097 : std::vector<Term> ParserState::bindBoundVars(
     199                 :            :     std::vector<std::pair<std::string, Sort>>& sortedVarNames, bool fresh)
     200                 :            : {
     201                 :      79097 :   std::vector<Term> vars;
     202         [ +  + ]:     224123 :   for (std::pair<std::string, Sort>& i : sortedVarNames)
     203                 :            :   {
     204                 :     145026 :     vars.push_back(bindBoundVar(i.first, i.second, fresh));
     205                 :            :   }
     206                 :      79097 :   return vars;
     207                 :          0 : }
     208                 :            : 
     209                 :      77635 : std::vector<Term> ParserState::bindBoundVarsCtx(
     210                 :            :     std::vector<std::pair<std::string, Sort>>& sortedVarNames,
     211                 :            :     std::vector<std::vector<std::pair<std::string, Term>>>& letBinders,
     212                 :            :     bool fresh)
     213                 :            : {
     214 [ +  + ][ +  + ]:      77635 :   if (fresh || letBinders.empty())
                 [ +  + ]
     215                 :            :   {
     216                 :            :     // does not matter if let binders are empty or if we are constructing fresh
     217                 :      70646 :     return bindBoundVars(sortedVarNames, fresh);
     218                 :            :   }
     219                 :       6989 :   std::vector<Term> vars;
     220         [ +  + ]:      16509 :   for (std::pair<std::string, Sort>& i : sortedVarNames)
     221                 :            :   {
     222                 :            :     std::map<std::pair<std::string, Sort>, Term>::const_iterator itv =
     223                 :       9520 :         d_varCache.find(i);
     224 [ +  + ][ +  + ]:       9520 :     if (itv == d_varCache.end() || !isDeclared(i.first))
                 [ +  + ]
     225                 :            :     {
     226                 :            :       // haven't created this variable yet, or its not declared
     227                 :       9496 :       Term v = bindBoundVar(i.first, i.second, fresh);
     228                 :       9496 :       vars.push_back(v);
     229                 :       9496 :       continue;
     230                 :       9496 :     }
     231                 :         24 :     Term v = itv->second;
     232                 :            :     // If we are here, then:
     233                 :            :     // (1) we are not using fresh declarations
     234                 :            :     // (2) there are let binders present,
     235                 :            :     // (3) the current variable was shadowed.
     236                 :            :     // We must check whether the variable is present in the let bindings.
     237                 :         24 :     bool reqFresh = false;
     238                 :            :     // a dummy variable used for checking containment below
     239                 :         48 :     Term vr = d_tm.mkVar(v.getSort(), "dummy");
     240                 :            :     // check if it is contained in a let binder, if so, we require making a
     241                 :            :     // fresh variable, despite fresh-binders being false.
     242         [ +  + ]:         45 :     for (std::vector<std::pair<std::string, Term>>& lbs : letBinders)
     243                 :            :     {
     244         [ +  + ]:         44 :       for (std::pair<std::string, Term>& lb : lbs)
     245                 :            :       {
     246                 :            :         // To test containment, we use Term::substitute.
     247                 :            :         // If the substitution does anything at all, then we will throw a
     248                 :            :         // warning. We expect this warning to be very rare.
     249                 :         23 :         Term slbt = lb.second.substitute({v}, {vr});
     250         [ +  + ]:         23 :         if (slbt != lb.second)
     251                 :            :         {
     252                 :          3 :           reqFresh = true;
     253                 :          3 :           break;
     254                 :            :         }
     255         [ +  + ]:         23 :       }
     256         [ +  + ]:         24 :       if (reqFresh)
     257                 :            :       {
     258                 :          3 :         break;
     259                 :            :       }
     260                 :            :     }
     261         [ +  + ]:         24 :     if (reqFresh)
     262                 :            :     {
     263                 :            :       // Note that if this warning is thrown:
     264                 :            :       // 1. proof reference checking will not be accurate in settings where
     265                 :            :       // variables are parsed as canonical.
     266                 :            :       // 2. the parser will not be deterministic for the same input even when
     267                 :            :       // fresh-binders is false, since we are constructing a fresh variable
     268                 :            :       // below.
     269         [ -  + ]:          6 :       Warning() << "Constructing a fresh variable for " << i.first
     270                 :            :                 << " since this symbol occurs in a let term that is present in "
     271                 :            :                    "the current context. Set fresh-binders to true or use -q "
     272                 :            :                    "to avoid "
     273                 :          3 :                    "this warning."
     274                 :          3 :                 << std::endl;
     275                 :            :     }
     276                 :         24 :     v = bindBoundVar(i.first, i.second, reqFresh);
     277                 :         24 :     vars.push_back(v);
     278                 :         24 :   }
     279                 :       6989 :   return vars;
     280                 :       6989 : }
     281                 :            : 
     282                 :          0 : std::vector<Term> ParserState::bindBoundVars(
     283                 :            :     const std::vector<std::string> names, const Sort& type)
     284                 :            : {
     285                 :          0 :   std::vector<Term> vars;
     286         [ -  - ]:          0 :   for (unsigned i = 0; i < names.size(); ++i)
     287                 :            :   {
     288                 :          0 :     vars.push_back(bindBoundVar(names[i], type));
     289                 :            :   }
     290                 :          0 :   return vars;
     291                 :          0 : }
     292                 :            : 
     293                 :     688906 : void ParserState::defineVar(const std::string& name,
     294                 :            :                             const Term& val,
     295                 :            :                             bool doOverload)
     296                 :            : {
     297         [ +  - ]:     688906 :   Trace("parser") << "defineVar( " << name << " := " << val << ")" << std::endl;
     298         [ -  + ]:     688906 :   if (!d_symtab->bind(name, val, doOverload))
     299                 :            :   {
     300                 :          0 :     std::stringstream ss;
     301                 :          0 :     ss << "Cannot bind " << name << " to symbol of type " << val.getSort();
     302                 :          0 :     ss << ", maybe the symbol has already been defined?";
     303                 :          0 :     parseError(ss.str());
     304                 :          0 :   }
     305 [ -  + ][ -  + ]:     688906 :   Assert(isDeclared(name));
                 [ -  - ]
     306                 :     688906 : }
     307                 :            : 
     308                 :     209804 : void ParserState::defineType(const std::string& name,
     309                 :            :                              const Sort& type,
     310                 :            :                              bool isUser)
     311                 :            : {
     312 [ +  + ][ +  + ]:     209804 :   if (!isUser && isDeclared(name, SYM_SORT))
                 [ +  + ]
     313                 :            :   {
     314 [ -  + ][ -  + ]:      13715 :     Assert(d_symtab->lookupType(name) == type);
                 [ -  - ]
     315                 :      13715 :     return;
     316                 :            :   }
     317                 :     196089 :   d_symman->bindType(name, type, isUser);
     318 [ -  + ][ -  + ]:     196089 :   Assert(isDeclared(name, SYM_SORT));
                 [ -  - ]
     319                 :            : }
     320                 :            : 
     321                 :        207 : void ParserState::defineType(const std::string& name,
     322                 :            :                              const std::vector<Sort>& params,
     323                 :            :                              const Sort& type,
     324                 :            :                              bool isUser)
     325                 :            : {
     326                 :        207 :   d_symman->bindType(name, params, type, isUser);
     327 [ -  + ][ -  + ]:        207 :   Assert(isDeclared(name, SYM_SORT));
                 [ -  - ]
     328                 :        207 : }
     329                 :            : 
     330                 :        266 : Sort ParserState::mkSort(const std::string& name)
     331                 :            : {
     332         [ +  - ]:        266 :   Trace("parser") << "newSort(" << name << ")" << std::endl;
     333                 :        266 :   Sort type = d_tm.mkUninterpretedSort(name);
     334                 :        266 :   defineType(name, type, true);
     335                 :        266 :   return type;
     336                 :          0 : }
     337                 :            : 
     338                 :          0 : Sort ParserState::mkSortConstructor(const std::string& name, size_t arity)
     339                 :            : {
     340         [ -  - ]:          0 :   Trace("parser") << "newSortConstructor(" << name << ", " << arity << ")"
     341                 :          0 :                   << std::endl;
     342                 :          0 :   Sort type = d_tm.mkUninterpretedSortConstructorSort(arity, name);
     343                 :          0 :   defineType(name, vector<Sort>(arity), type, true);
     344                 :          0 :   return type;
     345                 :          0 : }
     346                 :            : 
     347                 :       4698 : Sort ParserState::mkUnresolvedType(const std::string& name)
     348                 :            : {
     349                 :       4698 :   Sort unresolved = d_tm.mkUnresolvedDatatypeSort(name);
     350                 :       4698 :   defineType(name, unresolved, true);
     351                 :       4698 :   return unresolved;
     352                 :          0 : }
     353                 :            : 
     354                 :        207 : Sort ParserState::mkUnresolvedTypeConstructor(const std::string& name,
     355                 :            :                                               size_t arity)
     356                 :            : {
     357                 :        207 :   Sort unresolved = d_tm.mkUnresolvedDatatypeSort(name, arity);
     358                 :        207 :   defineType(name, vector<Sort>(arity), unresolved, true);
     359                 :        207 :   return unresolved;
     360                 :          0 : }
     361                 :            : 
     362                 :          0 : Sort ParserState::mkUnresolvedTypeConstructor(const std::string& name,
     363                 :            :                                               const std::vector<Sort>& params)
     364                 :            : {
     365         [ -  - ]:          0 :   Trace("parser") << "newSortConstructor(P)(" << name << ", " << params.size()
     366                 :          0 :                   << ")" << std::endl;
     367                 :          0 :   Sort unresolved = d_tm.mkUnresolvedDatatypeSort(name, params.size());
     368                 :          0 :   defineType(name, params, unresolved, true);
     369                 :          0 :   Sort t = getParametricSort(name, params);
     370                 :          0 :   return unresolved;
     371                 :          0 : }
     372                 :            : 
     373                 :       4905 : Sort ParserState::mkUnresolvedType(const std::string& name, size_t arity)
     374                 :            : {
     375         [ +  + ]:       4905 :   if (arity == 0)
     376                 :            :   {
     377                 :       4698 :     return mkUnresolvedType(name);
     378                 :            :   }
     379                 :        207 :   return mkUnresolvedTypeConstructor(name, arity);
     380                 :            : }
     381                 :            : 
     382                 :       3635 : std::vector<Sort> ParserState::mkMutualDatatypeTypes(
     383                 :            :     std::vector<DatatypeDecl>& datatypes)
     384                 :            : {
     385                 :            :   try
     386                 :            :   {
     387                 :       3635 :     std::vector<Sort> types = d_tm.mkDatatypeSorts(datatypes);
     388                 :            : 
     389 [ -  + ][ -  + ]:       3632 :     Assert(datatypes.size() == types.size());
                 [ -  - ]
     390                 :            : 
     391         [ +  + ]:       8532 :     for (unsigned i = 0; i < datatypes.size(); ++i)
     392                 :            :     {
     393                 :       4900 :       Sort t = types[i];
     394                 :       4900 :       const Datatype& dt = t.getDatatype();
     395                 :       4900 :       const std::string& name = dt.getName();
     396         [ +  - ]:       4900 :       Trace("parser-idt") << "define " << name << " as " << t << std::endl;
     397         [ -  + ]:       4900 :       if (isDeclared(name, SYM_SORT))
     398                 :            :       {
     399                 :          0 :         throw ParserException(name + " already declared");
     400                 :            :       }
     401                 :       4900 :       std::unordered_set<std::string> consNames;
     402                 :       4900 :       std::unordered_set<std::string> selNames;
     403         [ +  + ]:      13598 :       for (size_t j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
     404                 :            :       {
     405                 :       8698 :         const DatatypeConstructor& ctor = dt[j];
     406                 :       8698 :         Term constructor = ctor.getTerm();
     407         [ +  - ]:       8698 :         Trace("parser-idt") << "+ define " << constructor << std::endl;
     408                 :       8698 :         std::string constructorName = ctor.getName();
     409         [ +  - ]:       8698 :         if (consNames.find(constructorName) == consNames.end())
     410                 :            :         {
     411                 :       8698 :           consNames.insert(constructorName);
     412                 :            :         }
     413                 :            :         else
     414                 :            :         {
     415                 :          0 :           throw ParserException(constructorName
     416                 :          0 :                                 + " already declared in this datatype");
     417                 :            :         }
     418         [ +  + ]:      16603 :         for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++)
     419                 :            :         {
     420                 :       7905 :           const DatatypeSelector& sel = ctor[k];
     421                 :       7905 :           Term selector = sel.getTerm();
     422         [ +  - ]:       7905 :           Trace("parser-idt") << "+++ define " << selector << std::endl;
     423                 :       7905 :           std::string selectorName = sel.getName();
     424         [ +  - ]:       7905 :           if (selNames.find(selectorName) == selNames.end())
     425                 :            :           {
     426                 :       7905 :             selNames.insert(selectorName);
     427                 :            :           }
     428                 :            :           else
     429                 :            :           {
     430                 :          0 :             throw ParserException(selectorName
     431                 :          0 :                                   + " already declared in this datatype");
     432                 :            :           }
     433                 :       7905 :         }
     434                 :       8698 :       }
     435                 :       4900 :     }
     436                 :       7264 :     return types;
     437                 :       3632 :   }
     438         [ -  - ]:          0 :   catch (internal::IllegalArgumentException& ie)
     439                 :            :   {
     440                 :          0 :     throw ParserException(ie.getMessage());
     441                 :          0 :   }
     442                 :            : }
     443                 :            : 
     444                 :       7555 : Sort ParserState::flattenFunctionType(std::vector<Sort>& sorts,
     445                 :            :                                       Sort range,
     446                 :            :                                       std::vector<Term>& flattenVars)
     447                 :            : {
     448         [ +  + ]:       7555 :   if (range.isFunction())
     449                 :            :   {
     450                 :          9 :     std::vector<Sort> domainTypes = range.getFunctionDomainSorts();
     451         [ +  + ]:         24 :     for (unsigned i = 0, size = domainTypes.size(); i < size; i++)
     452                 :            :     {
     453                 :         15 :       sorts.push_back(domainTypes[i]);
     454                 :            :       // the introduced variable is internal (not parsable)
     455                 :         15 :       std::stringstream ss;
     456                 :         15 :       ss << "__flatten_var_" << i;
     457                 :         30 :       Term v = d_tm.mkVar(domainTypes[i], ss.str());
     458                 :         15 :       flattenVars.push_back(v);
     459                 :         15 :     }
     460                 :          9 :     range = range.getFunctionCodomainSort();
     461                 :          9 :   }
     462                 :       7555 :   return range;
     463                 :            : }
     464                 :            : 
     465                 :      56031 : Sort ParserState::flattenFunctionType(std::vector<Sort>& sorts, Sort range)
     466                 :            : {
     467         [ -  + ]:      56031 :   if (TraceIsOn("parser"))
     468                 :            :   {
     469         [ -  - ]:          0 :     Trace("parser") << "flattenFunctionType: range " << range
     470                 :          0 :                     << " and domains ";
     471         [ -  - ]:          0 :     for (Sort t : sorts)
     472                 :            :     {
     473         [ -  - ]:          0 :       Trace("parser") << " " << t;
     474                 :          0 :     }
     475         [ -  - ]:          0 :     Trace("parser") << "\n";
     476                 :            :   }
     477         [ +  + ]:      56441 :   while (range.isFunction())
     478                 :            :   {
     479                 :        410 :     std::vector<Sort> domainTypes = range.getFunctionDomainSorts();
     480                 :        410 :     sorts.insert(sorts.end(), domainTypes.begin(), domainTypes.end());
     481                 :        410 :     range = range.getFunctionCodomainSort();
     482                 :        410 :   }
     483                 :      56031 :   return range;
     484                 :            : }
     485                 :      18206 : Sort ParserState::mkFlatFunctionType(std::vector<Sort>& sorts, Sort range)
     486                 :            : {
     487                 :            :   // Note we require this flattening since the API explicitly checks that
     488                 :            :   // the range of functions is not a function.
     489                 :      18206 :   Sort newRange = flattenFunctionType(sorts, range);
     490         [ +  - ]:      18206 :   if (!sorts.empty())
     491                 :            :   {
     492                 :      18206 :     return d_tm.mkFunctionSort(sorts, newRange);
     493                 :            :   }
     494                 :          0 :   return newRange;
     495                 :      18206 : }
     496                 :            : 
     497                 :          9 : Term ParserState::mkHoApply(Term expr, const std::vector<Term>& args)
     498                 :            : {
     499         [ +  + ]:         24 :   for (size_t i = 0; i < args.size(); i++)
     500                 :            :   {
     501 [ +  + ][ -  - ]:         45 :     expr = d_tm.mkTerm(Kind::HO_APPLY, {expr, args[i]});
     502                 :            :   }
     503                 :          9 :   return expr;
     504                 :            : }
     505                 :            : 
     506                 :       1286 : Term ParserState::applyTypeAscription(Term t, Sort s)
     507                 :            : {
     508                 :       1286 :   Kind k = t.getKind();
     509         [ +  + ]:       1286 :   if (k == Kind::SET_EMPTY)
     510                 :            :   {
     511                 :        511 :     t = d_tm.mkEmptySet(s);
     512                 :            :   }
     513         [ +  + ]:        775 :   else if (k == Kind::BAG_EMPTY)
     514                 :            :   {
     515                 :        110 :     t = d_tm.mkEmptyBag(s);
     516                 :            :   }
     517         [ +  + ]:        665 :   else if (k == Kind::CONST_SEQUENCE)
     518                 :            :   {
     519         [ -  + ]:         97 :     if (!s.isSequence())
     520                 :            :     {
     521                 :          0 :       std::stringstream ss;
     522                 :          0 :       ss << "Type ascription on empty sequence must be a sequence, got " << s;
     523                 :          0 :       parseError(ss.str());
     524                 :          0 :     }
     525         [ -  + ]:         97 :     if (!t.getSequenceValue().empty())
     526                 :            :     {
     527                 :          0 :       std::stringstream ss;
     528                 :          0 :       ss << "Cannot apply a type ascription to a non-empty sequence";
     529                 :          0 :       parseError(ss.str());
     530                 :          0 :     }
     531                 :         97 :     t = d_tm.mkEmptySequence(s.getSequenceElementSort());
     532                 :            :   }
     533         [ +  + ]:        568 :   else if (k == Kind::SET_UNIVERSE)
     534                 :            :   {
     535                 :        223 :     t = d_tm.mkUniverseSet(s);
     536                 :            :   }
     537         [ +  + ]:        345 :   else if (k == Kind::SEP_NIL)
     538                 :            :   {
     539                 :        104 :     t = d_tm.mkSepNil(s);
     540                 :            :   }
     541         [ +  + ]:        241 :   else if (k == Kind::APPLY_CONSTRUCTOR)
     542                 :            :   {
     543                 :            :     // For nullable.null we do not have a kind.
     544                 :            :     // so we need to check the sort here.
     545         [ +  + ]:        127 :     if (s.isNullable())
     546                 :            :     {
     547                 :            :       // parsing (as nullable.null (Nullable T))
     548                 :         49 :       t = d_tm.mkNullableNull(s);
     549                 :            :     }
     550                 :            :     else
     551                 :            :     {
     552                 :        156 :       std::vector<Term> children(t.begin(), t.end());
     553                 :            :       // apply type ascription to the operator and reconstruct
     554                 :         78 :       children[0] = applyTypeAscription(children[0], s);
     555                 :         78 :       t = d_tm.mkTerm(Kind::APPLY_CONSTRUCTOR, children);
     556                 :         78 :     }
     557                 :            :   }
     558                 :       1286 :   Sort etype = t.getSort();
     559         [ +  + ]:       1286 :   if (etype.isDatatypeConstructor())
     560                 :            :   {
     561                 :            :     // Type ascriptions only have an effect on the node structure if this is a
     562                 :            :     // parametric datatype.
     563                 :            :     // get the datatype that t belongs to
     564                 :        105 :     Sort etyped = etype.getDatatypeConstructorCodomainSort();
     565                 :        105 :     Datatype d = etyped.getDatatype();
     566                 :            :     // Note that we check whether the datatype is parametric, and not whether
     567                 :            :     // etyped is a parametric datatype, since e.g. the smt2 parser constructs
     568                 :            :     // an arbitrary instantitated constructor term before it is resolved.
     569                 :            :     // Hence, etyped is an instantiated datatype type, but we correctly
     570                 :            :     // check if its datatype is parametric.
     571         [ +  + ]:        105 :     if (d.isParametric())
     572                 :            :     {
     573                 :            :       // lookup by name, using the raw symbol since toString() may print
     574                 :            :       // the name as a quoted symbol, e.g. |C,|
     575                 :            :       DatatypeConstructor dc =
     576         [ +  - ]:        101 :           d.getConstructor(t.hasSymbol() ? t.getSymbol() : t.toString());
     577                 :            :       // ask the constructor for the specialized constructor term
     578                 :        101 :       t = dc.getInstantiatedTerm(s);
     579                 :        101 :     }
     580                 :            :     // the type of t does not match the sort s by design (constructor type
     581                 :            :     // vs datatype type), thus we use an alternative check here.
     582         [ -  + ]:        105 :     if (t.getSort().getDatatypeConstructorCodomainSort() != s)
     583                 :            :     {
     584                 :          0 :       std::stringstream ss;
     585                 :          0 :       ss << "Type ascription on constructor not satisfied, term " << t
     586                 :          0 :          << " expected sort " << s << " but has sort " << etyped;
     587                 :          0 :       parseError(ss.str());
     588                 :          0 :     }
     589                 :        105 :     return t;
     590                 :        105 :   }
     591                 :            :   // Otherwise, check that the type is correct. Type ascriptions in SMT-LIB 2.6
     592                 :            :   // referred to the range of function sorts. Note that this is only a check
     593                 :            :   // and does not impact the returned term.
     594                 :       1181 :   Sort checkSort = t.getSort();
     595         [ +  + ]:       1181 :   if (checkSort.isFunction())
     596                 :            :   {
     597                 :          3 :     checkSort = checkSort.getFunctionCodomainSort();
     598                 :            :   }
     599         [ -  + ]:       1181 :   if (checkSort != s)
     600                 :            :   {
     601                 :          0 :     std::stringstream ss;
     602                 :          0 :     ss << "Type ascription not satisfied, term " << t
     603                 :          0 :        << " expected (codomain) sort " << s << " but has sort " << t.getSort();
     604                 :          0 :     parseError(ss.str());
     605                 :          0 :   }
     606                 :       1181 :   return t;
     607                 :       1286 : }
     608                 :            : 
     609                 :    1857302 : bool ParserState::isDeclared(const std::string& name, SymbolType type)
     610                 :            : {
     611 [ +  + ][ -  - ]:    1857302 :   switch (type)
     612                 :            :   {
     613                 :    1433194 :     case SYM_VARIABLE: return d_symtab->isBound(name);
     614                 :     424108 :     case SYM_SORT: return d_symtab->isBoundType(name);
     615                 :          0 :     case SYM_VERBATIM: Unreachable();
     616                 :            :   }
     617                 :          0 :   DebugUnhandled();  // Unhandled(type);
     618                 :            :   return false;
     619                 :            : }
     620                 :            : 
     621                 :    2155291 : void ParserState::checkDeclaration(const std::string& varName,
     622                 :            :                                    DeclarationCheck check,
     623                 :            :                                    SymbolType type,
     624                 :            :                                    std::string notes)
     625                 :            : {
     626         [ -  + ]:    2155291 :   if (!d_checksEnabled)
     627                 :            :   {
     628                 :          0 :     return;
     629                 :            :   }
     630                 :            : 
     631 [ +  + ][ +  - ]:    2155291 :   switch (check)
     632                 :            :   {
     633                 :     712922 :     case CHECK_DECLARED:
     634         [ +  + ]:     712922 :       if (!isDeclared(varName, type))
     635                 :            :       {
     636                 :        125 :         parseError("Symbol '" + varName + "' not declared as a "
     637         [ +  + ]:        100 :                    + (type == SYM_VARIABLE ? "variable" : "type")
     638         [ +  - ]:        150 :                    + (notes.size() == 0 ? notes : "\n" + notes));
     639                 :            :       }
     640                 :     712897 :       break;
     641                 :            : 
     642                 :      38140 :     case CHECK_UNDECLARED:
     643         [ +  + ]:      38140 :       if (isDeclared(varName, type))
     644                 :            :       {
     645                 :          5 :         parseError("Symbol '" + varName + "' previously declared as a "
     646         [ -  + ]:          4 :                    + (type == SYM_VARIABLE ? "variable" : "type")
     647         [ +  - ]:          6 :                    + (notes.size() == 0 ? notes : "\n" + notes));
     648                 :            :       }
     649                 :      38139 :       break;
     650                 :            : 
     651                 :    1404229 :     case CHECK_NONE: break;
     652                 :            : 
     653                 :          0 :     default: DebugUnhandled();  // Unhandled(check);
     654                 :            :   }
     655                 :            : }
     656                 :            : 
     657                 :     704643 : void ParserState::checkFunctionLike(Term fun)
     658                 :            : {
     659 [ +  - ][ +  + ]:     704643 :   if (d_checksEnabled && !isFunctionLike(fun))
         [ +  - ][ +  + ]
                 [ -  - ]
     660                 :            :   {
     661                 :          1 :     stringstream ss;
     662                 :          1 :     ss << "Expecting function-like symbol, found '";
     663                 :          1 :     ss << fun;
     664                 :          1 :     ss << "'";
     665                 :          2 :     parseError(ss.str());
     666                 :          1 :   }
     667                 :     704642 : }
     668                 :            : 
     669                 :    3703669 : void ParserState::addOperator(Kind kind) { d_logicOperators.insert(kind); }
     670                 :            : 
     671                 :        210 : void ParserState::warning(const std::string& msg) { d_psc->warning(msg); }
     672                 :            : 
     673                 :         46 : void ParserState::parseError(const std::string& msg) { d_psc->parseError(msg); }
     674                 :            : 
     675                 :          0 : void ParserState::unexpectedEOF(const std::string& msg)
     676                 :            : {
     677                 :          0 :   d_psc->unexpectedEOF(msg);
     678                 :          0 : }
     679                 :            : 
     680                 :        308 : void ParserState::attributeNotSupported(const std::string& attr)
     681                 :            : {
     682         [ +  + ]:        308 :   if (d_attributesWarnedAbout.find(attr) == d_attributesWarnedAbout.end())
     683                 :            :   {
     684                 :         32 :     stringstream ss;
     685                 :            :     ss << "warning: Attribute '" << attr
     686                 :         32 :        << "' not supported (ignoring this and all following uses)";
     687                 :         32 :     warning(ss.str());
     688                 :         32 :     d_attributesWarnedAbout.insert(attr);
     689                 :         32 :   }
     690                 :        308 : }
     691                 :            : 
     692                 :          0 : size_t ParserState::scopeLevel() const { return d_symman->scopeLevel(); }
     693                 :            : 
     694                 :     308817 : void ParserState::pushScope(bool isUserContext)
     695                 :            : {
     696                 :     308817 :   d_symman->pushScope(isUserContext);
     697                 :     308817 : }
     698                 :            : 
     699                 :        221 : void ParserState::pushGetValueScope()
     700                 :            : {
     701                 :        221 :   pushScope();
     702                 :            :   // We cannot ask for the model domain elements if we are in parse-only mode.
     703                 :            :   // Hence, we do nothing here.
     704         [ +  + ]:        221 :   if (d_parseOnly)
     705                 :            :   {
     706                 :        104 :     return;
     707                 :            :   }
     708                 :            :   // we must bind all relevant uninterpreted constants, which coincide with
     709                 :            :   // the set of uninterpreted constants that are printed in the definition
     710                 :            :   // of a model.
     711                 :        117 :   std::vector<Sort> declareSorts = d_symman->getDeclaredSorts();
     712         [ +  - ]:        234 :   Trace("parser") << "Push get value scope, with " << declareSorts.size()
     713                 :        117 :                   << " declared sorts" << std::endl;
     714                 :            :   try
     715                 :            :   {
     716         [ +  + ]:        135 :     for (const Sort& s : declareSorts)
     717                 :            :     {
     718                 :         22 :       std::vector<Term> elements = d_solver->getModelDomainElements(s);
     719         [ +  - ]:         18 :       Trace("parser") << "elements for " << s << ":" << std::endl;
     720         [ +  + ]:         36 :       for (const Term& e : elements)
     721                 :            :       {
     722         [ +  - ]:         18 :         Trace("parser") << "  " << e.getKind() << " " << e << std::endl;
     723         [ +  - ]:         18 :         if (e.getKind() == Kind::UNINTERPRETED_SORT_VALUE)
     724                 :            :         {
     725                 :         18 :           defineVar(e.getUninterpretedSortValue(), e);
     726                 :            :         }
     727                 :            :         else
     728                 :            :         {
     729                 :          0 :           DebugUnhandled()
     730                 :          0 :               << "model domain element is not an uninterpreted sort value: "
     731                 :            :               << e;
     732                 :            :         }
     733                 :            :       }
     734                 :         18 :     }
     735                 :            :   }
     736         [ -  + ]:          4 :   catch (const CVC5ApiRecoverableException& e)
     737                 :            :   {
     738                 :            :     // Let the get-value command report recoverable model-state errors itself
     739                 :            :     // instead of turning them into fatal parse errors while binding @U_i names.
     740         [ +  - ]:          8 :     Trace("parser") << "Skipping get-value model bindings: " << e.what()
     741                 :          4 :                     << std::endl;
     742                 :          4 :   }
     743                 :        117 : }
     744                 :            : 
     745                 :     284506 : void ParserState::popScope() { d_symman->popScope(); }
     746                 :            : 
     747                 :          0 : void ParserState::reset() {}
     748                 :            : 
     749                 :      66363 : SymManager* ParserState::getSymbolManager() { return d_symman; }
     750                 :            : 
     751                 :         12 : std::string ParserState::stripQuotes(const std::string& s)
     752                 :            : {
     753 [ +  - ][ +  - ]:         12 :   if (s.size() < 2 || s[0] != '\"' || s[s.size() - 1] != '\"')
         [ -  + ][ -  + ]
     754                 :            :   {
     755                 :          0 :     parseError("Expected a string delimited by quotes, got invalid string `" + s
     756                 :          0 :                + "`.");
     757                 :            :   }
     758                 :         12 :   return s.substr(1, s.size() - 2);
     759                 :            : }
     760                 :            : 
     761                 :         14 : Term ParserState::mkCharConstant(const std::string& s)
     762                 :            : {
     763 [ +  - ][ -  + ]:         28 :   if (!(s.find_first_not_of("0123456789abcdefABCDEF", 0) == std::string::npos
                 [ +  + ]
     764         [ +  + ]:         14 :         && s.size() <= 5 && s.size() > 0))
     765                 :            :   {
     766                 :          3 :     parseError("Unexpected string for hexadecimal character: `" + s + "'");
     767                 :            :   }
     768                 :         13 :   char32_t val = static_cast<char32_t>(std::stoul(s, nullptr, 16));
     769                 :         26 :   return d_tm.mkString(std::u32string(1, val));
     770                 :            : }
     771                 :            : 
     772                 :     752243 : bool stringToUnsigned(const std::string& str,
     773                 :            :                       uint32_t& result,
     774                 :            :                       std::ostream* os)
     775                 :            : {
     776 [ +  - ][ -  + ]:     752243 :   if (str.empty() || str.find_first_not_of("0123456789") != std::string::npos)
                 [ -  + ]
     777                 :            :   {
     778         [ -  - ]:          0 :     if (os != nullptr)
     779                 :            :     {
     780                 :          0 :       (*os) << " String is not a numeral.";
     781                 :            :     }
     782                 :          0 :     return false;
     783                 :            :   }
     784                 :     752243 :   size_t pos = 0;
     785                 :     752243 :   unsigned long long parsed = 0;
     786                 :            :   try
     787                 :            :   {
     788                 :     752243 :     parsed = std::stoull(str, &pos);
     789                 :            :   }
     790         [ -  - ]:          0 :   catch (const std::exception&)
     791                 :            :   {
     792         [ -  - ]:          0 :     if (os != nullptr)
     793                 :            :     {
     794                 :          0 :       (*os) << " Exception encountered in std::stoull.";
     795                 :            :     }
     796                 :          0 :     return false;
     797                 :          0 :   }
     798 [ +  - ][ +  + ]:     752243 :   if (pos != str.size() || parsed > std::numeric_limits<uint32_t>::max())
                 [ +  + ]
     799                 :            :   {
     800         [ +  + ]:          2 :     if (os != nullptr)
     801                 :            :     {
     802                 :          1 :       (*os) << " Numerals must fit into 32-bit unsigned integers.";
     803                 :            :     }
     804                 :          2 :     return false;
     805                 :            :   }
     806                 :     752241 :   result = static_cast<uint32_t>(parsed);
     807                 :     752241 :   return true;
     808                 :            : }
     809                 :            : 
     810                 :     752242 : uint32_t ParserState::parseStringToUnsigned(const std::string& str)
     811                 :            : {
     812                 :     752242 :   uint32_t result = 0;
     813         [ +  + ]:     752242 :   if (!stringToUnsigned(str, result))
     814                 :            :   {
     815                 :          1 :     std::stringstream ss;
     816                 :          1 :     ss << "Failed to parse numeral.";
     817                 :          1 :     stringToUnsigned(str, result, &ss);
     818                 :          2 :     parseError(ss.str());
     819                 :          1 :   }
     820                 :     752241 :   return result;
     821                 :            : }
     822                 :            : 
     823                 :            : }  // namespace parser
     824                 :            : }  // namespace cvc5

Generated by: LCOV version 1.14