GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/parser/parser.cpp Lines: 364 498 73.1 %
Date: 2021-09-16 Branches: 452 1327 34.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
6440
Parser::Parser(api::Solver* solver,
40
               SymbolManager* sm,
41
               bool strictMode,
42
6440
               bool parseOnly)
43
    : d_symman(sm),
44
6440
      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
12880
      d_solver(solver)
55
{
56
6440
}
57
58
12880
Parser::~Parser() {
59
6441
  for (std::list<Command*>::iterator iter = d_commandQueue.begin();
60
6441
       iter != d_commandQueue.end(); ++iter) {
61
1
    Command* command = *iter;
62
1
    delete command;
63
  }
64
6440
  d_commandQueue.clear();
65
6440
}
66
67
1005640
api::Solver* Parser::getSolver() const { return d_solver; }
68
69
3865863
api::Term Parser::getSymbol(const std::string& name, SymbolType type)
70
{
71
3865863
  checkDeclaration(name, CHECK_DECLARED, type);
72
3865863
  Assert(isDeclared(name, type));
73
3865863
  Assert(type == SYM_VARIABLE);
74
  // Functions share var namespace
75
3865863
  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
3865863
api::Term Parser::getVariable(const std::string& name)
86
{
87
3865863
  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
3485292
api::Term Parser::getExpressionForName(const std::string& name)
96
{
97
6970584
  api::Sort t;
98
6970584
  return getExpressionForNameAndType(name, t);
99
}
100
101
3485582
api::Term Parser::getExpressionForNameAndType(const std::string& name,
102
                                              api::Sort t)
103
{
104
3485582
  Assert(isDeclared(name));
105
  // first check if the variable is declared and not overloaded
106
3485582
  api::Term expr = getVariable(name);
107
3485582
  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
3485582
  Assert(!expr.isNull());
122
6971164
  api::Sort te = expr.getSort();
123
3485582
  if (te.isConstructor() && te.getConstructorArity() == 0)
124
  {
125
    // nullary constructors have APPLY_CONSTRUCTOR kind with no children
126
2163
    expr = d_solver->mkTerm(api::APPLY_CONSTRUCTOR, expr);
127
  }
128
6971164
  return expr;
129
}
130
131
bool Parser::getTesterName(api::Term cons, std::string& name) { return false; }
132
133
328177
api::Kind Parser::getKindForFunction(api::Term fun)
134
{
135
656354
  api::Sort t = fun.getSort();
136
328177
  if (t.isFunction())
137
  {
138
311064
    return api::APPLY_UF;
139
  }
140
17113
  else if (t.isConstructor())
141
  {
142
5093
    return api::APPLY_CONSTRUCTOR;
143
  }
144
12020
  else if (t.isSelector())
145
  {
146
10262
    return api::APPLY_SELECTOR;
147
  }
148
1758
  else if (t.isTester())
149
  {
150
1750
    return api::APPLY_TESTER;
151
  }
152
8
  else if (t.isUpdater())
153
  {
154
8
    return api::APPLY_UPDATER;
155
  }
156
  return api::UNDEFINED_KIND;
157
}
158
159
274439
api::Sort Parser::getSort(const std::string& name)
160
{
161
274440
  checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
162
274438
  Assert(isDeclared(name, SYM_SORT));
163
274438
  api::Sort t = d_symtab->lookupType(name);
164
274438
  return t;
165
}
166
167
590
api::Sort Parser::getSort(const std::string& name,
168
                          const std::vector<api::Sort>& params)
169
{
170
592
  checkDeclaration(name, CHECK_DECLARED, SYM_SORT);
171
588
  Assert(isDeclared(name, SYM_SORT));
172
588
  api::Sort t = d_symtab->lookupType(name, params);
173
588
  return t;
174
}
175
176
6188
size_t Parser::getArity(const std::string& sort_name) {
177
6188
  checkDeclaration(sort_name, CHECK_DECLARED, SYM_SORT);
178
6188
  Assert(isDeclared(sort_name, SYM_SORT));
179
6188
  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
326757
bool Parser::isFunctionLike(api::Term fun)
189
{
190
326757
  if(fun.isNull()) {
191
    return false;
192
  }
193
653514
  api::Sort type = fun.getSort();
194
337023
  return type.isFunction() || type.isConstructor() || type.isTester() ||
195
337023
         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
175311
api::Term Parser::bindVar(const std::string& name,
205
                          const api::Sort& type,
206
                          bool levelZero,
207
                          bool doOverload)
208
{
209
175311
  bool globalDecls = d_symman->getGlobalDeclarations();
210
175311
  Debug("parser") << "bindVar(" << name << ", " << type << ")" << std::endl;
211
175311
  api::Term expr = d_solver->mkConst(type, name);
212
175311
  defineVar(name, expr, globalDecls || levelZero, doOverload);
213
175311
  return expr;
214
}
215
216
57213
api::Term Parser::bindBoundVar(const std::string& name, const api::Sort& type)
217
{
218
114426
  Debug("parser") << "bindBoundVar(" << name << ", " << type << ")"
219
57213
                  << std::endl;
220
57213
  api::Term expr = d_solver->mkVar(type, name);
221
57213
  defineVar(name, expr);
222
57213
  return expr;
223
}
224
225
30323
std::vector<api::Term> Parser::bindBoundVars(
226
    std::vector<std::pair<std::string, api::Sort> >& sortedVarNames)
227
{
228
30323
  std::vector<api::Term> vars;
229
83905
  for (std::pair<std::string, api::Sort>& i : sortedVarNames)
230
  {
231
53582
    vars.push_back(bindBoundVar(i.first, i.second));
232
  }
233
30323
  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
30
std::vector<api::Term> Parser::bindBoundVars(
249
    const std::vector<std::string> names, const api::Sort& type)
250
{
251
30
  std::vector<api::Term> vars;
252
60
  for (unsigned i = 0; i < names.size(); ++i) {
253
30
    vars.push_back(bindBoundVar(names[i], type));
254
  }
255
30
  return vars;
256
}
257
258
374128
void Parser::defineVar(const std::string& name,
259
                       const api::Term& val,
260
                       bool levelZero,
261
                       bool doOverload)
262
{
263
374128
  Debug("parser") << "defineVar( " << name << " := " << val << ")" << std::endl;
264
374128
  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
374128
  Assert(isDeclared(name));
272
374128
}
273
274
33962
void Parser::defineType(const std::string& name,
275
                        const api::Sort& type,
276
                        bool levelZero,
277
                        bool skipExisting)
278
{
279
33962
  if (skipExisting && isDeclared(name, SYM_SORT))
280
  {
281
1880
    Assert(d_symtab->lookupType(name) == type);
282
1880
    return;
283
  }
284
32082
  d_symtab->bindType(name, type, levelZero);
285
32082
  Assert(isDeclared(name, SYM_SORT));
286
}
287
288
335
void Parser::defineType(const std::string& name,
289
                        const std::vector<api::Sort>& params,
290
                        const api::Sort& type,
291
                        bool levelZero)
292
{
293
335
  d_symtab->bindType(name, params, type, levelZero);
294
335
  Assert(isDeclared(name, SYM_SORT));
295
335
}
296
297
206
void Parser::defineParameterizedType(const std::string& name,
298
                                     const std::vector<api::Sort>& params,
299
                                     const api::Sort& type)
300
{
301
206
  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
206
  defineType(name, params, type);
313
206
}
314
315
4119
api::Sort Parser::mkSort(const std::string& name)
316
{
317
4119
  Debug("parser") << "newSort(" << name << ")" << std::endl;
318
4119
  bool globalDecls = d_symman->getGlobalDeclarations();
319
4119
  api::Sort type = d_solver->mkUninterpretedSort(name);
320
4119
  defineType(name, type, globalDecls);
321
4119
  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
1359
api::Sort Parser::mkUnresolvedType(const std::string& name)
335
{
336
1359
  api::Sort unresolved = d_solver->mkUninterpretedSort(name);
337
1359
  defineType(name, unresolved);
338
1359
  d_unresolved.insert(unresolved);
339
1359
  return unresolved;
340
}
341
342
42
api::Sort Parser::mkUnresolvedTypeConstructor(const std::string& name,
343
                                              size_t arity)
344
{
345
42
  api::Sort unresolved = d_solver->mkSortConstructorSort(name, arity);
346
42
  defineType(name, vector<api::Sort>(arity), unresolved);
347
42
  d_unresolved.insert(unresolved);
348
42
  return unresolved;
349
}
350
351
10
api::Sort Parser::mkUnresolvedTypeConstructor(
352
    const std::string& name, const std::vector<api::Sort>& params)
353
{
354
20
  Debug("parser") << "newSortConstructor(P)(" << name << ", " << params.size()
355
10
                  << ")" << std::endl;
356
10
  api::Sort unresolved = d_solver->mkSortConstructorSort(name, params.size());
357
10
  defineType(name, params, unresolved);
358
20
  api::Sort t = getSort(name, params);
359
10
  d_unresolved.insert(unresolved);
360
20
  return unresolved;
361
}
362
363
1201
api::Sort Parser::mkUnresolvedType(const std::string& name, size_t arity)
364
{
365
1201
  if (arity == 0)
366
  {
367
1159
    return mkUnresolvedType(name);
368
  }
369
42
  return mkUnresolvedTypeConstructor(name, arity);
370
}
371
372
214
bool Parser::isUnresolvedType(const std::string& name) {
373
214
  if (!isDeclared(name, SYM_SORT)) {
374
212
    return false;
375
  }
376
2
  return d_unresolved.find(getSort(name)) != d_unresolved.end();
377
}
378
379
1068
std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
380
    std::vector<api::DatatypeDecl>& datatypes, bool doOverload)
381
{
382
  try {
383
    std::vector<api::Sort> types =
384
2136
        d_solver->mkDatatypeSorts(datatypes, d_unresolved);
385
386
1068
    Assert(datatypes.size() == types.size());
387
1068
    bool globalDecls = d_symman->getGlobalDeclarations();
388
389
2476
    for (unsigned i = 0; i < datatypes.size(); ++i) {
390
2822
      api::Sort t = types[i];
391
2822
      const api::Datatype& dt = t.getDatatype();
392
2822
      const std::string& name = dt.getName();
393
1411
      Debug("parser-idt") << "define " << name << " as " << t << std::endl;
394
1411
      if (isDeclared(name, SYM_SORT)) {
395
        throw ParserException(name + " already declared");
396
      }
397
1411
      if (t.isParametricDatatype())
398
      {
399
108
        std::vector<api::Sort> paramTypes = t.getDatatypeParamSorts();
400
54
        defineType(name, paramTypes, t, globalDecls);
401
      }
402
      else
403
      {
404
1357
        defineType(name, t, globalDecls);
405
      }
406
2822
      std::unordered_set< std::string > consNames;
407
2822
      std::unordered_set< std::string > selNames;
408
4164
      for (size_t j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
409
      {
410
5512
        const api::DatatypeConstructor& ctor = dt[j];
411
5512
        api::Term constructor = ctor.getConstructorTerm();
412
2756
        Debug("parser-idt") << "+ define " << constructor << std::endl;
413
5512
        string constructorName = ctor.getName();
414
2756
        if(consNames.find(constructorName)==consNames.end()) {
415
2755
          if(!doOverload) {
416
560
            checkDeclaration(constructorName, CHECK_UNDECLARED);
417
          }
418
2753
          defineVar(constructorName, constructor, globalDecls, doOverload);
419
2753
          consNames.insert(constructorName);
420
        }else{
421
1
          throw ParserException(constructorName + " already declared in this datatype");
422
        }
423
5506
        std::string testerName;
424
2753
        if (getTesterName(constructor, testerName))
425
        {
426
5506
          api::Term tester = ctor.getTesterTerm();
427
2753
          Debug("parser-idt") << "+ define " << testerName << std::endl;
428
2753
          if (!doOverload)
429
          {
430
556
            checkDeclaration(testerName, CHECK_UNDECLARED);
431
          }
432
2753
          defineVar(testerName, tester, globalDecls, doOverload);
433
        }
434
5410
        for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++)
435
        {
436
5314
          const api::DatatypeSelector& sel = ctor[k];
437
5314
          api::Term selector = sel.getSelectorTerm();
438
2657
          Debug("parser-idt") << "+++ define " << selector << std::endl;
439
5314
          string selectorName = sel.getName();
440
2657
          if(selNames.find(selectorName)==selNames.end()) {
441
2657
            if(!doOverload) {
442
256
              checkDeclaration(selectorName, CHECK_UNDECLARED);
443
            }
444
2657
            defineVar(selectorName, selector, globalDecls, doOverload);
445
2657
            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
1065
    d_unresolved.clear();
457
458
    // throw exception if any datatype is not well-founded
459
2473
    for (unsigned i = 0; i < datatypes.size(); ++i) {
460
2816
      const api::Datatype& dt = types[i].getDatatype();
461
1408
      if (!dt.isCodatatype() && !dt.isWellFounded()) {
462
        throw ParserException(dt.getName() + " is not well-founded");
463
      }
464
    }
465
2130
    return types;
466
  } catch (IllegalArgumentException& ie) {
467
    throw ParserException(ie.getMessage());
468
  }
469
}
470
471
3422
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts,
472
                                     api::Sort range,
473
                                     std::vector<api::Term>& flattenVars)
474
{
475
3422
  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
3422
  if (sorts.empty())
490
  {
491
2083
    return range;
492
  }
493
1339
  return d_solver->mkFunctionSort(sorts, range);
494
}
495
496
18742
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts,
497
                                     api::Sort range)
498
{
499
18742
  if (sorts.empty())
500
  {
501
    // no difference
502
1172
    return range;
503
  }
504
17570
  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
17772
  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
17570
  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
393
api::Term Parser::applyTypeAscription(api::Term t, api::Sort s)
532
{
533
393
  api::Kind k = t.getKind();
534
393
  if (k == api::EMPTYSET)
535
  {
536
150
    t = d_solver->mkEmptySet(s);
537
  }
538
243
  else if (k == api::EMPTYBAG)
539
  {
540
16
    t = d_solver->mkEmptyBag(s);
541
  }
542
227
  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
216
  else if (k == api::UNIVERSE_SET)
559
  {
560
87
    t = d_solver->mkUniverseSet(s);
561
  }
562
129
  else if (k == api::SEP_NIL)
563
  {
564
43
    t = d_solver->mkSepNil(s);
565
  }
566
86
  else if (k == api::APPLY_CONSTRUCTOR)
567
  {
568
80
    std::vector<api::Term> children(t.begin(), t.end());
569
    // apply type ascription to the operator and reconstruct
570
40
    children[0] = applyTypeAscription(children[0], s);
571
40
    t = d_solver->mkTerm(api::APPLY_CONSTRUCTOR, children);
572
  }
573
  // !!! temporary until datatypes are refactored in the new API
574
786
  api::Sort etype = t.getSort();
575
393
  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, nothing to do
602
  // check that the type is correct
603
351
  if (t.getSort() != s)
604
  {
605
    std::stringstream ss;
606
    ss << "Type ascription not satisfied, term " << t << " expected sort " << s
607
       << " but has sort " << t.getSort();
608
    parseError(ss.str());
609
  }
610
351
  return t;
611
}
612
613
16103129
bool Parser::isDeclared(const std::string& name, SymbolType type) {
614
16103129
  switch (type) {
615
15463850
    case SYM_VARIABLE: return d_symtab->isBound(name);
616
639279
    case SYM_SORT:
617
639279
      return d_symtab->isBoundType(name);
618
  }
619
  Assert(false);  // Unhandled(type);
620
  return false;
621
}
622
623
11855581
void Parser::checkDeclaration(const std::string& varName,
624
                              DeclarationCheck check,
625
                              SymbolType type,
626
                              std::string notes)
627
{
628
11855581
  if (!d_checksEnabled) {
629
    return;
630
  }
631
632
11855581
  switch (check) {
633
4518995
    case CHECK_DECLARED:
634
4518995
      if (!isDeclared(varName, type)) {
635
84
        parseError("Symbol '" + varName + "' not declared as a " +
636
56
                   (type == SYM_VARIABLE ? "variable" : "type") +
637
56
                   (notes.size() == 0 ? notes : "\n" + notes));
638
      }
639
4518967
      break;
640
641
11434
    case CHECK_UNDECLARED:
642
11434
      if (isDeclared(varName, type)) {
643
30
        parseError("Symbol '" + varName + "' previously declared as a " +
644
20
                   (type == SYM_VARIABLE ? "variable" : "type") +
645
20
                   (notes.size() == 0 ? notes : "\n" + notes));
646
      }
647
11424
      break;
648
649
7325152
    case CHECK_NONE:
650
7325152
      break;
651
652
    default: Assert(false);  // Unhandled(check);
653
  }
654
}
655
656
326757
void Parser::checkFunctionLike(api::Term fun)
657
{
658
326757
  if (d_checksEnabled && !isFunctionLike(fun)) {
659
8
    stringstream ss;
660
4
    ss << "Expecting function-like symbol, found '";
661
4
    ss << fun;
662
4
    ss << "'";
663
8
    parseError(ss.str());
664
  }
665
326753
}
666
667
490668
void Parser::addOperator(api::Kind kind) { d_logicOperators.insert(kind); }
668
669
278
void Parser::preemptCommand(Command* cmd) { d_commandQueue.push_back(cmd); }
670
296175
Command* Parser::nextCommand()
671
{
672
296175
  Debug("parser") << "nextCommand()" << std::endl;
673
296175
  Command* cmd = NULL;
674
296175
  if (!d_commandQueue.empty()) {
675
277
    cmd = d_commandQueue.front();
676
277
    d_commandQueue.pop_front();
677
277
    setDone(cmd == NULL);
678
  } else {
679
    try {
680
295898
      cmd = d_input->parseCommand();
681
295818
      d_commandQueue.push_back(cmd);
682
295818
      cmd = d_commandQueue.front();
683
295818
      d_commandQueue.pop_front();
684
295818
      setDone(cmd == NULL);
685
154
    } catch (ParserException& e) {
686
77
      setDone();
687
77
      throw;
688
6
    } catch (exception& e) {
689
3
      setDone();
690
6
      parseError(e.what());
691
    }
692
  }
693
296095
  Debug("parser") << "nextCommand() => " << cmd << std::endl;
694
296095
  return cmd;
695
}
696
697
176
api::Term Parser::nextExpression()
698
{
699
176
  Debug("parser") << "nextExpression()" << std::endl;
700
176
  api::Term result;
701
176
  if (!done()) {
702
    try {
703
176
      result = d_input->parseExpr();
704
134
      setDone(result.isNull());
705
84
    } catch (ParserException& e) {
706
42
      setDone();
707
42
      throw;
708
    } catch (exception& e) {
709
      setDone();
710
      parseError(e.what());
711
    }
712
  }
713
134
  Debug("parser") << "nextExpression() => " << result << std::endl;
714
134
  return result;
715
}
716
717
161
void Parser::attributeNotSupported(const std::string& attr) {
718
161
  if (d_attributesWarnedAbout.find(attr) == d_attributesWarnedAbout.end()) {
719
28
    stringstream ss;
720
    ss << "warning: Attribute '" << attr
721
14
       << "' not supported (ignoring this and all following uses)";
722
14
    d_input->warning(ss.str());
723
14
    d_attributesWarnedAbout.insert(attr);
724
  }
725
161
}
726
727
2738
size_t Parser::scopeLevel() const { return d_symman->scopeLevel(); }
728
729
103395
void Parser::pushScope(bool isUserContext)
730
{
731
103395
  d_symman->pushScope(isUserContext);
732
103395
}
733
734
102842
void Parser::popScope()
735
{
736
102842
  d_symman->popScope();
737
102842
}
738
739
8
void Parser::reset() {}
740
741
12758
SymbolManager* Parser::getSymbolManager() { return d_symman; }
742
743
13169
std::wstring Parser::processAdHocStringEsc(const std::string& s)
744
{
745
26338
  std::wstring ws;
746
  {
747
13169
    std::setlocale(LC_ALL, "en_US.utf8");
748
13169
    std::mbtowc(nullptr, nullptr, 0);
749
13169
    const char* end = s.data() + s.size();
750
13169
    const char* ptr = s.data();
751
261693
    for (wchar_t c; ptr != end; ) {
752
124262
      int res = std::mbtowc(&c, ptr, end - ptr);
753
124262
      if (res == -1) {
754
        std::cerr << "Invalid escape sequence in " << s << std::endl;
755
        break;
756
124262
      } else if (res == 0) {
757
        break;
758
      } else {
759
124262
        ws += c;
760
124262
        ptr += res;
761
      }
762
    }
763
  }
764
765
13169
  std::wstring res;
766
13169
  unsigned i = 0;
767
261693
  while (i < ws.size())
768
  {
769
    // get the current character
770
248524
    if (ws[i] != '\\')
771
    {
772
      // don't worry about printable here
773
124262
      res.push_back(ws[i]);
774
124262
      ++i;
775
124262
      continue;
776
    }
777
    // slash is always escaped
778
    ++i;
779
    if (i >= ws.size())
780
    {
781
      // slash cannot be the last character if we are parsing escape sequences
782
      std::stringstream serr;
783
      serr << "Escape sequence at the end of string: \"" << s
784
           << "\" should be handled by lexer";
785
      parseError(serr.str());
786
    }
787
    switch (ws[i])
788
    {
789
      case 'n':
790
      {
791
        res.push_back('\n');
792
        i++;
793
      }
794
      break;
795
      case 't':
796
      {
797
        res.push_back('\t');
798
        i++;
799
      }
800
      break;
801
      case 'v':
802
      {
803
        res.push_back('\v');
804
        i++;
805
      }
806
      break;
807
      case 'b':
808
      {
809
        res.push_back('\b');
810
        i++;
811
      }
812
      break;
813
      case 'r':
814
      {
815
        res.push_back('\r');
816
        i++;
817
      }
818
      break;
819
      case 'f':
820
      {
821
        res.push_back('\f');
822
        i++;
823
      }
824
      break;
825
      case 'a':
826
      {
827
        res.push_back('\a');
828
        i++;
829
      }
830
      break;
831
      case '\\':
832
      {
833
        res.push_back('\\');
834
        i++;
835
      }
836
      break;
837
      case 'x':
838
      {
839
        bool isValid = false;
840
        if (i + 2 < ws.size())
841
        {
842
          if (std::isxdigit(ws[i + 1]) && std::isxdigit(ws[i + 2]))
843
          {
844
            std::wstringstream shex;
845
            shex << ws[i + 1] << ws[i + 2];
846
            unsigned val;
847
            shex >> std::hex >> val;
848
            res.push_back(val);
849
            i += 3;
850
            isValid = true;
851
          }
852
        }
853
        if (!isValid)
854
        {
855
          std::stringstream serr;
856
          serr << "Illegal String Literal: \"" << s
857
               << "\", must have two digits after \\x";
858
          parseError(serr.str());
859
        }
860
      }
861
      break;
862
      default:
863
      {
864
        if (std::isdigit(ws[i]))
865
        {
866
          // octal escape sequences  TODO : revisit (issue #1251).
867
          unsigned num = static_cast<unsigned>(ws[i]) - 48;
868
          bool flag = num < 4;
869
          if (i + 1 < ws.size() && num < 8 && std::isdigit(ws[i + 1])
870
              && ws[i + 1] < '8')
871
          {
872
            num = num * 8 + static_cast<unsigned>(ws[i + 1]) - 48;
873
            if (flag && i + 2 < ws.size() && std::isdigit(ws[i + 2])
874
                && ws[i + 2] < '8')
875
            {
876
              num = num * 8 + static_cast<unsigned>(ws[i + 2]) - 48;
877
              res.push_back(num);
878
              i += 3;
879
            }
880
            else
881
            {
882
              res.push_back(num);
883
              i += 2;
884
            }
885
          }
886
          else
887
          {
888
            res.push_back(num);
889
            i++;
890
          }
891
        }
892
      }
893
    }
894
  }
895
26338
  return res;
896
}
897
898
9206
api::Term Parser::mkStringConstant(const std::string& s)
899
{
900
9206
  if (d_solver->getOption("input-language") == "LANG_SMTLIB_V2_6")
901
  {
902
8686
    return d_solver->mkString(s, true);
903
  }
904
  // otherwise, we must process ad-hoc escape sequences
905
1040
  std::wstring str = processAdHocStringEsc(s);
906
520
  return d_solver->mkString(str);
907
}
908
909
8
api::Term Parser::mkCharConstant(const std::string& s)
910
{
911
8
  Assert(s.find_first_not_of("0123456789abcdefABCDEF", 0) == std::string::npos
912
         && s.size() <= 5 && s.size() > 0)
913
      << "Unexpected string for hexadecimal character " << s;
914
8
  wchar_t val = static_cast<wchar_t>(std::stoul(s, 0, 16));
915
8
  return d_solver->mkString(std::wstring(1, val));
916
}
917
918
}  // namespace parser
919
29562
}  // namespace cvc5