1 /* ******************* */
4 ** Top contributors (to current version):
5 ** Haniel Barbosa, Francois Bobot, Andrew Reynolds
6 ** This file is part of the CVC4 project.
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.\endverbatim
12 ** \brief Parser for TPTP input language.
14 ** Parser for TPTP input language.
15 ** cf. http://www.cs.miami.edu/~tptp/cgi-bin/SeeTPTP?Category=Documents&File=SyntaxBNF
24 // Skip the default error handling, just break with exceptions
25 // defaultErrorHandler = false;
27 // Only lookahead of <= k requested (disable for LL* parsing)
28 // Note that CVC4's BoundedTokenBuffer requires a fixed k !
29 // If you change this k, change it also in tptp_input.cpp !
35 ** This file is part of the CVC4 project.
36 ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS
37 ** in the top-level source directory) and their institutional affiliations.
38 ** All rights reserved. See the file COPYING in the top-level source
39 ** directory for licensing information.
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.
50 #pragma GCC system_header
52 /* This improves performance by ~10 percent on big inputs.
53 * This option is only valid if we know the input is ASCII (or some 8-bit encoding).
54 * If we know the input is UTF-16, we can use ANTLR3_INLINE_INPUT_UTF16.
55 * Otherwise, we have to let the lexer detect the encoding at runtime.
57 #define ANTLR3_INLINE_INPUT_ASCII
59 #include "parser/antlr_tracing.h"
61 }/* @lexer::includes */
65 #include "parser/tptp/tptp.h"
66 #include "parser/antlr_input.h"
69 using namespace CVC4::parser;
71 /* These need to be macros so they can refer to the PARSER macro, which will be defined
72 * by ANTLR *after* this section. (If they were functions, PARSER would be undefined.) */
74 #define PARSER_STATE ((Tptp*)LEXER->super)
76 #define SOLVER PARSER_STATE->getSolver()
78 #define MK_TERM SOLVER->mkTerm
80 #define MK_TERM SOLVER->mkTerm
81 #define UNSUPPORTED PARSER_STATE->unimplementedFeature
83 }/* @lexer::postinclude */
89 #include "smt/command.h"
90 #include "parser/parse_op.h"
91 #include "parser/parser.h"
92 #include "parser/tptp/tptp.h"
93 #include "parser/antlr_tracing.h"
95 }/* @parser::includes */
97 @parser::postinclude {
103 #include "api/cvc4cpp.h"
104 #include "base/output.h"
105 #include "parser/antlr_input.h"
106 #include "parser/parser.h"
107 #include "parser/tptp/tptp.h"
108 #include "util/integer.h"
109 #include "util/rational.h"
111 using namespace CVC4;
112 using namespace CVC4::parser;
114 /* These need to be macros so they can refer to the PARSER macro, which will be defined
115 * by ANTLR *after* this section. (If they were functions, PARSER would be undefined.) */
117 #define PARSER_STATE ((Tptp*)PARSER->super)
119 #define SOLVER PARSER_STATE->getSolver()
121 #define SYM_MAN PARSER_STATE->getSymbolManager()
123 #define MK_TERM SOLVER->mkTerm
124 #define UNSUPPORTED PARSER_STATE->unimplementedFeature
126 }/* parser::postinclude */
129 * Parses an expression.
130 * @return the parsed expression, or the Null CVC4::api::Term if we've reached
131 * the end of the input
133 parseExpr returns [CVC4::parser::tptp::myExpr expr]
140 * @return the parsed command, or NULL if we've reached the end of the input
142 parseCommand returns [CVC4::Command* cmd = NULL]
144 CVC4::api::Term expr;
145 Tptp::FormulaRole fr;
146 std::string name, inclSymbol;
149 : CNF_TOK LPAREN_TOK nameN[name] COMMA_TOK formulaRole[fr] COMMA_TOK
150 { PARSER_STATE->setCnf(true);
151 PARSER_STATE->setFof(false);
152 PARSER_STATE->pushScope(); }
154 { PARSER_STATE->popScope();
155 std::vector<api::Term> bvl = PARSER_STATE->getFreeVar();
157 expr = MK_TERM(api::FORALL,MK_TERM(api::BOUND_VAR_LIST,bvl),expr);
160 (COMMA_TOK anything*)? RPAREN_TOK DOT_TOK
162 CVC4::api::Term aexpr = PARSER_STATE->getAssertionExpr(fr, expr);
163 if( !aexpr.isNull() ){
164 // set the expression name (e.g. used with unsat core printing)
165 SYM_MAN->setExpressionName(aexpr, name, true);
167 // make the command to assert the formula
168 cmd = PARSER_STATE->makeAssertCommand(fr, aexpr, /* cnf == */ true, true);
170 | FOF_TOK LPAREN_TOK nameN[name] COMMA_TOK formulaRole[fr] COMMA_TOK
171 { PARSER_STATE->setCnf(false); PARSER_STATE->setFof(true); }
172 fofFormula[expr] (COMMA_TOK anything*)? RPAREN_TOK DOT_TOK
174 CVC4::api::Term aexpr = PARSER_STATE->getAssertionExpr(fr,expr);
175 if( !aexpr.isNull() ){
176 // set the expression name (e.g. used with unsat core printing)
177 SYM_MAN->setExpressionName(aexpr, name, true);
179 // make the command to assert the formula
180 cmd = PARSER_STATE->makeAssertCommand(fr, aexpr, /* cnf == */ false, true);
182 | TFF_TOK LPAREN_TOK nameN[name] COMMA_TOK
183 ( TYPE_TOK COMMA_TOK tffTypedAtom[cmd]
184 | formulaRole[fr] COMMA_TOK
185 { PARSER_STATE->setCnf(false); PARSER_STATE->setFof(false); }
186 tffFormula[expr] (COMMA_TOK anything*)?
188 CVC4::api::Term aexpr = PARSER_STATE->getAssertionExpr(fr,expr);
189 if( !aexpr.isNull() ){
190 // set the expression name (e.g. used with unsat core printing)
191 SYM_MAN->setExpressionName(aexpr, name, true);
193 // make the command to assert the formula
194 cmd = PARSER_STATE->makeAssertCommand(fr, aexpr, /* cnf == */ false, true);
197 | THF_TOK LPAREN_TOK nameN[name] COMMA_TOK
198 // Supported THF formulas: either a logic formula or a typing atom (i.e. we
199 // ignore subtyping and logic sequents). Also, only TH0
200 ( TYPE_TOK COMMA_TOK thfAtomTyping[cmd]
201 | formulaRole[fr] COMMA_TOK
202 { PARSER_STATE->setCnf(false); PARSER_STATE->setFof(false); }
203 thfLogicFormula[p] (COMMA_TOK anything*)?
205 if (p.d_expr.isNull())
207 PARSER_STATE->parseError("Top level expression must be a formula");
210 CVC4::api::Term aexpr = PARSER_STATE->getAssertionExpr(fr, expr);
213 // set the expression name (e.g. used with unsat core printing)
214 SYM_MAN->setExpressionName(aexpr, name, true);
216 // make the command to assert the formula
217 cmd = PARSER_STATE->makeAssertCommand(
218 fr, aexpr, /* cnf == */ false, true);
221 | INCLUDE_TOK LPAREN_TOK unquotedFileName[name]
222 ( COMMA_TOK LBRACK_TOK nameN[inclSymbol]
223 ( COMMA_TOK nameN[inclSymbol] )* RBRACK_TOK )?
225 { /* TODO - implement symbol filtering for file inclusion.
226 * the following removes duplicates and "all", just need to pass it
227 * through to includeFile() and implement it there.
228 std::sort(inclArgs.begin(), inclArgs.end());
229 std::vector<std::string>::iterator it =
230 std::unique(inclArgs.begin(), inclArgs.end());
231 inclArgs.resize(std::distance(inclArgs.begin(), it));
232 it = std::lower_bound(inclArgs.begin(), inclArgs.end(), std::string("all"));
233 if(it != inclArgs.end() && *it == "all") {
237 PARSER_STATE->includeFile(name /* , inclArgs */ );
238 // The command of the included file will be produced at the next parseCommand() call
239 cmd = new EmptyCommand("include::" + name);
243 CommandSequence* seq = new CommandSequence();
244 // assert that all distinct constants are distinct
245 CVC4::api::Term aexpr = PARSER_STATE->getAssertionDistinctConstants();
246 if( !aexpr.isNull() )
248 seq->addCommand(new AssertCommand(aexpr, false));
251 std::string filename = PARSER_STATE->getInput()->getInputStreamName();
252 size_t i = filename.find_last_of('/');
253 if(i != std::string::npos) {
254 filename = filename.substr(i + 1);
256 if(filename.substr(filename.length() - 2) == ".p") {
257 filename = filename.substr(0, filename.length() - 2);
259 seq->addCommand(new SetInfoCommand("filename", filename));
260 if(PARSER_STATE->hasConjecture()) {
261 seq->addCommand(new QueryCommand(SOLVER->mkFalse()));
263 seq->addCommand(new CheckSatCommand());
265 PARSER_STATE->preemptCommand(seq);
270 /* Parse a formula Role */
271 formulaRole[CVC4::parser::Tptp::FormulaRole& role]
274 std::string r = AntlrInput::tokenText($LOWER_WORD);
275 if (r == "axiom") role = Tptp::FR_AXIOM;
276 else if (r == "hypothesis") role = Tptp::FR_HYPOTHESIS;
277 else if (r == "definition") role = Tptp::FR_DEFINITION;
278 else if (r == "assumption") role = Tptp::FR_ASSUMPTION;
279 else if (r == "lemma") role = Tptp::FR_LEMMA;
280 else if (r == "theorem") role = Tptp::FR_THEOREM;
281 else if (r == "negated_conjecture") role = Tptp::FR_NEGATED_CONJECTURE;
282 else if (r == "conjecture") role = Tptp::FR_CONJECTURE;
283 else if (r == "unknown") role = Tptp::FR_UNKNOWN;
284 else if (r == "plain") role = Tptp::FR_PLAIN;
285 else if (r == "fi_domain") role = Tptp::FR_FI_DOMAIN;
286 else if (r == "fi_functor") role = Tptp::FR_FI_FUNCTORS;
287 else if (r == "fi_predicate") role = Tptp::FR_FI_PREDICATES;
288 else if (r == "type") role = Tptp::FR_TYPE;
289 else PARSER_STATE->parseError("Invalid formula role: " + r);
296 /* It can parse a little more than the cnf grammar: false and true can appear.
297 * Normally only false can appear and only at top level. */
299 cnfFormula[CVC4::api::Term& expr]
300 : LPAREN_TOK cnfDisjunction[expr] RPAREN_TOK
301 | cnfDisjunction[expr]
304 cnfDisjunction[CVC4::api::Term& expr]
306 std::vector<api::Term> args;
308 : cnfLiteral[expr] { args.push_back(expr); }
309 ( OR_TOK cnfLiteral[expr] { args.push_back(expr); } )*
310 { if(args.size() > 1) {
311 expr = MK_TERM(api::OR, args);
312 } // else its already in the expr
316 cnfLiteral[CVC4::api::Term& expr]
317 : atomicFormula[expr]
318 | NOT_TOK atomicFormula[expr] { expr = MK_TERM(api::NOT, expr); }
321 atomicFormula[CVC4::api::Term& expr]
323 CVC4::api::Term expr2;
325 std::vector<CVC4::api::Term> args;
329 : atomicWord[p.d_name] (LPAREN_TOK arguments[args] RPAREN_TOK)?
330 ( equalOp[equal] term[expr2]
331 { // equality/disequality between terms
332 expr = args.empty() ? PARSER_STATE->parseOpToExpr(p)
333 : PARSER_STATE->applyParseOp(p, args);
335 args.push_back(expr);
336 args.push_back(expr2);
337 ParseOp p1(api::EQUAL);
338 expr = PARSER_STATE->applyParseOp(p1, args);
341 expr = MK_TERM(api::NOT, expr);
345 p.d_type = SOLVER->getBooleanSort();
346 expr = args.empty() ? PARSER_STATE->parseOpToExpr(p)
347 : PARSER_STATE->applyParseOp(p, args);
352 LPAREN_TOK arguments[args] RPAREN_TOK
353 equalOp[equal] term[expr2]
355 expr = PARSER_STATE->applyParseOp(p, args);
357 args.push_back(expr);
358 args.push_back(expr2);
359 ParseOp p1(api::EQUAL);
360 expr = PARSER_STATE->applyParseOp(p1, args);
363 expr = MK_TERM(api::NOT, expr);
367 | (simpleTerm[expr] | letTerm[expr] | conditionalTerm[expr])
369 equalOp[equal] term[expr2]
370 { // equality/disequality between terms
371 args.push_back(expr);
372 args.push_back(expr2);
373 p.d_kind = api::EQUAL;
374 expr = PARSER_STATE->applyParseOp(p, args);
377 expr = MK_TERM(api::NOT, expr);
381 | definedPred[p] (LPAREN_TOK arguments[args] RPAREN_TOK)
383 p.d_type = SOLVER->getBooleanSort();
384 expr = PARSER_STATE->applyParseOp(p, args);
389 thfAtomicFormula[CVC4::ParseOp& p]
391 CVC4::api::Term expr2;
393 std::vector<CVC4::api::Term> args;
396 : atomicWord[p.d_name] (LPAREN_TOK arguments[args] RPAREN_TOK)?
398 p.d_expr = args.empty() ? PARSER_STATE->parseOpToExpr(p)
399 : PARSER_STATE->applyParseOp(p, args);
403 LPAREN_TOK arguments[args] RPAREN_TOK
404 equalOp[equal] term[expr2]
406 p.d_expr = PARSER_STATE->applyParseOp(p, args);
408 args.push_back(p.d_expr);
409 args.push_back(expr2);
410 ParseOp p1(api::EQUAL);
411 p.d_expr = PARSER_STATE->applyParseOp(p1, args);
414 p.d_expr = MK_TERM(api::NOT, p.d_expr);
418 | thfSimpleTerm[p.d_expr]
420 | conditionalTerm[p.d_expr]
421 | thfDefinedPred[p] (LPAREN_TOK arguments[args] RPAREN_TOK)?
423 p.d_type = SOLVER->getBooleanSort();
426 p.d_expr = PARSER_STATE->applyParseOp(p, args);
429 | definedProp[p.d_expr]
432 //%----Using <plain_term> removes a reduce/reduce ambiguity in lex/yacc.
433 //%----Note: "defined" means a word starting with one $ and "system" means $$.
435 definedProp[CVC4::api::Term& expr]
436 : TRUE_TOK { expr = SOLVER->mkTrue(); }
437 | FALSE_TOK { expr = SOLVER->mkFalse(); }
440 definedPred[CVC4::ParseOp& p]
458 // a real n is a rational if there exists q,r integers such that
459 // to_real(q) = n*to_real(r),
460 // where r is non-zero.
462 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
463 api::Term q = SOLVER->mkVar(SOLVER->getIntegerSort(), "Q");
464 api::Term qr = MK_TERM(api::TO_REAL, q);
465 api::Term r = SOLVER->mkVar(SOLVER->getIntegerSort(), "R");
466 api::Term rr = MK_TERM(api::TO_REAL, r);
470 MK_TERM(api::EQUAL, r, SOLVER->mkInteger(0))),
471 MK_TERM(api::EQUAL, qr, MK_TERM(api::MULT, n, rr)));
472 api::Term bvl = MK_TERM(api::BOUND_VAR_LIST, q, r);
473 body = MK_TERM(api::EXISTS, bvl, body);
474 api::Term lbvl = MK_TERM(api::BOUND_VAR_LIST, n);
475 p.d_kind = api::LAMBDA;
476 p.d_expr = MK_TERM(api::LAMBDA, lbvl, body);
480 p.d_kind = api::IS_INTEGER;
484 p.d_kind = api::DISTINCT;
492 p.d_kind = api::IMPLIES;
500 thfDefinedPred[CVC4::ParseOp& p]
518 // a real n is a rational if there exists q,r integers such that
519 // to_real(q) = n*to_real(r),
520 // where r is non-zero.
522 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
523 api::Term q = SOLVER->mkVar(SOLVER->getIntegerSort(), "Q");
524 api::Term qr = MK_TERM(api::TO_REAL, q);
525 api::Term r = SOLVER->mkVar(SOLVER->getIntegerSort(), "R");
526 api::Term rr = MK_TERM(api::TO_REAL, r);
527 api::Term body = MK_TERM(
530 MK_TERM(api::EQUAL, r, SOLVER->mkInteger(0))),
531 MK_TERM(api::EQUAL, qr, MK_TERM(api::MULT, n, rr)));
532 api::Term bvl = MK_TERM(api::BOUND_VAR_LIST, q, r);
533 body = MK_TERM(api::EXISTS, bvl, body);
534 api::Term lbvl = MK_TERM(api::BOUND_VAR_LIST, n);
535 p.d_kind = api::LAMBDA;
536 p.d_expr = MK_TERM(api::LAMBDA, lbvl, body);
540 p.d_kind = api::IS_INTEGER;
544 p.d_kind = api::DISTINCT;
558 p.d_kind = api::IMPLIES;
564 definedFun[CVC4::ParseOp& p]
566 bool remainder = false;
570 p.d_kind = api::UMINUS;
574 p.d_kind = api::PLUS;
578 p.d_kind = api::MINUS;
582 p.d_kind = api::MULT;
586 p.d_kind = api::DIVISION;
588 | ( '$quotient_e' { remainder = false; }
589 | '$remainder_e' { remainder = true; }
592 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
593 api::Term d = SOLVER->mkVar(SOLVER->getRealSort(), "D");
594 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n, d);
595 api::Term expr = MK_TERM(api::DIVISION, n, d);
596 expr = MK_TERM(api::ITE,
597 MK_TERM(api::GEQ, d, SOLVER->mkReal(0)),
598 MK_TERM(api::TO_INTEGER, expr),
600 MK_TERM(api::TO_INTEGER,
601 MK_TERM(api::UMINUS, expr))));
606 MK_TERM(api::MINUS, n, MK_TERM(api::MULT, expr, d)));
608 p.d_kind = api::LAMBDA;
609 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
611 | ( '$quotient_t' { remainder = false; }
612 | '$remainder_t' { remainder = true; }
615 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
616 api::Term d = SOLVER->mkVar(SOLVER->getRealSort(), "D");
617 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n, d);
618 api::Term expr = MK_TERM(api::DIVISION, n, d);
619 expr = MK_TERM(api::ITE,
620 MK_TERM(api::GEQ, expr, SOLVER->mkReal(0)),
621 MK_TERM(api::TO_INTEGER, expr),
623 MK_TERM(api::TO_INTEGER,
624 MK_TERM(api::UMINUS, expr))));
629 MK_TERM(api::MINUS, n, MK_TERM(api::MULT, expr, d)));
631 p.d_kind = api::LAMBDA;
632 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
634 | ( '$quotient_f' { remainder = false; }
635 | '$remainder_f' { remainder = true; }
638 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
639 api::Term d = SOLVER->mkVar(SOLVER->getRealSort(), "D");
640 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n, d);
641 api::Term expr = MK_TERM(api::DIVISION, n, d);
642 expr = MK_TERM(api::TO_INTEGER, expr);
645 expr = MK_TERM(api::TO_INTEGER,
646 MK_TERM(api::MINUS, n, MK_TERM(api::MULT, expr, d)));
648 p.d_kind = api::LAMBDA;
649 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
653 p.d_kind = api::TO_INTEGER;
657 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
658 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n);
659 api::Term expr = MK_TERM(api::UMINUS,
660 MK_TERM(api::TO_INTEGER, MK_TERM(api::UMINUS, n)));
661 p.d_kind = api::LAMBDA;
662 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
666 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
667 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n);
670 MK_TERM(api::GEQ, n, SOLVER->mkReal(0)),
671 MK_TERM(api::TO_INTEGER, n),
673 MK_TERM(api::TO_INTEGER, MK_TERM(api::UMINUS, n))));
674 p.d_kind = api::LAMBDA;
675 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
679 api::Term n = SOLVER->mkVar(SOLVER->getRealSort(), "N");
680 api::Term formals = MK_TERM(api::BOUND_VAR_LIST, n);
681 api::Term decPart = MK_TERM(api::MINUS, n, MK_TERM(api::TO_INTEGER, n));
682 api::Term expr = MK_TERM(
684 MK_TERM(api::LT, decPart, SOLVER->mkReal(1, 2)),
685 // if decPart < 0.5, round down
686 MK_TERM(api::TO_INTEGER, n),
688 MK_TERM(api::GT, decPart, SOLVER->mkReal(1, 2)),
689 // if decPart > 0.5, round up
690 MK_TERM(api::TO_INTEGER,
691 MK_TERM(api::PLUS, n, SOLVER->mkReal(1))),
692 // if decPart == 0.5, round to nearest even integer:
693 // result is: to_int(n/2 + .5) * 2
695 MK_TERM(api::TO_INTEGER,
697 MK_TERM(api::DIVISION,
700 SOLVER->mkReal(1, 2))),
701 SOLVER->mkInteger(2))));
702 p.d_kind = api::LAMBDA;
703 p.d_expr = MK_TERM(api::LAMBDA, formals, expr);
707 p.d_kind = api::TO_INTEGER;
711 p.d_kind = api::TO_REAL;
715 p.d_kind = api::TO_REAL;
719 //%----Pure CNF should not use $true or $false in problems, and use $false only
720 //%----at the roots of a refutation.
723 : EQUAL_TOK { equal = true; }
724 | DISEQUAL_TOK { equal = false; }
727 term[CVC4::api::Term& expr]
729 | conditionalTerm[expr]
734 letTerm[CVC4::api::Term& expr]
736 CVC4::api::Term lhs, rhs;
738 : '$let_ft' LPAREN_TOK { PARSER_STATE->pushScope(); }
739 tffLetFormulaDefn[lhs, rhs] COMMA_TOK
741 { PARSER_STATE->popScope();
742 expr = expr.substitute(lhs, rhs);
745 | '$let_tt' LPAREN_TOK { PARSER_STATE->pushScope(); }
746 tffLetTermDefn[lhs, rhs] COMMA_TOK
748 { PARSER_STATE->popScope();
749 expr = expr.substitute(lhs, rhs);
754 /* Not an application */
755 simpleTerm[CVC4::api::Term& expr]
757 | NUMBER { expr = PARSER_STATE->d_tmp_expr; }
758 | DISTINCT_OBJECT { expr = PARSER_STATE->convertStrToUnsorted(AntlrInput::tokenText($DISTINCT_OBJECT)); }
761 /* Not an application */
762 thfSimpleTerm[CVC4::api::Term& expr]
763 : NUMBER { expr = PARSER_STATE->d_tmp_expr; }
766 expr = PARSER_STATE->convertStrToUnsorted(
767 AntlrInput::tokenText($DISTINCT_OBJECT));
771 functionTerm[CVC4::api::Term& expr]
773 std::vector<CVC4::api::Term> args;
777 | definedFun[p] LPAREN_TOK arguments[args] RPAREN_TOK
779 expr = PARSER_STATE->applyParseOp(p, args);
783 conditionalTerm[CVC4::api::Term& expr]
785 CVC4::api::Term expr2, expr3;
787 : '$ite_t' LPAREN_TOK tffLogicFormula[expr] COMMA_TOK term[expr2] COMMA_TOK term[expr3] RPAREN_TOK
788 { expr = MK_TERM(api::ITE, expr, expr2, expr3); }
791 plainTerm[CVC4::api::Term& expr]
794 std::vector<api::Term> args;
797 : atomicWord[p.d_name] (LPAREN_TOK arguments[args] RPAREN_TOK)?
799 expr = args.empty() ? PARSER_STATE->parseOpToExpr(p)
800 : PARSER_STATE->applyParseOp(p, args);
804 arguments[std::vector<CVC4::api::Term>& args]
806 CVC4::api::Term expr;
809 term[expr] { args.push_back(expr); } ( COMMA_TOK term[expr] { args.push_back(expr); } )*
812 variable[CVC4::api::Term& expr]
815 std::string name = AntlrInput::tokenText($UPPER_WORD);
816 if(!PARSER_STATE->cnf() || PARSER_STATE->isDeclared(name)) {
817 expr = PARSER_STATE->getVariable(name);
819 expr = PARSER_STATE->bindBoundVar(name, PARSER_STATE->d_unsorted);
820 if(PARSER_STATE->cnf()) PARSER_STATE->addFreeVar(expr);
827 fofFormula[CVC4::api::Term& expr] : fofLogicFormula[expr] ;
829 fofLogicFormula[CVC4::api::Term& expr]
832 std::vector< CVC4::api::Term > args;
833 CVC4::api::Term expr2;
835 : fofUnitaryFormula[expr]
836 ( // Non-associative: <=> <~> ~& ~|
837 ( fofBinaryNonAssoc[na] fofUnitaryFormula[expr2]
840 expr = MK_TERM(api::EQUAL,expr,expr2);
842 case tptp::NA_REVIFF:
843 expr = MK_TERM(api::XOR,expr,expr2);
845 case tptp::NA_IMPLIES:
846 expr = MK_TERM(api::IMPLIES,expr,expr2);
848 case tptp::NA_REVIMPLIES:
849 expr = MK_TERM(api::IMPLIES,expr2,expr);
852 expr = MK_TERM(api::NOT,MK_TERM(api::OR,expr,expr2));
854 case tptp::NA_REVAND:
855 expr = MK_TERM(api::NOT,MK_TERM(api::AND,expr,expr2));
861 ( { args.push_back(expr); }
862 ( AND_TOK fofUnitaryFormula[expr] { args.push_back(expr); } )+
863 { expr = MK_TERM(api::AND, args); }
866 ( { args.push_back(expr); }
867 ( OR_TOK fofUnitaryFormula[expr] { args.push_back(expr); } )+
868 { expr = MK_TERM(api::OR, args); }
873 fofUnitaryFormula[CVC4::api::Term& expr]
876 std::vector< CVC4::api::Term > bv;
878 : atomicFormula[expr]
879 | LPAREN_TOK fofLogicFormula[expr] RPAREN_TOK
880 | NOT_TOK fofUnitaryFormula[expr] { expr = MK_TERM(api::NOT,expr); }
882 folQuantifier[kind] LBRACK_TOK {PARSER_STATE->pushScope();}
883 ( bindvariable[expr] { bv.push_back(expr); }
884 ( COMMA_TOK bindvariable[expr] { bv.push_back(expr); } )* ) RBRACK_TOK
885 COLON_TOK fofUnitaryFormula[expr]
886 { PARSER_STATE->popScope();
887 expr = MK_TERM(kind, MK_TERM(api::BOUND_VAR_LIST, bv), expr);
891 bindvariable[CVC4::api::Term& expr]
893 { std::string name = AntlrInput::tokenText($UPPER_WORD);
894 expr = PARSER_STATE->bindBoundVar(name, PARSER_STATE->d_unsorted);
898 fofBinaryNonAssoc[CVC4::parser::tptp::NonAssoc& na]
899 : IFF_TOK { na = tptp::NA_IFF; }
900 | REVIFF_TOK { na = tptp::NA_REVIFF; }
901 | REVOR_TOK { na = tptp::NA_REVOR; }
902 | REVAND_TOK { na = tptp::NA_REVAND; }
903 | IMPLIES_TOK { na = tptp::NA_IMPLIES; }
904 | REVIMPLIES_TOK { na = tptp::NA_REVIMPLIES; }
907 folQuantifier[CVC4::api::Kind& kind]
908 : FORALL_TOK { kind = api::FORALL; }
909 | EXISTS_TOK { kind = api::EXISTS; }
915 thfQuantifier[CVC4::api::Kind& kind]
916 : FORALL_TOK { kind = api::FORALL; }
917 | EXISTS_TOK { kind = api::EXISTS; }
918 | LAMBDA_TOK { kind = api::LAMBDA; }
921 UNSUPPORTED("Choice operator");
925 UNSUPPORTED("Description quantifier");
927 | (TH1_UN_A | TH1_UN_E)
929 UNSUPPORTED("TH1 operator");
933 thfAtomTyping[CVC4::Command*& cmd]
934 // for now only supports mapping types (i.e. no applied types)
936 CVC4::api::Term expr;
937 CVC4::api::Sort type;
940 : LPAREN_TOK thfAtomTyping[cmd] RPAREN_TOK
941 | nameN[name] COLON_TOK
944 if (PARSER_STATE->isDeclared(name, SYM_SORT))
946 // duplicate declaration is fine, they're compatible
947 cmd = new EmptyCommand("compatible redeclaration of sort " + name);
949 else if (PARSER_STATE->isDeclared(name, SYM_VARIABLE))
951 // error: cannot be both sort and constant
952 PARSER_STATE->parseError(
954 + "' previously declared as a constant; cannot also be a sort");
958 // as yet, it's undeclared
959 api::Sort atype = PARSER_STATE->mkSort(name);
960 cmd = new DeclareSortCommand(name, 0, atype);
965 if (PARSER_STATE->isDeclared(name, SYM_SORT))
967 // error: cannot be both sort and constant
968 PARSER_STATE->parseError("Symbol `" + name
969 + "' previously declared as a sort");
970 cmd = new EmptyCommand("compatible redeclaration of sort " + name);
972 else if (PARSER_STATE->isDeclared(name, SYM_VARIABLE))
974 if (type == PARSER_STATE->getVariable(name).getSort())
976 // duplicate declaration is fine, they're compatible
977 cmd = new EmptyCommand("compatible redeclaration of constant "
982 // error: sorts incompatible
983 PARSER_STATE->parseError(
985 + "' declared previously with a different sort");
990 // as of yet, it's undeclared
991 CVC4::api::Term freshExpr;
992 if (type.isFunction())
994 freshExpr = PARSER_STATE->bindVar(name, type);
998 freshExpr = PARSER_STATE->bindVar(name, type);
1000 cmd = new DeclareFunctionCommand(name, freshExpr, type);
1006 thfLogicFormula[CVC4::ParseOp& p]
1009 std::vector<CVC4::api::Term> args;
1010 std::vector<ParseOp> p_args;
1011 CVC4::api::Term expr2;
1015 //prefix unary formula case
1017 : thfUnitaryFormula[p]
1020 thfUnitaryFormula[p1]
1022 if (p.d_expr.isNull() && !p1.d_expr.isNull())
1024 // make p.d_expr with a lambda of the same type as p1.d_expr
1026 PARSER_STATE->mkLambdaWrapper(p.d_kind, p1.d_expr.getSort());
1028 else if (p1.d_expr.isNull() && !p.d_expr.isNull())
1030 // make p1.d_expr with a lambda of the same type as p.d_expr
1032 PARSER_STATE->mkLambdaWrapper(p1.d_kind, p.d_expr.getSort());
1034 else if (p.d_expr.isNull() && p1.d_expr.isNull())
1036 // Without a reference type it's not possible in general to know what
1037 // the lambda wrapping should be, so we fail in these cases
1038 UNSUPPORTED("Equality between theory functions");
1040 args.push_back(p.d_expr);
1041 args.push_back(p1.d_expr);
1042 p.d_expr = MK_TERM(api::EQUAL, args);
1045 p.d_expr = MK_TERM(api::NOT, p.d_expr);
1048 | // Non-associative: <=> <~> ~& ~|
1049 fofBinaryNonAssoc[na] thfUnitaryFormula[p1]
1051 if (p.d_expr.isNull() || p1.d_expr.isNull())
1053 PARSER_STATE->parseError(
1054 "Non-associative operator must be applied to formulas");
1059 p.d_expr = MK_TERM(api::EQUAL, p.d_expr, p1.d_expr);
1061 case tptp::NA_REVIFF:
1062 p.d_expr = MK_TERM(api::XOR, p.d_expr, p1.d_expr);
1064 case tptp::NA_IMPLIES:
1065 p.d_expr = MK_TERM(api::IMPLIES, p.d_expr, p1.d_expr);
1067 case tptp::NA_REVIMPLIES:
1068 p.d_expr = MK_TERM(api::IMPLIES, p1.d_expr, p.d_expr);
1070 case tptp::NA_REVOR:
1072 MK_TERM(api::NOT, MK_TERM(api::OR, p.d_expr, p1.d_expr));
1074 case tptp::NA_REVAND:
1076 MK_TERM(api::NOT, MK_TERM(api::AND, p.d_expr, p1.d_expr));
1083 if (p.d_expr.isNull())
1085 PARSER_STATE->parseError("AND must be applied to a formula");
1087 args.push_back(p.d_expr);
1090 ( AND_TOK thfUnitaryFormula[p]
1092 if (p.d_expr.isNull())
1094 PARSER_STATE->parseError("AND must be applied to a formula");
1096 args.push_back(p.d_expr);
1101 p.d_expr = MK_TERM(api::AND, args);
1107 if (p.d_expr.isNull())
1109 PARSER_STATE->parseError("OR must be applied to a formula");
1111 args.push_back(p.d_expr);
1114 ( OR_TOK thfUnitaryFormula[p]
1116 if (p.d_expr.isNull())
1118 PARSER_STATE->parseError("OR must be applied to a formula");
1120 args.push_back(p.d_expr);
1125 p.d_expr = MK_TERM(api::OR, args);
1130 // @ (denoting apply) is left-associative and lambda is right-associative.
1131 // ^ [X] : ^ [Y] : f @ g (where f is a <thf_apply_formula> and g is a
1132 // <thf_unitary_formula>) should be parsed as: (^ [X] : (^ [Y] : f)) @ g.
1133 // That is, g is not in the scope of either lambda.
1135 p_args.push_back(p);
1140 thfUnitaryFormula[p]
1142 p_args.push_back(p);
1146 { UNSUPPORTED("Tuple terms"); }
1152 if (p_args[0].d_expr.isNull())
1154 for (unsigned i = 1, size = p_args.size(); i < size; ++i)
1156 if (p_args[i].d_expr.isNull())
1158 PARSER_STATE->parseError(
1159 "Application chains with defined symbol heads and at least "
1160 "one defined symbol as argument are unsupported.");
1162 args.push_back(p_args[i].d_expr);
1164 p.d_expr = PARSER_STATE->applyParseOp(p_args[0], args);
1168 p.d_expr = p_args[0].d_expr;
1169 // check if any argument is a defined function, e.g. "~", and create a
1170 // lambda wrapper then, e.g. (\lambda x. ~ x)
1171 for (unsigned i = 1, size = p_args.size(); i < size; ++i)
1173 if (!p_args[i].d_expr.isNull())
1175 args.push_back(p_args[i].d_expr);
1178 // create a lambda wrapper, e.g. (\lambda x. ~ x).
1180 // The type is determined by the first element of the application
1181 // chain, which must be a function of type t1...tn -> t, so the
1182 // lambda must have type ti
1183 args.push_back(PARSER_STATE->mkLambdaWrapper(
1186 .getFunctionDomainSorts()[i - 1]));
1188 for (unsigned i = 0, size = args.size(); i < size; ++i)
1190 p.d_expr = MK_TERM(api::HO_APPLY, p.d_expr, args[i]);
1197 thfTupleForm[std::vector<CVC4::api::Term>& args]
1201 : thfUnitaryFormula[p]
1203 if (p.d_expr.isNull())
1205 PARSER_STATE->parseError("TUPLE element must be a formula");
1207 args.push_back(p.d_expr);
1209 ( COMMA_TOK thfUnitaryFormula[p]
1211 if (p.d_expr.isNull())
1213 PARSER_STATE->parseError("TUPLE element must be a formula");
1215 args.push_back(p.d_expr);
1220 thfUnitaryFormula[CVC4::ParseOp& p]
1223 std::vector< CVC4::api::Term > bv;
1224 CVC4::api::Term expr;
1228 : variable[p.d_expr]
1229 | thfAtomicFormula[p]
1235 p.d_kind = api::NOT;
1238 thfUnitaryFormula[p1]
1240 if (p1.d_expr.isNull())
1242 PARSER_STATE->parseError("NOT must be applied to a formula");
1244 std::vector<api::Term> args{p1.d_expr};
1245 p.d_expr = PARSER_STATE->applyParseOp(p, args);
1249 thfQuantifier[p.d_kind]
1250 LBRACK_TOK {PARSER_STATE->pushScope();}
1251 thfBindVariable[expr]
1255 ( COMMA_TOK thfBindVariable[expr]
1260 RBRACK_TOK COLON_TOK
1261 thfUnitaryFormula[p1]
1263 if (p1.d_expr.isNull())
1265 PARSER_STATE->parseError("In scope of binder there must be a formula.");
1268 PARSER_STATE->popScope();
1269 // handle lambda case, in which case return type must be flattened and the
1270 // auxiliary variables introduced in the proccess must be added no the
1273 // see documentation of mkFlatFunctionType for how it's done
1275 // flatten body via flattening its type
1276 std::vector<api::Sort> sorts;
1277 std::vector<api::Term> flattenVars;
1278 PARSER_STATE->mkFlatFunctionType(sorts, expr.getSort(), flattenVars);
1279 if (!flattenVars.empty())
1281 // apply body of lambda to flatten vars
1282 expr = PARSER_STATE->mkHoApply(expr, flattenVars);
1283 // add variables to BOUND_VAR_LIST
1284 bv.insert(bv.end(), flattenVars.begin(), flattenVars.end());
1286 p.d_expr = MK_TERM(p.d_kind, MK_TERM(api::BOUND_VAR_LIST, bv), expr);
1292 tffFormula[CVC4::api::Term& expr] : tffLogicFormula[expr];
1294 tffTypedAtom[CVC4::Command*& cmd]
1296 CVC4::api::Term expr;
1297 CVC4::api::Sort type;
1300 : LPAREN_TOK tffTypedAtom[cmd] RPAREN_TOK
1301 | nameN[name] COLON_TOK
1303 { if(PARSER_STATE->isDeclared(name, SYM_SORT)) {
1304 // duplicate declaration is fine, they're compatible
1305 cmd = new EmptyCommand("compatible redeclaration of sort " + name);
1306 } else if(PARSER_STATE->isDeclared(name, SYM_VARIABLE)) {
1307 // error: cannot be both sort and constant
1308 PARSER_STATE->parseError("Symbol `" + name + "' previously declared as a constant; cannot also be a sort");
1310 // as yet, it's undeclared
1311 api::Sort atype = PARSER_STATE->mkSort(name);
1312 cmd = new DeclareSortCommand(name, 0, atype);
1316 { if(PARSER_STATE->isDeclared(name, SYM_SORT)) {
1317 // error: cannot be both sort and constant
1318 PARSER_STATE->parseError("Symbol `" + name + "' previously declared as a sort");
1319 cmd = new EmptyCommand("compatible redeclaration of sort " + name);
1320 } else if(PARSER_STATE->isDeclared(name, SYM_VARIABLE)) {
1321 if(type == PARSER_STATE->getVariable(name).getSort()) {
1322 // duplicate declaration is fine, they're compatible
1323 cmd = new EmptyCommand("compatible redeclaration of constant " + name);
1325 // error: sorts incompatible
1326 PARSER_STATE->parseError("Symbol `" + name + "' declared previously with a different sort");
1329 // as yet, it's undeclared
1330 CVC4::api::Term aexpr = PARSER_STATE->bindVar(name, type);
1331 cmd = new DeclareFunctionCommand(name, aexpr, type);
1337 tffLogicFormula[CVC4::api::Term& expr]
1340 std::vector< CVC4::api::Term > args;
1341 CVC4::api::Term expr2;
1343 : tffUnitaryFormula[expr]
1344 ( // Non Assoc <=> <~> ~& ~|
1345 ( fofBinaryNonAssoc[na] tffUnitaryFormula[expr2]
1348 expr = MK_TERM(api::EQUAL,expr,expr2);
1350 case tptp::NA_REVIFF:
1351 expr = MK_TERM(api::XOR,expr,expr2);
1353 case tptp::NA_IMPLIES:
1354 expr = MK_TERM(api::IMPLIES,expr,expr2);
1356 case tptp::NA_REVIMPLIES:
1357 expr = MK_TERM(api::IMPLIES,expr2,expr);
1359 case tptp::NA_REVOR:
1360 expr = MK_TERM(api::NOT,MK_TERM(api::OR,expr,expr2));
1362 case tptp::NA_REVAND:
1363 expr = MK_TERM(api::NOT,MK_TERM(api::AND,expr,expr2));
1369 ( { args.push_back(expr); }
1370 ( AND_TOK tffUnitaryFormula[expr] { args.push_back(expr); } )+
1371 { expr = MK_TERM(api::AND,args); }
1374 ( { args.push_back(expr); }
1375 ( OR_TOK tffUnitaryFormula[expr] { args.push_back(expr); } )+
1376 { expr = MK_TERM(api::OR,args); }
1381 tffUnitaryFormula[CVC4::api::Term& expr]
1384 std::vector< CVC4::api::Term > bv;
1385 CVC4::api::Term lhs, rhs;
1387 : atomicFormula[expr]
1388 | LPAREN_TOK tffLogicFormula[expr] RPAREN_TOK
1389 | NOT_TOK tffUnitaryFormula[expr] { expr = MK_TERM(api::NOT,expr); }
1391 folQuantifier[kind] LBRACK_TOK {PARSER_STATE->pushScope();}
1392 ( tffbindvariable[expr] { bv.push_back(expr); }
1393 ( COMMA_TOK tffbindvariable[expr] { bv.push_back(expr); } )* ) RBRACK_TOK
1394 COLON_TOK tffUnitaryFormula[expr]
1395 { PARSER_STATE->popScope();
1396 expr = MK_TERM(kind, MK_TERM(api::BOUND_VAR_LIST, bv), expr);
1398 | '$ite_f' LPAREN_TOK tffLogicFormula[expr] COMMA_TOK tffLogicFormula[lhs] COMMA_TOK tffLogicFormula[rhs] RPAREN_TOK
1399 { expr = MK_TERM(api::ITE, expr, lhs, rhs); }
1400 | '$let_tf' LPAREN_TOK { PARSER_STATE->pushScope(); }
1401 tffLetTermDefn[lhs, rhs] COMMA_TOK
1403 { PARSER_STATE->popScope();
1404 expr = expr.substitute(lhs, rhs);
1407 | '$let_ff' LPAREN_TOK { PARSER_STATE->pushScope(); }
1408 tffLetFormulaDefn[lhs, rhs] COMMA_TOK
1410 { PARSER_STATE->popScope();
1411 expr = expr.substitute(lhs, rhs);
1416 tffLetTermDefn[CVC4::api::Term& lhs, CVC4::api::Term& rhs]
1418 std::vector<CVC4::api::Term> bvlist;
1420 : (FORALL_TOK LBRACK_TOK tffVariableList[bvlist] RBRACK_TOK COLON_TOK)*
1421 tffLetTermBinding[bvlist, lhs, rhs]
1424 tffLetTermBinding[std::vector<CVC4::api::Term> & bvlist,
1425 CVC4::api::Term& lhs,
1426 CVC4::api::Term& rhs]
1427 : term[lhs] EQUAL_TOK term[rhs]
1429 PARSER_STATE->checkLetBinding(bvlist, lhs, rhs, false);
1430 std::vector<api::Term> lchildren(++lhs.begin(), lhs.end());
1431 rhs = MK_TERM(api::LAMBDA, MK_TERM(api::BOUND_VAR_LIST, lchildren), rhs);
1432 // since lhs is always APPLY_UF (otherwise we'd have had a parser error in
1433 // checkLetBinding) the function to be replaced is always the first
1434 // argument. Note that the way in which lchildren is built above is also
1438 | LPAREN_TOK tffLetTermBinding[bvlist, lhs, rhs] RPAREN_TOK
1441 tffLetFormulaDefn[CVC4::api::Term& lhs, CVC4::api::Term& rhs]
1443 std::vector<CVC4::api::Term> bvlist;
1445 : (FORALL_TOK LBRACK_TOK tffVariableList[bvlist] RBRACK_TOK COLON_TOK)*
1446 tffLetFormulaBinding[bvlist, lhs, rhs]
1449 tffLetFormulaBinding[std::vector<CVC4::api::Term> & bvlist,
1450 CVC4::api::Term& lhs,
1451 CVC4::api::Term& rhs]
1453 : atomicFormula[lhs] IFF_TOK tffUnitaryFormula[rhs]
1455 PARSER_STATE->checkLetBinding(bvlist, lhs, rhs, true);
1456 std::vector<api::Term> lchildren(++lhs.begin(), lhs.end());
1457 rhs = MK_TERM(api::LAMBDA, MK_TERM(api::BOUND_VAR_LIST, lchildren), rhs);
1458 // since lhs is always APPLY_UF (otherwise we'd have had a parser error in
1459 // checkLetBinding) the function to be replaced is always the first
1460 // argument. Note that the way in which lchildren is built above is also
1464 | LPAREN_TOK tffLetFormulaBinding[bvlist, lhs, rhs] RPAREN_TOK
1467 thfBindVariable[CVC4::api::Term& expr]
1470 CVC4::api::Sort type = PARSER_STATE->d_unsorted;
1473 { name = AntlrInput::tokenText($UPPER_WORD); }
1474 ( COLON_TOK parseThfType[type] )?
1476 expr = PARSER_STATE->bindBoundVar(name, type);
1481 tffbindvariable[CVC4::api::Term& expr]
1483 CVC4::api::Sort type = PARSER_STATE->d_unsorted;
1486 ( COLON_TOK parseType[type] )?
1487 { std::string name = AntlrInput::tokenText($UPPER_WORD);
1488 expr = PARSER_STATE->bindBoundVar(name, type);
1492 // bvlist is accumulative; it can already contain elements
1493 // on the way in, which are left undisturbed
1494 tffVariableList[std::vector<CVC4::api::Term>& bvlist]
1498 : tffbindvariable[e] { bvlist.push_back(e); }
1499 ( COMMA_TOK tffbindvariable[e] { bvlist.push_back(e); } )*
1502 parseThfType[CVC4::api::Sort& type]
1503 // assumes only mapping types (arrows), no tuple type
1505 std::vector<CVC4::api::Sort> sorts;
1507 : thfType[type] { sorts.push_back(type); }
1509 (ARROW_TOK | TIMES_TOK) thfType[type] { sorts.push_back(type); }
1512 if (sorts.size() < 1)
1518 api::Sort range = sorts.back();
1520 type = PARSER_STATE->mkFlatFunctionType(sorts, range);
1525 thfType[CVC4::api::Sort& type]
1526 // assumes only mapping types (arrows), no tuple type
1528 | LPAREN_TOK parseThfType[type] RPAREN_TOK
1529 | LBRACK_TOK { UNSUPPORTED("Tuple types"); } parseThfType[type] RBRACK_TOK
1532 parseType[CVC4::api::Sort & type]
1535 std::vector<CVC4::api::Sort> v;
1538 | ( simpleType[type] { v.push_back(type); }
1539 | LPAREN_TOK simpleType[type] { v.push_back(type); }
1540 ( TIMES_TOK simpleType[type] { v.push_back(type); } )+
1543 ARROW_TOK simpleType[type]
1544 { type = SOLVER->mkFunctionSort(v,type);
1548 // non-function types
1549 simpleType[CVC4::api::Sort& type]
1554 { std::string s = AntlrInput::tokenText($DEFINED_SYMBOL);
1555 if(s == "\$i") type = PARSER_STATE->d_unsorted;
1556 else if(s == "\$o") type = SOLVER->getBooleanSort();
1557 else if(s == "\$int") type = SOLVER->getIntegerSort();
1558 else if(s == "\$rat") type = SOLVER->getRealSort();
1559 else if(s == "\$real") type = SOLVER->getRealSort();
1560 else if(s == "\$tType") PARSER_STATE->parseError("Type of types `\$tType' cannot be used here");
1561 else PARSER_STATE->parseError("unknown defined type `" + s + "'");
1564 { type = PARSER_STATE->getSort(name); }
1567 /***********************************************/
1568 /* Anything well parenthesis */
1571 : LPAREN_TOK anything* RPAREN_TOK
1572 | LBRACK_TOK anything* RBRACK_TOK
1603 | LOWER_WORD_SINGLE_QUOTED
1630 DEF_DESC_TOK : '@-';
1634 REVIMPLIES_TOK : '<=';
1648 FALSE_TOK : '$false';
1650 DISEQUAL_TOK : '!=';
1658 INCLUDE_TOK : 'include';
1660 //Other defined symbols, must be defined after all the other
1661 DEFINED_SYMBOL : '$' LOWER_WORD;
1667 * Matches and skips whitespace in the input.
1671 : (' ' | '\t' | '\f' | '\r' | '\n')+ { SKIP(); }
1676 * Matches a double or single quoted string literal. Escaping is supported, and
1677 * escape character '\' has to be escaped.
1679 DISTINCT_OBJECT : '"' (DO_CHAR)* '"' ;
1680 fragment DO_CHAR : ' '..'!'| '#'..'[' | ']'..'~' | '\\"' | '\\\\';
1682 //The order of this two rules is important
1683 LOWER_WORD_SINGLE_QUOTED : '\'' LOWER_WORD '\'' ;
1684 SINGLE_QUOTED : '\'' (SQ_CHAR)* '\'' ;
1686 fragment SQ_CHAR : ' '..'&' | '('..'[' | ']'..'~' | '\\\'' | '\\\\';
1688 /* Define upper (variable) and lower (everything else) word */
1689 fragment NUMERIC : '0'..'9';
1690 fragment LOWER_ALPHA : 'a'..'z';
1691 fragment UPPER_ALPHA : 'A'..'Z';
1692 fragment ALPHA_NUMERIC : LOWER_ALPHA | UPPER_ALPHA | NUMERIC | '_';
1693 UPPER_WORD : UPPER_ALPHA ALPHA_NUMERIC*;
1694 LOWER_WORD : LOWER_ALPHA ALPHA_NUMERIC*;
1697 unquotedFileName[std::string& name] /* Beware fileName identifier is used by the backend ... */
1698 : (s=LOWER_WORD_SINGLE_QUOTED | s=SINGLE_QUOTED)
1699 { name = AntlrInput::tokenText($s);
1700 name = name.substr(1, name.size() - 2 );
1704 nameN[std::string& name]
1706 | NUMBER { name = AntlrInput::tokenText($NUMBER); }
1709 /* atomic word everything (fof, cnf, thf, tff, include must not be keyword at this position ) */
1710 atomicWord[std::string& name]
1711 : FOF_TOK { name = "fof"; }
1712 | CNF_TOK { name = "cnf"; }
1713 | THF_TOK { name = "thf"; }
1714 | TFF_TOK { name = "tff"; }
1715 | TYPE_TOK { name = "type"; }
1716 | INCLUDE_TOK { name = "include"; }
1717 | LOWER_WORD { name = AntlrInput::tokenText($LOWER_WORD); }
1718 | LOWER_WORD_SINGLE_QUOTED // the lower word single quoted are considered without quote
1719 { /* strip off the quotes */
1720 name = AntlrInput::tokenTextSubstr($LOWER_WORD_SINGLE_QUOTED, 1 ,
1721 ($LOWER_WORD_SINGLE_QUOTED->stop - $LOWER_WORD_SINGLE_QUOTED->start) - 1);
1723 | SINGLE_QUOTED {name = AntlrInput::tokenText($SINGLE_QUOTED); }; //for the others the quote remains
1725 /** I don't understand how is made the difference between rational and real in SyntaxBNF. So I put all in rational */
1729 fragment EXPONENT : 'E' | 'e';
1730 fragment SLASH : '/';
1732 fragment DECIMAL : NUMERIC+;
1734 /* Currently we put all in the rational type */
1735 fragment SIGN[bool& pos]
1736 : PLUS_TOK { pos = true; }
1737 | MINUS_TOK { pos = false; }
1745 : ( SIGN[pos]? num=DECIMAL
1746 { std::stringstream ss;
1747 ss << ( pos ? "" : "-" ) << AntlrInput::tokenText($num);
1748 std::string str = ss.str();
1749 if (str.find(".") == std::string::npos)
1751 PARSER_STATE->d_tmp_expr = SOLVER->mkInteger(str);
1755 PARSER_STATE->d_tmp_expr = SOLVER->mkReal(str);
1758 | SIGN[pos]? num=DECIMAL DOT den=DECIMAL (EXPONENT SIGN[posE]? e=DECIMAL)?
1760 std::string snum = AntlrInput::tokenText($num);
1761 std::string sden = AntlrInput::tokenText($den);
1762 size_t exp = ($e == NULL ? 0 : AntlrInput::tokenToUnsigned($e));
1763 PARSER_STATE->d_tmp_expr = PARSER_STATE->mkDecimal(snum, sden, pos, exp, posE);
1765 | SIGN[pos]? num=DECIMAL SLASH den=DECIMAL
1766 { std::stringstream ss;
1767 ss << AntlrInput::tokenText($num) << "/" << AntlrInput::tokenText($den);
1768 PARSER_STATE->d_tmp_expr = SOLVER->mkReal(ss.str());
1771 { if(PARSER_STATE->cnf() || PARSER_STATE->fof()) {
1772 // We're in an unsorted context, so put a conversion around it
1773 PARSER_STATE->d_tmp_expr = PARSER_STATE->convertRatToUnsorted( PARSER_STATE->d_tmp_expr );
1779 * Matches the comments and ignores them
1782 : '%' (~('\n' | '\r'))* { SKIP(); } //comment line
1783 | '/*' ( options {greedy=false;} : . )* '*/' { SKIP(); } //comment block