%{ /******************************************************************** * AUTHORS: Vijay Ganesh, David L. Dill * * BEGIN DATE: July, 2006 * * This file is modified version of the CVCL's smtlib.y file. Please * see CVCL license below ********************************************************************/ /******************************************************************** * * \file smtlib.y * * Author: Sergey Berezin, Clark Barrett * * Created: Apr 30 2005 * *
* Copyright (C) 2004 by the Board of Trustees of Leland Stanford * Junior University and by New York University. * * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. In particular: * * - The above copyright notice and this permission notice must appear * in all copies of the software and related documentation. * * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES, * EXPRESSED OR IMPLIED. USE IT AT YOUR OWN RISK. * *
********************************************************************/ // -*- c++ -*- #include "../AST/AST.h" using namespace std; // Suppress the bogus warning suppression in bison (it generates // compile error) #undef __GNUC_MINOR__ extern char* yytext; extern int yylineno; //int yylineno; extern int yylex(void); int yyerror(char *s) { //yylineno = 0; cout << "syntax error: line " << yylineno << "\n" << s << endl; cout << " token: " << yytext << endl; BEEV::FatalError(""); return 1; } BEEV::ASTNode query; #define YYLTYPE_IS_TRIVIAL 1 #define YYMAXDEPTH 104857600 #define YYERROR_VERBOSE 1 #define YY_EXIT_FAILURE -1 %} %union { // FIXME: Why is this not an UNSIGNED int? int uintval; /* for numerals in types. */ // for BV32 BVCONST unsigned long long ullval; struct { //stores the indexwidth and valuewidth //indexwidth is 0 iff type is bitvector. positive iff type is //array, and stores the width of the indexing bitvector unsigned int indexwidth; //width of the bitvector type unsigned int valuewidth; } indexvaluewidth; //ASTNode,ASTVec BEEV::ASTNode *node; BEEV::ASTVec *vec; std::string *str; }; %start cmd %type sort_symb sort_symbs %type status %type bench_attributes an_formulas %type benchmark bench_name bench_attribute %type an_term an_nonbvconst_term an_formula %type var fvar logic_name %type user_value %token NUMERAL_TOK %token BVCONST_TOK %token BITCONST_TOK %token FORMID_TOK TERMID_TOK %token STRING_TOK %token USER_VAL_TOK %token SOURCE_TOK %token CATEGORY_TOK %token DIFFICULTY_TOK %token BITVEC_TOK %token ARRAY_TOK %token SELECT_TOK %token STORE_TOK %token TRUE_TOK %token FALSE_TOK %token NOT_TOK %token IMPLIES_TOK %token ITE_TOK %token IF_THEN_ELSE_TOK %token AND_TOK %token OR_TOK %token XOR_TOK %token IFF_TOK %token EXISTS_TOK %token FORALL_TOK %token LET_TOK %token FLET_TOK %token NOTES_TOK %token CVC_COMMAND_TOK %token SORTS_TOK %token FUNS_TOK %token PREDS_TOK %token EXTENSIONS_TOK %token DEFINITION_TOK %token AXIOMS_TOK %token LOGIC_TOK %token COLON_TOK %token LBRACKET_TOK %token RBRACKET_TOK %token LPAREN_TOK %token RPAREN_TOK %token SAT_TOK %token UNSAT_TOK %token UNKNOWN_TOK %token ASSUMPTION_TOK %token FORMULA_TOK %token STATUS_TOK %token BENCHMARK_TOK %token EXTRASORTS_TOK %token EXTRAFUNS_TOK %token EXTRAPREDS_TOK %token LANGUAGE_TOK %token DOLLAR_TOK %token QUESTION_TOK %token DISTINCT_TOK %token SEMICOLON_TOK %token EOF_TOK %token EQ_TOK /*BV SPECIFIC TOKENS*/ %token NAND_TOK %token NOR_TOK %token NEQ_TOK %token ASSIGN_TOK %token BV_TOK %token BOOLEAN_TOK %token BVLEFTSHIFT_TOK %token BVLEFTSHIFT_1_TOK %token BVRIGHTSHIFT_TOK %token BVRIGHTSHIFT_1_TOK %token BVPLUS_TOK %token BVSUB_TOK %token BVNOT_TOK //bvneg in CVCL %token BVMULT_TOK %token BVDIV_TOK %token BVMOD_TOK %token BVNEG_TOK //bvuminus in CVCL %token BVAND_TOK %token BVOR_TOK %token BVXOR_TOK %token BVNAND_TOK %token BVNOR_TOK %token BVXNOR_TOK %token BVCONCAT_TOK %token BVLT_TOK %token BVGT_TOK %token BVLE_TOK %token BVGE_TOK %token BVSLT_TOK %token BVSGT_TOK %token BVSLE_TOK %token BVSGE_TOK %token BVSX_TOK %token BOOLEXTRACT_TOK %token BOOL_TO_BV_TOK %token BVEXTRACT_TOK %left LBRACKET_TOK RBRACKET_TOK %% cmd: benchmark { if($1 != NULL) { BEEV::globalBeevMgr_for_parser->TopLevelSAT(*$1,query); delete $1; } YYACCEPT; } ; benchmark: LPAREN_TOK BENCHMARK_TOK bench_name bench_attributes RPAREN_TOK { if($4 != NULL){ if($4->size() > 1) $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND,*$4)); else $$ = new BEEV::ASTNode((*$4)[0]); delete $4; } else { $$ = NULL; } } /* | EOF_TOK */ /* { */ /* } */ ; bench_name: FORMID_TOK { } ; bench_attributes: bench_attribute { $$ = new BEEV::ASTVec; if ($1 != NULL) { $$->push_back(*$1); BEEV::globalBeevMgr_for_parser->AddAssert(*$1); delete $1; } } | bench_attributes bench_attribute { if ($1 != NULL && $2 != NULL) { $1->push_back(*$2); BEEV::globalBeevMgr_for_parser->AddAssert(*$2); $$ = $1; delete $2; } } ; bench_attribute: COLON_TOK ASSUMPTION_TOK an_formula { //assumptions are like asserts $$ = $3; } | COLON_TOK FORMULA_TOK an_formula { //the query query = BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT,*$3); BEEV::globalBeevMgr_for_parser->AddQuery(query); //dummy true $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE)); } | COLON_TOK STATUS_TOK status { $$ = NULL; } | COLON_TOK LOGIC_TOK logic_name { if (!(0 == strcmp($3->GetName(),"QF_UFBV") || 0 == strcmp($3->GetName(),"QF_AUFBV"))) { yyerror("Wrong input logic:"); } $$ = NULL; } | COLON_TOK EXTRAFUNS_TOK LPAREN_TOK var_decls RPAREN_TOK { $$ = NULL; } | COLON_TOK EXTRAPREDS_TOK LPAREN_TOK var_decls RPAREN_TOK { $$ = NULL; } | annotation { $$ = NULL; } ; logic_name: FORMID_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK { $$ = $1; } | FORMID_TOK { $$ = $1; } ; status: SAT_TOK { $$ = NULL; } | UNSAT_TOK { $$ = NULL; } | UNKNOWN_TOK { $$ = NULL; } ; /* annotations: */ /* annotation */ /* { */ /* } */ /* | annotations annotation */ /* { */ /* } */ /* ; */ annotation: attribute { } | attribute user_value { } ; user_value: USER_VAL_TOK { //cerr << "Printing user_value: " << *$1 << endl; } ; attribute: COLON_TOK SOURCE_TOK { } | COLON_TOK CATEGORY_TOK { } | COLON_TOK DIFFICULTY_TOK ; sort_symbs: sort_symb { //a single sort symbol here means either a BitVec or a Boolean $$.indexwidth = $1.indexwidth; $$.valuewidth = $1.valuewidth; } | sort_symb sort_symb { //two sort symbols mean f: type --> type $$.indexwidth = $1.valuewidth; $$.valuewidth = $2.valuewidth; } ; var_decls: var_decl { } // | LPAREN_TOK var_decl RPAREN_TOK | var_decls var_decl { } ; var_decl: LPAREN_TOK FORMID_TOK sort_symbs RPAREN_TOK { BEEV::_parser_symbol_table.insert(*$2); //Sort_symbs has the indexwidth/valuewidth. Set those fields in //var $2->SetIndexWidth($3.indexwidth); $2->SetValueWidth($3.valuewidth); } | LPAREN_TOK FORMID_TOK RPAREN_TOK { BEEV::_parser_symbol_table.insert(*$2); //Sort_symbs has the indexwidth/valuewidth. Set those fields in //var $2->SetIndexWidth(0); $2->SetValueWidth(0); } ; an_formulas: an_formula { $$ = new BEEV::ASTVec; if ($1 != NULL) { $$->push_back(*$1); delete $1; } } | an_formulas an_formula { if ($1 != NULL && $2 != NULL) { $1->push_back(*$2); $$ = $1; delete $2; } } ; an_formula: TRUE_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE)); $$->SetIndexWidth(0); $$->SetValueWidth(0); } | FALSE_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::FALSE)); $$->SetIndexWidth(0); $$->SetValueWidth(0); } | fvar { $$ = $1; } | LPAREN_TOK EQ_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK EQ_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedEQ(*$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVSLT_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVSLT_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLT, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVSLE_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVSLE_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLE, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVSGT_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVSGT_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGT, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVSGE_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVSGE_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGE, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVLT_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVLT_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLT, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVLE_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVLE_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLE, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVGT_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVGT_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGT, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK BVGE_TOK an_term an_term RPAREN_TOK //| LPAREN_TOK BVGE_TOK an_term an_term annotations RPAREN_TOK { BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGE, *$3, *$4)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $3; delete $4; } | LPAREN_TOK an_formula RPAREN_TOK { $$ = $2; } | LPAREN_TOK NOT_TOK an_formula RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT, *$3)); delete $3; } | LPAREN_TOK IMPLIES_TOK an_formula an_formula RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IMPLIES, *$3, *$4)); delete $3; delete $4; } | LPAREN_TOK IF_THEN_ELSE_TOK an_formula an_formula an_formula RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$3, *$4, *$5)); delete $3; delete $4; delete $5; } | LPAREN_TOK AND_TOK an_formulas RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND, *$3)); delete $3; } | LPAREN_TOK OR_TOK an_formulas RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::OR, *$3)); delete $3; } | LPAREN_TOK XOR_TOK an_formula an_formula RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::XOR, *$3, *$4)); delete $3; delete $4; } | LPAREN_TOK IFF_TOK an_formula an_formula RPAREN_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IFF, *$3, *$4)); delete $3; delete $4; } | letexpr_mgmt an_formula RPAREN_TOK //| letexpr_mgmt an_formula annotations RPAREN_TOK { $$ = $2; //Cleanup the LetIDToExprMap BEEV::globalBeevMgr_for_parser->CleanupLetIDMap(); } ; letexpr_mgmt: LPAREN_TOK LET_TOK LPAREN_TOK QUESTION_TOK FORMID_TOK an_term RPAREN_TOK { //Expr must typecheck BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6); //set the valuewidth of the identifier $5->SetValueWidth($6->GetValueWidth()); $5->SetIndexWidth($6->GetIndexWidth()); //populate the hashtable from LET-var --> //LET-exprs and then process them: // //1. ensure that LET variables do not clash //1. with declared variables. // //2. Ensure that LET variables are not //2. defined more than once BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6); delete $5; delete $6; } | LPAREN_TOK FLET_TOK LPAREN_TOK DOLLAR_TOK FORMID_TOK an_formula RPAREN_TOK { //Expr must typecheck BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6); //set the valuewidth of the identifier $5->SetValueWidth($6->GetValueWidth()); $5->SetIndexWidth($6->GetIndexWidth()); //Do LET-expr management BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6); delete $5; delete $6; } /* an_terms: */ /* an_term */ /* { */ /* } */ /* | an_terms an_term */ /* { */ /* } */ /* ; */ an_term: BVCONST_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(64, $1)); } | BVCONST_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst($3, $1)); } | an_nonbvconst_term ; an_nonbvconst_term: BITCONST_TOK { $$ = $1; } | var { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1; } | LPAREN_TOK an_term RPAREN_TOK //| LPAREN_TOK an_term annotations RPAREN_TOK { $$ = $2; //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(*$2)); //delete $2; } | LPAREN_TOK TERMID_TOK an_term RPAREN_TOK { //ARRAY READ // valuewidth is same as array, indexwidth is 0. BEEV::ASTNode in = *$2; BEEV::ASTNode m = *$3; unsigned int width = in.GetValueWidth(); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, in, m)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | SELECT_TOK an_term an_term { //ARRAY READ // valuewidth is same as array, indexwidth is 0. BEEV::ASTNode array = *$2; BEEV::ASTNode index = *$3; unsigned int width = array.GetValueWidth(); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, array, index)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | STORE_TOK an_term an_term an_term { //ARRAY WRITE unsigned int width = $4->GetValueWidth(); BEEV::ASTNode array = *$2; BEEV::ASTNode index = *$3; BEEV::ASTNode writeval = *$4; BEEV::ASTNode write_term = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,width,array,index,writeval); write_term.SetIndexWidth($2->GetIndexWidth()); BEEV::globalBeevMgr_for_parser->BVTypeCheck(write_term); BEEV::ASTNode * n = new BEEV::ASTNode(write_term); $$ = n; delete $2; delete $3; delete $4; } /* | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK BVCONST_TOK */ /* { */ /* // This special case is when we have an extract on top of a constant bv, which happens */ /* // almost all the time in the smt syntax. */ /* // $3 is high, $5 is low. They are ints (why not unsigned? See uintval) */ /* int hi = $3; */ /* int low = $5; */ /* int width = hi - low + 1; */ /* if (width < 0) */ /* yyerror("Negative width in extract"); */ /* unsigned long long int val = $7; */ /* // cut and past from BV32 const evaluator */ /* unsigned long long int mask1 = 0xffffffffffffffffLL; */ /* mask1 >>= 64-(hi+1); */ /* //extract val[hi:0] */ /* val &= mask1; */ /* //extract val[hi:low] */ /* val >>= low; */ /* // val is the desired BV32. */ /* BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(width, val)); */ /* $$ = n; */ /* } */ | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK an_term { int width = $3 - $5 + 1; if (width < 0) yyerror("Negative width in extract"); if((unsigned)$3 >= $7->GetValueWidth() || (unsigned)$5 < 0) yyerror("Parsing: Wrong width in BVEXTRACT\n"); BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $3); BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5); BEEV::ASTNode output = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT, width, *$7,hi,low); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(output)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $7; } | ITE_TOK an_formula an_term an_term { unsigned int width = $3->GetValueWidth(); if (width != $4->GetValueWidth()) { cerr << *$3; cerr << *$4; yyerror("Width mismatch in IF-THEN-ELSE"); } if($3->GetIndexWidth() != $4->GetIndexWidth()) yyerror("Width mismatch in IF-THEN-ELSE"); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4); $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedTermITE(*$2, *$3, *$4)); //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE,width,*$2, *$3, *$4)); $$->SetIndexWidth($4->GetIndexWidth()); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$); delete $2; delete $3; delete $4; } | BVCONCAT_TOK an_term an_term { unsigned int width = $2->GetValueWidth() + $3->GetValueWidth(); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVNOT_TOK an_term { //this is the BVNEG (term) in the CVCL language unsigned int width = $2->GetValueWidth(); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNEG, width, *$2)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; } | BVNEG_TOK an_term { //this is the BVUMINUS term in CVCL langauge unsigned width = $2->GetValueWidth(); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVUMINUS,width,*$2)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; } | BVAND_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in AND"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVAND, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVOR_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in OR"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVOR, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVXOR_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in XOR"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXOR, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVSUB_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in BVSUB"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSUB, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVPLUS_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in BVPLUS"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVPLUS, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVMULT_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in BVMULT"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMULT, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVNAND_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in BVNAND"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNAND, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVNOR_TOK an_term an_term { unsigned int width = $2->GetValueWidth(); if (width != $3->GetValueWidth()) { yyerror("Width mismatch in BVNOR"); } BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNOR, width, *$2, *$3)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $2; delete $3; } | BVLEFTSHIFT_TOK an_term NUMERAL_TOK { unsigned int w = $2->GetValueWidth(); if((unsigned)$3 < w) { BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0); BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-$3-1); BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0); BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; } else $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0)); delete $2; } | BVLEFTSHIFT_1_TOK an_term an_term { unsigned int w = $2->GetValueWidth(); unsigned int shift_amt = GetUnsignedConst(*$3); if((unsigned)shift_amt < w) { BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0); BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-shift_amt-1); BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0); BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; } else { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0)); } delete $2; //delete $3; } | BVRIGHTSHIFT_TOK an_term NUMERAL_TOK { BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0); unsigned int w = $2->GetValueWidth(); //the amount by which you are rightshifting //is less-than/equal-to the length of input //bitvector if((unsigned)$3 < w) { BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1); BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$3); BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; } else { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0)); } delete $2; } | BVRIGHTSHIFT_1_TOK an_term an_term { unsigned int shift_amt = GetUnsignedConst(*$3); BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0); unsigned int w = $2->GetValueWidth(); //the amount by which you are rightshifting //is less-than/equal-to the length of input //bitvector if((unsigned)shift_amt < w) { BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1); BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,shift_amt); BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low); BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; } else { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0)); } delete $2; } | BVSX_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK an_term { BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5); unsigned w = $5->GetValueWidth() + $3; BEEV::ASTNode width = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w); BEEV::ASTNode *n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSX,w,*$5,width)); BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n); $$ = n; delete $5; } ; sort_symb: BITVEC_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK { // Just return BV width. If sort is BOOL, width is 0. // Otherwise, BITVEC[w] returns w. // //((indexwidth is 0) && (valuewidth>0)) iff type is BV $$.indexwidth = 0; unsigned int length = $3; if(length > 0) { $$.valuewidth = length; } else { BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n"); } } | ARRAY_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK { unsigned int index_len = $3; unsigned int value_len = $5; if(index_len > 0) { $$.indexwidth = $3; } else { BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n"); } if(value_len > 0) { $$.valuewidth = $5; } else { BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n"); } } ; var: FORMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1; } | TERMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1; } | QUESTION_TOK TERMID_TOK { $$ = $2; } ; fvar: DOLLAR_TOK FORMID_TOK { $$ = $2; } | FORMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1; } ; %%