mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
Reorganizing the code
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
aa949693d4
commit
6bc591c67e
15 changed files with 4 additions and 2 deletions
94
src/ast/has_free_vars.cpp
Normal file
94
src/ast/has_free_vars.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
has_free_vars.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-23.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast.h"
|
||||
#include"expr_delta_pair.h"
|
||||
#include"hashtable.h"
|
||||
|
||||
class contains_vars {
|
||||
typedef hashtable<expr_delta_pair, obj_hash<expr_delta_pair>, default_eq<expr_delta_pair> > cache;
|
||||
cache m_cache;
|
||||
svector<expr_delta_pair> m_todo;
|
||||
bool m_contains;
|
||||
unsigned m_window;
|
||||
|
||||
void visit(expr * n, unsigned delta, bool & visited) {
|
||||
expr_delta_pair e(n, delta);
|
||||
if (!m_cache.contains(e)) {
|
||||
m_todo.push_back(e);
|
||||
visited = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_children(expr * n, unsigned delta) {
|
||||
bool visited = true;
|
||||
unsigned dw;
|
||||
unsigned j;
|
||||
switch (n->get_kind()) {
|
||||
case AST_VAR:
|
||||
dw = m_window <= UINT_MAX - delta ? m_window + delta : UINT_MAX;
|
||||
if (to_var(n)->get_idx() >= delta && to_var(n)->get_idx() <= dw)
|
||||
m_contains = true;
|
||||
break;
|
||||
case AST_APP:
|
||||
j = to_app(n)->get_num_args();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
visit(to_app(n)->get_arg(j), delta, visited);
|
||||
}
|
||||
break;
|
||||
case AST_QUANTIFIER:
|
||||
if (delta <= UINT_MAX - to_quantifier(n)->get_num_decls()) {
|
||||
visit(to_quantifier(n)->get_expr(), delta + to_quantifier(n)->get_num_decls(), visited);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return visited;
|
||||
}
|
||||
|
||||
public:
|
||||
// return true if n contains a variable in the range [begin, end]
|
||||
bool operator()(expr * n, unsigned begin = 0, unsigned end = UINT_MAX) {
|
||||
m_contains = false;
|
||||
m_window = end - begin;
|
||||
m_todo.reset();
|
||||
m_cache.reset();
|
||||
m_todo.push_back(expr_delta_pair(n, begin));
|
||||
while (!m_todo.empty()) {
|
||||
expr_delta_pair e = m_todo.back();
|
||||
if (visit_children(e.m_node, e.m_delta)) {
|
||||
m_cache.insert(e);
|
||||
m_todo.pop_back();
|
||||
}
|
||||
if (m_contains) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SASSERT(!m_contains);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
bool has_free_vars(expr * n) {
|
||||
contains_vars p;
|
||||
return p(n);
|
||||
}
|
||||
|
||||
|
27
src/ast/has_free_vars.h
Normal file
27
src/ast/has_free_vars.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
has_free_vars.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-23.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _HAS_FREE_VARS_H_
|
||||
#define _HAS_FREE_VARS_H_
|
||||
|
||||
class expr;
|
||||
|
||||
bool has_free_vars(expr * n);
|
||||
|
||||
#endif /* _HAS_FREE_VARS_H_ */
|
||||
|
121
src/framework/extension_model_converter.cpp
Normal file
121
src/framework/extension_model_converter.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
extension_model_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Model converter that introduces eliminated variables in a model.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-21
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"extension_model_converter.h"
|
||||
#include"model_evaluator.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"model_v2_pp.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
extension_model_converter::~extension_model_converter() {
|
||||
}
|
||||
|
||||
struct extension_model_converter::set_eval {
|
||||
extension_model_converter * m_owner;
|
||||
model_evaluator * m_old;
|
||||
set_eval(extension_model_converter * owner, model_evaluator * ev) {
|
||||
m_owner = owner;
|
||||
m_old = owner->m_eval;
|
||||
#pragma omp critical (extension_model_converter)
|
||||
{
|
||||
owner->m_eval = ev;
|
||||
}
|
||||
}
|
||||
~set_eval() {
|
||||
#pragma omp critical (extension_model_converter)
|
||||
{
|
||||
m_owner->m_eval = m_old;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static void display_decls_info(std::ostream & out, model_ref & md) {
|
||||
ast_manager & m = md->get_manager();
|
||||
unsigned sz = md->get_num_decls();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
func_decl * d = md->get_decl(i);
|
||||
out << d->get_name();
|
||||
out << " (";
|
||||
for (unsigned j = 0; j < d->get_arity(); j++)
|
||||
out << mk_pp(d->get_domain(j), m);
|
||||
out << mk_pp(d->get_range(), m);
|
||||
out << ") ";
|
||||
if (d->get_info())
|
||||
out << *(d->get_info());
|
||||
out << " :id " << d->get_id() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void extension_model_converter::operator()(model_ref & md, unsigned goal_idx) {
|
||||
SASSERT(goal_idx == 0);
|
||||
TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
|
||||
model_evaluator ev(*(md.get()));
|
||||
ev.set_model_completion(true);
|
||||
expr_ref val(m());
|
||||
{
|
||||
set_eval setter(this, &ev);
|
||||
unsigned i = m_vars.size();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
expr * def = m_defs.get(i);
|
||||
ev(def, val);
|
||||
TRACE("extension_mc", tout << m_vars.get(i)->get_name() << " ->\n" << mk_ismt2_pp(def, m()) << "\n==>\n" << mk_ismt2_pp(val, m()) << "\n";);
|
||||
func_decl * f = m_vars.get(i);
|
||||
unsigned arity = f->get_arity();
|
||||
if (arity == 0) {
|
||||
md->register_decl(f, val);
|
||||
}
|
||||
else {
|
||||
func_interp * new_fi = alloc(func_interp, m(), arity);
|
||||
new_fi->set_else(val);
|
||||
md->register_decl(f, new_fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
|
||||
}
|
||||
|
||||
void extension_model_converter::cancel() {
|
||||
#pragma omp critical (extension_model_converter)
|
||||
{
|
||||
if (m_eval)
|
||||
m_eval->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void extension_model_converter::display(std::ostream & out) {
|
||||
ast_manager & m = m_vars.get_manager();
|
||||
out << "(extension-model-converter";
|
||||
for (unsigned i = 0; i < m_vars.size(); i++) {
|
||||
out << "\n (" << m_vars.get(i)->get_name() << " ";
|
||||
unsigned indent = m_vars.get(i)->get_name().size() + 4;
|
||||
out << mk_ismt2_pp(m_defs.get(i), m, indent) << ")";
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
model_converter * extension_model_converter::translate(ast_translation & translator) {
|
||||
extension_model_converter * res = alloc(extension_model_converter, translator.to());
|
||||
for (unsigned i = 0; i < m_vars.size(); i++)
|
||||
res->m_vars.push_back(translator(m_vars[i].get()));
|
||||
for (unsigned i = 0; i < m_defs.size(); i++)
|
||||
res->m_defs.push_back(translator(m_defs[i].get()));
|
||||
// m_eval is a transient object. So, it doesn't need to be translated.
|
||||
return res;
|
||||
}
|
57
src/framework/extension_model_converter.h
Normal file
57
src/framework/extension_model_converter.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
extension_model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Model converter that introduces new interpretations into a model.
|
||||
It used to be called elim_var_model_converter
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-21
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _EXTENSION_MODEL_CONVERTER_H_
|
||||
#define _EXTENSION_MODEL_CONVERTER_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"model_converter.h"
|
||||
|
||||
class model_evaluator;
|
||||
|
||||
class extension_model_converter : public model_converter {
|
||||
func_decl_ref_vector m_vars;
|
||||
expr_ref_vector m_defs;
|
||||
model_evaluator * m_eval;
|
||||
struct set_eval;
|
||||
public:
|
||||
extension_model_converter(ast_manager & m):m_vars(m), m_defs(m), m_eval(0) {
|
||||
}
|
||||
|
||||
virtual ~extension_model_converter();
|
||||
|
||||
ast_manager & m() const { return m_vars.get_manager(); }
|
||||
|
||||
virtual void operator()(model_ref & md, unsigned goal_idx);
|
||||
|
||||
virtual void cancel();
|
||||
|
||||
virtual void display(std::ostream & out);
|
||||
|
||||
// register a variable that was eliminated
|
||||
void insert(func_decl * v, expr * def) {
|
||||
m_vars.push_back(v);
|
||||
m_defs.push_back(def);
|
||||
}
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
66
src/framework/filter_model_converter.cpp
Normal file
66
src/framework/filter_model_converter.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
filter_model_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Filter decls from a model
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-06
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"filter_model_converter.h"
|
||||
#include"model_v2_pp.h"
|
||||
|
||||
filter_model_converter::~filter_model_converter() {
|
||||
}
|
||||
|
||||
void filter_model_converter::operator()(model_ref & old_model, unsigned goal_idx) {
|
||||
TRACE("filter_mc", tout << "before filter_model_converter\n"; model_v2_pp(tout, *old_model); display(tout););
|
||||
ast_fast_mark1 fs;
|
||||
unsigned num = m_decls.size();
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
fs.mark(m_decls.get(i));
|
||||
model * new_model = alloc(model, m());
|
||||
num = old_model->get_num_constants();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
func_decl * f = old_model->get_constant(i);
|
||||
if (fs.is_marked(f))
|
||||
continue;
|
||||
expr * fi = old_model->get_const_interp(f);
|
||||
new_model->register_decl(f, fi);
|
||||
}
|
||||
num = old_model->get_num_functions();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
func_decl * f = old_model->get_function(i);
|
||||
if (fs.is_marked(f))
|
||||
continue;
|
||||
func_interp * fi = old_model->get_func_interp(f);
|
||||
new_model->register_decl(f, fi->copy());
|
||||
}
|
||||
new_model->copy_usort_interps(*old_model);
|
||||
old_model = new_model;
|
||||
TRACE("filter_mc", tout << "after filter_model_converter\n"; model_v2_pp(tout, *old_model););
|
||||
}
|
||||
|
||||
void filter_model_converter::display(std::ostream & out) {
|
||||
out << "(filter-model-converter";
|
||||
for (unsigned i = 0; i < m_decls.size(); i++) {
|
||||
out << " " << m_decls.get(i)->get_name();
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
model_converter * filter_model_converter::translate(ast_translation & translator) {
|
||||
filter_model_converter * res = alloc(filter_model_converter, translator.to());
|
||||
for (unsigned i = 0; i < m_decls.size(); i++)
|
||||
res->m_decls.push_back(translator(m_decls[i].get()));
|
||||
return res;
|
||||
}
|
48
src/framework/filter_model_converter.h
Normal file
48
src/framework/filter_model_converter.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
filter_model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Filter decls from a model
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-06
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _FILTER_MODEL_CONVERTER_H_
|
||||
#define _FILTER_MODEL_CONVERTER_H_
|
||||
|
||||
#include"model_converter.h"
|
||||
|
||||
class filter_model_converter : public model_converter {
|
||||
func_decl_ref_vector m_decls;
|
||||
public:
|
||||
filter_model_converter(ast_manager & m):m_decls(m) {}
|
||||
|
||||
virtual ~filter_model_converter();
|
||||
|
||||
ast_manager & m() const { return m_decls.get_manager(); }
|
||||
|
||||
virtual void operator()(model_ref & md, unsigned goal_idx);
|
||||
|
||||
virtual void operator()(model_ref & md) { operator()(md, 0); } // TODO: delete
|
||||
|
||||
virtual void cancel() {}
|
||||
|
||||
virtual void display(std::ostream & out);
|
||||
|
||||
void insert(func_decl * d) {
|
||||
m_decls.push_back(d);
|
||||
}
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator);
|
||||
};
|
||||
|
||||
#endif
|
2491
src/smt2parser/smt2parser.cpp
Normal file
2491
src/smt2parser/smt2parser.cpp
Normal file
File diff suppressed because it is too large
Load diff
26
src/smt2parser/smt2parser.h
Normal file
26
src/smt2parser/smt2parser.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt2parser.h
|
||||
|
||||
Abstract:
|
||||
|
||||
SMT 2.0 parser
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-03-01
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SMT2_PARSER_H_
|
||||
#define _SMT2_PARSER_H_
|
||||
|
||||
#include"cmd_context.h"
|
||||
|
||||
bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive = false);
|
||||
|
||||
#endif
|
355
src/smt2parser/smt2scanner.cpp
Normal file
355
src/smt2parser/smt2scanner.cpp
Normal file
|
@ -0,0 +1,355 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt2scanner.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"smt2scanner.h"
|
||||
|
||||
namespace smt2 {
|
||||
|
||||
void scanner::next() {
|
||||
if (m_cache_input)
|
||||
m_cache.push_back(m_curr);
|
||||
SASSERT(m_curr != EOF);
|
||||
if (m_interactive) {
|
||||
m_curr = m_stream.get();
|
||||
}
|
||||
else if (m_bpos < m_bend) {
|
||||
m_curr = m_buffer[m_bpos];
|
||||
m_bpos++;
|
||||
}
|
||||
else {
|
||||
m_stream.read(m_buffer, SCANNER_BUFFER_SIZE);
|
||||
m_bend = static_cast<unsigned>(m_stream.gcount());
|
||||
m_bpos = 0;
|
||||
if (m_bpos == m_bend) {
|
||||
m_curr = EOF;
|
||||
}
|
||||
else {
|
||||
m_curr = m_buffer[m_bpos];
|
||||
m_bpos++;
|
||||
}
|
||||
}
|
||||
m_spos++;
|
||||
}
|
||||
|
||||
void scanner::read_comment() {
|
||||
SASSERT(curr() == ';');
|
||||
next();
|
||||
while (true) {
|
||||
char c = curr();
|
||||
if (c == EOF)
|
||||
return;
|
||||
if (c == '\n') {
|
||||
new_line();
|
||||
next();
|
||||
return;
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
scanner::token scanner::read_quoted_symbol() {
|
||||
SASSERT(curr() == '|');
|
||||
bool escape = false;
|
||||
m_string.reset();
|
||||
next();
|
||||
while (true) {
|
||||
char c = curr();
|
||||
if (c == EOF) {
|
||||
throw scanner_exception("unexpected end of quoted symbol", m_line, m_spos);
|
||||
}
|
||||
else if (c == '\n') {
|
||||
new_line();
|
||||
}
|
||||
else if (c == '|' && !escape) {
|
||||
next();
|
||||
m_string.push_back(0);
|
||||
m_id = m_string.begin();
|
||||
TRACE("scanner", tout << "new quoted symbol: " << m_id << "\n";);
|
||||
return SYMBOL_TOKEN;
|
||||
}
|
||||
escape = (c == '\\');
|
||||
m_string.push_back(c);
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
scanner::token scanner::read_symbol_core() {
|
||||
while (true) {
|
||||
char c = curr();
|
||||
char n = m_normalized[static_cast<unsigned char>(c)];
|
||||
if (n == 'a' || n == '0' || n == '-') {
|
||||
m_string.push_back(c);
|
||||
next();
|
||||
}
|
||||
else {
|
||||
m_string.push_back(0);
|
||||
m_id = m_string.begin();
|
||||
TRACE("scanner", tout << "new symbol: " << m_id << "\n";);
|
||||
return SYMBOL_TOKEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scanner::token scanner::read_symbol() {
|
||||
SASSERT(m_normalized[static_cast<unsigned>(curr())] == 'a' || curr() == ':' || curr() == '-');
|
||||
m_string.reset();
|
||||
m_string.push_back(curr());
|
||||
next();
|
||||
return read_symbol_core();
|
||||
}
|
||||
|
||||
scanner::token scanner::read_number() {
|
||||
SASSERT('0' <= curr() && curr() <= '9');
|
||||
rational q(1);
|
||||
m_number = rational(curr() - '0');
|
||||
next();
|
||||
bool is_float = false;
|
||||
|
||||
while (true) {
|
||||
char c = curr();
|
||||
if ('0' <= c && c <= '9') {
|
||||
m_number = rational(10)*m_number + rational(c - '0');
|
||||
if (is_float)
|
||||
q *= rational(10);
|
||||
next();
|
||||
}
|
||||
else if (c == '.') {
|
||||
if (is_float)
|
||||
break;
|
||||
is_float = true;
|
||||
next();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_float)
|
||||
m_number /= q;
|
||||
TRACE("scanner", tout << "new number: " << m_number << "\n";);
|
||||
return is_float ? FLOAT_TOKEN : INT_TOKEN;
|
||||
}
|
||||
|
||||
scanner::token scanner::read_signed_number() {
|
||||
SASSERT(curr() == '-');
|
||||
next();
|
||||
if ('0' <= curr() && curr() <= '9') {
|
||||
scanner::token r = read_number();
|
||||
m_number.neg();
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
// it is a symbol.
|
||||
m_string.reset();
|
||||
m_string.push_back('-');
|
||||
return read_symbol_core();
|
||||
}
|
||||
}
|
||||
|
||||
scanner::token scanner::read_string() {
|
||||
SASSERT(curr() == '\"');
|
||||
next();
|
||||
m_string.reset();
|
||||
while (true) {
|
||||
char c = curr();
|
||||
if (c == EOF)
|
||||
throw scanner_exception("unexpected end of string", m_line, m_spos);
|
||||
if (c == '\"') {
|
||||
next();
|
||||
m_string.push_back(0);
|
||||
return STRING_TOKEN;
|
||||
}
|
||||
if (c == '\n')
|
||||
new_line();
|
||||
else if (c == '\\') {
|
||||
next();
|
||||
c = curr();
|
||||
if (c == EOF)
|
||||
throw scanner_exception("unexpected end of string", m_line, m_spos);
|
||||
if (c != '\\' && c != '\"')
|
||||
throw scanner_exception("invalid escape sequence", m_line, m_spos);
|
||||
}
|
||||
m_string.push_back(c);
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
scanner::token scanner::read_bv_literal() {
|
||||
SASSERT(curr() == '#');
|
||||
next();
|
||||
char c = curr();
|
||||
if (c == 'x') {
|
||||
next();
|
||||
c = curr();
|
||||
m_number = rational(0);
|
||||
m_bv_size = 0;
|
||||
while (true) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
m_number *= rational(16);
|
||||
m_number += rational(c - '0');
|
||||
}
|
||||
else if ('a' <= c && c <= 'f') {
|
||||
m_number *= rational(16);
|
||||
m_number += rational(10 + (c - 'a'));
|
||||
}
|
||||
else if ('A' <= c && c <= 'F') {
|
||||
m_number *= rational(16);
|
||||
m_number += rational(10 + (c - 'A'));
|
||||
}
|
||||
else {
|
||||
if (m_bv_size == 0)
|
||||
throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
|
||||
return BV_TOKEN;
|
||||
}
|
||||
m_bv_size += 4;
|
||||
next();
|
||||
c = curr();
|
||||
}
|
||||
}
|
||||
else if (c == 'b') {
|
||||
next();
|
||||
c = curr();
|
||||
m_number = rational(0);
|
||||
m_bv_size = 0;
|
||||
while (c == '0' || c == '1') {
|
||||
m_number *= rational(2);
|
||||
m_number += rational(c - '0');
|
||||
m_bv_size++;
|
||||
next();
|
||||
c = curr();
|
||||
}
|
||||
if (m_bv_size == 0)
|
||||
throw scanner_exception("invalid empty bit-vector literal", m_line, m_spos);
|
||||
return BV_TOKEN;
|
||||
}
|
||||
else {
|
||||
throw scanner_exception("invalid bit-vector literal, expecting 'x' or 'b'", m_line, m_spos);
|
||||
}
|
||||
}
|
||||
|
||||
scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive):
|
||||
m_ctx(ctx),
|
||||
m_interactive(interactive),
|
||||
m_spos(0),
|
||||
m_curr(0), // avoid Valgrind warning
|
||||
m_line(1),
|
||||
m_pos(0),
|
||||
m_bv_size(UINT_MAX),
|
||||
m_bpos(0),
|
||||
m_bend(0),
|
||||
m_stream(stream),
|
||||
m_cache_input(false) {
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
m_normalized[i] = (char) i;
|
||||
}
|
||||
m_normalized[static_cast<int>('\t')] = ' ';
|
||||
m_normalized[static_cast<int>('\r')] = ' ';
|
||||
// assert ('a' < 'z');
|
||||
for (char ch = 'b'; ch <= 'z'; ++ch) {
|
||||
m_normalized[static_cast<int>(ch)] = 'a';
|
||||
}
|
||||
for (char ch = 'A'; ch <= 'Z'; ++ch) {
|
||||
m_normalized[static_cast<int>(ch)] = 'a';
|
||||
}
|
||||
// assert ('0' < '9', '9' - '0' == 9);
|
||||
for (char ch = '1'; ch <= '9'; ++ch) {
|
||||
m_normalized[static_cast<int>(ch)] = '0';
|
||||
}
|
||||
// SMT2 "Symbols": ~ ! @ $ % ^ & * _ - + = < > . ? /
|
||||
m_normalized[static_cast<int>('~')] = 'a';
|
||||
m_normalized[static_cast<int>('!')] = 'a';
|
||||
m_normalized[static_cast<int>('@')] = 'a';
|
||||
m_normalized[static_cast<int>('$')] = 'a';
|
||||
m_normalized[static_cast<int>('%')] = 'a';
|
||||
m_normalized[static_cast<int>('^')] = 'a';
|
||||
m_normalized[static_cast<int>('&')] = 'a';
|
||||
m_normalized[static_cast<int>('*')] = 'a';
|
||||
m_normalized[static_cast<int>('_')] = 'a';
|
||||
m_normalized[static_cast<int>('-')] = '-';
|
||||
m_normalized[static_cast<int>('+')] = 'a';
|
||||
m_normalized[static_cast<int>('=')] = 'a';
|
||||
m_normalized[static_cast<int>('<')] = 'a';
|
||||
m_normalized[static_cast<int>('>')] = 'a';
|
||||
m_normalized[static_cast<int>('.')] = 'a';
|
||||
m_normalized[static_cast<int>('?')] = 'a';
|
||||
m_normalized[static_cast<int>('/')] = 'a';
|
||||
next();
|
||||
}
|
||||
|
||||
scanner::token scanner::scan() {
|
||||
while (true) {
|
||||
char c = curr();
|
||||
m_pos = m_spos;
|
||||
switch (m_normalized[(unsigned char) c]) {
|
||||
case ' ':
|
||||
next();
|
||||
break;
|
||||
case '\n':
|
||||
next();
|
||||
new_line();
|
||||
break;
|
||||
case ';':
|
||||
read_comment();
|
||||
break;
|
||||
case ':':
|
||||
read_symbol();
|
||||
return KEYWORD_TOKEN;
|
||||
case '(':
|
||||
next();
|
||||
return LEFT_PAREN;
|
||||
case ')':
|
||||
next();
|
||||
return RIGHT_PAREN;
|
||||
case '|':
|
||||
return read_quoted_symbol();
|
||||
case 'a':
|
||||
return read_symbol();
|
||||
case '"':
|
||||
return read_string();
|
||||
case '0':
|
||||
return read_number();
|
||||
case '#':
|
||||
return read_bv_literal();
|
||||
case '-':
|
||||
if (m_ctx.is_smtlib2_compliant())
|
||||
return read_symbol();
|
||||
else
|
||||
return read_signed_number();
|
||||
case -1:
|
||||
return EOF_TOKEN;
|
||||
default: {
|
||||
scanner_exception ex("unexpected character", m_line, m_spos);
|
||||
next();
|
||||
throw ex;
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
char const * scanner::cached_str(unsigned begin, unsigned end) {
|
||||
m_cache_result.reset();
|
||||
while (isspace(m_cache[begin]) && begin < end)
|
||||
begin++;
|
||||
while (begin < end && isspace(m_cache[end-1]))
|
||||
end--;
|
||||
for (unsigned i = begin; i < end; i++)
|
||||
m_cache_result.push_back(m_cache[i]);
|
||||
m_cache_result.push_back(0);
|
||||
return m_cache_result.begin();
|
||||
}
|
||||
|
||||
};
|
||||
|
108
src/smt2parser/smt2scanner.h
Normal file
108
src/smt2parser/smt2scanner.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt2scanner.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SMT2SCANNER_H_
|
||||
#define _SMT2SCANNER_H_
|
||||
|
||||
#include<iostream>
|
||||
#include"symbol.h"
|
||||
#include"vector.h"
|
||||
#include"rational.h"
|
||||
#include"cmd_context.h"
|
||||
|
||||
namespace smt2 {
|
||||
|
||||
typedef cmd_exception scanner_exception;
|
||||
|
||||
class scanner {
|
||||
private:
|
||||
cmd_context & m_ctx;
|
||||
bool m_interactive;
|
||||
int m_spos; // position in the current line of the stream
|
||||
char m_curr; // current char;
|
||||
|
||||
int m_line; // line
|
||||
int m_pos; // start position of the token
|
||||
// data
|
||||
symbol m_id;
|
||||
rational m_number;
|
||||
unsigned m_bv_size;
|
||||
// end of data
|
||||
char m_normalized[256];
|
||||
#define SCANNER_BUFFER_SIZE 1024
|
||||
char m_buffer[SCANNER_BUFFER_SIZE];
|
||||
unsigned m_bpos;
|
||||
unsigned m_bend;
|
||||
svector<char> m_string;
|
||||
std::istream& m_stream;
|
||||
|
||||
bool m_cache_input;
|
||||
svector<char> m_cache;
|
||||
svector<char> m_cache_result;
|
||||
|
||||
char curr() const { return m_curr; }
|
||||
void new_line() { m_line++; m_spos = 0; }
|
||||
void next();
|
||||
|
||||
public:
|
||||
|
||||
enum token {
|
||||
NULL_TOKEN = 0,
|
||||
LEFT_PAREN = 1,
|
||||
RIGHT_PAREN,
|
||||
KEYWORD_TOKEN,
|
||||
SYMBOL_TOKEN,
|
||||
STRING_TOKEN,
|
||||
INT_TOKEN,
|
||||
BV_TOKEN,
|
||||
FLOAT_TOKEN,
|
||||
EOF_TOKEN
|
||||
};
|
||||
|
||||
scanner(cmd_context & ctx, std::istream& stream, bool interactive = false);
|
||||
|
||||
~scanner() {}
|
||||
|
||||
int get_line() const { return m_line; }
|
||||
int get_pos() const { return m_pos; }
|
||||
symbol const & get_id() const { return m_id; }
|
||||
rational get_number() const { return m_number; }
|
||||
unsigned get_bv_size() const { return m_bv_size; }
|
||||
char const * get_string() const { return m_string.begin(); }
|
||||
token scan();
|
||||
|
||||
token read_symbol_core();
|
||||
token read_symbol();
|
||||
token read_quoted_symbol();
|
||||
void read_comment();
|
||||
token read_number();
|
||||
token read_signed_number();
|
||||
token read_string();
|
||||
token read_bv_literal();
|
||||
|
||||
void start_caching() { m_cache_input = true; m_cache.reset(); }
|
||||
void stop_caching() { m_cache_input = false; }
|
||||
unsigned cache_size() const { return m_cache.size(); }
|
||||
void reset_cache() { m_cache.reset(); }
|
||||
char const * cached_str(unsigned begin, unsigned end);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SCANNER_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue