SMTStabilizer API
Public API documentation for SMTStabilizer
Loading...
Searching...
No Matches
expr_parser.cpp
Go to the documentation of this file.
1/* -*- Source -*-
2 *
3 * An SMT/OMT Parser (Expression part)
4 *
5 * Author: Fuqi Jia <jiafq@ios.ac.cn>
6 *
7 * Copyright (C) 2025 Fuqi Jia
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27
28// Modified by Xiang Zhang, 2026
29// Additional changes licensed under the MIT License
30#include <memory>
31#include <stack>
32#include <vector>
33
34#include "parser.h"
35#include "parser/dag.h"
36#include "parser/sort.h"
37
38namespace stabilizer::parser {
39
40// State of the parser
41enum class FrameState {
42 Start,
43 ReadingHead, // reading head symbol
44 ProcessingSpecial, // processing special syntax
45 ProcessingParams, // processing parameter list
46 ProcessingBindings, // processing let bindings
47 ProcessingLetBody, // processing let body
48 ProcessingQuantVars, // processing quantifier variables
49 ProcessingQuantBody, // processing quantifier body
50 ProcessingParamFuncArgs, // processing parameter function arguments
51 ProcessingParamFuncParams, // processing parameter function parameters
52 Finish
53};
54
55// special processing type
56enum class SpecialType { None,
57 Let,
58 Exists,
59 Forall,
61 BV,
62 Underscore };
63
64// Frame of the parser
65struct ExprFrame {
68 std::string headSymbol; // head symbol
69 std::string second_symbol; // f of "(_ f …)"
70 std::vector<std::shared_ptr<DAGNode>> func_args; // function arguments
71 std::vector<std::shared_ptr<DAGNode>> oper_params; // operator parameters
72 int line = 0; // line number
73 std::shared_ptr<DAGNode> result; // result
74
76 // pre-allocate container space, reduce dynamic expansion overhead
77 // according to common expressions, most operators have 2-4 args and a lot
78 // of params
79 func_args.reserve(4);
80 oper_params.reserve(64);
81 }
82};
83
84// expr ::= const | func | (<identifier> <expr>+)
85std::shared_ptr<DAGNode> Parser::parseExpr() {
86 std::stack<ExprFrame> st;
87 st.push(ExprFrame());
88
89 while (!st.empty()) {
90 ExprFrame &frame = st.top();
91 switch (frame.state) {
92 case FrameState::Start: {
93 // handle the simplest symbol or constant
94 if (*bufptr != '(') {
95 size_t ln = line_number;
96 std::string sym = getSymbol();
97 auto node = parseConstFunc(sym);
98 if (node->isErr())
99 err_unkwn_sym(sym, ln);
100 frame.result = node;
102 break;
103 }
104
105 // complex expression
106 parseLpar();
107 frame.line = line_number;
108
109 // check ((_ f args) ...) or ((as const T) value)
110 if (*bufptr == '(') {
111 parseLpar();
112 std::string s = getSymbol();
113 if (s == "_") {
115 frame.second_symbol = getSymbol();
117 break;
118 }
119 else if (s == "as") {
120 // Handle ((as const T) value) pattern
121 std::string second = getSymbol();
122 if (second == "const") {
123 // Parse array sort
124 std::shared_ptr<Sort> array_sort = parseSort();
125 parseRpar(); // close (as const T)
126
127 // Parse value
128 std::shared_ptr<DAGNode> value = parseExpr();
129
130 // Create constant array
131 frame.result = mkConstArray(array_sort, value);
132 parseRpar(); // close outer parentheses
134 break;
135 }
136 else {
137 err_unkwn_sym("as " + second, frame.line);
140 break;
141 }
142 }
143 else if (s == "root-obj") {
144 // (root-obj (+ (^ x 2) (- 3)) 1)
145 // (root-obj <expr> <index>)
146 // Enable placeholder variables for polynomial expressions
147 bool old_allow_placeholder = allow_placeholder_vars;
148 std::shared_ptr<Sort> old_placeholder_sort = placeholder_var_sort;
151 SortManager::REAL_SORT; // Default to Real sort for polynomials
152
153 std::shared_ptr<DAGNode> expr = parseExpr();
154 std::string index_str = getSymbol();
155 parseRpar(); // close (root-obj ...)
156
157 // Restore original settings
158 allow_placeholder_vars = old_allow_placeholder;
159 placeholder_var_sort = old_placeholder_sort;
160
161 // Parse index as integer
162 int index = std::stoi(index_str);
163
164 // Create root-obj node
165 frame.result = mkRootObj(expr, index);
167 break;
168 }
169 else if (s == "root-of-with-interval") {
170 // ((root-of-with-interval (coeffs 1 (- 2)) 1 2))
171 // Parse (coeffs ...) as a whole
172 parseLpar(); // for (coeffs ...)
173 std::string coeffs_tag = getSymbol(); // read "coeffs"
174 // We don't validate coeffs_tag, just skip it
175
176 // Parse coefficients
177 std::vector<std::shared_ptr<DAGNode>> coeffs_list;
178 scanToNextSymbol(); // Skip whitespace before checking for ')'
179 while (*bufptr != ')') {
180 std::shared_ptr<DAGNode> coeff = parseExpr();
181 coeffs_list.push_back(coeff);
182 scanToNextSymbol(); // Skip whitespace before checking for ')' again
183 }
184 parseRpar(); // close (coeffs ...)
185
186 // Parse lower bound
187 std::shared_ptr<DAGNode> lower_bound = parseExpr();
188
189 // Parse upper bound
190 std::shared_ptr<DAGNode> upper_bound = parseExpr();
191
192 parseRpar(); // close (root-of-with-interval ...)
193
194 // Create root-of-with-interval node
195 frame.result =
196 mkRootOfWithInterval(coeffs_list, lower_bound, upper_bound);
198 break;
199 }
200 else {
201 err_unkwn_sym(s, frame.line);
204 break;
205 }
206 }
207
208 // read the head symbol
209 std::string head = getSymbol();
210 // std::cout << head << std::endl;
211 frame.headSymbol = head;
212
213 if (head == "exists" || head == "forall") {
214 in_quantifier_scope = true;
216 auto res = parseQuant(head);
217 parseRpar();
218 frame.result = res;
221 if (quant_nesting_depth == 0) {
222 in_quantifier_scope = false;
223 }
224 }
225 else if (head == "_") {
226 std::string second = getSymbol();
227 if (second.size() >= 2 && second[0] == 'b' && second[1] == 'v') {
228 std::string width_str = getSymbol();
229 size_t width = 0;
230 try {
231 width = std::stoul(width_str);
232 }
233 catch (...) {
234 width = 0;
235 }
236 std::string num = second.substr(2);
237 frame.result = mkConstBv(num, width);
238 parseRpar();
240 }
241 // Handle floating point special constants: (_ +zero eb sb), (_ -zero eb
242 // sb), (_ +oo eb sb), (_ -oo eb sb), (_ NaN eb sb)
243 else if (second == "+zero" || second == "-zero" || second == "+oo" ||
244 second == "-oo" || second == "NaN" || second == "+NaN" ||
245 second == "-NaN") {
246 std::string eb_str = getSymbol();
247 std::string sb_str = getSymbol();
248 size_t eb = 0;
249 size_t sb = 0;
250 try {
251 eb = std::stoul(eb_str);
252 }
253 catch (...) {
254 eb = 0;
255 }
256 try {
257 sb = std::stoul(sb_str);
258 }
259 catch (...) {
260 sb = 0;
261 }
262
263 std::shared_ptr<Sort> fp_sort = sort_manager->createFPSort(eb, sb);
264
265 // Use the appropriate mk* function which will create nodes with full
266 // names
267 if (second == "NaN" || second == "+NaN" || second == "-NaN") {
268 frame.result = mkNaN(fp_sort);
269 }
270 else if (second == "+oo") {
271 frame.result = mkPosInfinity(fp_sort);
272 }
273 else if (second == "-oo") {
274 frame.result = mkNegInfinity(fp_sort);
275 }
276 else {
277 // For +zero and -zero, create as NT_CONST with full name
278 std::string const_name =
279 "(_ " + second + " " + eb_str + " " + sb_str + ")";
280 frame.result = node_manager->createNode(
281 fp_sort, NODE_KIND::NT_CONST, const_name);
282 }
283
284 parseRpar();
286 }
287 else {
288 frame.second_symbol = second;
290 }
291 }
292 // Handle floating point bit representation: (fp sign exp mant)
293 else if (head == "fp") {
294 // Parse (fp sign exp mant) where sign, exp, mant are bit vectors
295 std::vector<std::shared_ptr<DAGNode>> fp_args;
296
297 // Parse sign bit
298 std::shared_ptr<DAGNode> sign = parseExpr();
299 fp_args.push_back(sign);
300
301 // Parse exponent
302 std::shared_ptr<DAGNode> exp = parseExpr();
303 fp_args.push_back(exp);
304
305 // Parse mantissa
306 std::shared_ptr<DAGNode> mant = parseExpr();
307 fp_args.push_back(mant);
308
309 // Create fp constant using the new mkFpConst function
310 frame.result = mkFpConst(sign, exp, mant);
311 parseRpar();
313 }
314 else if (head == "let") {
315 if (let_nesting_depth == 0) {
318 }
321 }
323
324 std::shared_ptr<DAGNode> res;
325 if (options->parsing_preserve_let) {
326 res = parsePreservingLet();
327 }
328 else {
329 res = parseLet();
330 }
331
333 if (let_nesting_depth == 0) {
335 }
336
337 if (res->isErr())
338 err_all(res, "let", frame.line);
339 parseRpar();
340 frame.result = res;
342 }
343 else if (head == "!") {
344 std::shared_ptr<DAGNode> formula = parseExpr();
345 // Consume possible multiple attributes after "!" such as :named and
346 // :pattern
347 std::vector<std::shared_ptr<DAGNode>> attributes;
348 while (true) {
350 if (key == KEYWORD::KW_NULL)
351 break;
352
353 if (key == KEYWORD::KW_NAMED) {
354 std::string name = getSymbol();
355 // Store the named formula for unsat core functionality
356 named_assertions[name] = formula;
357 }
358 else if (key == KEYWORD::KW_PATTERN) {
359 // :pattern ((p1 ...) (p2 ...) ...)
360 // Robustly skip the entire pattern payload without fully parsing
361 // terms, since patterns are meta-information that don't affect
362 // satisfiability. This avoids mis-parsing nested lists like
363 // ((select ...)) as "(( ...))" expressions.
364
365 // Consume outer pattern list
366 parseLpar();
368
369 std::vector<std::shared_ptr<DAGNode>> patterns;
370 while (*bufptr != ')') {
371 // Each alternative is typically a parenthesized list of terms
372 if (*bufptr == '(') {
373 // Consume inner list
374 // parseLpar();
375 // Skip to its matching ')', tolerating nested parentheses
376 // inside terms skipToRpar();
377 auto node = parseExpr();
378 patterns.push_back(node);
379 // std::cout << dumpSMTLIB2(node) << std::endl;
380 // parseRpar();
381 }
382 else {
383 // Tolerate a stray symbol term (non-standard but be permissive)
384 (void)getSymbol();
385 }
387 }
388 // Close outer list
389 parseRpar();
390
391 // Optionally, we could record patterns later; currently they are
392 // unused.
393 attributes.emplace_back(
394 mkPattern(SortManager::getNull(), ":pattern", patterns));
395 }
396 else if (key == KEYWORD::KW_NO_PATTERN) {
397 std::shared_ptr<DAGNode> pattern = parseExpr();
398
399 // Optionally, we could record patterns later; currently they are
400 // unused.
401 attributes.emplace_back(
402 mkNoPattern(SortManager::getNull(), ":no-pattern", pattern));
403 }
404 else if (key == KEYWORD::KW_WEIGHT) {
405 std::shared_ptr<DAGNode> weight = parseExpr();
406 attributes.emplace_back(
407 mkWeight(SortManager::getNull(), ":weight", weight));
408 }
409 else if (key == KEYWORD::KW_QID) {
410 std::string qid = getSymbol();
411
412 // [TODO] now ignore qid value
413 }
414 else if (key == KEYWORD::KW_SKOLEMID) {
415 std::string skolemid = getSymbol();
416
417 // [TODO] now ignore skolemid value
418 }
419 else if (key == KEYWORD::KW_LBLPOS) {
420 std::string lblpos = getSymbol();
421
422 // [TODO] now ignore lblpos value
423 }
424 else if (key == KEYWORD::KW_LBLNEG) {
425 std::string lblneg = getSymbol();
426
427 // [TODO] now ignore lblneg value
428 }
429 else {
430 // Unknown or unhandled attribute: try to consume its value(s)
431 // generically. Attribute values can be symbols or nested S-exprs.
432 // Use parseExpr when possible.
434 if (*bufptr == '(') {
435 // consume the s-expression value
436 (void)parseExpr();
437 }
438 else {
439 // consume a single symbol/value
440 // getSymbol will advance bufptr appropriately
441 try {
442 std::string dummy = getSymbol();
443 (void)dummy;
444 }
445 catch (...) {
446 // if getSymbol fails, break to avoid infinite loop
447 break;
448 }
449 }
450 }
451 }
452 if (!attributes.empty()) {
453 attributes.insert(attributes.begin(), formula);
454 formula = mkAttribute(formula->getSort(), "!", attributes);
455 }
456 frame.result = formula;
457 parseRpar();
459 }
460 else if (head == "root-of-with-interval") {
461 // (root-of-with-interval (coeffs 1 (- 2)) 1 2)
462 // Parse (coeffs ...) as a whole
463 parseLpar(); // for (coeffs ...)
464 std::string coeffs_tag = getSymbol(); // read "coeffs"
465 // We don't validate coeffs_tag, just skip it
466
467 // Parse coefficients
468 std::vector<std::shared_ptr<DAGNode>> coeffs_list;
469 scanToNextSymbol(); // Skip whitespace before checking for ')'
470 while (*bufptr != ')') {
471 std::shared_ptr<DAGNode> coeff = parseExpr();
472 coeffs_list.push_back(coeff);
473 scanToNextSymbol(); // Skip whitespace before checking for ')' again
474 }
475 parseRpar(); // close (coeffs ...)
476
477 // Parse lower bound
478 std::shared_ptr<DAGNode> lower_bound = parseExpr();
479
480 // Parse upper bound
481 std::shared_ptr<DAGNode> upper_bound = parseExpr();
482
483 parseRpar(); // close (root-of-with-interval ...)
484
485 // Create root-of-with-interval node
486 frame.result =
487 mkRootOfWithInterval(coeffs_list, lower_bound, upper_bound);
489 }
490
491 else {
493 }
494 break;
495 }
496
498 // Special handling for root-obj and root-of-with-interval: enable
499 // placeholder variables
500 bool old_allow_placeholder = allow_placeholder_vars;
501 std::shared_ptr<Sort> old_placeholder_sort = placeholder_var_sort;
502 const std::string &opName =
503 (frame.headSymbol == "_") ? frame.second_symbol : frame.headSymbol;
504 if (opName == "root-obj" || opName == "root-of-with-interval") {
507 }
508
509 // escape the space and comment
511 if (*bufptr == ')') {
512 parseRpar();
513 std::shared_ptr<DAGNode> res;
514
515 // inline the most common operators, avoid parseOper overhead
516 const std::string &opName =
517 (frame.headSymbol == "_") ? frame.second_symbol : frame.headSymbol;
518
519 // fast path: directly handle high frequency operators
520 if (opName == "=") {
521 res = mkEq(frame.oper_params);
522 }
523 else if (opName == "and") {
524 res = mkAnd(frame.oper_params);
525 }
526 else if (opName == "=>") {
527 res = mkImplies(frame.oper_params);
528 }
529 else if (opName == "or") {
530 res = mkOr(frame.oper_params);
531 }
532 else if (opName == "not") {
533 condAssert(frame.oper_params.size() == 1,
534 "Invalid number of parameters for not");
535 res = mkNot(frame.oper_params[0]);
536 }
537 else if (opName == "ite") {
538 condAssert(frame.oper_params.size() == 3,
539 "Invalid number of parameters for ite");
540 res = mkIte(frame.oper_params);
541 }
542 else if (opName == "distinct") {
543 res = mkDistinct(frame.oper_params);
544 }
545 else if (opName == "+") {
546 res = mkAdd(frame.oper_params);
547 }
548 else if (opName == "-") {
549 res = mkSub(frame.oper_params);
550 }
551 else if (opName == "*") {
552 res = mkMul(frame.oper_params);
553 }
554 else if (opName == "<=") {
555 // condAssert(frame.oper_params.size() == 2, "Invalid number of
556 // parameters for <=");
557 res = mkLe(frame.oper_params);
558 }
559 else if (opName == "<") {
560 // condAssert(frame.oper_params.size() == 2, "Invalid number of
561 // parameters for <");
562 res = mkLt(frame.oper_params);
563 }
564 else if (opName == ">=") {
565 // condAssert(frame.oper_params.size() == 2, "Invalid number of
566 // parameters for >=");
567 res = mkGe(frame.oper_params);
568 }
569 else if (opName == ">") {
570 // condAssert(frame.oper_params.size() == 2, "Invalid number of
571 // parameters for >");
572 res = mkGt(frame.oper_params);
573 }
574 else if (opName == "bvult") {
575 condAssert(frame.oper_params.size() == 2,
576 "Invalid number of parameters for bvult");
577 res = mkBvUlt(frame.oper_params[0], frame.oper_params[1]);
578 }
579 else if (opName == "bvugt") {
580 condAssert(frame.oper_params.size() == 2,
581 "Invalid number of parameters for bvugt");
582 res = mkBvUgt(frame.oper_params[0], frame.oper_params[1]);
583 }
584 else if (opName == "bvule") {
585 condAssert(frame.oper_params.size() == 2,
586 "Invalid number of parameters for bvule");
587 res = mkBvUle(frame.oper_params[0], frame.oper_params[1]);
588 }
589 else if (opName == "bvuge") {
590 condAssert(frame.oper_params.size() == 2,
591 "Invalid number of parameters for bvuge");
592 res = mkBvUge(frame.oper_params[0], frame.oper_params[1]);
593 }
594 else if (opName == "bvsgt") {
595 condAssert(frame.oper_params.size() == 2,
596 "Invalid number of parameters for bvsgt");
597 res = mkBvSgt(frame.oper_params[0], frame.oper_params[1]);
598 }
599 else if (opName == "bvsle") {
600 condAssert(frame.oper_params.size() == 2,
601 "Invalid number of parameters for bvsle");
602 res = mkBvSle(frame.oper_params[0], frame.oper_params[1]);
603 }
604 else if (opName == "bvslt") {
605 condAssert(frame.oper_params.size() == 2,
606 "Invalid number of parameters for bvslt");
607 res = mkBvSlt(frame.oper_params[0], frame.oper_params[1]);
608 }
609 else if (opName == "bvsge") {
610 condAssert(frame.oper_params.size() == 2,
611 "Invalid number of parameters for bvsge");
612 res = mkBvSge(frame.oper_params[0], frame.oper_params[1]);
613 }
614 else {
615 // slow path: call parseOper
616 res = parseOper(opName, frame.func_args, frame.oper_params);
617 }
618
619 if (res->isErr())
620 err_all(res, frame.headSymbol, frame.line);
621 frame.result = res;
623
624 // Restore placeholder settings
625 if (opName == "root-obj" || opName == "root-of-with-interval") {
626 allow_placeholder_vars = old_allow_placeholder;
627 placeholder_var_sort = old_placeholder_sort;
628 }
629 break;
630 }
631 st.push(ExprFrame());
632 break;
633 }
634
636 // escape the space and comment
638 if (*bufptr == ')') {
639 parseRpar();
641 break;
642 }
643 st.push(ExprFrame());
644 break;
645 }
646
648 // escape the space and comment
650 if (*bufptr == ')') {
651 parseRpar();
652 std::shared_ptr<DAGNode> res;
653
654 // inline the most common operators
655 const std::string &opName = frame.second_symbol;
656
657 res = parseOper(opName, frame.func_args, frame.oper_params);
658
659 if (res->isErr())
660 err_all(res, frame.second_symbol, frame.line);
661 frame.result = res;
663 break;
664 }
665 st.push(ExprFrame());
666 break;
667 }
668
669 case FrameState::Finish: {
670 auto res = frame.result;
671 st.pop();
672 if (st.empty())
673 return res;
674 ExprFrame &parent = st.top();
675 if (parent.state == FrameState::ProcessingParams) {
676 parent.oper_params.emplace_back(res);
677 }
678 else if (parent.state == FrameState::ProcessingParamFuncArgs) {
679 parent.func_args.emplace_back(res);
680 }
681 else if (parent.state == FrameState::ProcessingParamFuncParams) {
682 parent.oper_params.emplace_back(res);
683 }
684 break;
685 }
686 default: {
687 st.pop();
688 break;
689 }
690 }
691 }
692
693 return mkErr(ERROR_TYPE::ERR_UNKWN_SYM); // cannot reach here
694}
695
696std::shared_ptr<DAGNode> Parser::parseConstFunc(const std::string &s) {
697 // first handle the special symbols
698 if (s == "true") {
699 return mkTrue();
700 }
701 else if (s == "false") {
702 return mkFalse();
703 }
704 else if (allow_placeholder_vars &&
706 // placeholder variable name (only when placeholder mode is enabled)
707 auto var = node_manager->getNode(placeholder_var_names[s]);
708 var->incUseCount();
709 return var;
710 }
711
712 // these have the highest priority
713 std::string preserving_let_name = s + PRESERVING_LET_BIND_VAR_SUFFIX +
714 std::to_string(preserving_let_counter);
715 if (options->parsing_preserve_let &&
717 preserving_let_key_map.find(preserving_let_name) !=
719 auto key_var = preserving_let_key_map[preserving_let_name];
720 key_var->incUseCount();
721 return key_var;
722 }
723 else if (!options->parsing_preserve_let &&
725 let_key_map.find(s) != let_key_map.end()) {
726 auto key_var = let_key_map[s];
727 key_var->incUseCount();
728 return key_var;
729 }
730 else if (fun_key_map.find(s) != fun_key_map.end()) {
731 // function name
732 auto fun_var = fun_key_map[s];
733 // Special-case: datatype constructor/selector used in term position.
734 // For nullary datatype constructors, SMT-LIB treats the symbol as a
735 // constant term. Instead of returning the bare function declaration node
736 // (which later gets renamed), materialize a DT_FUN_APPLY with zero
737 // parameters so dumping is consistent with declare-datatypes.
739 // mkFuncDec stores a NULL child at index 0, followed by param nodes; so
740 // arity = childrenSize - 1
741 size_t arity =
742 (fun_var->getChildrenSize() > 0 ? fun_var->getChildrenSize() - 1 : 0);
743 if (arity == 0) {
744 return mkApplyDTFun(fun_var->getSort(), s, {});
745 }
746 }
747 fun_var->incUseCount();
748 return fun_var;
749 }
750 else if (fun_var_map.find(s) != fun_var_map.end()) {
751 // function variable name
752 auto fun_var = fun_var_map[s];
753 fun_var->incUseCount();
754 return fun_var;
755 }
756 else if (in_quantifier_scope &&
757 quant_var_map.find(s) != quant_var_map.end()) {
758 // in quantifier scope, first use quantifier variable name
759 // quantifier variable name
760 auto quant_var = quant_var_map[s].back();
761 quant_var->incUseCount();
762 return quant_var;
763 }
764 // support -3 (before only - 3)
765 else if (TypeChecker::isInt(s)) {
766 // additional process -> constant can be real or integer
767 // 0 -> Int or Real?
768 return mkConstInt(s);
769 }
770 else if (TypeChecker::isReal(s)) {
771 return mkConstReal(s);
772 }
774 // parse scientific notation and convert to real
775 std::string parsed = ConversionUtils::parseScientificNotation(s);
776 return mkConstReal(parsed);
777 }
778 else if (TypeChecker::isBV(s)) {
779 size_t width;
780 if (s[1] == 'b' || s[1] == 'B') {
781 // Binary: each character is 1 bit
782 width = s.size() - 2;
783 }
784 else if (s[1] == 'x' || s[1] == 'X') {
785 // Hexadecimal: each character is 4 bits
786 width = (s.size() - 2) * 4;
787 }
788 else if (s[1] == 'd' || s[1] == 'D') {
789 // Decimal: convert to binary to determine width
790 std::string decimal_part = s.substr(2);
791 Integer value(decimal_part);
792 std::string binary = value.toString(2);
793 width = binary.size();
794 }
795 else {
796 // Fallback to original behavior
797 width = s.size() - 2;
798 }
799 return mkConstBv(s, width);
800 }
801 else if (TypeChecker::isFP(s)) {
802 return mkConstFP(s);
803 }
804 else if (TypeChecker::isString(s)) {
805 return mkConstStr(s);
806 }
807 else if (var_names.find(s) != var_names.end()) {
808 // the last one, global variable name
809 auto var = node_manager->getNode(var_names[s]);
810 var->incUseCount();
811 return var;
812 }
813 // following Common Lisp's conventions, enclosing
814 // a simple symbol in vertical bars does not produce a new symbol.
815 else if (s.size() > 2 && s[0] == '|' && s[s.size() - 1] == '|' &&
816 var_names.find(s.substr(1, s.size() - 2)) != var_names.end()) {
817 // string
818 auto var = node_manager->getNode(var_names[s.substr(1, s.size() - 2)]);
819 var->incUseCount();
820 return var;
821 }
822 else if (!TypeChecker::isNumber(s) &&
823 var_names.find('|' + s + '|') != var_names.end()) {
824 // string
825 auto var = node_manager->getNode(var_names['|' + s + '|']);
826 var->incUseCount();
827 return var;
828 }
829 // otherwise, it is a constant
830 else if (s == "pi") {
831 return mkPi();
832 }
833 else if (s == "e") {
834 return mkE();
835 }
836 else if (s == "inf") {
837 return mkInfinity(options->isIntTheory() ? SortManager::INT_SORT
839 }
840 else if (s == "+inf") {
841 return mkPosInfinity(options->isIntTheory() ? SortManager::INT_SORT
843 }
844 else if (s == "-inf") {
845 return mkNegInfinity(options->isIntTheory() ? SortManager::INT_SORT
847 }
848 else if (s == "epsion") {
849 return mkEpsilon();
850 }
851 else if (s == "+epsilon") {
852 return mkPosEpsilon();
853 }
854 else if (s == "-epsilon") {
855 return mkNegEpsilon();
856 }
857 else if (s == "NaN" || s == "+NaN" || s == "-NaN") {
858 return mkNaN();
859 }
860
861 // no parameters
862 else if (s == "re.none") {
863 return mkRegNone();
864 }
865 else if (s == "re.all") {
866 return mkRegAll();
867 }
868 else if (s == "re.allchar") {
869 return mkRegAllChar();
870 }
871 // Rounding mode constants for floating point operations
872 else if (s == "RNE" || s == "roundNearestTiesToEven") {
873 return mkRoundingMode("RNE");
874 }
875 else if (s == "RNA" || s == "roundNearestTiesToAway") {
876 return mkRoundingMode("RNA");
877 }
878 else if (s == "RTP" || s == "roundTowardPositive") {
879 return mkRoundingMode("RTP");
880 }
881 else if (s == "RTN" || s == "roundTowardNegative") {
882 return mkRoundingMode("RTN");
883 }
884 else if (s == "RTZ" || s == "roundTowardZero") {
885 return mkRoundingMode("RTZ");
886 }
887 else {
888 // If allow_placeholder_vars is true, create a placeholder variable
890 return mkPlaceholderVar(s);
891 }
893 }
895}
896
897NODE_KIND Parser::getKind(const std::string &s) {
898 auto kind = stabilizer::parser::getOperKind(s);
899 if (kind == NODE_KIND::NT_UNKNOWN &&
900 fun_key_map.find(s) != fun_key_map.end()) {
902 }
903 return kind;
904}
905
906std::shared_ptr<DAGNode>
907Parser::parseOper(const std::string &s,
908 const std::vector<std::shared_ptr<DAGNode>> &func_args,
909 const std::vector<std::shared_ptr<DAGNode>> &oper_params) {
910 if (fun_key_map.find(s) != fun_key_map.end()) {
911 // Found a function definition or declaration, apply it with parameters
912 auto func = fun_key_map[s];
913 // std::cout << func->getName() << std::endl;
914 auto x = applyFun(func, oper_params);
915 // std::cout << x->getChild(0)->getName() << ' ' <<
916 // x->getChild(1)->getName() << std::endl;
917 return x;
918 }
919
920 // Special handling for root-obj
921 if (s == "root-obj") {
922 condAssert(oper_params.size() == 2,
923 "root-obj requires exactly 2 parameters");
924 auto expr = oper_params[0];
925 auto index_node = oper_params[1];
926 condAssert(index_node->isConst() && index_node->getSort()->isInt(),
927 "root-obj index must be integer constant");
928 int index = std::stoi(index_node->getName());
929 return mkRootObj(expr, index);
930 }
931
933 switch (kind) {
935 return mkAnd(oper_params);
936 case NODE_KIND::NT_OR:
937 return mkOr(oper_params);
939 condAssert(oper_params.size() == 1, "Invalid number of parameters for not");
940 return mkNot(oper_params[0]);
942 return mkImplies(oper_params);
944 return mkXor(oper_params);
945 case NODE_KIND::NT_EQ:
946 return mkEq(oper_params);
948 return mkDistinct(oper_params);
950 return mkIte(oper_params);
952 return mkAdd(oper_params);
954 condAssert(oper_params.size() == 1, "Invalid number of parameters for neg");
955 return mkNeg(oper_params[0]);
957 return mkSub(oper_params);
959 return mkMul(oper_params);
961 return mkIand(oper_params);
963 condAssert(oper_params.size() == 1,
964 "Invalid number of parameters for pow2");
965 return mkPow2(oper_params[0]);
967 condAssert(oper_params.size() == 2, "Invalid number of parameters for pow");
968 return mkPow(oper_params[0], oper_params[1]);
970 condAssert(oper_params.size() == 2, "Invalid number of parameters for div");
971 return mkDivInt(oper_params);
973 condAssert(oper_params.size() == 2, "Invalid number of parameters for div");
974 return mkDivReal(oper_params);
976 condAssert(oper_params.size() == 2, "Invalid number of parameters for mod");
977 return mkMod(oper_params[0], oper_params[1]);
979 condAssert(oper_params.size() == 1, "Invalid number of parameters for abs");
980 return mkAbs(oper_params[0]);
982 condAssert(oper_params.size() == 1,
983 "Invalid number of parameters for sqrt");
984 return mkSqrt(oper_params[0]);
986 condAssert(oper_params.size() == 1,
987 "Invalid number of parameters for safeSqrt");
988 return mkSafeSqrt(oper_params[0]);
990 condAssert(oper_params.size() == 1,
991 "Invalid number of parameters for ceil");
992 return mkCeil(oper_params[0]);
994 condAssert(oper_params.size() == 1,
995 "Invalid number of parameters for floor");
996 return mkFloor(oper_params[0]);
998 condAssert(oper_params.size() == 1,
999 "Invalid number of parameters for round");
1000 return mkRound(oper_params[0]);
1001 case NODE_KIND::NT_EXP:
1002 condAssert(oper_params.size() == 1, "Invalid number of parameters for exp");
1003 return mkExp(oper_params[0]);
1004 case NODE_KIND::NT_LN:
1005 condAssert(oper_params.size() == 1, "Invalid number of parameters for ln");
1006 return mkLn(oper_params[0]);
1007 case NODE_KIND::NT_LG:
1008 condAssert(oper_params.size() == 1, "Invalid number of parameters for lg");
1009 return mkLg(oper_params[0]);
1010 case NODE_KIND::NT_LB:
1011 condAssert(oper_params.size() == 1, "Invalid number of parameters for lb");
1012 return mkLb(oper_params[0]);
1013 case NODE_KIND::NT_LOG:
1014 if (oper_params.size() == 1) {
1015 return mkLn(oper_params[0]);
1016 }
1017 else if (oper_params.size() == 2) {
1018 return mkLog(oper_params[0], oper_params[1]);
1019 }
1020 else {
1021 err_param_mis("log", line_number);
1023 }
1024 case NODE_KIND::NT_SIN:
1025 condAssert(oper_params.size() == 1, "Invalid number of parameters for sin");
1026 return mkSin(oper_params[0]);
1027 case NODE_KIND::NT_COS:
1028 condAssert(oper_params.size() == 1, "Invalid number of parameters for cos");
1029 return mkCos(oper_params[0]);
1030 case NODE_KIND::NT_TAN:
1031 condAssert(oper_params.size() == 1, "Invalid number of parameters for tan");
1032 return mkTan(oper_params[0]);
1033 case NODE_KIND::NT_COT:
1034 condAssert(oper_params.size() == 1, "Invalid number of parameters for cot");
1035 return mkCot(oper_params[0]);
1036 case NODE_KIND::NT_SEC:
1037 condAssert(oper_params.size() == 1, "Invalid number of parameters for sec");
1038 return mkSec(oper_params[0]);
1039 case NODE_KIND::NT_CSC:
1040 condAssert(oper_params.size() == 1, "Invalid number of parameters for csc");
1041 return mkCsc(oper_params[0]);
1042 case NODE_KIND::NT_ASIN:
1043 condAssert(oper_params.size() == 1,
1044 "Invalid number of parameters for asin");
1045 return mkAsin(oper_params[0]);
1046 case NODE_KIND::NT_ACOS:
1047 condAssert(oper_params.size() == 1,
1048 "Invalid number of parameters for acos");
1049 return mkAcos(oper_params[0]);
1050 case NODE_KIND::NT_ATAN:
1051 condAssert(oper_params.size() == 1,
1052 "Invalid number of parameters for atan");
1053 return mkAtan(oper_params[0]);
1054 case NODE_KIND::NT_ACOT:
1055 condAssert(oper_params.size() == 1,
1056 "Invalid number of parameters for acot");
1057 return mkAcot(oper_params[0]);
1058 case NODE_KIND::NT_ASEC:
1059 condAssert(oper_params.size() == 1,
1060 "Invalid number of parameters for asec");
1061 return mkAsec(oper_params[0]);
1062 case NODE_KIND::NT_ACSC:
1063 condAssert(oper_params.size() == 1,
1064 "Invalid number of parameters for acsc");
1065 return mkAcsc(oper_params[0]);
1066 case NODE_KIND::NT_SINH:
1067 condAssert(oper_params.size() == 1,
1068 "Invalid number of parameters for sinh");
1069 return mkSinh(oper_params[0]);
1070 case NODE_KIND::NT_COSH:
1071 condAssert(oper_params.size() == 1,
1072 "Invalid number of parameters for cosh");
1073 return mkCosh(oper_params[0]);
1074 case NODE_KIND::NT_TANH:
1075 condAssert(oper_params.size() == 1,
1076 "Invalid number of parameters for tanh");
1077 return mkTanh(oper_params[0]);
1079 condAssert(oper_params.size() == 1,
1080 "Invalid number of parameters for asech");
1081 return mkAsech(oper_params[0]);
1083 condAssert(oper_params.size() == 1,
1084 "Invalid number of parameters for acsch");
1085 return mkAcsch(oper_params[0]);
1087 condAssert(oper_params.size() == 1,
1088 "Invalid number of parameters for acoth");
1089 return mkAcoth(oper_params[0]);
1091 condAssert(oper_params.size() == 2,
1092 "Invalid number of parameters for atan2");
1093 return mkAtan2(oper_params[0], oper_params[1]);
1095 condAssert(oper_params.size() == 1,
1096 "Invalid number of parameters for asinh");
1097 return mkAsinh(oper_params[0]);
1099 condAssert(oper_params.size() == 1,
1100 "Invalid number of parameters for acosh");
1101 return mkAcosh(oper_params[0]);
1103 condAssert(oper_params.size() == 1,
1104 "Invalid number of parameters for atanh");
1105 return mkAtanh(oper_params[0]);
1106 case NODE_KIND::NT_SECH:
1107 condAssert(oper_params.size() == 1,
1108 "Invalid number of parameters for sech");
1109 return mkSech(oper_params[0]);
1110 case NODE_KIND::NT_CSCH:
1111 condAssert(oper_params.size() == 1,
1112 "Invalid number of parameters for csch");
1113 return mkCsch(oper_params[0]);
1114 case NODE_KIND::NT_LE:
1115 // condAssert(oper_params.size() == 2, "Invalid number of parameters for <=
1116 // ");
1117 return mkLe(oper_params);
1118 case NODE_KIND::NT_LT:
1119 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1120 // <");
1121 return mkLt(oper_params);
1122 case NODE_KIND::NT_GE:
1123 // condAssert(oper_params.size() == 2, "Invalid number of parameters for >=
1124 // ");
1125 return mkGe(oper_params);
1126 case NODE_KIND::NT_GT:
1127 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1128 // >");
1129 return mkGt(oper_params);
1131 condAssert(oper_params.size() == 1,
1132 "Invalid number of parameters for to_real");
1133 return mkToReal(oper_params[0]);
1135 condAssert(oper_params.size() == 1,
1136 "Invalid number of parameters for to_int");
1137 return mkToInt(oper_params[0]);
1139 condAssert(oper_params.size() == 1,
1140 "Invalid number of parameters for is_int");
1141 return mkIsInt(oper_params[0]);
1143 condAssert(oper_params.size() == 2,
1144 "Invalid number of parameters for is_divisible");
1145 return mkIsDivisible(oper_params[0], oper_params[1]);
1147 condAssert(oper_params.size() == 1,
1148 "Invalid number of parameters for is_prime");
1149 return mkIsPrime(oper_params[0]);
1151 condAssert(oper_params.size() == 1,
1152 "Invalid number of parameters for is_even");
1153 return mkIsEven(oper_params[0]);
1155 condAssert(oper_params.size() == 1,
1156 "Invalid number of parameters for is_odd");
1157 return mkIsOdd(oper_params[0]);
1158 case NODE_KIND::NT_GCD:
1159 condAssert(oper_params.size() == 2, "Invalid number of parameters for gcd");
1160 return mkGcd(oper_params[0], oper_params[1]);
1161 case NODE_KIND::NT_LCM:
1162 condAssert(oper_params.size() == 2, "Invalid number of parameters for lcm");
1163 return mkLcm(oper_params[0], oper_params[1]);
1164 case NODE_KIND::NT_FACT:
1165 condAssert(oper_params.size() == 1,
1166 "Invalid number of parameters for factorial");
1167 return mkFact(oper_params[0]);
1169 condAssert(oper_params.size() == 1,
1170 "Invalid number of parameters for bvnot");
1171 return mkBvNot(oper_params[0]);
1173 condAssert(oper_params.size() == 1,
1174 "Invalid number of parameters for bvneg");
1175 return mkBvNeg(oper_params[0]);
1177 return mkBvAnd(oper_params);
1179 return mkBvOr(oper_params);
1181 return mkBvXor(oper_params);
1183 return mkBvNand(oper_params.at(0), oper_params.at(1));
1185 return mkBvNor(oper_params.at(0), oper_params.at(1));
1187 return mkBvXnor(oper_params.at(0), oper_params.at(1));
1189 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1190 // bvcomp");
1191 return mkBvComp(oper_params);
1193 return mkBvAdd(oper_params);
1195 return mkBvSub(oper_params.at(0), oper_params.at(1));
1197 return mkBvMul(oper_params);
1199 condAssert(oper_params.size() == 2,
1200 "Invalid number of parameters for bvudiv");
1201 return mkBvUdiv(oper_params[0], oper_params[1]);
1203 condAssert(oper_params.size() == 2,
1204 "Invalid number of parameters for bvurem");
1205 return mkBvUrem(oper_params[0], oper_params[1]);
1207 condAssert(oper_params.size() == 2,
1208 "Invalid number of parameters for bvsdiv");
1209 return mkBvSdiv(oper_params[0], oper_params[1]);
1211 condAssert(oper_params.size() == 2,
1212 "Invalid number of parameters for bvsrem");
1213 return mkBvSrem(oper_params[0], oper_params[1]);
1215 condAssert(oper_params.size() == 2,
1216 "Invalid number of parameters for bvsrem");
1217 return mkBvSmod(oper_params[0], oper_params[1]);
1219 condAssert(oper_params.size() == 2,
1220 "Invalid number of parameters for bvshl");
1221 return mkBvShl(oper_params[0], oper_params[1]);
1223 condAssert(oper_params.size() == 2,
1224 "Invalid number of parameters for bvlshr");
1225 return mkBvLshr(oper_params[0], oper_params[1]);
1227 condAssert(oper_params.size() == 2,
1228 "Invalid number of parameters for bvashr");
1229 return mkBvAshr(oper_params[0], oper_params[1]);
1231 condAssert(oper_params.size() == 2,
1232 "Invalid number of parameters for bvult");
1233 return mkBvUlt(oper_params[0], oper_params[1]);
1235 condAssert(oper_params.size() == 2,
1236 "Invalid number of parameters for bvule");
1237 return mkBvUle(oper_params[0], oper_params[1]);
1239 condAssert(oper_params.size() == 2,
1240 "Invalid number of parameters for bvugt");
1241 return mkBvUgt(oper_params[0], oper_params[1]);
1243 condAssert(oper_params.size() == 2,
1244 "Invalid number of parameters for bvuge");
1245 return mkBvUge(oper_params[0], oper_params[1]);
1247 condAssert(oper_params.size() == 2,
1248 "Invalid number of parameters for bvslt");
1249 return mkBvSlt(oper_params[0], oper_params[1]);
1251 condAssert(oper_params.size() == 2,
1252 "Invalid number of parameters for bvsle");
1253 return mkBvSle(oper_params[0], oper_params[1]);
1255 condAssert(oper_params.size() == 2,
1256 "Invalid number of parameters for bvsgt");
1257 return mkBvSgt(oper_params[0], oper_params[1]);
1259 condAssert(oper_params.size() == 2,
1260 "Invalid number of parameters for bvsge");
1261 return mkBvSge(oper_params[0], oper_params[1]);
1263 return mkBvConcat(oper_params);
1265 condAssert(oper_params.size() == 1,
1266 "Invalid number of parameters for bv2int");
1267 return mkBvToInt(oper_params[0]);
1269 condAssert(oper_params.size() == 1,
1270 "Invalid number of parameters for ubv2int");
1271 return mkUbvToInt(oper_params[0]);
1273 condAssert(oper_params.size() == 1,
1274 "Invalid number of parameters for sbv2int");
1275 return mkUbvToInt(oper_params[0]);
1277 condAssert(oper_params.size() == 1,
1278 "Invalid number of parameters for bv2nat");
1279 return mkBvToNat(oper_params[0]);
1281 condAssert(oper_params.size() == 2,
1282 "Invalid number of parameters for nat2bv");
1283 return mkNatToBv(oper_params[0], oper_params[1]);
1285 condAssert(func_args.size() == 1,
1286 "Invalid number of arguments for int_to_bv");
1287 condAssert(oper_params.size() == 1,
1288 "Invalid number of parameters for int_to_bv");
1289 return mkIntToBv(oper_params[0], func_args[0]);
1291 condAssert(func_args.size() == 2,
1292 "Invalid number of arguments for extract");
1293 condAssert(oper_params.size() == 1,
1294 "Invalid number of parameters for extract");
1295 return mkBvExtract(oper_params[0], func_args[0], func_args[1]);
1297 condAssert(func_args.size() == 1, "Invalid number of arguments for repeat");
1298 condAssert(oper_params.size() == 1,
1299 "Invalid number of parameters for repeat");
1300 return mkBvRepeat(oper_params[0], func_args[0]);
1302 condAssert(func_args.size() == 1,
1303 "Invalid number of arguments for zero_extend");
1304 condAssert(oper_params.size() == 1,
1305 "Invalid number of parameters for zero_extend");
1306 return mkBvZeroExt(oper_params[0], func_args[0]);
1308 condAssert(func_args.size() == 1,
1309 "Invalid number of arguments for sign_extend");
1310 condAssert(oper_params.size() == 1,
1311 "Invalid number of parameters for sign_extend");
1312 return mkBvSignExt(oper_params[0], func_args[0]);
1314 condAssert(func_args.size() == 1,
1315 "Invalid number of arguments for rotate_left");
1316 condAssert(oper_params.size() == 1,
1317 "Invalid number of parameters for rotate_left");
1318 return mkBvRotateLeft(oper_params[0], func_args[0]);
1320 condAssert(func_args.size() == 1,
1321 "Invalid number of arguments for rotate_right");
1322 condAssert(oper_params.size() == 1,
1323 "Invalid number of parameters for rotate_right");
1324 return mkBvRotateRight(oper_params[0], func_args[0]);
1326 condAssert(oper_params.size() == 1,
1327 "Invalid number of parameters for fp.abs");
1328 return mkFpAbs(oper_params[0]);
1330 condAssert(oper_params.size() == 1,
1331 "Invalid number of parameters for fp.neg");
1332 return mkFpNeg(oper_params[0]);
1334 return mkFpAdd(oper_params);
1336 return mkFpSub(oper_params);
1338 return mkFpMul(oper_params);
1340 return mkFpDiv(oper_params);
1342 // condAssert(oper_params.size() == 3, "Invalid number of parameters for
1343 // fp.fma");
1344 return mkFpFma(oper_params);
1346 if (oper_params.size() == 1) {
1347 return mkFpSqrt(oper_params[0]);
1348 }
1349 else if (oper_params.size() == 2) {
1350 return mkFpSqrt(oper_params[0], oper_params[1]);
1351 }
1352 else {
1353 err_param_mis("fp.sqrt", line_number);
1355 }
1357 condAssert(oper_params.size() == 2,
1358 "Invalid number of parameters for fp.rem");
1359 return mkFpRem(oper_params[0], oper_params[1]);
1361 if (oper_params.size() == 1) {
1362 return mkFpRoundToIntegral(oper_params[0]);
1363 }
1364 else if (oper_params.size() == 2) {
1365 return mkFpRoundToIntegral(oper_params[0], oper_params[1]);
1366 }
1367 else {
1368 err_param_mis("fp.roundToIntegral", line_number);
1370 }
1372 condAssert(oper_params.size() == 2,
1373 "Invalid number of parameters for fp.min");
1374 return mkFpMin(oper_params.at(0), oper_params.at(1));
1376 condAssert(oper_params.size() == 2,
1377 "Invalid number of parameters for fp.max");
1378 return mkFpMax(oper_params.at(0), oper_params.at(1));
1380 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1381 // fp.leq");
1382 return mkFpLe(oper_params);
1384 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1385 // fp.lt");
1386 return mkFpLt(oper_params);
1388 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1389 // fp.geq");
1390 return mkFpGe(oper_params);
1392 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1393 // fp.gt");
1394 return mkFpGt(oper_params);
1396 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1397 // fp.eq");
1398 return mkFpEq(oper_params);
1400 condAssert(func_args.size() == 1 && oper_params.size() == 2,
1401 "Invalid number of parameters for fp.to_ubv");
1402 return mkFpToUbv(oper_params[0], oper_params[1], func_args[0]);
1404 condAssert(func_args.size() == 1 && oper_params.size() == 2,
1405 "Invalid number of parameters for fp.to_sbv");
1406 return mkFpToSbv(oper_params[0], oper_params[1], func_args[0]);
1408 condAssert(oper_params.size() == 1,
1409 "Invalid number of parameters for fp.to_real");
1410 return mkFpToReal(oper_params[0]);
1412 // Handle different to_fp syntax:
1413 // 1. ((_ to_fp eb sb) RoundingMode Real) -> func_args: [eb, sb],
1414 // oper_params: [RoundingMode, Real]
1415 // 2. ((_ to_fp eb sb) RoundingMode (_ BitVec m)) -> func_args: [eb, sb],
1416 // oper_params: [RoundingMode, BitVec]
1417 // 3. ((_ to_fp eb sb) (_ BitVec m)) -> func_args: [eb, sb], oper_params:
1418 // [BitVec]
1419 if (func_args.size() == 2) {
1420 if (oper_params.size() == 2) {
1421 // Case 1 and 2: RoundingMode + Real/BitVec
1422 return mkToFp(func_args[0], func_args[1], oper_params[0], oper_params[1]);
1423 }
1424 else if (oper_params.size() == 1) {
1425 // Case 3: BitVec only
1426 return mkToFp(func_args[0], func_args[1], oper_params[0]);
1427 }
1428 else {
1429 err_param_mis("to_fp", line_number);
1431 }
1432 }
1433 else if (oper_params.size() == 3) {
1434 // Direct to_fp call with 3 parameters: eb, sb, value/rm+value
1435 return mkToFp(oper_params[0], oper_params[1], oper_params[2]);
1436 }
1437 else {
1438 err_param_mis("to_fp", line_number);
1440 }
1442 // Handle to_fp_unsigned syntax:
1443 // ((_ to_fp_unsigned eb sb) RoundingMode (_ BitVec m)) -> func_args: [eb,
1444 // sb], oper_params: [RoundingMode, BitVec]
1445 if (func_args.size() == 2 && oper_params.size() == 2) {
1446 return mkToFpUnsigned(func_args[0], func_args[1], oper_params[0], oper_params[1]);
1447 }
1448 else {
1449 err_param_mis("to_fp_unsigned", line_number);
1451 }
1452
1454 condAssert(oper_params.size() == 1,
1455 "Invalid number of parameters for fp.isNormal");
1456 return mkFpIsNormal(oper_params[0]);
1458 condAssert(oper_params.size() == 1,
1459 "Invalid number of parameters for fp.isSubnormal");
1460 return mkFpIsSubnormal(oper_params[0]);
1462 condAssert(oper_params.size() == 1,
1463 "Invalid number of parameters for fp.isZero");
1464 return mkFpIsZero(oper_params[0]);
1466 condAssert(oper_params.size() == 1,
1467 "Invalid number of parameters for fp.isInfinite");
1468 return mkFpIsInf(oper_params[0]);
1470 condAssert(oper_params.size() == 1,
1471 "Invalid number of parameters for fp.isNaN");
1472 return mkFpIsNaN(oper_params[0]);
1474 condAssert(oper_params.size() == 1,
1475 "Invalid number of parameters for fp.isNegative");
1476 return mkFpIsNeg(oper_params[0]);
1478 condAssert(oper_params.size() == 1,
1479 "Invalid number of parameters for fp.isPositive");
1480 return mkFpIsPos(oper_params[0]);
1482 condAssert(oper_params.size() == 2,
1483 "Invalid number of parameters for select");
1484 return mkSelect(oper_params[0], oper_params[1]);
1486 condAssert(oper_params.size() == 3,
1487 "Invalid number of parameters for store");
1488 return mkStore(oper_params[0], oper_params[1], oper_params[2]);
1490 condAssert(oper_params.size() == 1,
1491 "Invalid number of parameters for str.len");
1492 return mkStrLen(oper_params[0]);
1494 return mkStrConcat(oper_params);
1496 condAssert(oper_params.size() == 3,
1497 "Invalid number of parameters for str.substr");
1498 return mkStrSubstr(oper_params[0], oper_params[1], oper_params[2]);
1500 condAssert(oper_params.size() == 2,
1501 "Invalid number of parameters for str.prefixof");
1502 return mkStrPrefixof(oper_params[0], oper_params[1]);
1504 condAssert(oper_params.size() == 2,
1505 "Invalid number of parameters for str.suffixof");
1506 return mkStrSuffixof(oper_params[0], oper_params[1]);
1508 condAssert(oper_params.size() == 3,
1509 "Invalid number of parameters for str.indexof");
1510 return mkStrIndexof(oper_params[0], oper_params[1], oper_params[2]);
1512 condAssert(oper_params.size() == 2,
1513 "Invalid number of parameters for str.at");
1514 return mkStrCharat(oper_params[0], oper_params[1]);
1516 condAssert(oper_params.size() == 3,
1517 "Invalid number of parameters for str.update");
1518 return mkStrUpdate(oper_params[0], oper_params[1], oper_params[2]);
1520 condAssert(oper_params.size() == 3,
1521 "Invalid number of parameters for str.replace");
1522 return mkStrReplace(oper_params[0], oper_params[1], oper_params[2]);
1524 condAssert(oper_params.size() == 3,
1525 "Invalid number of parameters for str.replace_all");
1526 return mkStrReplaceAll(oper_params[0], oper_params[1], oper_params[2]);
1528 condAssert(oper_params.size() == 3,
1529 "Invalid number of parameters for str.replace_re");
1530 return mkStrReplaceReg(oper_params[0], oper_params[1], oper_params[2]);
1532 condAssert(oper_params.size() == 3,
1533 "Invalid number of parameters for str.replace_re_all");
1534 return mkStrReplaceRegAll(oper_params[0], oper_params[1], oper_params[2]);
1536 condAssert(oper_params.size() == 2,
1537 "Invalid number of parameters for str.indexof_re");
1538 return mkStrIndexofReg(oper_params[0], oper_params[1]);
1540 condAssert(oper_params.size() == 1,
1541 "Invalid number of parameters for str.to_lower");
1542 return mkStrToLower(oper_params[0]);
1544 condAssert(oper_params.size() == 1,
1545 "Invalid number of parameters for str.to_upper");
1546 return mkStrToUpper(oper_params[0]);
1548 condAssert(oper_params.size() == 1,
1549 "Invalid number of parameters for str.rev");
1550 return mkStrRev(oper_params[0]);
1552 condAssert(oper_params.size() == 2,
1553 "Invalid number of parameters for str.split");
1554 return mkStrSplit(oper_params[0], oper_params[1]);
1556 condAssert(oper_params.size() == 3,
1557 "Invalid number of parameters for str.split_at");
1558 return mkStrSplitAt(oper_params[0], oper_params[1], oper_params[2]);
1560 condAssert(oper_params.size() == 3,
1561 "Invalid number of parameters for str.split_rest");
1562 return mkStrSplitRest(oper_params[0], oper_params[1], oper_params[2]);
1564 condAssert(oper_params.size() == 2,
1565 "Invalid number of parameters for str.num_splits");
1566 return mkStrNumSplits(oper_params[0], oper_params[1]);
1568 condAssert(oper_params.size() == 3,
1569 "Invalid number of parameters for str.split_at_re");
1570 return mkStrSplitAtRe(oper_params[0], oper_params[1], oper_params[2]);
1572 condAssert(oper_params.size() == 3,
1573 "Invalid number of parameters for str.split_rest_re");
1574 return mkStrSplitRestRe(oper_params[0], oper_params[1], oper_params[2]);
1576 condAssert(oper_params.size() == 2,
1577 "Invalid number of parameters for str.num_splits_re");
1578 return mkStrNumSplitsRe(oper_params[0], oper_params[1]);
1580 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1581 // str.<");
1582 return mkStrLt(oper_params);
1584 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1585 // str.<=");
1586 return mkStrLe(oper_params);
1588 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1589 // str.>");
1590 return mkStrGt(oper_params);
1592 // condAssert(oper_params.size() == 2, "Invalid number of parameters for
1593 // str.>=");
1594 return mkStrGe(oper_params);
1596 condAssert(oper_params.size() == 2,
1597 "Invalid number of parameters for str.in_re");
1598 return mkStrInReg(oper_params[0], oper_params[1]);
1600 condAssert(oper_params.size() == 2,
1601 "Invalid number of parameters for str.contains");
1602 return mkStrContains(oper_params[0], oper_params[1]);
1604 condAssert(oper_params.size() == 1,
1605 "Invalid number of parameters for str.is_digit");
1606 return mkStrIsDigit(oper_params[0]);
1608 condAssert(oper_params.size() == 1,
1609 "Invalid number of parameters for str.from_int");
1610 return mkStrFromInt(oper_params[0]);
1612 condAssert(oper_params.size() == 1,
1613 "Invalid number of parameters for str.to_int");
1614 return mkStrToInt(oper_params[0]);
1616 condAssert(oper_params.size() == 1,
1617 "Invalid number of parameters for str.to_re");
1618 return mkStrToReg(oper_params[0]);
1620 condAssert(oper_params.size() == 1,
1621 "Invalid number of parameters for str.to_code");
1622 return mkStrToCode(oper_params[0]);
1624 condAssert(oper_params.size() == 1,
1625 "Invalid number of parameters for str.from_code");
1626 return mkStrFromCode(oper_params[0]);
1628 return mkRegConcat(oper_params);
1630 return mkRegUnion(oper_params);
1632 return mkRegInter(oper_params);
1634 return mkRegDiff(oper_params);
1636 condAssert(oper_params.size() == 1,
1637 "Invalid number of parameters for re.*");
1638 return mkRegStar(oper_params[0]);
1640 condAssert(oper_params.size() == 1,
1641 "Invalid number of parameters for re.+");
1642 return mkRegPlus(oper_params[0]);
1644 condAssert(oper_params.size() == 1,
1645 "Invalid number of parameters for re.?");
1646 return mkRegOpt(oper_params[0]);
1648 condAssert(oper_params.size() == 2,
1649 "Invalid number of parameters for re.range");
1650 return mkRegRange(oper_params[0], oper_params[1]);
1652 condAssert(oper_params.size() == 2,
1653 "Invalid number of parameters for re.repeat");
1654 return mkRegRepeat(oper_params[0], oper_params[1]);
1656 condAssert(oper_params.size() == 1,
1657 "Invalid number of parameters for re.comp");
1658 return mkRegComplement(oper_params[0]);
1660 condAssert(oper_params.size() == 1,
1661 "Invalid number of parameters for re.loop");
1662 condAssert(func_args.size() == 2,
1663 "Invalid number of arguments for re.loop");
1664 return mkRegLoop(oper_params[0], func_args[0], func_args[1]);
1665 // Datatype testers and updaters
1667 condAssert(func_args.size() == 1 && oper_params.size() == 1,
1668 "Invalid parameters for ((_ is C) t)");
1669 // func_args[0] is constructor function symbol node
1670 std::string ctor_name = func_args[0]->getName();
1671 auto t = oper_params[0];
1672 // if (t->getSort() != func_args[0]->getSort())
1673 // return mkFalse();
1674 // else
1675 // return mkTrue();
1676 // std::cout << func_args[0]->getSort()->toString() << ", " <<
1677 // t->getSort()->toString() << std::endl; std::cout << t->toString() <<
1678 // std::endl; Create a boolean tester node carrying constructor name return
1679 // node_manager->createNode(SortManager::BOOL_SORT, NODE_KIND::NT_DT_TESTER,
1680 // ctor_name, std::vector<std::shared_ptr<DAGNode>>{t});
1681
1682 return node_manager->createNode(
1683 SortManager::BOOL_SORT, NODE_KIND::NT_DT_TESTER, ctor_name, std::vector<std::shared_ptr<DAGNode>>{mkApplyUF(func_args.at(0)->getSort(), ctor_name, {t})});
1684 }
1686 condAssert(func_args.size() == 1 && oper_params.size() == 2,
1687 "Invalid parameters for ((_ update S) t u)");
1688 std::string sel_name = func_args[0]->getName();
1689 auto t = oper_params[0];
1690 auto u = oper_params[1];
1691 // result sort is same as t
1692 return node_manager->createNode(
1693 t->getSort(), NODE_KIND::NT_DT_UPDATER, sel_name, std::vector<std::shared_ptr<DAGNode>>{t, u});
1694 }
1695 // Tuple operations
1697 // (tuple e1 e2 ...)
1698 std::vector<std::shared_ptr<Sort>> fields;
1699 fields.reserve(oper_params.size());
1700 for (auto &ch : oper_params)
1701 fields.push_back(ch->getSort());
1702 auto tup_sort = sort_manager->createTupleSort(fields);
1703 return node_manager->createNode(tup_sort, NODE_KIND::NT_TUPLE_CONSTRUCTOR, "", oper_params);
1704 }
1706 auto unit_sort = sort_manager->createTupleSort({});
1707 return node_manager->createNode(unit_sort, NODE_KIND::NT_TUPLE_UNIT, "");
1708 }
1710 condAssert(func_args.size() == 1 && oper_params.size() == 1,
1711 "Invalid parameters for ((_ tuple.select i) t)");
1712 auto t = oper_params[0];
1713 auto idx = func_args[0];
1714 std::shared_ptr<Sort> out_sort = SortManager::NULL_SORT;
1715 if (t->getSort()->isTuple()) {
1716 try {
1717 size_t i = static_cast<size_t>(std::stoul(idx->getName()));
1718 if (i < t->getSort()->children.size())
1719 out_sort = t->getSort()->children[i];
1720 }
1721 catch (...) {
1722 }
1723 }
1724 if (out_sort == SortManager::NULL_SORT)
1725 out_sort = t->getSort();
1726 return node_manager->createNode(
1727 out_sort, NODE_KIND::NT_TUPLE_SELECT, "", std::vector<std::shared_ptr<DAGNode>>{t, idx});
1728 }
1730 condAssert(func_args.size() == 1 && oper_params.size() == 2,
1731 "Invalid parameters for ((_ tuple.update i) t u)");
1732 auto t = oper_params[0];
1733 auto idx = func_args[0];
1734 auto u = oper_params[1];
1735 // result sort is same as tuple sort
1736 return node_manager->createNode(
1737 t->getSort(), NODE_KIND::NT_TUPLE_UPDATE, "", std::vector<std::shared_ptr<DAGNode>>{t, idx, u});
1738 }
1740 condAssert(!func_args.empty() && oper_params.size() == 1,
1741 "Invalid parameters for ((_ tuple.project i1 ... in) t)");
1742 auto t = oper_params[0];
1743 std::vector<std::shared_ptr<DAGNode>> ch;
1744 ch.reserve(1 + func_args.size());
1745 ch.push_back(t);
1746 for (auto &a : func_args)
1747 ch.push_back(a);
1748 // result sort is a tuple of projected fields if possible
1749 std::vector<std::shared_ptr<Sort>> fields;
1750 if (t->getSort()->isTuple()) {
1751 for (auto &a : func_args) {
1752 try {
1753 size_t i = static_cast<size_t>(std::stoul(a->getName()));
1754 if (i < t->getSort()->children.size())
1755 fields.push_back(t->getSort()->children[i]);
1756 }
1757 catch (...) {
1758 }
1759 }
1760 }
1761 std::shared_ptr<Sort> out_sort =
1762 fields.empty() ? t->getSort() : sort_manager->createTupleSort(fields);
1763 return node_manager->createNode(out_sort, NODE_KIND::NT_TUPLE_PROJECT, "", ch);
1764 }
1767 case NODE_KIND::NT_NULL:
1769 case NODE_KIND::NT_VAR:
1774 case NODE_KIND::NT_MAX:
1775 case NODE_KIND::NT_MIN:
1776 case NODE_KIND::NT_LET:
1785 condAssert(false, "Invalid kind");
1786 default:
1789 }
1790}
1791} // namespace stabilizer::parser
#define condAssert(cond, msg)
Definition asserting.h:35
static std::string parseScientificNotation(const std::string &str)
Definition util.cpp:148
std::string toString(int base=10) const
Definition number.cpp:1026
std::shared_ptr< DAGNode > mkSelect(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an array select node.
std::shared_ptr< DAGNode > mkBvSub(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector subtraction node.
void err_all(const ERROR_TYPE e, const std::string s="", const size_t ln=0) const
std::shared_ptr< DAGNode > mkAnd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an and node.
std::shared_ptr< DAGNode > mkCot(std::shared_ptr< DAGNode > param)
Create a cot node.
std::shared_ptr< GlobalOptions > options
Definition parser.h:242
std::shared_ptr< DAGNode > mkSin(std::shared_ptr< DAGNode > param)
Create an sin node.
std::shared_ptr< DAGNode > mkConstArray(std::shared_ptr< Sort > sort, std::shared_ptr< DAGNode > value)
Create a constant array node.
std::shared_ptr< DAGNode > mkStrLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string less-than node.
void err_param_mis(const std::string nm, const size_t ln) const
std::shared_ptr< DAGNode > mkFpToSbv(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > size)
Create a floating-point to signed bitvector conversion node.
std::unordered_map< std::string, std::vector< std::shared_ptr< DAGNode > > > quant_var_map
Definition parser.h:214
std::unordered_map< std::string, std::shared_ptr< DAGNode > > fun_var_map
Definition parser.h:211
std::shared_ptr< DAGNode > mkAsinh(std::shared_ptr< DAGNode > param)
Create an asinh node.
std::shared_ptr< DAGNode > mkAsec(std::shared_ptr< DAGNode > param)
Create an asec node.
std::shared_ptr< DAGNode > mkCeil(std::shared_ptr< DAGNode > param)
Create an ceil node.
std::shared_ptr< DAGNode > mkLcm(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a lcm node.
std::shared_ptr< DAGNode > mkXor(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an xor node.
std::shared_ptr< DAGNode > mkStrPrefixof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string prefix check node.
std::shared_ptr< DAGNode > mkStrToReg(std::shared_ptr< DAGNode > param)
Create a string to-regex conversion node.
std::shared_ptr< DAGNode > mkIntToBv(std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > width)
Create an integer to bitvector conversion node.
std::shared_ptr< DAGNode > mkAcsc(std::shared_ptr< DAGNode > param)
Create an acsc node.
std::shared_ptr< DAGNode > mkFpEq(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point equality node.
std::shared_ptr< DAGNode > mkBvAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector addition node.
std::shared_ptr< DAGNode > mkStrSplitAt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::shared_ptr< DAGNode > mkBvSmod(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed modulo node.
std::shared_ptr< DAGNode > applyFun(std::shared_ptr< DAGNode > fun, const std::vector< std::shared_ptr< DAGNode > > &params)
Apply a function to a list of parameters.
std::shared_ptr< DAGNode > mkStrInReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string in-regex check node.
std::unordered_set< std::string > datatype_function_names
Definition parser.h:227
std::shared_ptr< DAGNode > mkBvXnor(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector xnor node.
std::shared_ptr< DAGNode > mkTan(std::shared_ptr< DAGNode > param)
Create an tan node.
std::shared_ptr< DAGNode > mkFalse()
Create a false node.
Definition op_parser.cpp:79
std::shared_ptr< DAGNode > mkGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a gt node.
std::shared_ptr< DAGNode > mkNegEpsilon()
Create a negative epsilon node.
std::shared_ptr< DAGNode > mkBvSrem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed remainder node.
std::shared_ptr< DAGNode > mkNegInfinity(std::shared_ptr< Sort > sort=nullptr)
Create a negative infinity node.
std::shared_ptr< DAGNode > mkTanh(std::shared_ptr< DAGNode > param)
Create a tanh node.
std::shared_ptr< DAGNode > mkCsch(std::shared_ptr< DAGNode > param)
Create a csch node.
std::shared_ptr< DAGNode > mkIsInt(std::shared_ptr< DAGNode > param)
Create a is_int node.
std::shared_ptr< DAGNode > mkNot(std::shared_ptr< DAGNode > param)
Create a not node.
std::shared_ptr< DAGNode > mkBvSdiv(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed division node.
std::shared_ptr< DAGNode > mkBvUlt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned less than node.
std::shared_ptr< DAGNode > mkIsOdd(std::shared_ptr< DAGNode > param)
Create a is_odd node.
std::shared_ptr< DAGNode > mkSec(std::shared_ptr< DAGNode > param)
Create an sec node.
std::shared_ptr< DAGNode > mkUbvToInt(std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkStrReplaceReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-regex node.
std::shared_ptr< DAGNode > mkLb(std::shared_ptr< DAGNode > param)
Create an lb/log2 node.
std::shared_ptr< DAGNode > mkBvZeroExt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector zero extension node.
std::shared_ptr< DAGNode > mkEpsilon()
Create a epsilon node.
std::shared_ptr< DAGNode > mkMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an mul node.
std::shared_ptr< DAGNode > mkRegInter(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex intersection node.
std::shared_ptr< DAGNode > mkLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a le node.
std::shared_ptr< DAGNode > mkStrContains(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string contains check node.
std::shared_ptr< DAGNode > mkFpIsSubnormal(std::shared_ptr< DAGNode > param)
Create a floating-point is-subnormal check node.
std::shared_ptr< DAGNode > parseConstFunc(const std::string &s)
std::shared_ptr< DAGNode > mkRegAll()
Create a regex all node.
std::shared_ptr< DAGNode > mkStore(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create an array store node.
std::shared_ptr< DAGNode > mkFpRoundToIntegral(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a floating-point round to integral node.
std::shared_ptr< DAGNode > mkRegOpt(std::shared_ptr< DAGNode > param)
Create a regex option node.
std::shared_ptr< DAGNode > mkRegLoop(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a regex loop node.
std::shared_ptr< DAGNode > mkRegUnion(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex union node.
std::shared_ptr< DAGNode > mkRegDiff(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex difference node.
std::shared_ptr< DAGNode > mkDistinct(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a distinct node.
std::shared_ptr< DAGNode > mkFpDiv(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point division node.
std::shared_ptr< DAGNode > mkAcsch(std::shared_ptr< DAGNode > param)
Create an acsch node.
std::shared_ptr< Sort > placeholder_var_sort
Definition parser.h:195
std::shared_ptr< DAGNode > mkFpSqrt(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a floating-point square root node.
std::unordered_map< std::string, std::shared_ptr< DAGNode > > preserving_let_key_map
Definition parser.h:208
std::shared_ptr< DAGNode > parseLet()
std::shared_ptr< DAGNode > mkIsEven(std::shared_ptr< DAGNode > param)
Create a is_even node.
std::shared_ptr< DAGNode > mkTrue()
Create a true node.
Definition op_parser.cpp:78
std::shared_ptr< DAGNode > mkAsin(std::shared_ptr< DAGNode > param)
Create an asin node.
std::shared_ptr< DAGNode > mkAcosh(std::shared_ptr< DAGNode > param)
Create an acosh node.
std::shared_ptr< DAGNode > parsePreservingLet()
std::shared_ptr< DAGNode > mkStrCharat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string char-at node.
std::shared_ptr< DAGNode > mkBvToNat(std::shared_ptr< DAGNode > param)
Create a bitvector to natural number conversion node.
std::shared_ptr< DAGNode > mkRegRepeat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a regex repeat node.
std::shared_ptr< DAGNode > mkSub(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an sub node.
std::shared_ptr< DAGNode > mkBvNot(std::shared_ptr< DAGNode > param)
Create a bitvector not node.
std::shared_ptr< DAGNode > mkWeight(const std::shared_ptr< Sort > &sort, const std::string &name, std::shared_ptr< DAGNode > weight)
std::shared_ptr< DAGNode > mkRegConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a regex concatenation node.
std::unordered_map< std::string, size_t > var_names
Definition parser.h:231
std::shared_ptr< DAGNode > mkFpIsZero(std::shared_ptr< DAGNode > param)
Create a floating-point is-zero check node.
std::shared_ptr< DAGNode > mkInfinity(std::shared_ptr< Sort > sort)
Create a infinity node.
std::shared_ptr< DAGNode > mkStrSubstr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a string substring node.
std::shared_ptr< DAGNode > mkConstBv(const std::string &v, const size_t &width)
Create a bit-vector constant.
std::shared_ptr< DAGNode > mkFpRem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point remainder node.
std::shared_ptr< DAGNode > mkApplyDTFun(const std::shared_ptr< Sort > &sort, const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params)
std::shared_ptr< DAGNode > mkBvRotateLeft(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector rotate left node.
std::shared_ptr< DAGNode > mkPosInfinity(std::shared_ptr< Sort > sort=nullptr)
Create a positive infinity node.
std::shared_ptr< DAGNode > mkBvToInt(std::shared_ptr< DAGNode > param)
Create a bitvector to integer conversion node.
std::shared_ptr< DAGNode > mkBvNeg(std::shared_ptr< DAGNode > param)
Create a bitvector negation node.
std::shared_ptr< DAGNode > mkStrReplace(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace node.
std::shared_ptr< DAGNode > mkConstReal(const std::string &v)
Create a real constant from string.
std::shared_ptr< DAGNode > mkRegComplement(std::shared_ptr< DAGNode > param)
Create a regex complement node.
std::shared_ptr< DAGNode > mkDivReal(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an div node.
std::shared_ptr< DAGNode > mkToFp(std::shared_ptr< DAGNode > eb, std::shared_ptr< DAGNode > sb, std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
Create a value to floating-point conversion node.
std::shared_ptr< DAGNode > mkFpMin(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point minimum node.
std::shared_ptr< DAGNode > mkStrSplit(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string split node.
std::shared_ptr< DAGNode > mkFpConst(std::shared_ptr< DAGNode > sign, std::shared_ptr< DAGNode > exp, std::shared_ptr< DAGNode > mant)
std::shared_ptr< DAGNode > mkCosh(std::shared_ptr< DAGNode > param)
Create a cosh node.
std::shared_ptr< DAGNode > mkFpMax(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a floating-point maximum node.
std::shared_ptr< DAGNode > mkErr(const ERROR_TYPE t)
std::shared_ptr< DAGNode > mkFpLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point less than node.
std::shared_ptr< DAGNode > mkStrGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string greater-than node.
std::shared_ptr< DAGNode > mkToReal(std::shared_ptr< DAGNode > param)
Create a to_real node.
std::shared_ptr< DAGNode > mkOr(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an or node.
std::shared_ptr< DAGNode > mkBvRepeat(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector repeat node.
std::shared_ptr< DAGNode > mkIsPrime(std::shared_ptr< DAGNode > param)
Create a is_prime node.
std::shared_ptr< DAGNode > mkBvShl(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector shift left node.
std::shared_ptr< DAGNode > mkAcos(std::shared_ptr< DAGNode > param)
Create an acos node.
std::shared_ptr< DAGNode > mkSafeSqrt(std::shared_ptr< DAGNode > param)
Create an safeSqrt node.
std::shared_ptr< DAGNode > mkStrToUpper(std::shared_ptr< DAGNode > param)
Create a string to-upper node.
std::shared_ptr< DAGNode > mkBvUle(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned less than or equal node.
std::shared_ptr< DAGNode > mkStrToInt(std::shared_ptr< DAGNode > param)
Create a string to-integer conversion node.
std::shared_ptr< DAGNode > mkBvConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector concatenation node.
std::shared_ptr< DAGNode > mkConstInt(const std::string &v)
Create an integer constant from string.
std::shared_ptr< DAGNode > mkIsDivisible(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a is_divisible node.
std::shared_ptr< DAGNode > mkBvComp(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector comparison node.
std::shared_ptr< DAGNode > mkPattern(const std::shared_ptr< Sort > &sort, const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params)
std::shared_ptr< DAGNode > mkStrNumSplits(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
std::shared_ptr< DAGNode > mkStrFromCode(std::shared_ptr< DAGNode > param)
Create a string from-code conversion node.
std::shared_ptr< DAGNode > mkBvUrem(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned remainder node.
std::shared_ptr< DAGNode > mkFpToReal(std::shared_ptr< DAGNode > param)
Create a floating-point to real conversion node.
std::shared_ptr< DAGNode > mkSqrt(std::shared_ptr< DAGNode > param)
Create an sqrt node.
std::shared_ptr< DAGNode > mkStrIndexof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a string index-of node.
std::shared_ptr< DAGNode > mkE()
Create a e node.
std::shared_ptr< DAGNode > mkFpToUbv(std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > size)
Create a floating-point to unsigned bitvector conversion node.
std::shared_ptr< DAGNode > mkCos(std::shared_ptr< DAGNode > param)
Create an cos node.
std::shared_ptr< DAGNode > mkFpAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point addition node.
std::shared_ptr< DAGNode > mkRegAllChar()
Create a regex allchar node.
std::shared_ptr< DAGNode > mkRootObj(std::shared_ptr< DAGNode > expr, int index)
std::shared_ptr< DAGNode > mkGcd(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a gcd node.
std::shared_ptr< DAGNode > mkToFpUnsigned(std::shared_ptr< DAGNode > eb, std::shared_ptr< DAGNode > sb, std::shared_ptr< DAGNode > rm, std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkRootOfWithInterval(const std::vector< std::shared_ptr< DAGNode > > &coeffs, std::shared_ptr< DAGNode > lower_bound, std::shared_ptr< DAGNode > upper_bound)
std::shared_ptr< DAGNode > mkStrIsDigit(std::shared_ptr< DAGNode > param)
Create a string is-digit check node.
std::shared_ptr< DAGNode > parseOper(const std::string &s, const std::vector< std::shared_ptr< DAGNode > > &func_args, const std::vector< std::shared_ptr< DAGNode > > &oper_params)
std::shared_ptr< DAGNode > mkGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a ge node.
std::shared_ptr< DAGNode > mkBvSignExt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector sign extension node.
std::shared_ptr< DAGNode > mkFpGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point greater than or equal node.
std::shared_ptr< DAGNode > parseQuant(const std::string &type)
std::shared_ptr< DAGNode > mkPi()
Create a pi node.
std::shared_ptr< DAGNode > mkFact(std::shared_ptr< DAGNode > param)
Create a factorial node.
std::shared_ptr< DAGNode > mkFpIsPos(std::shared_ptr< DAGNode > param)
Create a floating-point is-positive check node.
std::shared_ptr< DAGNode > mkDivInt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an div node.
void err_unkwn_sym(const std::string nm, const size_t ln) const
std::shared_ptr< DAGNode > mkFpNeg(std::shared_ptr< DAGNode > param)
Create a floating-point negation node.
std::shared_ptr< DAGNode > mkRegStar(std::shared_ptr< DAGNode > param)
Create a regex star node.
std::shared_ptr< DAGNode > mkStrSplitRestRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::unordered_map< std::string, std::shared_ptr< DAGNode > > named_assertions
Definition parser.h:268
std::unordered_map< std::string, std::shared_ptr< DAGNode > > let_key_map
Definition parser.h:206
std::shared_ptr< DAGNode > mkStrUpdate(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string update node.
std::shared_ptr< DAGNode > mkBvUdiv(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned division node.
std::shared_ptr< DAGNode > mkRegPlus(std::shared_ptr< DAGNode > param)
Create a regex plus node.
std::shared_ptr< DAGNode > mkStrConcat(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string concatenation node.
std::shared_ptr< DAGNode > mkEq(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an equality node.
std::shared_ptr< DAGNode > mkBvSlt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed less than node.
std::shared_ptr< DAGNode > mkSinh(std::shared_ptr< DAGNode > param)
Create a sinh node.
std::shared_ptr< DAGNode > mkNoPattern(const std::shared_ptr< Sort > &sort, const std::string &name, std::shared_ptr< DAGNode > param)
std::shared_ptr< DAGNode > mkApplyUF(const std::shared_ptr< Sort > &sort, const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params)
Apply an uninterpreted function.
std::shared_ptr< Sort > parseSort()
std::shared_ptr< DAGNode > mkSech(std::shared_ptr< DAGNode > param)
Create a sech node.
std::shared_ptr< DAGNode > mkBvRotateRight(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector rotate right node.
std::shared_ptr< DAGNode > mkBvOr(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector or node.
std::shared_ptr< DAGNode > mkBvMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector multiplication node.
std::shared_ptr< DAGNode > mkLn(std::shared_ptr< DAGNode > param)
Create an ln node.
std::shared_ptr< DAGNode > mkFpIsInf(std::shared_ptr< DAGNode > param)
Create a floating-point is-infinity check node.
std::shared_ptr< DAGNode > mkPow2(std::shared_ptr< DAGNode > param)
Create an pow2 node.
std::shared_ptr< DAGNode > mkConstFP(const std::string &fp_expr)
Create a floating-point constant from expression.
std::shared_ptr< DAGNode > mkFpAbs(std::shared_ptr< DAGNode > param)
Create a floating-point absolute value node.
std::shared_ptr< DAGNode > mkBvExtract(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
Create a bitvector extract node.
std::shared_ptr< DAGNode > mkFpIsNeg(std::shared_ptr< DAGNode > param)
Create a floating-point is-negative check node.
std::shared_ptr< DAGNode > mkBvAshr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector arithmetic shift right node.
std::shared_ptr< DAGNode > mkBvAnd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector and node.
std::shared_ptr< DAGNode > mkBvNor(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector nor node.
std::shared_ptr< DAGNode > mkAcoth(std::shared_ptr< DAGNode > param)
Create an acoth node.
std::shared_ptr< DAGNode > mkRegNone()
Create a regex none node.
std::shared_ptr< DAGNode > mkAtan(std::shared_ptr< DAGNode > param)
Create an atan node.
std::shared_ptr< DAGNode > mkStrLen(std::shared_ptr< DAGNode > param)
Create a string length node.
std::shared_ptr< DAGNode > mkStrLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string less-than-or-equal node.
std::shared_ptr< DAGNode > mkRound(std::shared_ptr< DAGNode > param)
Create an round node.
std::shared_ptr< DAGNode > mkIte(std::shared_ptr< DAGNode > cond, std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an ite node.
std::shared_ptr< DAGNode > mkStrToLower(std::shared_ptr< DAGNode > param)
Create a string to-lower node.
std::shared_ptr< DAGNode > mkAtanh(std::shared_ptr< DAGNode > param)
Create an atanh node.
std::shared_ptr< DAGNode > mkBvNand(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector nand node.
std::shared_ptr< DAGNode > mkPosEpsilon()
Create a positive epsilon node.
std::unordered_map< std::string, size_t > placeholder_var_names
Definition parser.h:236
std::shared_ptr< DAGNode > mkToInt(std::shared_ptr< DAGNode > param)
Create a to_int node.
std::shared_ptr< DAGNode > mkStrFromInt(std::shared_ptr< DAGNode > param)
Create a string from-integer conversion node.
std::shared_ptr< DAGNode > mkNaN(std::shared_ptr< Sort > sort=nullptr)
Create a NaN node.
std::shared_ptr< DAGNode > mkAsech(std::shared_ptr< DAGNode > param)
Create an asech node.
std::shared_ptr< DAGNode > mkAdd(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an add node.
std::shared_ptr< DAGNode > mkBvSle(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed less than or equal node.
std::shared_ptr< DAGNode > mkPow(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an pow node.
std::shared_ptr< DAGNode > mkBvSge(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed greater than or equal node.
std::shared_ptr< DAGNode > mkStrIndexofReg(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string indexof-regex node.
std::shared_ptr< DAGNode > mkFpFma(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point fused multiply-add node.
std::shared_ptr< DAGNode > mkStrReplaceAll(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-all node.
std::shared_ptr< DAGNode > mkLg(std::shared_ptr< DAGNode > param)
Create an lg/log10 node.
std::shared_ptr< DAGNode > mkBvUge(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned greater than or equal node.
std::shared_ptr< DAGNode > mkBvXor(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a bitvector xor node.
std::shared_ptr< DAGNode > mkNatToBv(std::shared_ptr< DAGNode > param, std::shared_ptr< DAGNode > width)
Create a natural number to bitvector conversion node.
std::shared_ptr< DAGNode > mkStrNumSplitsRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
std::shared_ptr< DAGNode > mkFpIsNormal(std::shared_ptr< DAGNode > param)
Create a floating-point is-normal check node.
std::shared_ptr< DAGNode > mkLt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a lt node.
NODE_KIND getKind(const std::string &s)
Get kind.
std::shared_ptr< DAGNode > mkFpLe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point less than or equal node.
std::shared_ptr< DAGNode > mkFpIsNaN(std::shared_ptr< DAGNode > param)
Create a floating-point is-NaN check node.
std::shared_ptr< DAGNode > mkIand(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an iand node.
std::shared_ptr< DAGNode > parseExpr()
std::shared_ptr< DAGNode > mkRegRange(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a regex range node.
std::shared_ptr< DAGNode > mkAttribute(const std::shared_ptr< Sort > &sort, const std::string &name, const std::vector< std::shared_ptr< DAGNode > > &params)
std::shared_ptr< DAGNode > mkBvSgt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector signed greater than node.
std::shared_ptr< DAGNode > mkFpMul(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point multiplication node.
std::shared_ptr< DAGNode > mkLog(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an log node.
std::shared_ptr< DAGNode > mkStrGe(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a string greater-than-or-equal node.
std::shared_ptr< DAGNode > mkStrSplitAtRe(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::unique_ptr< NodeManager > node_manager
Definition parser.h:201
std::shared_ptr< DAGNode > mkStrSuffixof(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a string suffix check node.
std::shared_ptr< DAGNode > mkAtan2(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an atan2 node.
std::shared_ptr< DAGNode > mkStrToCode(std::shared_ptr< DAGNode > param)
Create a string to-code conversion node.
std::shared_ptr< DAGNode > mkConstStr(const std::string &v)
Create a string constant.
std::unique_ptr< SortManager > sort_manager
Definition parser.h:203
std::shared_ptr< DAGNode > mkPlaceholderVar(const std::string &name)
std::shared_ptr< DAGNode > mkRoundingMode(const std::string &mode)
Create a rounding mode constant.
std::shared_ptr< DAGNode > mkStrReplaceRegAll(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > v)
Create a string replace-regex-all node.
std::shared_ptr< DAGNode > mkImplies(const std::vector< std::shared_ptr< DAGNode > > &params)
Create an implies node.
std::shared_ptr< DAGNode > mkStrRev(std::shared_ptr< DAGNode > param)
Create a string reverse node.
std::shared_ptr< DAGNode > mkCsc(std::shared_ptr< DAGNode > param)
Create an csc node.
std::shared_ptr< DAGNode > mkBvUgt(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector unsigned greater than node.
std::shared_ptr< Sort > getSort(const std::vector< std::shared_ptr< DAGNode > > &params)
Get sort.
std::shared_ptr< DAGNode > mkFpGt(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point greater than node.
std::unordered_map< std::string, std::shared_ptr< DAGNode > > fun_key_map
Definition parser.h:209
std::shared_ptr< DAGNode > mkFpSub(const std::vector< std::shared_ptr< DAGNode > > &params)
Create a floating-point subtraction node.
std::shared_ptr< DAGNode > mkFloor(std::shared_ptr< DAGNode > param)
Create an floor node.
std::shared_ptr< DAGNode > mkAbs(std::shared_ptr< DAGNode > param)
Create an abs node.
std::shared_ptr< DAGNode > mkNeg(std::shared_ptr< DAGNode > param)
Create an neg node.
std::shared_ptr< DAGNode > mkExp(std::shared_ptr< DAGNode > param)
Create an exp node.
std::shared_ptr< DAGNode > mkBvLshr(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create a bitvector logical shift right node.
std::shared_ptr< DAGNode > mkStrSplitRest(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r, std::shared_ptr< DAGNode > s)
std::shared_ptr< DAGNode > mkAcot(std::shared_ptr< DAGNode > param)
Create an acot node.
std::shared_ptr< DAGNode > mkMod(std::shared_ptr< DAGNode > l, std::shared_ptr< DAGNode > r)
Create an mod node.
static const std::shared_ptr< Sort > INT_SORT
Definition sort.h:390
static std::shared_ptr< Sort > getNull()
Definition sort.h:351
static const std::shared_ptr< Sort > BOOL_SORT
Definition sort.h:388
static const std::shared_ptr< Sort > REAL_SORT
Definition sort.h:392
static const std::shared_ptr< Sort > NULL_SORT
Definition sort.h:384
static bool isReal(const std::string &str)
Definition util.cpp:58
static bool isScientificNotation(const std::string &str)
Definition util.cpp:75
static bool isFP(const std::string &str)
Definition util.cpp:248
static bool isString(const std::string &str)
Definition util.cpp:259
static bool isInt(const std::string &str)
Definition util.cpp:47
static bool isBV(const std::string &str)
Definition util.cpp:219
static bool isNumber(const std::string &str)
Definition util.cpp:43
const std::string PRESERVING_LET_BIND_VAR_SUFFIX
Definition kind.h:370
NODE_KIND getOperKind(const std::string &s)
Definition kind.cpp:718
std::shared_ptr< DAGNode > result
std::vector< std::shared_ptr< DAGNode > > func_args
std::vector< std::shared_ptr< DAGNode > > oper_params