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