GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/parser/parser.cpp Lines: 357 517 69.1 %
Date: 2021-11-07 Branches: 442 1377 32.1 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Christopher L. Conway
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Parser state implementation.
14
 */
15
16
#include "parser/parser.h"
17
18
#include <clocale>
19
#include <fstream>
20
#include <iostream>
21
#include <iterator>
22
#include <sstream>
23
#include <unordered_set>
24
25
#include "api/cpp/cvc5.h"
26
#include "base/check.h"
27
#include "base/output.h"
28
#include "expr/kind.h"
29
#include "parser/input.h"
30
#include "parser/parser_exception.h"
31
#include "smt/command.h"
32
33
using namespace std;
34
using namespace cvc5::kind;
35
36
namespace cvc5 {
37
namespace parser {
38
39
6738
Parser::Parser(api::Solver* solver,
40
               SymbolManager* sm,
41
               bool strictMode,
42
6738
               bool parseOnly)
43
    : d_symman(sm),
44
6738
      d_symtab(sm->getSymbolTable()),
45
      d_assertionLevel(0),
46
      d_anonymousFunctionCount(0),
47
      d_done(true),
48
      d_checksEnabled(true),
49
      d_strictMode(strictMode),
50
      d_parseOnly(parseOnly),
51
      d_canIncludeFile(true),
52
      d_logicIsForced(false),
53
      d_forcedLogic(),
54
13476
      d_solver(solver)
55
{
56
6738
}
57
58
13476
Parser::~Parser() {
59
6740
  for (std::list<Command*>::iterator iter = d_commandQueue.begin();
60
6740
       iter != d_commandQueue.end(); ++iter) {
61
2
    Command* command = *iter;
62
2
    delete command;
63
  }
64
6738
  d_commandQueue.clear();
65
6738
}
66
67
651302
api::Solver* Parser::getSolver() const { return d_solver; }
68
69
2854959
api::Term Parser::getSymbol(const std::string& name, SymbolType type)
70
{
71
2854959
  checkDeclaration(name, CHECK_DECLARED, type);
72
2854959
  Assert(isDeclared(name, type));
73
2854959
  Assert(type == SYM_VARIABLE);
74
  // Functions share var namespace
75
2854959
  return d_symtab->lookup(name);
76
}
77
78
9
void Parser::forceLogic(const std::string& logic)
79
{
80
9
  Assert(!d_logicIsForced);
81
9
  d_logicIsForced = true;
82
9
  d_forcedLogic = logic;
83
9
}
84
85
2854959
api::Term Parser::getVariable(const std::string& name)
86
{
87
2854959
  return getSymbol(name, SYM_VARIABLE);
88
}
89
90
api::Term Parser::getFunction(const std::string& name)
91
{
92
  return getSymbol(name, SYM_VARIABLE);
93
}
94
95
2513654
api::Term Parser::getExpressionForName(const std::string& name)
96
{
97
5027308
  api::Sort t;
98
5027308
  return getExpressionForNameAndType(name, t);
99
}
100
101
2514025
api::Term Parser::getExpressionForNameAndType(const std::string& name,
102
                                              api::Sort t)
103
{
104
2514025
  Assert(isDeclared(name));
105
  // first check if the variable is declared and not overloaded
106
2514025
  api::Term expr = getVariable(name);
107
2514025
  if(expr.isNull()) {
108
    // the variable is overloaded, try with type if the type exists
109
6
    if(!t.isNull()) {
110
      // if we decide later to support annotations for function types, this will
111
      // update to separate t into ( argument types, return type )
112
6
      expr = getOverloadedConstantForType(name, t);
113
6
      if(expr.isNull()) {
114
        parseError("Cannot get overloaded constant for type ascription.");
115
      }
116
    }else{
117
      parseError("Overloaded constants must be type cast.");
118
    }
119
  }
120
  // now, post-process the expression
121
2514025
  Assert(!expr.isNull());
122
5028050
  api::Sort te = expr.getSort();
123
2514025
  if (te.isConstructor() && te.getConstructorArity() == 0)
124
  {
125
    // nullary constructors have APPLY_CONSTRUCTOR kind with no children
126
2669
    expr = d_solver->mkTerm(api::APPLY_CONSTRUCTOR, expr);
127
  }
128
5028050
  return expr;
129
}
130
131
bool Parser::getTesterName(api::Term cons, std::string& name) { return false; }
132
133
331312
api::Kind Parser::getKindForFunction(api::Term fun)
134
{
135
662624
  api::Sort t = fun.getSort();
136
331312
  if (t.isFunction())
137
  {
138
313673
    return api::APPLY_UF;
139
  }
140
17639
  else if (t.isConstructor())
141
  {
142
5282
    return api::APPLY_CONSTRUCTOR;
143
  }
144
12357
  else if (t.isSelector())
145
  {
146
10574
    return api::APPLY_SELECTOR;
147
  }
148
1783
  else if (t.isTester())
149
  {
150
1752
    return api::APPLY_TESTER;
151
  }
152
31
  else if (t.isUpdater())
153
  {
154
31
    return api::APPLY_UPDATER;
155
  }
156
  return api::UNDEFINED_KIND;
157
}
158
159
219522
api::Sort Parser::getSort(const std::string& name)
160
{
161
219523
  checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
162
219521
  Assert(isDeclared(name, SYM_SORT));
163
219521
  api::Sort t = d_symtab->lookupType(name);
164
219521
  return t;
165
}
166
167
594
api::Sort Parser::getSort(const std::string& name,
168
                          const std::vector<api::Sort>& params)
169
{
170
596
  checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
171
592
  Assert(isDeclared(name, SYM_SORT));
172
592
  api::Sort t = d_symtab->lookupType(name, params);
173
592
  return t;
174
}
175
176
size_t Parser::getArity(const std::string& sort_name) {
177
  checkDeclaration(sort_name, CHECK_DECLARED, SYM_SORT);
178
  Assert(isDeclared(sort_name, SYM_SORT));
179
  return d_symtab->lookupArity(sort_name);
180
}
181
182
/* Returns true if name is bound to a boolean variable. */
183
bool Parser::isBoolean(const std::string& name) {
184
  api::Term expr = getVariable(name);
185
  return !expr.isNull() && expr.getSort().isBoolean();
186
}
187
188
329585
bool Parser::isFunctionLike(api::Term fun)
189
{
190
329585
  if(fun.isNull()) {
191
    return false;
192
  }
193
659170
  api::Sort type = fun.getSort();
194
340161
  return type.isFunction() || type.isConstructor() || type.isTester() ||
195
340161
         type.isSelector();
196
}
197
198
/* Returns true if name is bound to a function returning boolean. */
199
bool Parser::isPredicate(const std::string& name) {
200
  api::Term expr = getVariable(name);
201
  return !expr.isNull() && expr.getSort().isPredicate();
202
}
203
204
106636
api::Term Parser::bindVar(const std::string& name,
205
                          const api::Sort& type,
206
                          bool levelZero,
207
                          bool doOverload)
208
{
209
106636
  bool globalDecls = d_symman->getGlobalDeclarations();
210
106636
  Debug("parser") << "bindVar(" << name << ", " << type << ")" << std::endl;
211
106636
  api::Term expr = d_solver->mkConst(type, name);
212
106636
  defineVar(name, expr, globalDecls || levelZero, doOverload);
213
106636
  return expr;
214
}
215
216
60510
api::Term Parser::bindBoundVar(const std::string& name, const api::Sort& type)
217
{
218
121020
  Debug("parser") << "bindBoundVar(" << name << ", " << type << ")"
219
60510
                  << std::endl;
220
60510
  api::Term expr = d_solver->mkVar(type, name);
221
60510
  defineVar(name, expr);
222
60510
  return expr;
223
}
224
225
31677
std::vector<api::Term> Parser::bindBoundVars(
226
    std::vector<std::pair<std::string, api::Sort> >& sortedVarNames)
227
{
228
31677
  std::vector<api::Term> vars;
229
88379
  for (std::pair<std::string, api::Sort>& i : sortedVarNames)
230
  {
231
56702
    vars.push_back(bindBoundVar(i.first, i.second));
232
  }
233
31677
  return vars;
234
}
235
236
std::vector<api::Term> Parser::bindVars(const std::vector<std::string> names,
237
                                        const api::Sort& type,
238
                                        bool levelZero,
239
                                        bool doOverload)
240
{
241
  std::vector<api::Term> vars;
242
  for (unsigned i = 0; i < names.size(); ++i) {
243
    vars.push_back(bindVar(names[i], type, levelZero, doOverload));
244
  }
245
  return vars;
246
}
247
248
std::vector<api::Term> Parser::bindBoundVars(
249
    const std::vector<std::string> names, const api::Sort& type)
250
{
251
  std::vector<api::Term> vars;
252
  for (unsigned i = 0; i < names.size(); ++i) {
253
    vars.push_back(bindBoundVar(names[i], type));
254
  }
255
  return vars;
256
}
257
258
333569
void Parser::defineVar(const std::string& name,
259
                       const api::Term& val,
260
                       bool levelZero,
261
                       bool doOverload)
262
{
263
333569
  Debug("parser") << "defineVar( " << name << " := " << val << ")" << std::endl;
264
333569
  if (!d_symtab->bind(name, val, levelZero, doOverload))
265
  {
266
    std::stringstream ss;
267
    ss << "Cannot bind " << name << " to symbol of type " << val.getSort();
268
    ss << ", maybe the symbol has already been defined?";
269
    parseError(ss.str());
270
  }
271
333569
  Assert(isDeclared(name));
272
333569
}
273
274
46329
void Parser::defineType(const std::string& name,
275
                        const api::Sort& type,
276
                        bool levelZero,
277
                        bool skipExisting)
278
{
279
46329
  if (skipExisting && isDeclared(name, SYM_SORT))
280
  {
281
2907
    Assert(d_symtab->lookupType(name) == type);
282
2907
    return;
283
  }
284
43422
  d_symtab->bindType(name, type, levelZero);
285
43422
  Assert(isDeclared(name, SYM_SORT));
286
}
287
288
354
void Parser::defineType(const std::string& name,
289
                        const std::vector<api::Sort>& params,
290
                        const api::Sort& type,
291
                        bool levelZero)
292
{
293
354
  d_symtab->bindType(name, params, type, levelZero);
294
354
  Assert(isDeclared(name, SYM_SORT));
295
354
}
296
297
217
void Parser::defineParameterizedType(const std::string& name,
298
                                     const std::vector<api::Sort>& params,
299
                                     const api::Sort& type)
300
{
301
217
  if (Debug.isOn("parser")) {
302
    Debug("parser") << "defineParameterizedType(" << name << ", "
303
                    << params.size() << ", [";
304
    if (params.size() > 0) {
305
      copy(params.begin(),
306
           params.end() - 1,
307
           ostream_iterator<api::Sort>(Debug("parser"), ", "));
308
      Debug("parser") << params.back();
309
    }
310
    Debug("parser") << "], " << type << ")" << std::endl;
311
  }
312
217
  defineType(name, params, type);
313
217
}
314
315
4168
api::Sort Parser::mkSort(const std::string& name)
316
{
317
4168
  Debug("parser") << "newSort(" << name << ")" << std::endl;
318
4168
  bool globalDecls = d_symman->getGlobalDeclarations();
319
4168
  api::Sort type = d_solver->mkUninterpretedSort(name);
320
4168
  defineType(name, type, globalDecls);
321
4168
  return type;
322
}
323
324
23
api::Sort Parser::mkSortConstructor(const std::string& name, size_t arity)
325
{
326
46
  Debug("parser") << "newSortConstructor(" << name << ", " << arity << ")"
327
23
                  << std::endl;
328
23
  bool globalDecls = d_symman->getGlobalDeclarations();
329
23
  api::Sort type = d_solver->mkSortConstructorSort(name, arity);
330
23
  defineType(name, vector<api::Sort>(arity), type, globalDecls);
331
23
  return type;
332
}
333
334
1469
api::Sort Parser::mkUnresolvedType(const std::string& name)
335
{
336
1469
  api::Sort unresolved = d_solver->mkUninterpretedSort(name);
337
1469
  defineType(name, unresolved);
338
1469
  d_unresolved.insert(unresolved);
339
1469
  return unresolved;
340
}
341
342
57
api::Sort Parser::mkUnresolvedTypeConstructor(const std::string& name,
343
                                              size_t arity)
344
{
345
57
  api::Sort unresolved = d_solver->mkSortConstructorSort(name, arity);
346
57
  defineType(name, vector<api::Sort>(arity), unresolved);
347
57
  d_unresolved.insert(unresolved);
348
57
  return unresolved;
349
}
350
351
api::Sort Parser::mkUnresolvedTypeConstructor(
352
    const std::string& name, const std::vector<api::Sort>& params)
353
{
354
  Debug("parser") << "newSortConstructor(P)(" << name << ", " << params.size()
355
                  << ")" << std::endl;
356
  api::Sort unresolved = d_solver->mkSortConstructorSort(name, params.size());
357
  defineType(name, params, unresolved);
358
  api::Sort t = getSort(name, params);
359
  d_unresolved.insert(unresolved);
360
  return unresolved;
361
}
362
363
1526
api::Sort Parser::mkUnresolvedType(const std::string& name, size_t arity)
364
{
365
1526
  if (arity == 0)
366
  {
367
1469
    return mkUnresolvedType(name);
368
  }
369
57
  return mkUnresolvedTypeConstructor(name, arity);
370
}
371
372
bool Parser::isUnresolvedType(const std::string& name) {
373
  if (!isDeclared(name, SYM_SORT)) {
374
    return false;
375
  }
376
  return d_unresolved.find(getSort(name)) != d_unresolved.end();
377
}
378
379
1168
std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
380
    std::vector<api::DatatypeDecl>& datatypes, bool doOverload)
381
{
382
  try {
383
    std::vector<api::Sort> types =
384
2336
        d_solver->mkDatatypeSorts(datatypes, d_unresolved);
385
386
1168
    Assert(datatypes.size() == types.size());
387
1168
    bool globalDecls = d_symman->getGlobalDeclarations();
388
389
2694
    for (unsigned i = 0; i < datatypes.size(); ++i) {
390
3052
      api::Sort t = types[i];
391
3052
      const api::Datatype& dt = t.getDatatype();
392
3052
      const std::string& name = dt.getName();
393
1526
      Debug("parser-idt") << "define " << name << " as " << t << std::endl;
394
1526
      if (isDeclared(name, SYM_SORT)) {
395
        throw ParserException(name + " already declared");
396
      }
397
1526
      if (t.isParametricDatatype())
398
      {
399
114
        std::vector<api::Sort> paramTypes = t.getDatatypeParamSorts();
400
57
        defineType(name, paramTypes, t, globalDecls);
401
      }
402
      else
403
      {
404
1469
        defineType(name, t, globalDecls);
405
      }
406
3052
      std::unordered_set< std::string > consNames;
407
3052
      std::unordered_set< std::string > selNames;
408
4429
      for (size_t j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
409
      {
410
5806
        const api::DatatypeConstructor& ctor = dt[j];
411
5806
        api::Term constructor = ctor.getConstructorTerm();
412
2903
        Debug("parser-idt") << "+ define " << constructor << std::endl;
413
5806
        string constructorName = ctor.getName();
414
2903
        if(consNames.find(constructorName)==consNames.end()) {
415
2903
          if(!doOverload) {
416
            checkDeclaration(constructorName, CHECK_UNDECLARED);
417
          }
418
2903
          defineVar(constructorName, constructor, globalDecls, doOverload);
419
2903
          consNames.insert(constructorName);
420
        }else{
421
          throw ParserException(constructorName + " already declared in this datatype");
422
        }
423
5806
        std::string testerName;
424
2903
        if (getTesterName(constructor, testerName))
425
        {
426
5806
          api::Term tester = ctor.getTesterTerm();
427
2903
          Debug("parser-idt") << "+ define " << testerName << std::endl;
428
2903
          if (!doOverload)
429
          {
430
            checkDeclaration(testerName, CHECK_UNDECLARED);
431
          }
432
2903
          defineVar(testerName, tester, globalDecls, doOverload);
433
        }
434
5774
        for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++)
435
        {
436
5742
          const api::DatatypeSelector& sel = ctor[k];
437
5742
          api::Term selector = sel.getSelectorTerm();
438
2871
          Debug("parser-idt") << "+++ define " << selector << std::endl;
439
5742
          string selectorName = sel.getName();
440
2871
          if(selNames.find(selectorName)==selNames.end()) {
441
2871
            if(!doOverload) {
442
              checkDeclaration(selectorName, CHECK_UNDECLARED);
443
            }
444
2871
            defineVar(selectorName, selector, globalDecls, doOverload);
445
2871
            selNames.insert(selectorName);
446
          }else{
447
            throw ParserException(selectorName + " already declared in this datatype");
448
          }
449
        }
450
      }
451
    }
452
453
    // These are no longer used, and the ExprManager would have
454
    // complained of a bad substitution if anything is left unresolved.
455
    // Clear out the set.
456
1168
    d_unresolved.clear();
457
458
    // throw exception if any datatype is not well-founded
459
2694
    for (unsigned i = 0; i < datatypes.size(); ++i) {
460
3052
      const api::Datatype& dt = types[i].getDatatype();
461
1526
      if (!dt.isCodatatype() && !dt.isWellFounded()) {
462
        throw ParserException(dt.getName() + " is not well-founded");
463
      }
464
    }
465
2336
    return types;
466
  } catch (IllegalArgumentException& ie) {
467
    throw ParserException(ie.getMessage());
468
  }
469
}
470
471
3996
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts,
472
                                     api::Sort range,
473
                                     std::vector<api::Term>& flattenVars)
474
{
475
3996
  if (range.isFunction())
476
  {
477
16
    std::vector<api::Sort> domainTypes = range.getFunctionDomainSorts();
478
17
    for (unsigned i = 0, size = domainTypes.size(); i < size; i++)
479
    {
480
9
      sorts.push_back(domainTypes[i]);
481
      // the introduced variable is internal (not parsable)
482
18
      std::stringstream ss;
483
9
      ss << "__flatten_var_" << i;
484
18
      api::Term v = d_solver->mkVar(domainTypes[i], ss.str());
485
9
      flattenVars.push_back(v);
486
    }
487
8
    range = range.getFunctionCodomainSort();
488
  }
489
3996
  if (sorts.empty())
490
  {
491
2357
    return range;
492
  }
493
1639
  return d_solver->mkFunctionSort(sorts, range);
494
}
495
496
19111
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts,
497
                                     api::Sort range)
498
{
499
19111
  if (sorts.empty())
500
  {
501
    // no difference
502
1176
    return range;
503
  }
504
17935
  if (Debug.isOn("parser"))
505
  {
506
    Debug("parser") << "mkFlatFunctionType: range " << range << " and domains ";
507
    for (api::Sort t : sorts)
508
    {
509
      Debug("parser") << " " << t;
510
    }
511
    Debug("parser") << "\n";
512
  }
513
18137
  while (range.isFunction())
514
  {
515
202
    std::vector<api::Sort> domainTypes = range.getFunctionDomainSorts();
516
101
    sorts.insert(sorts.end(), domainTypes.begin(), domainTypes.end());
517
101
    range = range.getFunctionCodomainSort();
518
  }
519
17935
  return d_solver->mkFunctionSort(sorts, range);
520
}
521
522
8
api::Term Parser::mkHoApply(api::Term expr, const std::vector<api::Term>& args)
523
{
524
17
  for (unsigned i = 0; i < args.size(); i++)
525
  {
526
9
    expr = d_solver->mkTerm(api::HO_APPLY, expr, args[i]);
527
  }
528
8
  return expr;
529
}
530
531
405
api::Term Parser::applyTypeAscription(api::Term t, api::Sort s)
532
{
533
405
  api::Kind k = t.getKind();
534
405
  if (k == api::EMPTYSET)
535
  {
536
162
    t = d_solver->mkEmptySet(s);
537
  }
538
243
  else if (k == api::EMPTYBAG)
539
  {
540
19
    t = d_solver->mkEmptyBag(s);
541
  }
542
224
  else if (k == api::CONST_SEQUENCE)
543
  {
544
11
    if (!s.isSequence())
545
    {
546
      std::stringstream ss;
547
      ss << "Type ascription on empty sequence must be a sequence, got " << s;
548
      parseError(ss.str());
549
    }
550
11
    if (!t.getSequenceValue().empty())
551
    {
552
      std::stringstream ss;
553
      ss << "Cannot apply a type ascription to a non-empty sequence";
554
      parseError(ss.str());
555
    }
556
11
    t = d_solver->mkEmptySequence(s.getSequenceElementSort());
557
  }
558
213
  else if (k == api::UNIVERSE_SET)
559
  {
560
88
    t = d_solver->mkUniverseSet(s);
561
  }
562
125
  else if (k == api::SEP_NIL)
563
  {
564
43
    t = d_solver->mkSepNil(s);
565
  }
566
82
  else if (k == api::APPLY_CONSTRUCTOR)
567
  {
568
68
    std::vector<api::Term> children(t.begin(), t.end());
569
    // apply type ascription to the operator and reconstruct
570
34
    children[0] = applyTypeAscription(children[0], s);
571
34
    t = d_solver->mkTerm(api::APPLY_CONSTRUCTOR, children);
572
  }
573
  // !!! temporary until datatypes are refactored in the new API
574
810
  api::Sort etype = t.getSort();
575
405
  if (etype.isConstructor())
576
  {
577
    // Type ascriptions only have an effect on the node structure if this is a
578
    // parametric datatype.
579
42
    if (s.isParametricDatatype())
580
    {
581
      // get the datatype that t belongs to
582
72
      api::Sort etyped = etype.getConstructorCodomainSort();
583
72
      api::Datatype d = etyped.getDatatype();
584
      // lookup by name
585
72
      api::DatatypeConstructor dc = d.getConstructor(t.toString());
586
      // ask the constructor for the specialized constructor term
587
36
      t = dc.getSpecializedConstructorTerm(s);
588
    }
589
    // the type of t does not match the sort s by design (constructor type
590
    // vs datatype type), thus we use an alternative check here.
591
42
    if (t.getSort().getConstructorCodomainSort() != s)
592
    {
593
      std::stringstream ss;
594
      ss << "Type ascription on constructor not satisfied, term " << t
595
         << " expected sort " << s << " but has sort "
596
         << t.getSort().getConstructorCodomainSort();
597
      parseError(ss.str());
598
    }
599
42
    return t;
600
  }
601
  // Otherwise, check that the type is correct. Type ascriptions in SMT-LIB 2.6
602
  // referred to the range of function sorts. Note that this is only a check
603
  // and does not impact the returned term.
604
726
  api::Sort checkSort = t.getSort();
605
363
  if (checkSort.isFunction())
606
  {
607
2
    checkSort = checkSort.getFunctionCodomainSort();
608
  }
609
363
  if (checkSort != s)
610
  {
611
    std::stringstream ss;
612
    ss << "Type ascription not satisfied, term " << t
613
       << " expected (codomain) sort " << s << " but has sort " << t.getSort();
614
    parseError(ss.str());
615
  }
616
363
  return t;
617
}
618
619
11950966
bool Parser::isDeclared(const std::string& name, SymbolType type) {
620
11950966
  switch (type) {
621
11416809
    case SYM_VARIABLE: return d_symtab->isBound(name);
622
534157
    case SYM_SORT:
623
534157
      return d_symtab->isBoundType(name);
624
  }
625
  Assert(false);  // Unhandled(type);
626
  return false;
627
}
628
629
8801950
void Parser::checkDeclaration(const std::string& varName,
630
                              DeclarationCheck check,
631
                              SymbolType type,
632
                              std::string notes)
633
{
634
8801950
  if (!d_checksEnabled) {
635
    return;
636
  }
637
638
8801950
  switch (check) {
639
3404819
    case CHECK_DECLARED:
640
3404819
      if (!isDeclared(varName, type)) {
641
78
        parseError("Symbol '" + varName + "' not declared as a " +
642
52
                   (type == SYM_VARIABLE ? "variable" : "type") +
643
52
                   (notes.size() == 0 ? notes : "\n" + notes));
644
      }
645
3404793
      break;
646
647
15480
    case CHECK_UNDECLARED:
648
15480
      if (isDeclared(varName, type)) {
649
6
        parseError("Symbol '" + varName + "' previously declared as a " +
650
4
                   (type == SYM_VARIABLE ? "variable" : "type") +
651
4
                   (notes.size() == 0 ? notes : "\n" + notes));
652
      }
653
15478
      break;
654
655
5381651
    case CHECK_NONE:
656
5381651
      break;
657
658
    default: Assert(false);  // Unhandled(check);
659
  }
660
}
661
662
329585
void Parser::checkFunctionLike(api::Term fun)
663
{
664
329585
  if (d_checksEnabled && !isFunctionLike(fun)) {
665
4
    stringstream ss;
666
2
    ss << "Expecting function-like symbol, found '";
667
2
    ss << fun;
668
2
    ss << "'";
669
4
    parseError(ss.str());
670
  }
671
329583
}
672
673
724262
void Parser::addOperator(api::Kind kind) { d_logicOperators.insert(kind); }
674
675
5201
void Parser::preemptCommand(Command* cmd) { d_commandQueue.push_back(cmd); }
676
242337
Command* Parser::nextCommand()
677
{
678
242337
  Debug("parser") << "nextCommand()" << std::endl;
679
242337
  Command* cmd = NULL;
680
242337
  if (!d_commandQueue.empty()) {
681
5199
    cmd = d_commandQueue.front();
682
5199
    d_commandQueue.pop_front();
683
5199
    setDone(cmd == NULL);
684
  } else {
685
    try {
686
237138
      cmd = d_input->parseCommand();
687
237102
      d_commandQueue.push_back(cmd);
688
237102
      cmd = d_commandQueue.front();
689
237102
      d_commandQueue.pop_front();
690
237102
      setDone(cmd == NULL);
691
64
    } catch (ParserException& e) {
692
32
      setDone();
693
32
      throw;
694
8
    } catch (exception& e) {
695
4
      setDone();
696
8
      parseError(e.what());
697
    }
698
  }
699
242301
  Debug("parser") << "nextCommand() => " << cmd << std::endl;
700
242301
  return cmd;
701
}
702
703
120
api::Term Parser::nextExpression()
704
{
705
120
  Debug("parser") << "nextExpression()" << std::endl;
706
120
  api::Term result;
707
120
  if (!done()) {
708
    try {
709
120
      result = d_input->parseExpr();
710
78
      setDone(result.isNull());
711
84
    } catch (ParserException& e) {
712
42
      setDone();
713
42
      throw;
714
    } catch (exception& e) {
715
      setDone();
716
      parseError(e.what());
717
    }
718
  }
719
78
  Debug("parser") << "nextExpression() => " << result << std::endl;
720
78
  return result;
721
}
722
723
167
void Parser::attributeNotSupported(const std::string& attr) {
724
167
  if (d_attributesWarnedAbout.find(attr) == d_attributesWarnedAbout.end()) {
725
40
    stringstream ss;
726
    ss << "warning: Attribute '" << attr
727
20
       << "' not supported (ignoring this and all following uses)";
728
20
    d_input->warning(ss.str());
729
20
    d_attributesWarnedAbout.insert(attr);
730
  }
731
167
}
732
733
2568
size_t Parser::scopeLevel() const { return d_symman->scopeLevel(); }
734
735
103501
void Parser::pushScope(bool isUserContext)
736
{
737
103501
  d_symman->pushScope(isUserContext);
738
103501
}
739
740
68
void Parser::pushGetValueScope()
741
{
742
68
  pushScope();
743
  // we must bind all relevant uninterpreted constants, which coincide with
744
  // the set of uninterpreted constants that are printed in the definition
745
  // of a model.
746
136
  std::vector<api::Sort> declareSorts = d_symman->getModelDeclareSorts();
747
136
  Trace("parser") << "Push get value scope, with " << declareSorts.size()
748
68
                  << " declared sorts" << std::endl;
749
72
  for (const api::Sort& s : declareSorts)
750
  {
751
8
    std::vector<api::Term> elements = d_solver->getModelDomainElements(s);
752
8
    for (const api::Term& e : elements)
753
    {
754
      // Uninterpreted constants are abstract values, which by SMT-LIB are
755
      // required to be annotated with their type, e.g. (as @uc_Foo_0 Foo).
756
      // Thus, the element is not printed simply as its name.
757
8
      std::string en = e.toString();
758
4
      size_t index = en.find("(as ");
759
4
      if (index == 0)
760
      {
761
4
        index = en.find(" ", 4);
762
4
        en = en.substr(4, index - 4);
763
      }
764
4
      Trace("parser") << "Get value scope : " << en << " -> " << e << std::endl;
765
4
      defineVar(en, e);
766
    }
767
  }
768
68
}
769
770
102935
void Parser::popScope()
771
{
772
102935
  d_symman->popScope();
773
102935
}
774
775
void Parser::reset() {}
776
777
11145
SymbolManager* Parser::getSymbolManager() { return d_symman; }
778
779
9484
std::wstring Parser::processAdHocStringEsc(const std::string& s)
780
{
781
18968
  std::wstring ws;
782
  {
783
9484
    std::setlocale(LC_ALL, "en_US.utf8");
784
9484
    std::mbtowc(nullptr, nullptr, 0);
785
9484
    const char* end = s.data() + s.size();
786
9484
    const char* ptr = s.data();
787
222802
    for (wchar_t c; ptr != end; ) {
788
106659
      int res = std::mbtowc(&c, ptr, end - ptr);
789
106659
      if (res == -1) {
790
        std::cerr << "Invalid escape sequence in " << s << std::endl;
791
        break;
792
106659
      } else if (res == 0) {
793
        break;
794
      } else {
795
106659
        ws += c;
796
106659
        ptr += res;
797
      }
798
    }
799
  }
800
801
9484
  std::wstring res;
802
9484
  unsigned i = 0;
803
222802
  while (i < ws.size())
804
  {
805
    // get the current character
806
213318
    if (ws[i] != '\\')
807
    {
808
      // don't worry about printable here
809
106659
      res.push_back(ws[i]);
810
106659
      ++i;
811
106659
      continue;
812
    }
813
    // slash is always escaped
814
    ++i;
815
    if (i >= ws.size())
816
    {
817
      // slash cannot be the last character if we are parsing escape sequences
818
      std::stringstream serr;
819
      serr << "Escape sequence at the end of string: \"" << s
820
           << "\" should be handled by lexer";
821
      parseError(serr.str());
822
    }
823
    switch (ws[i])
824
    {
825
      case 'n':
826
      {
827
        res.push_back('\n');
828
        i++;
829
      }
830
      break;
831
      case 't':
832
      {
833
        res.push_back('\t');
834
        i++;
835
      }
836
      break;
837
      case 'v':
838
      {
839
        res.push_back('\v');
840
        i++;
841
      }
842
      break;
843
      case 'b':
844
      {
845
        res.push_back('\b');
846
        i++;
847
      }
848
      break;
849
      case 'r':
850
      {
851
        res.push_back('\r');
852
        i++;
853
      }
854
      break;
855
      case 'f':
856
      {
857
        res.push_back('\f');
858
        i++;
859
      }
860
      break;
861
      case 'a':
862
      {
863
        res.push_back('\a');
864
        i++;
865
      }
866
      break;
867
      case '\\':
868
      {
869
        res.push_back('\\');
870
        i++;
871
      }
872
      break;
873
      case 'x':
874
      {
875
        bool isValid = false;
876
        if (i + 2 < ws.size())
877
        {
878
          if (std::isxdigit(ws[i + 1]) && std::isxdigit(ws[i + 2]))
879
          {
880
            std::wstringstream shex;
881
            shex << ws[i + 1] << ws[i + 2];
882
            unsigned val;
883
            shex >> std::hex >> val;
884
            res.push_back(val);
885
            i += 3;
886
            isValid = true;
887
          }
888
        }
889
        if (!isValid)
890
        {
891
          std::stringstream serr;
892
          serr << "Illegal String Literal: \"" << s
893
               << "\", must have two digits after \\x";
894
          parseError(serr.str());
895
        }
896
      }
897
      break;
898
      default:
899
      {
900
        if (std::isdigit(ws[i]))
901
        {
902
          // octal escape sequences  TODO : revisit (issue #1251).
903
          unsigned num = static_cast<unsigned>(ws[i]) - 48;
904
          bool flag = num < 4;
905
          if (i + 1 < ws.size() && num < 8 && std::isdigit(ws[i + 1])
906
              && ws[i + 1] < '8')
907
          {
908
            num = num * 8 + static_cast<unsigned>(ws[i + 1]) - 48;
909
            if (flag && i + 2 < ws.size() && std::isdigit(ws[i + 2])
910
                && ws[i + 2] < '8')
911
            {
912
              num = num * 8 + static_cast<unsigned>(ws[i + 2]) - 48;
913
              res.push_back(num);
914
              i += 3;
915
            }
916
            else
917
            {
918
              res.push_back(num);
919
              i += 2;
920
            }
921
          }
922
          else
923
          {
924
            res.push_back(num);
925
            i++;
926
          }
927
        }
928
      }
929
    }
930
  }
931
18968
  return res;
932
}
933
934
9794
api::Term Parser::mkStringConstant(const std::string& s)
935
{
936
9794
  if (d_solver->getOption("input-language") == "LANG_SMTLIB_V2_6")
937
  {
938
8911
    return d_solver->mkString(s, true);
939
  }
940
  // otherwise, we must process ad-hoc escape sequences
941
1766
  std::wstring str = processAdHocStringEsc(s);
942
883
  return d_solver->mkString(str);
943
}
944
945
8
api::Term Parser::mkCharConstant(const std::string& s)
946
{
947
8
  Assert(s.find_first_not_of("0123456789abcdefABCDEF", 0) == std::string::npos
948
         && s.size() <= 5 && s.size() > 0)
949
      << "Unexpected string for hexadecimal character " << s;
950
8
  wchar_t val = static_cast<wchar_t>(std::stoul(s, 0, 16));
951
8
  return d_solver->mkString(std::wstring(1, val));
952
}
953
954
}  // namespace parser
955
31116
}  // namespace cvc5