Support sygus version 2.1 command assume (#7081)
[cvc5.git] / src / parser / smt2 / Smt2.g
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 for SMT-LIB v2 input language.
14 */
15
16 grammar Smt2;
17
18 options {
19 // C output for antlr
20 language = 'C';
21
22 // Skip the default error handling, just break with exceptions
23 // defaultErrorHandler = false;
24
25 // Only lookahead of <= k requested (disable for LL* parsing)
26 // Note that cvc5's BoundedTokenBuffer requires a fixed k !
27 // If you change this k, change it also in smt2_input.cpp !
28 k = 2;
29 }/* options */
30
31 @header {
32 /* ****************************************************************************
33 * This file is part of the cvc5 project.
34 *
35 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
36 * in the top-level source directory and their institutional affiliations.
37 * All rights reserved. See the file COPYING in the top-level source
38 * directory for licensing information.
39 * ****************************************************************************
40 */
41 }/* @header */
42
43 @lexer::includes {
44
45 /** This suppresses warnings about the redefinition of token symbols between
46 * different parsers. The redefinitions should be harmless as long as no
47 * client: (a) #include's the lexer headers for two grammars AND (b) uses the
48 * token symbol definitions.
49 */
50 #pragma GCC system_header
51
52 #if defined(CVC5_COMPETITION_MODE) && !defined(CVC5_SMTCOMP_APPLICATION_TRACK)
53 /* This improves performance by ~10 percent on big inputs.
54 * This option is only valid if we know the input is ASCII (or some 8-bit encoding).
55 * If we know the input is UTF-16, we can use ANTLR3_INLINE_INPUT_UTF16.
56 * Otherwise, we have to let the lexer detect the encoding at runtime.
57 */
58 # define ANTLR3_INLINE_INPUT_ASCII
59 # define ANTLR3_INLINE_INPUT_8BIT
60 #endif /* CVC5_COMPETITION_MODE && !CVC5_SMTCOMP_APPLICATION_TRACK */
61
62 #include "parser/antlr_tracing.h"
63
64 }/* @lexer::includes */
65
66 @lexer::postinclude {
67 #include "parser/smt2/smt2.h"
68 #include "parser/antlr_input.h"
69
70 using namespace cvc5;
71 using namespace cvc5::parser;
72
73 #undef PARSER_STATE
74 #define PARSER_STATE ((Smt2*)LEXER->super)
75 }/* @lexer::postinclude */
76
77 @parser::includes {
78
79 #include <memory>
80
81 #include "base/check.h"
82 #include "parser/antlr_tracing.h"
83 #include "parser/parse_op.h"
84 #include "parser/parser.h"
85 #include "smt/command.h"
86
87 namespace cvc5 {
88
89 namespace api {
90 class Term;
91 class Sort;
92 }
93
94 }/* cvc5 namespace */
95
96 }/* @parser::includes */
97
98 @parser::postinclude {
99
100 #include <set>
101 #include <sstream>
102 #include <string>
103 #include <unordered_set>
104 #include <vector>
105
106 #include "api/cpp/cvc5.h"
107 #include "base/output.h"
108 #include "options/set_language.h"
109 #include "parser/antlr_input.h"
110 #include "parser/parser.h"
111 #include "parser/smt2/smt2.h"
112 #include "util/floatingpoint_size.h"
113 #include "util/hash.h"
114
115 using namespace cvc5;
116 using namespace cvc5::parser;
117
118 /* These need to be macros so they can refer to the PARSER macro, which
119 * will be defined by ANTLR *after* this section. (If they were functions,
120 * PARSER would be undefined.) */
121 #undef PARSER_STATE
122 #define PARSER_STATE ((Smt2*)PARSER->super)
123 #undef SOLVER
124 #define SOLVER PARSER_STATE->getSolver()
125 #undef SYM_MAN
126 #define SYM_MAN PARSER_STATE->getSymbolManager()
127 #undef MK_TERM
128 #define MK_TERM SOLVER->mkTerm
129 #define UNSUPPORTED PARSER_STATE->unimplementedFeature
130
131 }/* parser::postinclude */
132
133 /**
134 * Parses an expression.
135 * @return the parsed expression, or the Null Expr if we've reached the
136 * end of the input
137 */
138 parseExpr returns [cvc5::api::Term expr = cvc5::api::Term()]
139 @declarations {
140 cvc5::api::Term expr2;
141 }
142 : term[expr, expr2]
143 | EOF
144 ;
145
146 /**
147 * Parses a command
148 * @return the parsed command, or NULL if we've reached the end of the input
149 */
150 parseCommand returns [cvc5::Command* cmd_return = NULL]
151 @declarations {
152 std::unique_ptr<cvc5::Command> cmd;
153 std::string name;
154 }
155 @after {
156 cmd_return = cmd.release();
157 }
158 : LPAREN_TOK command[&cmd] RPAREN_TOK
159
160 /* This extended command has to be in the outermost production so that
161 * the RPAREN_TOK is properly eaten and we are in a good state to read
162 * the included file's tokens. */
163 | LPAREN_TOK INCLUDE_TOK str[name,true] RPAREN_TOK
164 { if(!PARSER_STATE->canIncludeFile()) {
165 PARSER_STATE->parseError("include-file feature was disabled for this "
166 "run.");
167 }
168 if(PARSER_STATE->strictModeEnabled()) {
169 PARSER_STATE->parseError("Extended commands are not permitted while "
170 "operating in strict compliance mode.");
171 }
172 PARSER_STATE->includeFile(name);
173 // The command of the included file will be produced at the next
174 // parseCommand() call
175 cmd.reset(new EmptyCommand("include::" + name));
176 }
177
178 | EOF
179 ;
180
181 /**
182 * Parses a SyGuS command.
183 * @return the parsed SyGuS command, or NULL if we've reached the end of the
184 * input
185 */
186 parseSygus returns [cvc5::Command* cmd_return = NULL]
187 @declarations {
188 std::string name;
189 }
190 @after {
191 cmd_return = cmd.release();
192 }
193 : LPAREN_TOK cmd=sygusCommand RPAREN_TOK
194 | EOF
195 ;
196
197 /**
198 * Parse the internal portion of the command, ignoring the surrounding
199 * parentheses.
200 */
201 command [std::unique_ptr<cvc5::Command>* cmd]
202 @declarations {
203 std::string name;
204 std::vector<std::string> names;
205 cvc5::api::Term expr, expr2;
206 cvc5::api::Sort t;
207 std::vector<cvc5::api::Term> terms;
208 std::vector<api::Sort> sorts;
209 std::vector<std::pair<std::string, cvc5::api::Sort> > sortedVarNames;
210 std::vector<cvc5::api::Term> flattenVars;
211 }
212 : /* set the logic */
213 SET_LOGIC_TOK symbol[name,CHECK_NONE,SYM_SORT]
214 {
215 cmd->reset(PARSER_STATE->setLogic(name));
216 }
217 | /* set-info */
218 SET_INFO_TOK setInfoInternal[cmd]
219 | /* get-info */
220 GET_INFO_TOK KEYWORD
221 { cmd->reset(new GetInfoCommand(
222 AntlrInput::tokenText($KEYWORD).c_str() + 1));
223 }
224 | /* set-option */
225 SET_OPTION_TOK setOptionInternal[cmd]
226 | /* get-option */
227 GET_OPTION_TOK KEYWORD
228 { cmd->reset(new GetOptionCommand(
229 AntlrInput::tokenText($KEYWORD).c_str() + 1));
230 }
231 | /* sort declaration */
232 DECLARE_SORT_TOK
233 {
234 PARSER_STATE->checkThatLogicIsSet();
235 PARSER_STATE->checkLogicAllowsFreeSorts();
236 }
237 symbol[name,CHECK_UNDECLARED,SYM_SORT]
238 { PARSER_STATE->checkUserSymbol(name); }
239 n=INTEGER_LITERAL
240 { Debug("parser") << "declare sort: '" << name
241 << "' arity=" << n << std::endl;
242 unsigned arity = AntlrInput::tokenToUnsigned(n);
243 if(arity == 0) {
244 api::Sort type = PARSER_STATE->mkSort(name);
245 cmd->reset(new DeclareSortCommand(name, 0, type));
246 } else {
247 api::Sort type = PARSER_STATE->mkSortConstructor(name, arity);
248 cmd->reset(new DeclareSortCommand(name, arity, type));
249 }
250 }
251 | /* sort definition */
252 DEFINE_SORT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
253 symbol[name,CHECK_UNDECLARED,SYM_SORT]
254 { PARSER_STATE->checkUserSymbol(name); }
255 LPAREN_TOK symbolList[names,CHECK_NONE,SYM_SORT] RPAREN_TOK
256 { PARSER_STATE->pushScope();
257 for(std::vector<std::string>::const_iterator i = names.begin(),
258 iend = names.end();
259 i != iend;
260 ++i) {
261 sorts.push_back(PARSER_STATE->mkSort(*i));
262 }
263 }
264 sortSymbol[t,CHECK_DECLARED]
265 { PARSER_STATE->popScope();
266 // Do NOT call mkSort, since that creates a new sort!
267 // This name is not its own distinct sort, it's an alias.
268 PARSER_STATE->defineParameterizedType(name, sorts, t);
269 cmd->reset(new DefineSortCommand(name, sorts, t));
270 }
271 | /* function declaration */
272 DECLARE_FUN_TOK { PARSER_STATE->checkThatLogicIsSet(); }
273 symbol[name,CHECK_NONE,SYM_VARIABLE]
274 { PARSER_STATE->checkUserSymbol(name); }
275 LPAREN_TOK sortList[sorts] RPAREN_TOK
276 sortSymbol[t,CHECK_DECLARED]
277 { Debug("parser") << "declare fun: '" << name << "'" << std::endl;
278 if( !sorts.empty() ) {
279 t = PARSER_STATE->mkFlatFunctionType(sorts, t);
280 }
281 if(t.isFunction())
282 {
283 PARSER_STATE->checkLogicAllowsFunctions();
284 }
285 // we allow overloading for function declarations
286 if( PARSER_STATE->sygus() )
287 {
288 PARSER_STATE->parseErrorLogic("declare-fun are not allowed in sygus "
289 "version 2.0");
290 }
291 else
292 {
293 api::Term func =
294 PARSER_STATE->bindVar(name, t, false, true);
295 cmd->reset(new DeclareFunctionCommand(name, func, t));
296 }
297 }
298 | /* function definition */
299 DEFINE_FUN_TOK { PARSER_STATE->checkThatLogicIsSet(); }
300 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
301 { PARSER_STATE->checkUserSymbol(name); }
302 LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
303 sortSymbol[t,CHECK_DECLARED]
304 { /* add variables to parser state before parsing term */
305 Debug("parser") << "define fun: '" << name << "'" << std::endl;
306 if( sortedVarNames.size() > 0 ) {
307 sorts.reserve(sortedVarNames.size());
308 for(std::vector<std::pair<std::string, api::Sort> >::const_iterator i =
309 sortedVarNames.begin(), iend = sortedVarNames.end();
310 i != iend;
311 ++i) {
312 sorts.push_back((*i).second);
313 }
314 }
315
316 t = PARSER_STATE->mkFlatFunctionType(sorts, t, flattenVars);
317 if (sortedVarNames.size() > 0)
318 {
319 PARSER_STATE->pushScope();
320 }
321 terms = PARSER_STATE->bindBoundVars(sortedVarNames);
322 }
323 term[expr, expr2]
324 {
325 if( !flattenVars.empty() ){
326 // if this function has any implicit variables flattenVars,
327 // we apply the body of the definition to the flatten vars
328 expr = PARSER_STATE->mkHoApply(expr, flattenVars);
329 terms.insert(terms.end(), flattenVars.begin(), flattenVars.end());
330 }
331 if (sortedVarNames.size() > 0)
332 {
333 PARSER_STATE->popScope();
334 }
335 // declare the name down here (while parsing term, signature
336 // must not be extended with the name itself; no recursion
337 // permitted)
338 // we allow overloading for function definitions
339 api::Term func = PARSER_STATE->bindVar(name, t, false, true);
340 cmd->reset(new DefineFunctionCommand(
341 name, func, terms, expr, SYM_MAN->getGlobalDeclarations()));
342 }
343 | DECLARE_DATATYPE_TOK datatypeDefCommand[false, cmd]
344 | DECLARE_DATATYPES_TOK datatypesDefCommand[false, cmd]
345 | /* value query */
346 GET_VALUE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
347 ( LPAREN_TOK termList[terms,expr] RPAREN_TOK
348 { cmd->reset(new GetValueCommand(terms)); }
349 | ~LPAREN_TOK
350 { PARSER_STATE->parseError("The get-value command expects a list of "
351 "terms. Perhaps you forgot a pair of "
352 "parentheses?");
353 }
354 )
355 | /* get-assignment */
356 GET_ASSIGNMENT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
357 { cmd->reset(new GetAssignmentCommand()); }
358 | /* assertion */
359 ASSERT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
360 { PARSER_STATE->clearLastNamedTerm(); }
361 term[expr, expr2]
362 { cmd->reset(new AssertCommand(expr));
363 if (PARSER_STATE->lastNamedTerm().first == expr)
364 {
365 // set the expression name, if there was a named term
366 std::pair<api::Term, std::string> namedTerm =
367 PARSER_STATE->lastNamedTerm();
368 SYM_MAN->setExpressionName(namedTerm.first, namedTerm.second, true);
369 }
370 }
371 | /* check-sat */
372 CHECK_SAT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
373 { if( PARSER_STATE->sygus() ){
374 PARSER_STATE->parseError("Sygus does not support check-sat command.");
375 }
376 }
377 ( term[expr, expr2]
378 { if(PARSER_STATE->strictModeEnabled()) {
379 PARSER_STATE->parseError(
380 "Extended commands (such as check-sat with an argument) are not "
381 "permitted while operating in strict compliance mode.");
382 }
383 }
384 | { expr = api::Term(); }
385 )
386 { cmd->reset(new CheckSatCommand(expr)); }
387 | /* check-sat-assuming */
388 CHECK_SAT_ASSUMING_TOK { PARSER_STATE->checkThatLogicIsSet(); }
389 ( LPAREN_TOK termList[terms,expr] RPAREN_TOK
390 {
391 cmd->reset(new CheckSatAssumingCommand(terms));
392 }
393 | ~LPAREN_TOK
394 { PARSER_STATE->parseError("The check-sat-assuming command expects a "
395 "list of terms. Perhaps you forgot a pair of "
396 "parentheses?");
397 }
398 )
399 | /* get-assertions */
400 GET_ASSERTIONS_TOK { PARSER_STATE->checkThatLogicIsSet(); }
401 { cmd->reset(new GetAssertionsCommand()); }
402 | /* get-proof */
403 GET_PROOF_TOK { PARSER_STATE->checkThatLogicIsSet(); }
404 { cmd->reset(new GetProofCommand()); }
405 | /* get-unsat-assumptions */
406 GET_UNSAT_ASSUMPTIONS_TOK { PARSER_STATE->checkThatLogicIsSet(); }
407 { cmd->reset(new GetUnsatAssumptionsCommand); }
408 | /* get-unsat-core */
409 GET_UNSAT_CORE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
410 { cmd->reset(new GetUnsatCoreCommand); }
411 | /* push */
412 PUSH_TOK { PARSER_STATE->checkThatLogicIsSet(); }
413 { if( PARSER_STATE->sygus() ){
414 PARSER_STATE->parseError("Sygus does not support push command.");
415 }
416 }
417 ( k=INTEGER_LITERAL
418 { unsigned num = AntlrInput::tokenToUnsigned(k);
419 if(num == 0) {
420 cmd->reset(new EmptyCommand());
421 } else if(num == 1) {
422 PARSER_STATE->pushScope(true);
423 cmd->reset(new PushCommand());
424 } else {
425 std::unique_ptr<CommandSequence> seq(new CommandSequence());
426 do {
427 PARSER_STATE->pushScope(true);
428 Command* push_cmd = new PushCommand();
429 push_cmd->setMuted(num > 1);
430 seq->addCommand(push_cmd);
431 --num;
432 } while(num > 0);
433 cmd->reset(seq.release());
434 }
435 }
436 | { if(PARSER_STATE->strictModeEnabled()) {
437 PARSER_STATE->parseError(
438 "Strict compliance mode demands an integer to be provided to "
439 "PUSH. Maybe you want (push 1)?");
440 } else {
441 PARSER_STATE->pushScope(true);
442 cmd->reset(new PushCommand());
443 }
444 } )
445 | POP_TOK { PARSER_STATE->checkThatLogicIsSet(); }
446 { if( PARSER_STATE->sygus() ){
447 PARSER_STATE->parseError("Sygus does not support pop command.");
448 }
449 }
450 ( k=INTEGER_LITERAL
451 { unsigned num = AntlrInput::tokenToUnsigned(k);
452 if(num > PARSER_STATE->scopeLevel()) {
453 PARSER_STATE->parseError("Attempted to pop above the top stack "
454 "frame.");
455 }
456 if(num == 0) {
457 cmd->reset(new EmptyCommand());
458 } else if(num == 1) {
459 PARSER_STATE->popScope();
460 cmd->reset(new PopCommand());
461 } else {
462 std::unique_ptr<CommandSequence> seq(new CommandSequence());
463 do {
464 PARSER_STATE->popScope();
465 Command* pop_command = new PopCommand();
466 pop_command->setMuted(num > 1);
467 seq->addCommand(pop_command);
468 --num;
469 } while(num > 0);
470 cmd->reset(seq.release());
471 }
472 }
473 | { if(PARSER_STATE->strictModeEnabled()) {
474 PARSER_STATE->parseError(
475 "Strict compliance mode demands an integer to be provided to POP."
476 "Maybe you want (pop 1)?");
477 } else {
478 PARSER_STATE->popScope();
479 cmd->reset(new PopCommand());
480 }
481 }
482 )
483 /* exit */
484 | EXIT_TOK
485 { cmd->reset(new QuitCommand()); }
486
487 /* New SMT-LIB 2.5 command set */
488 | smt25Command[cmd]
489
490 /* cvc5-extended SMT-LIB commands */
491 | extendedCommand[cmd]
492 { if(PARSER_STATE->strictModeEnabled()) {
493 PARSER_STATE->parseError(
494 "Extended commands are not permitted while operating in strict "
495 "compliance mode.");
496 }
497 }
498
499 /* error handling */
500 | SIMPLE_SYMBOL
501 { std::string id = AntlrInput::tokenText($SIMPLE_SYMBOL);
502 if(id == "benchmark") {
503 PARSER_STATE->parseError(
504 "In SMT-LIBv2 mode, but got something that looks like SMT-LIBv1, "
505 "which is not supported anymore.");
506 } else {
507 PARSER_STATE->parseError("expected SMT-LIBv2 command, got `" + id +
508 "'.");
509 }
510 }
511 ;
512
513 sygusCommand returns [std::unique_ptr<cvc5::Command> cmd]
514 @declarations {
515 cvc5::api::Term expr, expr2, fun;
516 cvc5::api::Sort t, range;
517 std::vector<std::string> names;
518 std::vector<std::pair<std::string, cvc5::api::Sort> > sortedVarNames;
519 std::vector<cvc5::api::Term> sygusVars;
520 std::string name;
521 bool isAssume;
522 bool isInv;
523 cvc5::api::Grammar* grammar = nullptr;
524 }
525 : /* declare-var */
526 DECLARE_VAR_TOK { PARSER_STATE->checkThatLogicIsSet(); }
527 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
528 { PARSER_STATE->checkUserSymbol(name); }
529 sortSymbol[t,CHECK_DECLARED]
530 {
531 api::Term var = SOLVER->mkSygusVar(t, name);
532 PARSER_STATE->defineVar(name, var);
533 cmd.reset(new DeclareSygusVarCommand(name, var, t));
534 }
535 | /* synth-fun */
536 ( SYNTH_FUN_TOK { isInv = false; }
537 | SYNTH_INV_TOK { isInv = true; range = SOLVER->getBooleanSort(); }
538 )
539 { PARSER_STATE->checkThatLogicIsSet(); }
540 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
541 LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
542 ( sortSymbol[range,CHECK_DECLARED] )?
543 {
544 PARSER_STATE->pushScope();
545 sygusVars = PARSER_STATE->bindBoundVars(sortedVarNames);
546 }
547 (
548 // optionally, read the sygus grammar
549 //
550 // `grammar` specifies the required grammar for the function to
551 // synthesize, expressed as a type
552 sygusGrammar[grammar, sygusVars, name]
553 )?
554 {
555 Debug("parser-sygus") << "Define synth fun : " << name << std::endl;
556
557 fun = isInv ? (grammar == nullptr
558 ? SOLVER->synthInv(name, sygusVars)
559 : SOLVER->synthInv(name, sygusVars, *grammar))
560 : (grammar == nullptr
561 ? SOLVER->synthFun(name, sygusVars, range)
562 : SOLVER->synthFun(name, sygusVars, range, *grammar));
563
564 Debug("parser-sygus") << "...read synth fun " << name << std::endl;
565 PARSER_STATE->popScope();
566 // we do not allow overloading for synth fun
567 PARSER_STATE->defineVar(name, fun);
568 cmd = std::unique_ptr<Command>(
569 new SynthFunCommand(name, fun, sygusVars, range, isInv, grammar));
570 }
571 | /* constraint */
572 ( CONSTRAINT_TOK { isAssume = false; } | ASSUME_TOK { isAssume = true; } )
573 {
574 PARSER_STATE->checkThatLogicIsSet();
575 }
576 term[expr, expr2]
577 { Debug("parser-sygus") << "...read constraint " << expr << std::endl;
578 cmd.reset(new SygusConstraintCommand(expr, isAssume));
579 }
580 | /* inv-constraint */
581 INV_CONSTRAINT_TOK
582 ( symbol[name,CHECK_NONE,SYM_VARIABLE] { names.push_back(name); } )+
583 {
584 cmd = PARSER_STATE->invConstraint(names);
585 }
586 | /* check-synth */
587 CHECK_SYNTH_TOK
588 {
589 PARSER_STATE->checkThatLogicIsSet();
590 cmd.reset(new CheckSynthCommand());
591 }
592 | /* set-feature */
593 SET_FEATURE_TOK keyword[name] symbolicExpr[expr]
594 {
595 PARSER_STATE->checkThatLogicIsSet();
596 // ":grammars" is defined in the SyGuS version 2.1 standard and is by
597 // default supported, all other features are not.
598 if (name != ":grammars")
599 {
600 std::stringstream ss;
601 ss << "SyGuS feature " << name << " not currently supported";
602 PARSER_STATE->warning(ss.str());
603 }
604 cmd.reset(new EmptyCommand());
605 }
606 | command[&cmd]
607 ;
608
609
610 /** Reads a sygus grammar in the sygus version 2 format
611 *
612 * The resulting sygus datatype encoding the grammar is stored in ret.
613 * The argument sygusVars indicates the sygus bound variable list, which is
614 * the argument list of the function-to-synthesize (or null if the grammar
615 * has bound variables).
616 * The argument fun is a unique identifier to avoid naming clashes for the
617 * datatypes constructed by this call.
618 */
619 sygusGrammar[cvc5::api::Grammar*& ret,
620 const std::vector<cvc5::api::Term>& sygusVars,
621 const std::string& fun]
622 @declarations
623 {
624 // the pre-declaration
625 std::vector<std::pair<std::string, cvc5::api::Sort>> sortedVarNames;
626 // non-terminal symbols of the grammar
627 std::vector<cvc5::api::Term> ntSyms;
628 cvc5::api::Sort t;
629 std::string name;
630 cvc5::api::Term e, e2;
631 unsigned dtProcessed = 0;
632 }
633 :
634 // predeclaration
635 LPAREN_TOK
636 // We read a sorted variable list here in a custom way that throws an
637 // error to recognize if the user is using the (deprecated) version 1.0
638 // sygus syntax.
639 ( LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE]
640 sortSymbol[t,CHECK_DECLARED] (
641 // SyGuS version 1.0 expects a grammar ((Start Int ( ...
642 // SyGuS version 2.0 expects a predeclaration ((Start Int) ...
643 LPAREN_TOK
644 {
645 std::stringstream sse;
646 if (sortedVarNames.empty())
647 {
648 sse << "The expected SyGuS language is version 2.0, whereas the "
649 << "input appears to be SyGuS version 1.0 format. The version "
650 << "2.0 format requires a predeclaration of the non-terminal "
651 << "symbols of the grammar to be given prior to the definition "
652 << "of the grammar. See https://sygus.org/language/ for details "
653 << "and examples. cvc5 versions past 1.8 do not support SyGuS "
654 << "version 1.0.";
655 }
656 else
657 {
658 // an unknown syntax error
659 sse << "Unexpected syntax for SyGuS predeclaration.";
660 }
661 PARSER_STATE->parseError(sse.str().c_str());
662 }
663 | RPAREN_TOK )
664 { sortedVarNames.push_back(make_pair(name, t)); }
665 )*
666 RPAREN_TOK
667 {
668 // non-terminal symbols in the pre-declaration are locally scoped
669 PARSER_STATE->pushScope();
670 for (std::pair<std::string, api::Sort>& i : sortedVarNames)
671 {
672 PARSER_STATE->checkDeclaration(name, CHECK_UNDECLARED, SYM_SORT);
673 // make the non-terminal symbol, which will be parsed as an ordinary
674 // free variable.
675 api::Term nts = PARSER_STATE->bindBoundVar(i.first, i.second);
676 ntSyms.push_back(nts);
677 }
678 ret = PARSER_STATE->mkGrammar(sygusVars, ntSyms);
679 }
680 // the grouped rule listing
681 LPAREN_TOK
682 (
683 LPAREN_TOK
684 symbol[name, CHECK_DECLARED, SYM_VARIABLE] sortSymbol[t, CHECK_DECLARED]
685 {
686 // check that it matches sortedVarNames
687 if (sortedVarNames[dtProcessed].first != name)
688 {
689 std::stringstream sse;
690 sse << "Grouped rule listing " << name
691 << " does not match the name (in order) from the predeclaration ("
692 << sortedVarNames[dtProcessed].first << ")." << std::endl;
693 PARSER_STATE->parseError(sse.str().c_str());
694 }
695 if (sortedVarNames[dtProcessed].second != t)
696 {
697 std::stringstream sse;
698 sse << "Type for grouped rule listing " << name
699 << " does not match the type (in order) from the predeclaration ("
700 << sortedVarNames[dtProcessed].second << ")." << std::endl;
701 PARSER_STATE->parseError(sse.str().c_str());
702 }
703 }
704 LPAREN_TOK
705 (
706 term[e,e2] {
707 // add term as constructor to datatype
708 ret->addRule(ntSyms[dtProcessed], e);
709 }
710 | LPAREN_TOK SYGUS_CONSTANT_TOK sortSymbol[t, CHECK_DECLARED] RPAREN_TOK {
711 // allow constants in datatype for ntSyms[dtProcessed]
712 ret->addAnyConstant(ntSyms[dtProcessed]);
713 }
714 | LPAREN_TOK SYGUS_VARIABLE_TOK sortSymbol[t, CHECK_DECLARED] RPAREN_TOK {
715 // add variable constructors to datatype
716 ret->addAnyVariable(ntSyms[dtProcessed]);
717 }
718 )+
719 RPAREN_TOK
720 RPAREN_TOK
721 {
722 dtProcessed++;
723 }
724 )+
725 RPAREN_TOK
726 {
727 // pop scope from the pre-declaration
728 PARSER_STATE->popScope();
729 }
730 ;
731
732 setInfoInternal[std::unique_ptr<cvc5::Command>* cmd]
733 @declarations {
734 std::string name;
735 api::Term sexpr;
736 }
737 : KEYWORD symbolicExpr[sexpr]
738 { name = AntlrInput::tokenText($KEYWORD);
739 cmd->reset(new SetInfoCommand(name.c_str() + 1, sexprToString(sexpr)));
740 }
741 ;
742
743 setOptionInternal[std::unique_ptr<cvc5::Command>* cmd]
744 @init {
745 std::string name;
746 api::Term sexpr;
747 }
748 : keyword[name] symbolicExpr[sexpr]
749 { cmd->reset(new SetOptionCommand(name.c_str() + 1, sexprToString(sexpr)));
750 // Ugly that this changes the state of the parser; but
751 // global-declarations affects parsing, so we can't hold off
752 // on this until some SmtEngine eventually (if ever) executes it.
753 if(name == ":global-declarations")
754 {
755 SYM_MAN->setGlobalDeclarations(sexprToString(sexpr) == "true");
756 }
757 }
758 ;
759
760 smt25Command[std::unique_ptr<cvc5::Command>* cmd]
761 @declarations {
762 std::string name;
763 std::string fname;
764 cvc5::api::Term expr, expr2;
765 std::vector<std::pair<std::string, cvc5::api::Sort> > sortedVarNames;
766 std::string s;
767 cvc5::api::Sort t;
768 cvc5::api::Term func;
769 std::vector<cvc5::api::Term> bvs;
770 std::vector<std::vector<std::pair<std::string, cvc5::api::Sort>>>
771 sortedVarNamesList;
772 std::vector<std::vector<cvc5::api::Term>> flattenVarsList;
773 std::vector<std::vector<cvc5::api::Term>> formals;
774 std::vector<cvc5::api::Term> funcs;
775 std::vector<cvc5::api::Term> func_defs;
776 cvc5::api::Term aexpr;
777 std::unique_ptr<cvc5::CommandSequence> seq;
778 std::vector<api::Sort> sorts;
779 std::vector<cvc5::api::Term> flattenVars;
780 }
781 /* declare-const */
782 : DECLARE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); }
783 symbol[name,CHECK_NONE,SYM_VARIABLE]
784 { PARSER_STATE->checkUserSymbol(name); }
785 sortSymbol[t,CHECK_DECLARED]
786 { // allow overloading here
787 if( PARSER_STATE->sygus() )
788 {
789 PARSER_STATE->parseErrorLogic("declare-const is not allowed in sygus "
790 "version 2.0");
791 }
792 api::Term c =
793 PARSER_STATE->bindVar(name, t, false, true);
794 cmd->reset(new DeclareFunctionCommand(name, c, t)); }
795
796 /* get model */
797 | GET_MODEL_TOK { PARSER_STATE->checkThatLogicIsSet(); }
798 { cmd->reset(new GetModelCommand()); }
799
800 /* echo */
801 | ECHO_TOK
802 ( simpleSymbolicExpr[s]
803 { cmd->reset(new EchoCommand(s)); }
804 | { cmd->reset(new EchoCommand()); }
805 )
806
807 /* reset: reset everything, returning solver to initial state.
808 * Logic and options must be set again. */
809 | RESET_TOK
810 {
811 cmd->reset(new ResetCommand());
812 // reset the state of the parser, which is independent of the symbol
813 // manager
814 PARSER_STATE->reset();
815 }
816 /* reset-assertions: reset assertions, assertion stack, declarations,
817 * etc., but the logic and options remain as they were. */
818 | RESET_ASSERTIONS_TOK
819 { cmd->reset(new ResetAssertionsCommand());
820 }
821 | DEFINE_FUN_REC_TOK
822 { PARSER_STATE->checkThatLogicIsSet(); }
823 symbol[fname,CHECK_NONE,SYM_VARIABLE]
824 { PARSER_STATE->checkUserSymbol(fname); }
825 LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
826 sortSymbol[t,CHECK_DECLARED]
827 {
828 func =
829 PARSER_STATE->bindDefineFunRec(fname, sortedVarNames, t, flattenVars);
830 PARSER_STATE->pushDefineFunRecScope(
831 sortedVarNames, func, flattenVars, bvs);
832 }
833 term[expr, expr2]
834 { PARSER_STATE->popScope();
835 if( !flattenVars.empty() ){
836 expr = PARSER_STATE->mkHoApply( expr, flattenVars );
837 }
838 cmd->reset(new DefineFunctionRecCommand(
839 func, bvs, expr, SYM_MAN->getGlobalDeclarations()));
840 }
841 | DEFINE_FUNS_REC_TOK
842 { PARSER_STATE->checkThatLogicIsSet();}
843 LPAREN_TOK
844 ( LPAREN_TOK
845 symbol[fname,CHECK_UNDECLARED,SYM_VARIABLE]
846 { PARSER_STATE->checkUserSymbol(fname); }
847 LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
848 sortSymbol[t,CHECK_DECLARED]
849 {
850 flattenVars.clear();
851 func = PARSER_STATE->bindDefineFunRec(
852 fname, sortedVarNames, t, flattenVars);
853 funcs.push_back( func );
854
855 // add to lists (need to remember for when parsing the bodies)
856 sortedVarNamesList.push_back( sortedVarNames );
857 flattenVarsList.push_back( flattenVars );
858
859 // set up parsing the next variable list block
860 sortedVarNames.clear();
861 flattenVars.clear();
862 }
863 RPAREN_TOK
864 )+
865 RPAREN_TOK
866 LPAREN_TOK
867 {
868 //set up the first scope
869 if( sortedVarNamesList.empty() ){
870 PARSER_STATE->parseError("Must define at least one function in "
871 "define-funs-rec");
872 }
873 bvs.clear();
874 PARSER_STATE->pushDefineFunRecScope( sortedVarNamesList[0], funcs[0],
875 flattenVarsList[0], bvs);
876 }
877 (
878 term[expr,expr2]
879 {
880 unsigned j = func_defs.size();
881 if( !flattenVarsList[j].empty() ){
882 expr = PARSER_STATE->mkHoApply( expr, flattenVarsList[j] );
883 }
884 func_defs.push_back( expr );
885 formals.push_back(bvs);
886 j++;
887 //set up the next scope
888 PARSER_STATE->popScope();
889 if( func_defs.size()<funcs.size() ){
890 bvs.clear();
891 PARSER_STATE->pushDefineFunRecScope( sortedVarNamesList[j], funcs[j],
892 flattenVarsList[j], bvs);
893 }
894 }
895 )+
896 RPAREN_TOK
897 { if( funcs.size()!=func_defs.size() ){
898 PARSER_STATE->parseError(std::string(
899 "Number of functions defined does not match number listed in "
900 "define-funs-rec"));
901 }
902 cmd->reset(new DefineFunctionRecCommand(
903 funcs, formals, func_defs, SYM_MAN->getGlobalDeclarations()));
904 }
905 ;
906
907 extendedCommand[std::unique_ptr<cvc5::Command>* cmd]
908 @declarations {
909 std::vector<api::DatatypeDecl> dts;
910 cvc5::api::Term e, e2;
911 cvc5::api::Sort t, s;
912 std::string name;
913 std::vector<std::string> names;
914 std::vector<cvc5::api::Term> terms;
915 std::vector<api::Sort> sorts;
916 std::vector<std::pair<std::string, cvc5::api::Sort> > sortedVarNames;
917 std::unique_ptr<cvc5::CommandSequence> seq;
918 api::Grammar* g = nullptr;
919 }
920 /* Extended SMT-LIB set of commands syntax, not permitted in
921 * --smtlib2 compliance mode. */
922 : DECLARE_CODATATYPE_TOK datatypeDefCommand[true, cmd]
923 | DECLARE_CODATATYPES_TOK datatypesDefCommand[true, cmd]
924
925 /* Support some of Z3's extended SMT-LIB commands */
926
927 | DECLARE_SORTS_TOK
928 {
929 PARSER_STATE->checkThatLogicIsSet();
930 PARSER_STATE->checkLogicAllowsFreeSorts();
931 seq.reset(new cvc5::CommandSequence());
932 }
933 LPAREN_TOK
934 ( symbol[name,CHECK_UNDECLARED,SYM_SORT]
935 { PARSER_STATE->checkUserSymbol(name);
936 api::Sort type = PARSER_STATE->mkSort(name);
937 seq->addCommand(new DeclareSortCommand(name, 0, type));
938 }
939 )+
940 RPAREN_TOK
941 { cmd->reset(seq.release()); }
942
943 | DECLARE_FUNS_TOK { PARSER_STATE->checkThatLogicIsSet(); }
944 { seq.reset(new cvc5::CommandSequence()); }
945 LPAREN_TOK
946 ( LPAREN_TOK symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
947 { PARSER_STATE->checkUserSymbol(name); }
948 nonemptySortList[sorts] RPAREN_TOK
949 { api::Sort tt;
950 if(sorts.size() > 1) {
951 PARSER_STATE->checkLogicAllowsFunctions();
952 // must flatten
953 api::Sort range = sorts.back();
954 sorts.pop_back();
955 tt = PARSER_STATE->mkFlatFunctionType(sorts, range);
956 } else {
957 tt = sorts[0];
958 }
959 // allow overloading
960 api::Term func =
961 PARSER_STATE->bindVar(name, tt, false, true);
962 seq->addCommand(new DeclareFunctionCommand(name, func, tt));
963 sorts.clear();
964 }
965 )+
966 RPAREN_TOK
967 { cmd->reset(seq.release()); }
968 | DECLARE_PREDS_TOK { PARSER_STATE->checkThatLogicIsSet(); }
969 { seq.reset(new cvc5::CommandSequence()); }
970 LPAREN_TOK
971 ( LPAREN_TOK symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
972 { PARSER_STATE->checkUserSymbol(name); }
973 sortList[sorts] RPAREN_TOK
974 { t = SOLVER->getBooleanSort();
975 if(sorts.size() > 0) {
976 PARSER_STATE->checkLogicAllowsFunctions();
977 t = SOLVER->mkFunctionSort(sorts, t);
978 }
979 // allow overloading
980 api::Term func =
981 PARSER_STATE->bindVar(name, t, false, true);
982 seq->addCommand(new DeclareFunctionCommand(name, func, t));
983 sorts.clear();
984 }
985 )+
986 RPAREN_TOK
987 { cmd->reset(seq.release()); }
988
989 | DEFINE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
990 ( // (define f t)
991 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
992 { PARSER_STATE->checkUserSymbol(name); }
993 term[e,e2]
994 {
995 api::Term func = PARSER_STATE->bindVar(name, e.getSort());
996 cmd->reset(new DefineFunctionCommand(
997 name, func, e, SYM_MAN->getGlobalDeclarations()));
998 }
999 | // (define (f (v U) ...) t)
1000 LPAREN_TOK
1001 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
1002 { PARSER_STATE->checkUserSymbol(name); }
1003 sortedVarList[sortedVarNames] RPAREN_TOK
1004 { /* add variables to parser state before parsing term */
1005 Debug("parser") << "define fun: '" << name << "'" << std::endl;
1006 PARSER_STATE->pushScope();
1007 terms = PARSER_STATE->bindBoundVars(sortedVarNames);
1008 }
1009 term[e,e2]
1010 {
1011 PARSER_STATE->popScope();
1012 // declare the name down here (while parsing term, signature
1013 // must not be extended with the name itself; no recursion
1014 // permitted)
1015 api::Sort tt = e.getSort();
1016 if( sortedVarNames.size() > 0 ) {
1017 sorts.reserve(sortedVarNames.size());
1018 for(std::vector<std::pair<std::string, api::Sort> >::const_iterator
1019 i = sortedVarNames.begin(), iend = sortedVarNames.end();
1020 i != iend; ++i) {
1021 sorts.push_back((*i).second);
1022 }
1023 tt = SOLVER->mkFunctionSort(sorts, tt);
1024 }
1025 api::Term func = PARSER_STATE->bindVar(name, tt);
1026 cmd->reset(new DefineFunctionCommand(
1027 name, func, terms, e, SYM_MAN->getGlobalDeclarations()));
1028 }
1029 )
1030 | // (define-const x U t)
1031 DEFINE_CONST_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1032 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
1033 { PARSER_STATE->checkUserSymbol(name); }
1034 sortSymbol[t,CHECK_DECLARED]
1035 term[e, e2]
1036 {
1037 // declare the name down here (while parsing term, signature
1038 // must not be extended with the name itself; no recursion
1039 // permitted)
1040 api::Term func = PARSER_STATE->bindVar(name, t);
1041 cmd->reset(new DefineFunctionCommand(
1042 name, func, terms, e, SYM_MAN->getGlobalDeclarations()));
1043 }
1044
1045 | SIMPLIFY_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1046 term[e,e2]
1047 { cmd->reset(new SimplifyCommand(e)); }
1048 | GET_QE_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1049 term[e,e2]
1050 { cmd->reset(new GetQuantifierEliminationCommand(e, true)); }
1051 | GET_QE_DISJUNCT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1052 term[e,e2]
1053 { cmd->reset(new GetQuantifierEliminationCommand(e, false)); }
1054 | GET_ABDUCT_TOK {
1055 PARSER_STATE->checkThatLogicIsSet();
1056 }
1057 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
1058 term[e,e2]
1059 (
1060 sygusGrammar[g, terms, name]
1061 )?
1062 {
1063 cmd->reset(new GetAbductCommand(name, e, g));
1064 }
1065 | GET_INTERPOL_TOK {
1066 PARSER_STATE->checkThatLogicIsSet();
1067 }
1068 symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
1069 term[e,e2]
1070 (
1071 sygusGrammar[g, terms, name]
1072 )?
1073 {
1074 cmd->reset(new GetInterpolCommand(name, e, g));
1075 }
1076 | DECLARE_HEAP LPAREN_TOK
1077 sortSymbol[t, CHECK_DECLARED]
1078 sortSymbol[s, CHECK_DECLARED]
1079 { cmd->reset(new DeclareHeapCommand(t, s)); }
1080 RPAREN_TOK
1081 | DECLARE_POOL { PARSER_STATE->checkThatLogicIsSet(); }
1082 symbol[name,CHECK_NONE,SYM_VARIABLE]
1083 { PARSER_STATE->checkUserSymbol(name); }
1084 sortSymbol[t,CHECK_DECLARED]
1085 LPAREN_TOK
1086 ( term[e, e2]
1087 { terms.push_back( e ); }
1088 )* RPAREN_TOK
1089 { Debug("parser") << "declare pool: '" << name << "'" << std::endl;
1090 api::Term pool = SOLVER->declarePool(name, t, terms);
1091 PARSER_STATE->defineVar(name, pool);
1092 cmd->reset(new DeclarePoolCommand(name, pool, t, terms));
1093 }
1094 | BLOCK_MODEL_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1095 { cmd->reset(new BlockModelCommand()); }
1096
1097 | BLOCK_MODEL_VALUES_TOK { PARSER_STATE->checkThatLogicIsSet(); }
1098 ( LPAREN_TOK termList[terms,e] RPAREN_TOK
1099 { cmd->reset(new BlockModelValuesCommand(terms)); }
1100 | ~LPAREN_TOK
1101 { PARSER_STATE->parseError("The block-model-value command expects a list "
1102 "of terms. Perhaps you forgot a pair of "
1103 "parentheses?");
1104 }
1105 )
1106 ;
1107
1108 datatypeDefCommand[bool isCo, std::unique_ptr<cvc5::Command>* cmd]
1109 @declarations {
1110 std::vector<api::DatatypeDecl> dts;
1111 std::string name;
1112 std::vector<std::string> dnames;
1113 std::vector<int> arities;
1114 }
1115 : { PARSER_STATE->checkThatLogicIsSet(); }
1116 symbol[name,CHECK_UNDECLARED,SYM_SORT]
1117 {
1118 dnames.push_back(name);
1119 arities.push_back(-1);
1120 }
1121 datatypesDef[isCo, dnames, arities, cmd]
1122 ;
1123
1124 datatypesDefCommand[bool isCo, std::unique_ptr<cvc5::Command>* cmd]
1125 @declarations {
1126 std::vector<api::DatatypeDecl> dts;
1127 std::string name;
1128 std::vector<std::string> dnames;
1129 std::vector<int> arities;
1130 }
1131 : { PARSER_STATE->checkThatLogicIsSet(); }
1132 LPAREN_TOK /* datatype definition prelude */
1133 ( LPAREN_TOK symbol[name,CHECK_UNDECLARED,SYM_SORT] n=INTEGER_LITERAL RPAREN_TOK
1134 { unsigned arity = AntlrInput::tokenToUnsigned(n);
1135 Debug("parser-dt") << "Datatype : " << name << ", arity = " << arity << std::endl;
1136 dnames.push_back(name);
1137 arities.push_back( static_cast<int>(arity) );
1138 }
1139 )*
1140 RPAREN_TOK
1141 LPAREN_TOK
1142 datatypesDef[isCo, dnames, arities, cmd]
1143 RPAREN_TOK
1144 ;
1145
1146 /**
1147 * Read a list of datatype definitions for datatypes with names dnames and
1148 * parametric arities arities. A negative value in arities indicates that the
1149 * arity for the corresponding datatype has not been fixed: notice that we do
1150 * not know the arity of datatypes in the declare-datatype command prior to
1151 * parsing their body, whereas the arity of datatypes in declare-datatypes is
1152 * given in the preamble of that command and thus is known prior to this call.
1153 */
1154 datatypesDef[bool isCo,
1155 const std::vector<std::string>& dnames,
1156 const std::vector<int>& arities,
1157 std::unique_ptr<cvc5::Command>* cmd]
1158 @declarations {
1159 std::vector<api::DatatypeDecl> dts;
1160 std::string name;
1161 std::vector<api::Sort> params;
1162 }
1163 : { PARSER_STATE->pushScope();
1164 // Declare the datatypes that are currently being defined as unresolved
1165 // types. If we do not know the arity of the datatype yet, we wait to
1166 // define it until parsing the preamble of its body, which may optionally
1167 // involve `par`. This is limited to the case of single datatypes defined
1168 // via declare-datatype, and hence no datatype body is parsed without
1169 // having all types declared. This ensures we can parse datatypes with
1170 // nested recursion, e.g. datatypes D having a subfield type
1171 // (Array Int D).
1172 for (unsigned i=0, dsize=dnames.size(); i<dsize; i++)
1173 {
1174 if( arities[i]<0 )
1175 {
1176 // do not know the arity yet
1177 continue;
1178 }
1179 unsigned arity = static_cast<unsigned>(arities[i]);
1180 PARSER_STATE->mkUnresolvedType(dnames[i], arity);
1181 }
1182 }
1183 ( LPAREN_TOK {
1184 params.clear();
1185 Debug("parser-dt") << "Processing datatype #" << dts.size() << std::endl;
1186 if( dts.size()>=dnames.size() ){
1187 PARSER_STATE->parseError("Too many datatypes defined in this block.");
1188 }
1189 }
1190 ( PAR_TOK { PARSER_STATE->pushScope(); } LPAREN_TOK
1191 ( symbol[name,CHECK_UNDECLARED,SYM_SORT]
1192 {
1193 params.push_back( PARSER_STATE->mkSort(name)); }
1194 )*
1195 RPAREN_TOK {
1196 // if the arity was fixed by prelude and is not equal to the number of parameters
1197 if( arities[dts.size()]>=0 && static_cast<int>(params.size())!=arities[dts.size()] ){
1198 PARSER_STATE->parseError("Wrong number of parameters for datatype.");
1199 }
1200 if (arities[dts.size()]<0)
1201 {
1202 // now declare it as an unresolved type
1203 PARSER_STATE->mkUnresolvedType(dnames[dts.size()], params.size());
1204 }
1205 Debug("parser-dt") << params.size() << " parameters for " << dnames[dts.size()] << std::endl;
1206 dts.push_back(SOLVER->mkDatatypeDecl(dnames[dts.size()], params, isCo));
1207 }
1208 LPAREN_TOK
1209 ( LPAREN_TOK constructorDef[dts.back()] RPAREN_TOK )+
1210 RPAREN_TOK { PARSER_STATE->popScope(); }
1211 | { // if the arity was fixed by prelude and is not equal to 0
1212 if( arities[dts.size()]>0 ){
1213 PARSER_STATE->parseError("No parameters given for datatype.");
1214 }
1215 else if (arities[dts.size()]<0)
1216 {
1217 // now declare it as an unresolved type
1218 PARSER_STATE->mkUnresolvedType(dnames[dts.size()], 0);
1219 }
1220 Debug("parser-dt") << params.size() << " parameters for " << dnames[dts.size()] << std::endl;
1221 dts.push_back(SOLVER->mkDatatypeDecl(dnames[dts.size()],
1222 params,
1223 isCo));
1224 }
1225 ( LPAREN_TOK constructorDef[dts.back()] RPAREN_TOK )+
1226 )
1227 RPAREN_TOK
1228 )+
1229 {
1230 if (dts.size() != dnames.size())
1231 {
1232 PARSER_STATE->parseError("Wrong number of datatypes provided.");
1233 }
1234 PARSER_STATE->popScope();
1235 cmd->reset(new DatatypeDeclarationCommand(
1236 PARSER_STATE->bindMutualDatatypeTypes(dts, true)));
1237 }
1238 ;
1239
1240 simpleSymbolicExprNoKeyword[std::string& s]
1241 : INTEGER_LITERAL
1242 { s = AntlrInput::tokenText($INTEGER_LITERAL); }
1243 | DECIMAL_LITERAL
1244 { s = AntlrInput::tokenText($DECIMAL_LITERAL); }
1245 | HEX_LITERAL
1246 { s = AntlrInput::tokenText($HEX_LITERAL); }
1247 | BINARY_LITERAL
1248 { s = AntlrInput::tokenText($BINARY_LITERAL); }
1249 | str[s,false]
1250 | symbol[s,CHECK_NONE,SYM_SORT]
1251 | tok=(ASSERT_TOK | CHECK_SAT_TOK | CHECK_SAT_ASSUMING_TOK | DECLARE_FUN_TOK
1252 | DECLARE_SORT_TOK
1253 | DEFINE_FUN_TOK | DEFINE_FUN_REC_TOK | DEFINE_FUNS_REC_TOK
1254 | DEFINE_SORT_TOK | GET_VALUE_TOK | GET_ASSIGNMENT_TOK
1255 | GET_ASSERTIONS_TOK | GET_PROOF_TOK | GET_UNSAT_ASSUMPTIONS_TOK
1256 | GET_UNSAT_CORE_TOK | EXIT_TOK
1257 | RESET_TOK | RESET_ASSERTIONS_TOK | SET_LOGIC_TOK | SET_INFO_TOK
1258 | GET_INFO_TOK | SET_OPTION_TOK | GET_OPTION_TOK | PUSH_TOK | POP_TOK
1259 | DECLARE_DATATYPES_TOK | GET_MODEL_TOK | ECHO_TOK | SIMPLIFY_TOK)
1260 { s = AntlrInput::tokenText($tok); }
1261 ;
1262
1263 keyword[std::string& s]
1264 : KEYWORD
1265 { s = AntlrInput::tokenText($KEYWORD); }
1266 ;
1267
1268 simpleSymbolicExpr[std::string& s]
1269 : simpleSymbolicExprNoKeyword[s]
1270 | KEYWORD { s = AntlrInput::tokenText($KEYWORD); }
1271 ;
1272
1273 symbolicExpr[cvc5::api::Term& sexpr]
1274 @declarations {
1275 std::string s;
1276 std::vector<api::Term> children;
1277 }
1278 : simpleSymbolicExpr[s]
1279 { sexpr = SOLVER->mkString(PARSER_STATE->processAdHocStringEsc(s)); }
1280 | LPAREN_TOK
1281 ( symbolicExpr[sexpr] { children.push_back(sexpr); } )* RPAREN_TOK
1282 { sexpr = SOLVER->mkTerm(cvc5::api::SEXPR, children); }
1283 ;
1284
1285 /**
1286 * Matches a term.
1287 * @return the expression representing the term.
1288 */
1289 term[cvc5::api::Term& expr, cvc5::api::Term& expr2]
1290 @init {
1291 api::Kind kind = api::NULL_EXPR;
1292 cvc5::api::Term f;
1293 std::string name;
1294 cvc5::api::Sort type;
1295 ParseOp p;
1296 }
1297 : termNonVariable[expr, expr2]
1298
1299 // a qualified identifier (section 3.6 of SMT-LIB version 2.6)
1300
1301 | qualIdentifier[p]
1302 {
1303 expr = PARSER_STATE->parseOpToExpr(p);
1304 }
1305 ;
1306
1307 /**
1308 * Matches a non-variable term.
1309 * @return the expression expr representing the term or formula, and expr2, an
1310 * optional annotation for expr (for instance, for attributed expressions).
1311 */
1312 termNonVariable[cvc5::api::Term& expr, cvc5::api::Term& expr2]
1313 @init {
1314 Debug("parser") << "term: " << AntlrInput::tokenText(LT(1)) << std::endl;
1315 api::Kind kind = api::NULL_EXPR;
1316 std::string name;
1317 std::vector<cvc5::api::Term> args;
1318 std::vector< std::pair<std::string, cvc5::api::Sort> > sortedVarNames;
1319 cvc5::api::Term bvl;
1320 cvc5::api::Term f, f2, f3;
1321 std::string attr;
1322 cvc5::api::Term attexpr;
1323 std::vector<cvc5::api::Term> patexprs;
1324 std::vector<cvc5::api::Term> matchcases;
1325 std::unordered_set<std::string> names;
1326 std::vector< std::pair<std::string, cvc5::api::Term> > binders;
1327 cvc5::api::Sort type;
1328 cvc5::api::Sort type2;
1329 api::Term atomTerm;
1330 ParseOp p;
1331 std::vector<api::Sort> argTypes;
1332 }
1333 : LPAREN_TOK quantOp[kind]
1334 {
1335 if (!PARSER_STATE->isTheoryEnabled(theory::THEORY_QUANTIFIERS))
1336 {
1337 PARSER_STATE->parseError("Quantifier used in non-quantified logic.");
1338 }
1339 PARSER_STATE->pushScope();
1340 }
1341 boundVarList[bvl]
1342 term[f, f2] RPAREN_TOK
1343 {
1344 args.push_back(bvl);
1345
1346 PARSER_STATE->popScope();
1347 args.push_back(f);
1348 if(! f2.isNull()){
1349 args.push_back(f2);
1350 }
1351 expr = MK_TERM(kind, args);
1352 }
1353 | LPAREN_TOK COMPREHENSION_TOK
1354 { PARSER_STATE->pushScope(); }
1355 boundVarList[bvl]
1356 {
1357 args.push_back(bvl);
1358 }
1359 term[f, f2] { args.push_back(f); }
1360 term[f, f2] {
1361 args.push_back(f);
1362 expr = MK_TERM(api::COMPREHENSION, args);
1363 }
1364 RPAREN_TOK
1365 | LPAREN_TOK qualIdentifier[p]
1366 termList[args,expr] RPAREN_TOK
1367 {
1368 expr = PARSER_STATE->applyParseOp(p, args);
1369 }
1370 | /* a let or sygus let binding */
1371 LPAREN_TOK
1372 LET_TOK LPAREN_TOK
1373 { PARSER_STATE->pushScope(); }
1374 ( LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE]
1375 term[expr, f2]
1376 RPAREN_TOK
1377 // this is a parallel let, so we have to save up all the contributions
1378 // of the let and define them only later on
1379 { if(names.count(name) == 1) {
1380 std::stringstream ss;
1381 ss << "warning: symbol `" << name << "' bound multiple times by let;"
1382 << " the last binding will be used, shadowing earlier ones";
1383 PARSER_STATE->warning(ss.str());
1384 } else {
1385 names.insert(name);
1386 }
1387 binders.push_back(std::make_pair(name, expr)); } )+
1388 { // now implement these bindings
1389 for (const std::pair<std::string, api::Term>& binder : binders)
1390 {
1391 {
1392 PARSER_STATE->defineVar(binder.first, binder.second);
1393 }
1394 }
1395 }
1396 RPAREN_TOK
1397 term[expr, f2]
1398 RPAREN_TOK
1399 { PARSER_STATE->popScope(); }
1400 | /* match expression */
1401 LPAREN_TOK MATCH_TOK term[expr, f2] {
1402 if( !expr.getSort().isDatatype() ){
1403 PARSER_STATE->parseError("Cannot match on non-datatype term.");
1404 }
1405 }
1406 LPAREN_TOK
1407 (
1408 // case with non-nullary pattern
1409 LPAREN_TOK LPAREN_TOK term[f, f2] {
1410 args.clear();
1411 PARSER_STATE->pushScope();
1412 // f should be a constructor
1413 type = f.getSort();
1414 Debug("parser-dt") << "Pattern head : " << f << " " << type << std::endl;
1415 if (!type.isConstructor())
1416 {
1417 PARSER_STATE->parseError("Pattern must be application of a constructor or a variable.");
1418 }
1419 api::Datatype dt = type.getConstructorCodomainSort().getDatatype();
1420 if (dt.isParametric())
1421 {
1422 // lookup constructor by name
1423 api::DatatypeConstructor dc = dt.getConstructor(f.toString());
1424 api::Term scons = dc.getSpecializedConstructorTerm(expr.getSort());
1425 // take the type of the specialized constructor instead
1426 type = scons.getSort();
1427 }
1428 argTypes = type.getConstructorDomainSorts();
1429 }
1430 // arguments of the pattern
1431 ( symbol[name,CHECK_NONE,SYM_VARIABLE] {
1432 if (args.size() >= argTypes.size())
1433 {
1434 PARSER_STATE->parseError("Too many arguments for pattern.");
1435 }
1436 //make of proper type
1437 api::Term arg = PARSER_STATE->bindBoundVar(name, argTypes[args.size()]);
1438 args.push_back( arg );
1439 }
1440 )*
1441 RPAREN_TOK term[f3, f2] {
1442 // make the match case
1443 std::vector<cvc5::api::Term> cargs;
1444 cargs.push_back(f);
1445 cargs.insert(cargs.end(),args.begin(),args.end());
1446 api::Term c = MK_TERM(api::APPLY_CONSTRUCTOR,cargs);
1447 api::Term bvla = MK_TERM(api::BOUND_VAR_LIST,args);
1448 api::Term mc = MK_TERM(api::MATCH_BIND_CASE, bvla, c, f3);
1449 matchcases.push_back(mc);
1450 // now, pop the scope
1451 PARSER_STATE->popScope();
1452 }
1453 RPAREN_TOK
1454 // case with nullary or variable pattern
1455 | LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE] {
1456 if (PARSER_STATE->isDeclared(name,SYM_VARIABLE))
1457 {
1458 f = PARSER_STATE->getVariable(name);
1459 type = f.getSort();
1460 if (!type.isConstructor() ||
1461 !type.getConstructorDomainSorts().empty())
1462 {
1463 PARSER_STATE->parseError("Must apply constructors of arity greater than 0 to arguments in pattern.");
1464 }
1465 // make nullary constructor application
1466 f = MK_TERM(api::APPLY_CONSTRUCTOR, f);
1467 }
1468 else
1469 {
1470 // it has the type of the head expr
1471 f = PARSER_STATE->bindBoundVar(name, expr.getSort());
1472 }
1473 }
1474 term[f3, f2] {
1475 api::Term mc;
1476 if (f.getKind() == api::VARIABLE)
1477 {
1478 api::Term bvlf = MK_TERM(api::BOUND_VAR_LIST, f);
1479 mc = MK_TERM(api::MATCH_BIND_CASE, bvlf, f, f3);
1480 }
1481 else
1482 {
1483 mc = MK_TERM(api::MATCH_CASE, f, f3);
1484 }
1485 matchcases.push_back(mc);
1486 }
1487 RPAREN_TOK
1488 )+
1489 RPAREN_TOK RPAREN_TOK {
1490 //now, make the match
1491 if (matchcases.empty())
1492 {
1493 PARSER_STATE->parseError("Must have at least one case in match.");
1494 }
1495 std::vector<api::Term> mchildren;
1496 mchildren.push_back(expr);
1497 mchildren.insert(mchildren.end(), matchcases.begin(), matchcases.end());
1498 expr = MK_TERM(api::MATCH, mchildren);
1499 }
1500
1501 /* attributed expressions */
1502 | LPAREN_TOK ATTRIBUTE_TOK term[expr, f2]
1503 ( attribute[expr, attexpr]
1504 { if( ! attexpr.isNull()) {
1505 patexprs.push_back( attexpr );
1506 }
1507 }
1508 )+ RPAREN_TOK
1509 {
1510 if(! patexprs.empty()) {
1511 if( !f2.isNull() && f2.getKind()==api::INST_PATTERN_LIST ){
1512 for( size_t i=0; i<f2.getNumChildren(); i++ ){
1513 patexprs.push_back( f2[i] );
1514 }
1515 }
1516 expr2 = MK_TERM(api::INST_PATTERN_LIST, patexprs);
1517 } else {
1518 expr2 = f2;
1519 }
1520 }
1521 | /* lambda */
1522 LPAREN_TOK HO_LAMBDA_TOK
1523 { PARSER_STATE->pushScope(); }
1524 boundVarList[bvl]
1525 term[f, f2] RPAREN_TOK
1526 {
1527 args.push_back(bvl);
1528 args.push_back(f);
1529 PARSER_STATE->popScope();
1530 expr = MK_TERM(api::LAMBDA, args);
1531 }
1532 | LPAREN_TOK TUPLE_CONST_TOK termList[args,expr] RPAREN_TOK
1533 {
1534 std::vector<api::Sort> sorts;
1535 std::vector<api::Term> terms;
1536 for (const api::Term& arg : args)
1537 {
1538 sorts.emplace_back(arg.getSort());
1539 terms.emplace_back(arg);
1540 }
1541 expr = SOLVER->mkTuple(sorts, terms);
1542 }
1543 | LPAREN_TOK TUPLE_PROJECT_TOK term[expr,expr2] RPAREN_TOK
1544 {
1545 std::vector<uint32_t> indices;
1546 api::Op op = SOLVER->mkOp(api::TUPLE_PROJECT, indices);
1547 expr = SOLVER->mkTerm(op, expr);
1548 }
1549 | /* an atomic term (a term with no subterms) */
1550 termAtomic[atomTerm] { expr = atomTerm; }
1551 ;
1552
1553
1554 /**
1555 * Matches a qualified identifier, which can be a combination of one or more of
1556 * the following, stored in the ParseOp utility class:
1557 * (1) A kind.
1558 * (2) A string name.
1559 * (3) An expression expr.
1560 * (4) A type t.
1561 *
1562 * A qualified identifier is the generic case of function heads.
1563 * With respect to the standard definition (Section 3.6 of SMT-LIB version 2.6)
1564 * of qualified identifiers, we additionally parse:
1565 * - "Array constant specifications" of the form (as const (Array T1 T2)),
1566 * which notice are used as function heads e.g. ((as const (Array Int Int)) 0)
1567 * specifies the constant array over integers consisting of constant 0. This
1568 * is handled as if it were a special case of an operator here.
1569 *
1570 * Examples:
1571 *
1572 * (Identifiers)
1573 *
1574 * - For declared functions f, we return (2).
1575 * - For indexed functions like testers (_ is C) and bitvector extract
1576 * (_ extract n m), we return (3) for the appropriate operator.
1577 * - For tuple selectors (_ tupSel n), we return (1) and (3). api::Kind is set to
1578 * APPLY_SELECTOR, and expr is set to n, which is to be interpreted by the
1579 * caller as the n^th generic tuple selector. We do this since there is no
1580 * AST expression representing generic tuple select, and we do not have enough
1581 * type information at this point to know the type of the tuple we will be
1582 * selecting from.
1583 *
1584 * (Ascripted Identifiers)
1585 *
1586 * - For ascripted nullary parametric datatype constructors like
1587 * (as nil (List Int)), we return (APPLY_CONSTRUCTOR C) for the appropriate
1588 * specialized constructor C as (3).
1589 * - For ascripted non-nullary parametric datatype constructors like
1590 * (as cons (List Int)), we return the appropriate specialized constructor C
1591 * as (3).
1592 * - Overloaded non-parametric constructors (as C T) return the appropriate
1593 * expression, analogous to the parametric cases above.
1594 * - For other ascripted nullary constants like (as emptyset (Set T)),
1595 * (as sep.nil T), we return the appropriate expression (3).
1596 * - For array constant specifications (as const (Array T1 T2)), we return (1)
1597 * and (4), where kind is set to STORE_ALL and type is set to (Array T1 T2),
1598 * where this is to be interpreted by the caller as converting the next parsed
1599 * constant of type T2 to an Array of type (Array T1 T2) over that constant.
1600 * - For ascriptions on normal symbols (as f T), we return the appropriate
1601 * expression (3), which may involve disambiguating f based on type T if it is
1602 * overloaded.
1603 */
1604 qualIdentifier[cvc5::ParseOp& p]
1605 @init {
1606 api::Kind k;
1607 std::string baseName;
1608 cvc5::api::Term f;
1609 cvc5::api::Sort type;
1610 }
1611 : identifier[p]
1612 | LPAREN_TOK AS_TOK
1613 ( CONST_TOK sortSymbol[type, CHECK_DECLARED]
1614 {
1615 p.d_kind = api::CONST_ARRAY;
1616 PARSER_STATE->parseOpApplyTypeAscription(p, type);
1617 }
1618 | identifier[p]
1619 sortSymbol[type, CHECK_DECLARED]
1620 {
1621 PARSER_STATE->parseOpApplyTypeAscription(p, type);
1622 }
1623 )
1624 RPAREN_TOK
1625 ;
1626
1627 /**
1628 * Matches an identifier, which can be a combination of one or more of the
1629 * following, stored in the ParseOp utility class:
1630 * (1) A kind.
1631 * (2) A string name.
1632 * (3) An expression expr.
1633 * For examples, see documentation of qualIdentifier.
1634 */
1635 identifier[cvc5::ParseOp& p]
1636 @init {
1637 cvc5::api::Term f;
1638 cvc5::api::Term f2;
1639 std::vector<uint64_t> numerals;
1640 }
1641 : functionName[p.d_name, CHECK_NONE]
1642
1643 // indexed functions
1644
1645 | LPAREN_TOK INDEX_TOK
1646 ( TESTER_TOK term[f, f2]
1647 {
1648 if (f.getKind() == api::APPLY_CONSTRUCTOR && f.getNumChildren() == 1)
1649 {
1650 // for nullary constructors, must get the operator
1651 f = f[0];
1652 }
1653 if (!f.getSort().isConstructor())
1654 {
1655 PARSER_STATE->parseError(
1656 "Bad syntax for test (_ is X), X must be a constructor.");
1657 }
1658 // get the datatype that f belongs to
1659 api::Sort sf = f.getSort().getConstructorCodomainSort();
1660 api::Datatype d = sf.getDatatype();
1661 // lookup by name
1662 api::DatatypeConstructor dc = d.getConstructor(f.toString());
1663 p.d_expr = dc.getTesterTerm();
1664 }
1665 | UPDATE_TOK term[f, f2]
1666 {
1667 if (!f.getSort().isSelector())
1668 {
1669 PARSER_STATE->parseError(
1670 "Bad syntax for test (_ update X), X must be a selector.");
1671 }
1672 std::string sname = f.toString();
1673 // get the datatype that f belongs to
1674 api::Sort sf = f.getSort().getSelectorDomainSort();
1675 api::Datatype d = sf.getDatatype();
1676 // find the selector
1677 api::DatatypeSelector ds = d.getSelector(f.toString());
1678 // get the updater term
1679 p.d_expr = ds.getUpdaterTerm();
1680 }
1681 | TUPLE_SEL_TOK m=INTEGER_LITERAL
1682 {
1683 // we adopt a special syntax (_ tupSel n)
1684 p.d_kind = api::APPLY_SELECTOR;
1685 // put m in expr so that the caller can deal with this case
1686 p.d_expr = SOLVER->mkInteger(AntlrInput::tokenToUnsigned($m));
1687 }
1688 | TUPLE_PROJECT_TOK nonemptyNumeralList[numerals]
1689 {
1690 // we adopt a special syntax (_ tuple_project i_1 ... i_n) where
1691 // i_1, ..., i_n are numerals
1692 p.d_kind = api::TUPLE_PROJECT;
1693 std::vector<uint32_t> indices(numerals.size());
1694 for(size_t i = 0; i < numerals.size(); ++i)
1695 {
1696 // convert uint64_t to uint32_t
1697 indices[i] = numerals[i];
1698 }
1699 p.d_op = SOLVER->mkOp(api::TUPLE_PROJECT, indices);
1700 }
1701 | sym=SIMPLE_SYMBOL nonemptyNumeralList[numerals]
1702 {
1703 p.d_op = PARSER_STATE->mkIndexedOp(AntlrInput::tokenText($sym), numerals);
1704 }
1705 )
1706 RPAREN_TOK
1707 ;
1708
1709 /**
1710 * Matches an atomic term (a term with no subterms).
1711 * @return the expression expr representing the term or formula.
1712 */
1713 termAtomic[cvc5::api::Term& atomTerm]
1714 @init {
1715 cvc5::api::Sort type;
1716 cvc5::api::Sort type2;
1717 std::string s;
1718 std::vector<uint64_t> numerals;
1719 }
1720 /* constants */
1721 : INTEGER_LITERAL
1722 {
1723 std::string intStr = AntlrInput::tokenText($INTEGER_LITERAL);
1724 atomTerm = SOLVER->mkInteger(intStr);
1725 }
1726 | DECIMAL_LITERAL
1727 {
1728 std::string realStr = AntlrInput::tokenText($DECIMAL_LITERAL);
1729 atomTerm = SOLVER->ensureTermSort(SOLVER->mkReal(realStr),
1730 SOLVER->getRealSort());
1731 }
1732
1733 // Constants using indexed identifiers, e.g. (_ +oo 8 24) (positive infinity
1734 // as a 32-bit floating-point constant)
1735 | LPAREN_TOK INDEX_TOK
1736 ( EMP_TOK
1737 sortSymbol[type,CHECK_DECLARED]
1738 sortSymbol[type2,CHECK_DECLARED]
1739 {
1740 // Empty heap constant in seperation logic
1741 api::Term v1 = SOLVER->mkConst(api::Sort(type), "_emp1");
1742 api::Term v2 = SOLVER->mkConst(api::Sort(type2), "_emp2");
1743 atomTerm = SOLVER->mkTerm(api::SEP_EMP, v1, v2);
1744 }
1745 | CHAR_TOK HEX_LITERAL
1746 {
1747 std::string hexStr = AntlrInput::tokenTextSubstr($HEX_LITERAL, 2);
1748 atomTerm = PARSER_STATE->mkCharConstant(hexStr);
1749 }
1750 | sym=SIMPLE_SYMBOL nonemptyNumeralList[numerals]
1751 {
1752 atomTerm =
1753 PARSER_STATE->mkIndexedConstant(AntlrInput::tokenText($sym),
1754 numerals);
1755 }
1756 )
1757 RPAREN_TOK
1758
1759 // Bit-vector constants
1760 | HEX_LITERAL
1761 {
1762 Assert(AntlrInput::tokenText($HEX_LITERAL).find("#x") == 0);
1763 std::string hexStr = AntlrInput::tokenTextSubstr($HEX_LITERAL, 2);
1764 atomTerm = SOLVER->mkBitVector(hexStr.size() * 4, hexStr, 16);
1765 }
1766 | BINARY_LITERAL
1767 {
1768 Assert(AntlrInput::tokenText($BINARY_LITERAL).find("#b") == 0);
1769 std::string binStr = AntlrInput::tokenTextSubstr($BINARY_LITERAL, 2);
1770 atomTerm = SOLVER->mkBitVector(binStr.size(), binStr, 2);
1771 }
1772
1773 // String constant
1774 | str[s,false] { atomTerm = PARSER_STATE->mkStringConstant(s); }
1775
1776 // NOTE: Theory constants go here
1777
1778 // Empty tuple constant
1779 | TUPLE_CONST_TOK
1780 {
1781 atomTerm = SOLVER->mkTuple(std::vector<api::Sort>(),
1782 std::vector<api::Term>());
1783 }
1784 ;
1785
1786 /**
1787 * Read attribute
1788 */
1789 attribute[cvc5::api::Term& expr, cvc5::api::Term& retExpr]
1790 @init {
1791 api::Term sexpr;
1792 std::string s;
1793 cvc5::api::Term patexpr;
1794 std::vector<cvc5::api::Term> patexprs;
1795 cvc5::api::Term e2;
1796 bool hasValue = false;
1797 api::Kind k;
1798 }
1799 : KEYWORD ( simpleSymbolicExprNoKeyword[s] { hasValue = true; } )?
1800 {
1801 PARSER_STATE->attributeNotSupported(AntlrInput::tokenText($KEYWORD));
1802 }
1803 | ( ATTRIBUTE_PATTERN_TOK { k = api::INST_PATTERN; } |
1804 ATTRIBUTE_POOL_TOK { k = api::INST_POOL; } |
1805 ATTRIBUTE_INST_ADD_TO_POOL_TOK { k = api::INST_ADD_TO_POOL; } |
1806 ATTRIBUTE_SKOLEM_ADD_TO_POOL_TOK{ k = api::SKOLEM_ADD_TO_POOL; }
1807 )
1808 LPAREN_TOK
1809 ( term[patexpr, e2]
1810 { patexprs.push_back( patexpr ); }
1811 )+ RPAREN_TOK
1812 {
1813 retExpr = MK_TERM(k, patexprs);
1814 }
1815 | ATTRIBUTE_NO_PATTERN_TOK term[patexpr, e2]
1816 {
1817 retExpr = MK_TERM(api::INST_NO_PATTERN, patexpr);
1818 }
1819 | tok=( ATTRIBUTE_INST_LEVEL ) INTEGER_LITERAL
1820 {
1821 std::stringstream sIntLit;
1822 sIntLit << $INTEGER_LITERAL;
1823 api::Term keyword = SOLVER->mkString("quant-inst-max-level");
1824 api::Term n = SOLVER->mkInteger(sIntLit.str());
1825 retExpr = MK_TERM(api::INST_ATTRIBUTE, keyword, n);
1826 }
1827 | tok=( ATTRIBUTE_QUANTIFIER_ID_TOK ) symbolicExpr[sexpr]
1828 {
1829 api::Term keyword = SOLVER->mkString("qid");
1830 api::Term name = SOLVER->mkString(sexprToString(sexpr));
1831 retExpr = MK_TERM(api::INST_ATTRIBUTE, keyword, name);
1832 }
1833 | ATTRIBUTE_NAMED_TOK symbolicExpr[sexpr]
1834 {
1835 // notify that expression was given a name
1836 PARSER_STATE->notifyNamedExpression(expr, sexprToString(sexpr));
1837 }
1838 ;
1839
1840 /**
1841 * Matches a sequence of terms and puts them into the formulas
1842 * vector.
1843 * @param formulas the vector to fill with terms
1844 * @param expr an cvc5::api::Term reference for the elements of the sequence
1845 */
1846 /* NOTE: We pass an cvc5::api::Term in here just to avoid allocating a fresh cvc5::api::Term every
1847 * time through this rule. */
1848 termList[std::vector<cvc5::api::Term>& formulas, cvc5::api::Term& expr]
1849 @declarations {
1850 cvc5::api::Term expr2;
1851 }
1852 : ( term[expr, expr2] { formulas.push_back(expr); } )+
1853 ;
1854
1855 /**
1856 * Matches a string, and strips off the quotes.
1857 */
1858 str[std::string& s, bool fsmtlib]
1859 : STRING_LITERAL
1860 {
1861 s = AntlrInput::tokenText($STRING_LITERAL);
1862 /* strip off the quotes */
1863 s = s.substr(1, s.size() - 2);
1864 for (size_t i = 0; i < s.size(); i++)
1865 {
1866 if ((unsigned)s[i] > 127 && !isprint(s[i]))
1867 {
1868 PARSER_STATE->parseError(
1869 "Extended/unprintable characters are not "
1870 "part of SMT-LIB, and they must be encoded "
1871 "as escape sequences");
1872 }
1873 }
1874 if (fsmtlib || PARSER_STATE->escapeDupDblQuote())
1875 {
1876 char* p_orig = strdup(s.c_str());
1877 char *p = p_orig, *q = p_orig;
1878 while (*q != '\0')
1879 {
1880 if (PARSER_STATE->escapeDupDblQuote() && *q == '"')
1881 {
1882 // Handle SMT-LIB >=2.5 standard escape '""'.
1883 ++q;
1884 Assert(*q == '"');
1885 }
1886 else if (!PARSER_STATE->escapeDupDblQuote() && *q == '\\')
1887 {
1888 ++q;
1889 // Handle SMT-LIB 2.0 standard escapes '\\' and '\"'.
1890 if (*q != '\\' && *q != '"')
1891 {
1892 Assert(*q != '\0');
1893 *p++ = '\\';
1894 }
1895 }
1896 *p++ = *q++;
1897 }
1898 *p = '\0';
1899 s = p_orig;
1900 free(p_orig);
1901 }
1902 }
1903 ;
1904
1905 quantOp[cvc5::api::Kind& kind]
1906 @init {
1907 Debug("parser") << "quant: " << AntlrInput::tokenText(LT(1)) << std::endl;
1908 }
1909 : EXISTS_TOK { $kind = api::EXISTS; }
1910 | FORALL_TOK { $kind = api::FORALL; }
1911 ;
1912
1913 /**
1914 * Matches a (possibly undeclared) function symbol (returning the string)
1915 * @param check what kind of check to do with the symbol
1916 */
1917 functionName[std::string& name, cvc5::parser::DeclarationCheck check]
1918 : symbol[name,check,SYM_VARIABLE]
1919 ;
1920
1921 /**
1922 * Matches a sequence of sort symbols and fills them into the given
1923 * vector.
1924 */
1925 sortList[std::vector<cvc5::api::Sort>& sorts]
1926 @declarations {
1927 cvc5::api::Sort t;
1928 }
1929 : ( sortSymbol[t,CHECK_DECLARED] { sorts.push_back(t); } )*
1930 ;
1931
1932 nonemptySortList[std::vector<cvc5::api::Sort>& sorts]
1933 @declarations {
1934 cvc5::api::Sort t;
1935 }
1936 : ( sortSymbol[t,CHECK_DECLARED] { sorts.push_back(t); } )+
1937 ;
1938
1939 /**
1940 * Matches a sequence of (variable,sort) symbol pairs and fills them
1941 * into the given vector.
1942 */
1943 sortedVarList[std::vector<std::pair<std::string, cvc5::api::Sort> >& sortedVars]
1944 @declarations {
1945 std::string name;
1946 cvc5::api::Sort t;
1947 }
1948 : ( LPAREN_TOK symbol[name,CHECK_NONE,SYM_VARIABLE]
1949 sortSymbol[t,CHECK_DECLARED] RPAREN_TOK
1950 { sortedVars.push_back(make_pair(name, t)); }
1951 )*
1952 ;
1953
1954 /**
1955 * Matches a sequence of (variable, sort) symbol pairs, registers them as bound
1956 * variables, and returns a term corresponding to the list of pairs.
1957 */
1958 boundVarList[cvc5::api::Term& expr]
1959 @declarations {
1960 std::vector<std::pair<std::string, cvc5::api::Sort>> sortedVarNames;
1961 }
1962 : LPAREN_TOK sortedVarList[sortedVarNames] RPAREN_TOK
1963 {
1964 std::vector<cvc5::api::Term> args =
1965 PARSER_STATE->bindBoundVars(sortedVarNames);
1966 expr = MK_TERM(api::BOUND_VAR_LIST, args);
1967 }
1968 ;
1969
1970 /**
1971 * Matches the sort symbol, which can be an arbitrary symbol.
1972 * @param check the check to perform on the name
1973 */
1974 sortName[std::string& name, cvc5::parser::DeclarationCheck check]
1975 : symbol[name,check,SYM_SORT]
1976 ;
1977
1978 sortSymbol[cvc5::api::Sort& t, cvc5::parser::DeclarationCheck check]
1979 @declarations {
1980 std::string name;
1981 std::vector<cvc5::api::Sort> args;
1982 std::vector<uint64_t> numerals;
1983 bool indexed = false;
1984 }
1985 : sortName[name,CHECK_NONE]
1986 {
1987 if(check == CHECK_DECLARED || PARSER_STATE->isDeclared(name, SYM_SORT)) {
1988 t = PARSER_STATE->getSort(name);
1989 } else {
1990 t = PARSER_STATE->mkUnresolvedType(name);
1991 }
1992 }
1993 | LPAREN_TOK (INDEX_TOK {indexed = true;} | {indexed = false;})
1994 symbol[name,CHECK_NONE,SYM_SORT]
1995 ( nonemptyNumeralList[numerals]
1996 {
1997 if (!indexed)
1998 {
1999 std::stringstream ss;
2000 ss << "SMT-LIB requires use of an indexed sort here, e.g. (_ " << name
2001 << " ...)";
2002 PARSER_STATE->parseError(ss.str());
2003 }
2004 if( name == "BitVec" ) {
2005 if( numerals.size() != 1 ) {
2006 PARSER_STATE->parseError("Illegal bitvector type.");
2007 }
2008 if(numerals.front() == 0) {
2009 PARSER_STATE->parseError("Illegal bitvector size: 0");
2010 }
2011 t = SOLVER->mkBitVectorSort(numerals.front());
2012 } else if ( name == "FloatingPoint" ) {
2013 if( numerals.size() != 2 ) {
2014 PARSER_STATE->parseError("Illegal floating-point type.");
2015 }
2016 if(!validExponentSize(numerals[0])) {
2017 PARSER_STATE->parseError("Illegal floating-point exponent size");
2018 }
2019 if(!validSignificandSize(numerals[1])) {
2020 PARSER_STATE->parseError("Illegal floating-point significand size");
2021 }
2022 t = SOLVER->mkFloatingPointSort(numerals[0],numerals[1]);
2023 } else {
2024 std::stringstream ss;
2025 ss << "unknown indexed sort symbol `" << name << "'";
2026 PARSER_STATE->parseError(ss.str());
2027 }
2028 }
2029 | sortList[args]
2030 { if( indexed ) {
2031 std::stringstream ss;
2032 ss << "Unexpected use of indexing operator `_' before `" << name
2033 << "', try leaving it out";
2034 PARSER_STATE->parseError(ss.str());
2035 }
2036 if(args.empty()) {
2037 PARSER_STATE->parseError("Extra parentheses around sort name not "
2038 "permitted in SMT-LIB");
2039 } else if(name == "Array" &&
2040 PARSER_STATE->isTheoryEnabled(theory::THEORY_ARRAYS) ) {
2041 if(args.size() != 2) {
2042 PARSER_STATE->parseError("Illegal array type.");
2043 }
2044 t = SOLVER->mkArraySort( args[0], args[1] );
2045 } else if(name == "Set" &&
2046 PARSER_STATE->isTheoryEnabled(theory::THEORY_SETS) ) {
2047 if(args.size() != 1) {
2048 PARSER_STATE->parseError("Illegal set type.");
2049 }
2050 t = SOLVER->mkSetSort( args[0] );
2051 }
2052 else if(name == "Bag" &&
2053 PARSER_STATE->isTheoryEnabled(theory::THEORY_BAGS) ) {
2054 if(args.size() != 1) {
2055 PARSER_STATE->parseError("Illegal bag type.");
2056 }
2057 t = SOLVER->mkBagSort( args[0] );
2058 }
2059 else if(name == "Seq" && !PARSER_STATE->strictModeEnabled() &&
2060 PARSER_STATE->isTheoryEnabled(theory::THEORY_STRINGS) ) {
2061 if(args.size() != 1) {
2062 PARSER_STATE->parseError("Illegal sequence type.");
2063 }
2064 t = SOLVER->mkSequenceSort( args[0] );
2065 } else if (name == "Tuple" && !PARSER_STATE->strictModeEnabled()) {
2066 t = SOLVER->mkTupleSort(args);
2067 } else if(check == CHECK_DECLARED ||
2068 PARSER_STATE->isDeclared(name, SYM_SORT)) {
2069 t = PARSER_STATE->getSort(name, args);
2070 } else {
2071 // make unresolved type
2072 if(args.empty()) {
2073 t = PARSER_STATE->mkUnresolvedType(name);
2074 Debug("parser-param") << "param: make unres type " << name
2075 << std::endl;
2076 } else {
2077 t = PARSER_STATE->mkUnresolvedTypeConstructor(name,args);
2078 t = t.instantiate( args );
2079 Debug("parser-param")
2080 << "param: make unres param type " << name << " " << args.size()
2081 << " " << PARSER_STATE->getArity( name ) << std::endl;
2082 }
2083 }
2084 }
2085 ) RPAREN_TOK
2086 | LPAREN_TOK HO_ARROW_TOK sortList[args] RPAREN_TOK
2087 {
2088 if(args.size()<2) {
2089 PARSER_STATE->parseError("Arrow types must have at least 2 arguments");
2090 }
2091 //flatten the type
2092 api::Sort rangeType = args.back();
2093 args.pop_back();
2094 t = PARSER_STATE->mkFlatFunctionType( args, rangeType );
2095 }
2096 ;
2097
2098 /**
2099 * Matches a list of symbols, with check and type arguments as for the
2100 * symbol[] rule below.
2101 */
2102 symbolList[std::vector<std::string>& names,
2103 cvc5::parser::DeclarationCheck check,
2104 cvc5::parser::SymbolType type]
2105 @declarations {
2106 std::string id;
2107 }
2108 : ( symbol[id,check,type] { names.push_back(id); } )*
2109 ;
2110
2111 /**
2112 * Matches an symbol and sets the string reference parameter id.
2113 * @param id string to hold the symbol
2114 * @param check what kinds of check to do on the symbol
2115 * @param type the intended namespace for the symbol
2116 */
2117 symbol[std::string& id,
2118 cvc5::parser::DeclarationCheck check,
2119 cvc5::parser::SymbolType type]
2120 : SIMPLE_SYMBOL
2121 { id = AntlrInput::tokenText($SIMPLE_SYMBOL);
2122 if(!PARSER_STATE->isAbstractValue(id)) {
2123 // if an abstract value, SmtEngine handles declaration
2124 PARSER_STATE->checkDeclaration(id, check, type);
2125 }
2126 }
2127 | QUOTED_SYMBOL
2128 { id = AntlrInput::tokenText($QUOTED_SYMBOL);
2129 /* strip off the quotes */
2130 id = id.substr(1, id.size() - 2);
2131 if(!PARSER_STATE->isAbstractValue(id)) {
2132 // if an abstract value, SmtEngine handles declaration
2133 PARSER_STATE->checkDeclaration(id, check, type);
2134 }
2135 }
2136 | UNTERMINATED_QUOTED_SYMBOL
2137 ( EOF
2138 { PARSER_STATE->unexpectedEOF("unterminated |quoted| symbol"); }
2139 | '\\'
2140 { PARSER_STATE->unexpectedEOF("backslash not permitted in |quoted| "
2141 "symbol"); }
2142 )
2143 ;
2144
2145 /**
2146 * Matches a nonempty list of numerals.
2147 * @param numerals the (empty) vector to house the numerals.
2148 */
2149 nonemptyNumeralList[std::vector<uint64_t>& numerals]
2150 : ( INTEGER_LITERAL
2151 { numerals.push_back(AntlrInput::tokenToUnsigned($INTEGER_LITERAL)); }
2152 )+
2153 ;
2154
2155 /**
2156 * Parses a datatype definition
2157 */
2158 datatypeDef[bool isCo, std::vector<cvc5::api::DatatypeDecl>& datatypes,
2159 std::vector< cvc5::api::Sort >& params]
2160 @init {
2161 std::string id;
2162 }
2163 /* This really needs to be CHECK_NONE, or mutually-recursive
2164 * datatypes won't work, because this type will already be
2165 * "defined" as an unresolved type; don't worry, we check
2166 * below. */
2167 : symbol[id,CHECK_NONE,SYM_SORT] { PARSER_STATE->pushScope(); }
2168 {
2169 datatypes.push_back(SOLVER->mkDatatypeDecl(id, params, isCo));
2170 }
2171 ( LPAREN_TOK constructorDef[datatypes.back()] RPAREN_TOK )+
2172 { PARSER_STATE->popScope(); }
2173 ;
2174
2175 /**
2176 * Parses a constructor defintion for type
2177 */
2178 constructorDef[cvc5::api::DatatypeDecl& type]
2179 @init {
2180 std::string id;
2181 cvc5::api::DatatypeConstructorDecl* ctor = NULL;
2182 }
2183 : symbol[id,CHECK_NONE,SYM_VARIABLE]
2184 {
2185 ctor = new api::DatatypeConstructorDecl(
2186 SOLVER->mkDatatypeConstructorDecl(id));
2187 }
2188 ( LPAREN_TOK selector[*ctor] RPAREN_TOK )*
2189 { // make the constructor
2190 type.addConstructor(*ctor);
2191 Debug("parser-idt") << "constructor: " << id.c_str() << std::endl;
2192 delete ctor;
2193 }
2194 ;
2195
2196 selector[cvc5::api::DatatypeConstructorDecl& ctor]
2197 @init {
2198 std::string id;
2199 cvc5::api::Sort t, t2;
2200 }
2201 : symbol[id,CHECK_NONE,SYM_SORT] sortSymbol[t,CHECK_NONE]
2202 {
2203 ctor.addSelector(id, t);
2204 Debug("parser-idt") << "selector: " << id.c_str()
2205 << " of type " << t << std::endl;
2206 }
2207 ;
2208
2209 // Base SMT-LIB tokens
2210 ASSERT_TOK : 'assert';
2211 CHECK_SAT_TOK : 'check-sat';
2212 CHECK_SAT_ASSUMING_TOK : 'check-sat-assuming';
2213 DECLARE_FUN_TOK : 'declare-fun';
2214 DECLARE_SORT_TOK : 'declare-sort';
2215 DEFINE_FUN_TOK : 'define-fun';
2216 DEFINE_FUN_REC_TOK : 'define-fun-rec';
2217 DEFINE_FUNS_REC_TOK : 'define-funs-rec';
2218 DEFINE_SORT_TOK : 'define-sort';
2219 GET_VALUE_TOK : 'get-value';
2220 GET_ASSIGNMENT_TOK : 'get-assignment';
2221 GET_ASSERTIONS_TOK : 'get-assertions';
2222 GET_PROOF_TOK : 'get-proof';
2223 GET_UNSAT_ASSUMPTIONS_TOK : 'get-unsat-assumptions';
2224 GET_UNSAT_CORE_TOK : 'get-unsat-core';
2225 EXIT_TOK : 'exit';
2226 RESET_TOK : 'reset';
2227 RESET_ASSERTIONS_TOK : 'reset-assertions';
2228 LET_TOK : 'let';
2229 ATTRIBUTE_TOK : '!';
2230 LPAREN_TOK : '(';
2231 RPAREN_TOK : ')';
2232 INDEX_TOK : '_';
2233 SET_LOGIC_TOK : 'set-logic';
2234 SET_INFO_TOK : 'set-info';
2235 GET_INFO_TOK : 'get-info';
2236 SET_OPTION_TOK : 'set-option';
2237 GET_OPTION_TOK : 'get-option';
2238 PUSH_TOK : 'push';
2239 POP_TOK : 'pop';
2240 AS_TOK : 'as';
2241 CONST_TOK : { !PARSER_STATE->strictModeEnabled() }? 'const';
2242
2243 // extended commands
2244 DECLARE_CODATATYPE_TOK : { PARSER_STATE->v2_6() || PARSER_STATE->sygus() }? 'declare-codatatype';
2245 DECLARE_DATATYPE_TOK : { PARSER_STATE->v2_6() || PARSER_STATE->sygus() }? 'declare-datatype';
2246 DECLARE_DATATYPES_2_5_TOK : { !( PARSER_STATE->v2_6() || PARSER_STATE->sygus() ) }?'declare-datatypes';
2247 DECLARE_DATATYPES_TOK : { PARSER_STATE->v2_6() || PARSER_STATE->sygus() }?'declare-datatypes';
2248 DECLARE_CODATATYPES_2_5_TOK : { !( PARSER_STATE->v2_6() || PARSER_STATE->sygus() ) }?'declare-codatatypes';
2249 DECLARE_CODATATYPES_TOK : { PARSER_STATE->v2_6() || PARSER_STATE->sygus() }?'declare-codatatypes';
2250 PAR_TOK : { PARSER_STATE->v2_6() || PARSER_STATE->sygus() }?'par';
2251 COMPREHENSION_TOK : { PARSER_STATE->isTheoryEnabled(theory::THEORY_SETS) }?'comprehension';
2252 TESTER_TOK : { ( PARSER_STATE->v2_6() || PARSER_STATE->sygus() ) && PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }?'is';
2253 UPDATE_TOK : { ( PARSER_STATE->v2_6() || PARSER_STATE->sygus() ) && PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }?'update';
2254 MATCH_TOK : { ( PARSER_STATE->v2_6() || PARSER_STATE->sygus() ) && PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }?'match';
2255 GET_MODEL_TOK : 'get-model';
2256 BLOCK_MODEL_TOK : 'block-model';
2257 BLOCK_MODEL_VALUES_TOK : 'block-model-values';
2258 ECHO_TOK : 'echo';
2259 DECLARE_SORTS_TOK : 'declare-sorts';
2260 DECLARE_FUNS_TOK : 'declare-funs';
2261 DECLARE_PREDS_TOK : 'declare-preds';
2262 DEFINE_TOK : 'define';
2263 DECLARE_CONST_TOK : 'declare-const';
2264 DEFINE_CONST_TOK : 'define-const';
2265 SIMPLIFY_TOK : 'simplify';
2266 INCLUDE_TOK : 'include';
2267 GET_QE_TOK : 'get-qe';
2268 GET_QE_DISJUNCT_TOK : 'get-qe-disjunct';
2269 GET_ABDUCT_TOK : 'get-abduct';
2270 GET_INTERPOL_TOK : 'get-interpol';
2271 DECLARE_HEAP : 'declare-heap';
2272 DECLARE_POOL : 'declare-pool';
2273
2274 // SyGuS commands
2275 SYNTH_FUN_TOK : { PARSER_STATE->sygus() }?'synth-fun';
2276 SYNTH_INV_TOK : { PARSER_STATE->sygus()}?'synth-inv';
2277 CHECK_SYNTH_TOK : { PARSER_STATE->sygus()}?'check-synth';
2278 DECLARE_VAR_TOK : { PARSER_STATE->sygus()}?'declare-var';
2279 CONSTRAINT_TOK : { PARSER_STATE->sygus()}?'constraint';
2280 ASSUME_TOK : { PARSER_STATE->sygus()}?'assume';
2281 INV_CONSTRAINT_TOK : { PARSER_STATE->sygus()}?'inv-constraint';
2282 SET_FEATURE_TOK : { PARSER_STATE->sygus() }? 'set-feature';
2283 SYGUS_CONSTANT_TOK : { PARSER_STATE->sygus() }? 'Constant';
2284 SYGUS_VARIABLE_TOK : { PARSER_STATE->sygus() }? 'Variable';
2285
2286 // attributes
2287 ATTRIBUTE_PATTERN_TOK : ':pattern';
2288 ATTRIBUTE_NO_PATTERN_TOK : ':no-pattern';
2289 ATTRIBUTE_POOL_TOK : ':pool';
2290 ATTRIBUTE_INST_ADD_TO_POOL_TOK : ':inst-add-to-pool';
2291 ATTRIBUTE_SKOLEM_ADD_TO_POOL_TOK : ':skolem-add-to-pool';
2292 ATTRIBUTE_NAMED_TOK : ':named';
2293 ATTRIBUTE_INST_LEVEL : ':quant-inst-max-level';
2294 ATTRIBUTE_QUANTIFIER_ID_TOK : ':qid';
2295
2296 // operators (NOTE: theory symbols go here)
2297 EXISTS_TOK : 'exists';
2298 FORALL_TOK : 'forall';
2299
2300 EMP_TOK : { PARSER_STATE->isTheoryEnabled(theory::THEORY_SEP) }? 'emp';
2301 CHAR_TOK : { PARSER_STATE->isTheoryEnabled(theory::THEORY_STRINGS) }? 'char';
2302 TUPLE_CONST_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'mkTuple';
2303 TUPLE_SEL_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'tupSel';
2304 TUPLE_PROJECT_TOK: { PARSER_STATE->isTheoryEnabled(theory::THEORY_DATATYPES) }? 'tuple_project';
2305
2306 HO_ARROW_TOK : { PARSER_STATE->isHoEnabled() }? '->';
2307 HO_LAMBDA_TOK : { PARSER_STATE->isHoEnabled() }? 'lambda';
2308
2309 /**
2310 * A sequence of printable ASCII characters (except backslash) that starts
2311 * and ends with | and does not otherwise contain |.
2312 *
2313 * You shouldn't generally use this in parser rules, as the |quoting|
2314 * will be part of the token text. Use the symbol[] parser rule instead.
2315 */
2316 QUOTED_SYMBOL
2317 : '|' ~('|' | '\\')* '|'
2318 ;
2319 UNTERMINATED_QUOTED_SYMBOL
2320 : '|' ~('|' | '\\')*
2321 ;
2322
2323 /**
2324 * Matches a keyword from the input. A keyword is a simple symbol prefixed
2325 * with a colon.
2326 */
2327 KEYWORD
2328 : ':' (ALPHA | DIGIT | SYMBOL_CHAR)+
2329 ;
2330
2331 /**
2332 * Matches a "simple" symbol: a non-empty sequence of letters, digits and
2333 * the characters + - / * = % ? ! . $ ~ & ^ < > @ that does not start with a
2334 * digit, and is not the special reserved symbols '!' or '_'.
2335 */
2336 SIMPLE_SYMBOL
2337 : ALPHA (ALPHA | DIGIT | SYMBOL_CHAR)*
2338 | SYMBOL_CHAR (ALPHA | DIGIT | SYMBOL_CHAR)+
2339 | SYMBOL_CHAR_NOUNDERSCORE_NOATTRIBUTE
2340 ;
2341
2342 /**
2343 * Matches and skips whitespace in the input.
2344 */
2345 WHITESPACE
2346 : (' ' | '\t' | '\f' | '\r' | '\n')+ { SKIP(); }
2347 ;
2348
2349 /**
2350 * Matches an integer constant from the input (non-empty sequence of
2351 * digits, with no leading zeroes).
2352 */
2353 INTEGER_LITERAL
2354 : NUMERAL
2355 ;
2356
2357 /**
2358 * Match an integer constant. In non-strict mode, this is any sequence
2359 * of digits. In strict mode, non-zero integers can't have leading
2360 * zeroes.
2361 */
2362 fragment NUMERAL
2363 @init {
2364 char *start = (char*) GETCHARINDEX();
2365 }
2366 : DIGIT+
2367 { Debug("parser-extra") << "NUMERAL: "
2368 << (uintptr_t)start << ".." << GETCHARINDEX()
2369 << " strict? " << (bool)(PARSER_STATE->strictModeEnabled())
2370 << " ^0? " << (bool)(*start == '0')
2371 << " len>1? " << (bool)(start < (char*)(GETCHARINDEX() - 1))
2372 << std::endl; }
2373 { !PARSER_STATE->strictModeEnabled() ||
2374 *start != '0' ||
2375 start == (char*)(GETCHARINDEX() - 1) }?
2376 ;
2377
2378 /**
2379 * Matches a decimal constant from the input.
2380 */
2381 DECIMAL_LITERAL
2382 : NUMERAL '.' DIGIT+
2383 ;
2384
2385 /**
2386 * Matches a hexadecimal constant.
2387 */
2388 HEX_LITERAL
2389 : '#x' HEX_DIGIT+
2390 ;
2391
2392 /**
2393 * Matches a binary constant.
2394 */
2395 BINARY_LITERAL
2396 : '#b' ('0' | '1')+
2397 ;
2398
2399 /**
2400 * Matches a double-quoted string literal. Depending on the language that is
2401 * being parsed, different escape sequences are supported:
2402 *
2403 * For SMT-LIB 2.0 the sequence \" is interpreted as a double quote (") and the
2404 * sequence \\ is interpreted as a backslash (\).
2405 *
2406 * For SMT-LIB >=2.5 and SyGuS a double-quote inside a string is escaped with
2407 * "", e.g., "This is a string literal with "" a single, embedded double
2408 * quote."
2409 *
2410 * You shouldn't generally use this in parser rules, as the quotes
2411 * will be part of the token text. Use the str[] parser rule instead.
2412 */
2413 STRING_LITERAL
2414 : { !PARSER_STATE->escapeDupDblQuote() }?=>
2415 '"' ('\\' . | ~('\\' | '"'))* '"'
2416 | { PARSER_STATE->escapeDupDblQuote() }?=>
2417 '"' (~('"') | '""')* '"'
2418 ;
2419
2420 /**
2421 * Matches the comments and ignores them
2422 */
2423 COMMENT
2424 : ';' (~('\n' | '\r'))* { SKIP(); }
2425 ;
2426
2427 /**
2428 * Matches any letter ('a'-'z' and 'A'-'Z').
2429 */
2430 fragment
2431 ALPHA
2432 : 'a'..'z'
2433 | 'A'..'Z'
2434 ;
2435
2436 /**
2437 * Matches the digits (0-9)
2438 */
2439 fragment DIGIT : '0'..'9';
2440
2441 fragment HEX_DIGIT : DIGIT | 'a'..'f' | 'A'..'F';
2442
2443 /**
2444 * Matches the characters that may appear as a one-character "symbol"
2445 * (which excludes _ and !, which are reserved words in SMT-LIB).
2446 */
2447 fragment SYMBOL_CHAR_NOUNDERSCORE_NOATTRIBUTE
2448 : '+' | '-' | '/' | '*' | '=' | '%' | '?' | '.' | '$' | '~'
2449 | '&' | '^' | '<' | '>' | '@'
2450 ;
2451
2452 /**
2453 * Matches the characters that may appear in a "symbol" (i.e., an identifier)
2454 */
2455 fragment SYMBOL_CHAR
2456 : SYMBOL_CHAR_NOUNDERSCORE_NOATTRIBUTE | '_' | '!'
2457 ;