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 |
6427 |
Parser::Parser(api::Solver* solver, |
40 |
|
SymbolManager* sm, |
41 |
|
bool strictMode, |
42 |
6427 |
bool parseOnly) |
43 |
|
: d_symman(sm), |
44 |
6427 |
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 |
12854 |
d_solver(solver) |
55 |
|
{ |
56 |
6427 |
} |
57 |
|
|
58 |
12854 |
Parser::~Parser() { |
59 |
6428 |
for (std::list<Command*>::iterator iter = d_commandQueue.begin(); |
60 |
6428 |
iter != d_commandQueue.end(); ++iter) { |
61 |
1 |
Command* command = *iter; |
62 |
1 |
delete command; |
63 |
|
} |
64 |
6427 |
d_commandQueue.clear(); |
65 |
6427 |
} |
66 |
|
|
67 |
1005342 |
api::Solver* Parser::getSolver() const { return d_solver; } |
68 |
|
|
69 |
3865000 |
api::Term Parser::getSymbol(const std::string& name, SymbolType type) |
70 |
|
{ |
71 |
3865000 |
checkDeclaration(name, CHECK_DECLARED, type); |
72 |
3865000 |
Assert(isDeclared(name, type)); |
73 |
3865000 |
Assert(type == SYM_VARIABLE); |
74 |
|
// Functions share var namespace |
75 |
3865000 |
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 |
3865000 |
api::Term Parser::getVariable(const std::string& name) |
86 |
|
{ |
87 |
3865000 |
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 |
3484556 |
api::Term Parser::getExpressionForName(const std::string& name) |
96 |
|
{ |
97 |
6969112 |
api::Sort t; |
98 |
6969112 |
return getExpressionForNameAndType(name, t); |
99 |
|
} |
100 |
|
|
101 |
3484846 |
api::Term Parser::getExpressionForNameAndType(const std::string& name, |
102 |
|
api::Sort t) |
103 |
|
{ |
104 |
3484846 |
Assert(isDeclared(name)); |
105 |
|
// first check if the variable is declared and not overloaded |
106 |
3484846 |
api::Term expr = getVariable(name); |
107 |
3484846 |
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 |
3484846 |
Assert(!expr.isNull()); |
122 |
6969692 |
api::Sort te = expr.getSort(); |
123 |
3484846 |
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 |
6969692 |
return expr; |
129 |
|
} |
130 |
|
|
131 |
|
bool Parser::getTesterName(api::Term cons, std::string& name) { return false; } |
132 |
|
|
133 |
328050 |
api::Kind Parser::getKindForFunction(api::Term fun) |
134 |
|
{ |
135 |
656100 |
api::Sort t = fun.getSort(); |
136 |
328050 |
if (t.isFunction()) |
137 |
|
{ |
138 |
310923 |
return api::APPLY_UF; |
139 |
|
} |
140 |
17127 |
else if (t.isConstructor()) |
141 |
|
{ |
142 |
5095 |
return api::APPLY_CONSTRUCTOR; |
143 |
|
} |
144 |
12032 |
else if (t.isSelector()) |
145 |
|
{ |
146 |
10274 |
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 |
274191 |
api::Sort Parser::getSort(const std::string& name) |
160 |
|
{ |
161 |
274192 |
checkDeclaration(name, CHECK_DECLARED, SYM_SORT); |
162 |
274190 |
Assert(isDeclared(name, SYM_SORT)); |
163 |
274190 |
api::Sort t = d_symtab->lookupType(name); |
164 |
274190 |
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 |
326630 |
bool Parser::isFunctionLike(api::Term fun) |
189 |
|
{ |
190 |
326630 |
if(fun.isNull()) { |
191 |
|
return false; |
192 |
|
} |
193 |
653260 |
api::Sort type = fun.getSort(); |
194 |
336908 |
return type.isFunction() || type.isConstructor() || type.isTester() || |
195 |
336908 |
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 |
175286 |
api::Term Parser::bindVar(const std::string& name, |
205 |
|
const api::Sort& type, |
206 |
|
bool levelZero, |
207 |
|
bool doOverload) |
208 |
|
{ |
209 |
175286 |
bool globalDecls = d_symman->getGlobalDeclarations(); |
210 |
175286 |
Debug("parser") << "bindVar(" << name << ", " << type << ")" << std::endl; |
211 |
175286 |
api::Term expr = d_solver->mkConst(type, name); |
212 |
175286 |
defineVar(name, expr, globalDecls || levelZero, doOverload); |
213 |
175286 |
return expr; |
214 |
|
} |
215 |
|
|
216 |
57045 |
api::Term Parser::bindBoundVar(const std::string& name, const api::Sort& type) |
217 |
|
{ |
218 |
114090 |
Debug("parser") << "bindBoundVar(" << name << ", " << type << ")" |
219 |
57045 |
<< std::endl; |
220 |
57045 |
api::Term expr = d_solver->mkVar(type, name); |
221 |
57045 |
defineVar(name, expr); |
222 |
57045 |
return expr; |
223 |
|
} |
224 |
|
|
225 |
30268 |
std::vector<api::Term> Parser::bindBoundVars( |
226 |
|
std::vector<std::pair<std::string, api::Sort> >& sortedVarNames) |
227 |
|
{ |
228 |
30268 |
std::vector<api::Term> vars; |
229 |
83679 |
for (std::pair<std::string, api::Sort>& i : sortedVarNames) |
230 |
|
{ |
231 |
53411 |
vars.push_back(bindBoundVar(i.first, i.second)); |
232 |
|
} |
233 |
30268 |
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 |
373751 |
void Parser::defineVar(const std::string& name, |
259 |
|
const api::Term& val, |
260 |
|
bool levelZero, |
261 |
|
bool doOverload) |
262 |
|
{ |
263 |
373751 |
Debug("parser") << "defineVar( " << name << " := " << val << ")" << std::endl; |
264 |
373751 |
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 |
373751 |
Assert(isDeclared(name)); |
272 |
373751 |
} |
273 |
|
|
274 |
33937 |
void Parser::defineType(const std::string& name, |
275 |
|
const api::Sort& type, |
276 |
|
bool levelZero, |
277 |
|
bool skipExisting) |
278 |
|
{ |
279 |
33937 |
if (skipExisting && isDeclared(name, SYM_SORT)) |
280 |
|
{ |
281 |
1879 |
Assert(d_symtab->lookupType(name) == type); |
282 |
1879 |
return; |
283 |
|
} |
284 |
32058 |
d_symtab->bindType(name, type, levelZero); |
285 |
32058 |
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 |
1360 |
api::Sort Parser::mkUnresolvedType(const std::string& name) |
335 |
|
{ |
336 |
1360 |
api::Sort unresolved = d_solver->mkUninterpretedSort(name); |
337 |
1360 |
defineType(name, unresolved); |
338 |
1360 |
d_unresolved.insert(unresolved); |
339 |
1360 |
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 |
1202 |
api::Sort Parser::mkUnresolvedType(const std::string& name, size_t arity) |
364 |
|
{ |
365 |
1202 |
if (arity == 0) |
366 |
|
{ |
367 |
1160 |
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 |
1069 |
std::vector<api::Sort> Parser::bindMutualDatatypeTypes( |
380 |
|
std::vector<api::DatatypeDecl>& datatypes, bool doOverload) |
381 |
|
{ |
382 |
|
try { |
383 |
|
std::vector<api::Sort> types = |
384 |
2138 |
d_solver->mkDatatypeSorts(datatypes, d_unresolved); |
385 |
|
|
386 |
1069 |
Assert(datatypes.size() == types.size()); |
387 |
1069 |
bool globalDecls = d_symman->getGlobalDeclarations(); |
388 |
|
|
389 |
2478 |
for (unsigned i = 0; i < datatypes.size(); ++i) { |
390 |
2824 |
api::Sort t = types[i]; |
391 |
2824 |
const api::Datatype& dt = t.getDatatype(); |
392 |
2824 |
const std::string& name = dt.getName(); |
393 |
1412 |
Debug("parser-idt") << "define " << name << " as " << t << std::endl; |
394 |
1412 |
if (isDeclared(name, SYM_SORT)) { |
395 |
|
throw ParserException(name + " already declared"); |
396 |
|
} |
397 |
1412 |
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 |
1358 |
defineType(name, t, globalDecls); |
405 |
|
} |
406 |
2824 |
std::unordered_set< std::string > consNames; |
407 |
2824 |
std::unordered_set< std::string > selNames; |
408 |
4166 |
for (size_t j = 0, ncons = dt.getNumConstructors(); j < ncons; j++) |
409 |
|
{ |
410 |
5514 |
const api::DatatypeConstructor& ctor = dt[j]; |
411 |
5514 |
api::Term constructor = ctor.getConstructorTerm(); |
412 |
2757 |
Debug("parser-idt") << "+ define " << constructor << std::endl; |
413 |
5514 |
string constructorName = ctor.getName(); |
414 |
2757 |
if(consNames.find(constructorName)==consNames.end()) { |
415 |
2756 |
if(!doOverload) { |
416 |
560 |
checkDeclaration(constructorName, CHECK_UNDECLARED); |
417 |
|
} |
418 |
2754 |
defineVar(constructorName, constructor, globalDecls, doOverload); |
419 |
2754 |
consNames.insert(constructorName); |
420 |
|
}else{ |
421 |
1 |
throw ParserException(constructorName + " already declared in this datatype"); |
422 |
|
} |
423 |
5508 |
std::string testerName; |
424 |
2754 |
if (getTesterName(constructor, testerName)) |
425 |
|
{ |
426 |
5508 |
api::Term tester = ctor.getTesterTerm(); |
427 |
2754 |
Debug("parser-idt") << "+ define " << testerName << std::endl; |
428 |
2754 |
if (!doOverload) |
429 |
|
{ |
430 |
556 |
checkDeclaration(testerName, CHECK_UNDECLARED); |
431 |
|
} |
432 |
2754 |
defineVar(testerName, tester, globalDecls, doOverload); |
433 |
|
} |
434 |
5413 |
for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++) |
435 |
|
{ |
436 |
5318 |
const api::DatatypeSelector& sel = ctor[k]; |
437 |
5318 |
api::Term selector = sel.getSelectorTerm(); |
438 |
2659 |
Debug("parser-idt") << "+++ define " << selector << std::endl; |
439 |
5318 |
string selectorName = sel.getName(); |
440 |
2659 |
if(selNames.find(selectorName)==selNames.end()) { |
441 |
2659 |
if(!doOverload) { |
442 |
256 |
checkDeclaration(selectorName, CHECK_UNDECLARED); |
443 |
|
} |
444 |
2659 |
defineVar(selectorName, selector, globalDecls, doOverload); |
445 |
2659 |
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 |
1066 |
d_unresolved.clear(); |
457 |
|
|
458 |
|
// throw exception if any datatype is not well-founded |
459 |
2475 |
for (unsigned i = 0; i < datatypes.size(); ++i) { |
460 |
2818 |
const api::Datatype& dt = types[i].getDatatype(); |
461 |
1409 |
if (!dt.isCodatatype() && !dt.isWellFounded()) { |
462 |
|
throw ParserException(dt.getName() + " is not well-founded"); |
463 |
|
} |
464 |
|
} |
465 |
2132 |
return types; |
466 |
|
} catch (IllegalArgumentException& ie) { |
467 |
|
throw ParserException(ie.getMessage()); |
468 |
|
} |
469 |
|
} |
470 |
|
|
471 |
3427 |
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts, |
472 |
|
api::Sort range, |
473 |
|
std::vector<api::Term>& flattenVars) |
474 |
|
{ |
475 |
3427 |
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 |
3427 |
if (sorts.empty()) |
490 |
|
{ |
491 |
2083 |
return range; |
492 |
|
} |
493 |
1344 |
return d_solver->mkFunctionSort(sorts, range); |
494 |
|
} |
495 |
|
|
496 |
18739 |
api::Sort Parser::mkFlatFunctionType(std::vector<api::Sort>& sorts, |
497 |
|
api::Sort range) |
498 |
|
{ |
499 |
18739 |
if (sorts.empty()) |
500 |
|
{ |
501 |
|
// no difference |
502 |
1172 |
return range; |
503 |
|
} |
504 |
17567 |
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 |
17769 |
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 |
17567 |
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 |
16098826 |
bool Parser::isDeclared(const std::string& name, SymbolType type) { |
614 |
16098826 |
switch (type) { |
615 |
15460087 |
case SYM_VARIABLE: return d_symtab->isBound(name); |
616 |
638739 |
case SYM_SORT: |
617 |
638739 |
return d_symtab->isBoundType(name); |
618 |
|
} |
619 |
|
Assert(false); // Unhandled(type); |
620 |
|
return false; |
621 |
|
} |
622 |
|
|
623 |
11852226 |
void Parser::checkDeclaration(const std::string& varName, |
624 |
|
DeclarationCheck check, |
625 |
|
SymbolType type, |
626 |
|
std::string notes) |
627 |
|
{ |
628 |
11852226 |
if (!d_checksEnabled) { |
629 |
|
return; |
630 |
|
} |
631 |
|
|
632 |
11852226 |
switch (check) { |
633 |
4517760 |
case CHECK_DECLARED: |
634 |
4517760 |
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 |
4517732 |
break; |
640 |
|
|
641 |
11374 |
case CHECK_UNDECLARED: |
642 |
11374 |
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 |
11364 |
break; |
648 |
|
|
649 |
7323092 |
case CHECK_NONE: |
650 |
7323092 |
break; |
651 |
|
|
652 |
|
default: Assert(false); // Unhandled(check); |
653 |
|
} |
654 |
|
} |
655 |
|
|
656 |
326630 |
void Parser::checkFunctionLike(api::Term fun) |
657 |
|
{ |
658 |
326630 |
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 |
326626 |
} |
666 |
|
|
667 |
489962 |
void Parser::addOperator(api::Kind kind) { d_logicOperators.insert(kind); } |
668 |
|
|
669 |
278 |
void Parser::preemptCommand(Command* cmd) { d_commandQueue.push_back(cmd); } |
670 |
295998 |
Command* Parser::nextCommand() |
671 |
|
{ |
672 |
295998 |
Debug("parser") << "nextCommand()" << std::endl; |
673 |
295998 |
Command* cmd = NULL; |
674 |
295998 |
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 |
295721 |
cmd = d_input->parseCommand(); |
681 |
295641 |
d_commandQueue.push_back(cmd); |
682 |
295641 |
cmd = d_commandQueue.front(); |
683 |
295641 |
d_commandQueue.pop_front(); |
684 |
295641 |
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 |
295918 |
Debug("parser") << "nextCommand() => " << cmd << std::endl; |
694 |
295918 |
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 |
103268 |
void Parser::pushScope(bool isUserContext) |
730 |
|
{ |
731 |
103268 |
d_symman->pushScope(isUserContext); |
732 |
103268 |
} |
733 |
|
|
734 |
102715 |
void Parser::popScope() |
735 |
|
{ |
736 |
102715 |
d_symman->popScope(); |
737 |
102715 |
} |
738 |
|
|
739 |
8 |
void Parser::reset() {} |
740 |
|
|
741 |
12763 |
SymbolManager* Parser::getSymbolManager() { return d_symman; } |
742 |
|
|
743 |
13155 |
std::wstring Parser::processAdHocStringEsc(const std::string& s) |
744 |
|
{ |
745 |
26310 |
std::wstring ws; |
746 |
|
{ |
747 |
13155 |
std::setlocale(LC_ALL, "en_US.utf8"); |
748 |
13155 |
std::mbtowc(nullptr, nullptr, 0); |
749 |
13155 |
const char* end = s.data() + s.size(); |
750 |
13155 |
const char* ptr = s.data(); |
751 |
261521 |
for (wchar_t c; ptr != end; ) { |
752 |
124183 |
int res = std::mbtowc(&c, ptr, end - ptr); |
753 |
124183 |
if (res == -1) { |
754 |
|
std::cerr << "Invalid escape sequence in " << s << std::endl; |
755 |
|
break; |
756 |
124183 |
} else if (res == 0) { |
757 |
|
break; |
758 |
|
} else { |
759 |
124183 |
ws += c; |
760 |
124183 |
ptr += res; |
761 |
|
} |
762 |
|
} |
763 |
|
} |
764 |
|
|
765 |
13155 |
std::wstring res; |
766 |
13155 |
unsigned i = 0; |
767 |
261521 |
while (i < ws.size()) |
768 |
|
{ |
769 |
|
// get the current character |
770 |
248366 |
if (ws[i] != '\\') |
771 |
|
{ |
772 |
|
// don't worry about printable here |
773 |
124183 |
res.push_back(ws[i]); |
774 |
124183 |
++i; |
775 |
124183 |
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 |
26310 |
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 |
29490 |
} // namespace cvc5 |