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