GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/parser/parser.cpp Lines: 364 498 73.1 %
Date: 2021-05-22 Branches: 454 1329 34.2 %

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