/*****************************************************************************/
/*!
* \file parser.cpp
* \brief The top-level API to the parser. See parser.h for details.
*
* Author: Sergey Berezin
*
* Created: Wed Feb 5 11:46:57 2003
*
*
*
* 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.
*
*
*
*/
/*****************************************************************************/
#include
#include
#include
#include
#include "parser_temp.h"
#include "parser.h"
using namespace std;
// The communication entry points of the actual parsers
// for smtlib language (smtlib.y and smtlib.lex)
extern int smtlibparse();
extern void *smtlib_createBuffer(int);
extern void smtlib_deleteBuffer(void *);
extern void smtlib_switchToBuffer(void *);
extern int smtlib_bufSize();
extern void *smtlibBufState();
void smtlib_setInteractive(bool);
namespace CVC3 {
// The global pointer to ParserTemp. Each instance of class Parser
// sets this pointer before any calls to the lexer. We do it this
// way because flex and bison use global vars, and we want each
// Parser object to appear independent.
// FIXME: This should probably go away eventually, when I figure out
// flex++ -- Sergey.
ParserTemp* parserTemp;
int ParserTemp::error(const string& s) {
// FIXME: Fail better?
std::cerr << "error: " << s << "\n";
exit(1);
return 0;
}
// Internal storage class; I'll use member names without 'd_'s here
class ParserData {
public:
// Is the input given by the file name or as istream?
bool useName;
ParserTemp temp;
// Internal buffer used by the parser
void* buffer;
};
// Constructors
Parser::Parser(bool interactive, const std::string& fileName)
: d_data(new ParserData) {
if(fileName == "") {
// Use std::cin
d_data->useName = false;
d_data->temp.is = &cin;
d_data->temp.fileName = "stdin";
d_data->temp.interactive = interactive;
} else {
// Open the file by name
d_data->useName = true;
d_data->temp.fileName = fileName;
d_data->temp.is = new ifstream(fileName.c_str());
if (!(*d_data->temp.is)) {
// FIXME: Fail better?
std::cerr << "error: File not found: " << fileName << "\n";
exit(1);
}
d_data->temp.interactive = false;
}
initParser();
}
Parser::Parser(std::istream& is, bool interactive)
: d_data(new ParserData) {
d_data->useName = false;
d_data->temp.is = &is;
d_data->temp.fileName = "stdin";
d_data->temp.interactive = interactive;
initParser();
}
// Destructor
Parser::~Parser() {
if(d_data->useName) // Stream is ours; delete it
delete d_data->temp.is;
deleteParser();
delete d_data;
}
// Initialize the actual parser
void Parser::initParser() {
d_data->buffer = smtlib_createBuffer(smtlib_bufSize());
d_data->temp.lineNum = 1;
}
// Clean up the parser's internal data structures
void Parser::deleteParser() {
smtlib_deleteBuffer(d_data->buffer);
}
klee::expr::ExprHandle Parser::next() {
// If no more commands are available, return a Null Expr
if(d_data->temp.done) return NULL;//Expr();
// Set the global var so the parser uses the right stream and EM
parserTemp = &(d_data->temp);
// Switch to our buffer, in case there are multiple instances of
// the parser running
smtlib_switchToBuffer(d_data->buffer);
smtlib_setInteractive(d_data->temp.interactive);
smtlibparse();
// Reset the prompt to the main one
d_data->temp.setPrompt1();
return d_data->temp.expr;
}
bool Parser::done() const { return d_data->temp.done; }
void Parser::printLocation(ostream & out) const
{
out << d_data->temp.fileName << ":" << d_data->temp.lineNum;
}
void Parser::reset()
{
d_data->temp.expr = NULL;//Expr();
}
} // end of namespace CVC3