diff --git a/examples/c_parser_context/CMakeLists.txt b/examples/c_parser_context/CMakeLists.txt new file mode 100644 index 000000000..daed8ed36 --- /dev/null +++ b/examples/c_parser_context/CMakeLists.txt @@ -0,0 +1,56 @@ +################################################################################ +# Example C parser context project +################################################################################ +# NOTE: Even though this is a C project, libz3 uses C++. When using libz3 +# as a static library if we don't configure this project to also support +# C++ we will use the C linker rather than the C++ linker and will not link +# the C++ standard library in resulting in a link failure. +project(Z3_C_PARSER_CONTEXT_EXAMPLE C CXX) +cmake_minimum_required(VERSION 3.4) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_EXTENSIONS OFF) + +find_package(Z3 + REQUIRED + CONFIG + # `NO_DEFAULT_PATH` is set so that -DZ3_DIR has to be passed to find Z3. + # This should prevent us from accidentally picking up an installed + # copy of Z3. This is here to benefit Z3's build system when building + # this project. When making your own project you probably shouldn't + # use this option. + NO_DEFAULT_PATH +) +message(STATUS "Z3_FOUND: ${Z3_FOUND}") +message(STATUS "Found Z3 ${Z3_VERSION_STRING}") +message(STATUS "Z3_DIR: ${Z3_DIR}") + +add_executable(c_parser_context_example parser_context_example.c) +target_include_directories(c_parser_context_example PRIVATE ${Z3_C_INCLUDE_DIRS}) +target_link_libraries(c_parser_context_example PRIVATE ${Z3_LIBRARIES}) + +option(FORCE_CXX_LINKER "Force linker with C++ linker" OFF) +if (FORCE_CXX_LINKER) + # This is a hack for avoiding UBSan linking errors + message(STATUS "Forcing use of C++ linker") + set_target_properties(c_parser_context_example + PROPERTIES + LINKER_LANGUAGE CXX + ) +endif() + +if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows") + # On Windows we need to copy the Z3 libraries + # into the same directory as the executable + # so that they can be found. + foreach (z3_lib ${Z3_LIBRARIES}) + message(STATUS "Adding copy rule for ${z3_lib}") + add_custom_command(TARGET c_parser_context_example + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + $ + $ + ) + endforeach() +endif() diff --git a/examples/c_parser_context/README b/examples/c_parser_context/README new file mode 100644 index 000000000..d4ab741e4 --- /dev/null +++ b/examples/c_parser_context/README @@ -0,0 +1,18 @@ +Example demonstrating Z3_parser_context for incremental SMTLIB2 parsing. + +To build the example using the Python build system, execute: + make examples +in the build directory. + +This will create the executable c_parser_context_example. + +To build using CMake, from the examples/c_parser_context directory: + mkdir build + cd build + cmake -DZ3_DIR= .. + make + +On Windows, you can just execute the binary. +On macOS and Linux, you must install z3 first using + sudo make install +OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) with the build directory to find the Z3 shared library. diff --git a/examples/c_parser_context/parser_context_example.c b/examples/c_parser_context/parser_context_example.c new file mode 100644 index 000000000..e449aca9f --- /dev/null +++ b/examples/c_parser_context/parser_context_example.c @@ -0,0 +1,268 @@ +/*++ +Copyright (c) 2024 Microsoft Corporation + +Module Name: + + parser_context_example.c + +Abstract: + + Example demonstrating the use of Z3_parser_context for incremental parsing. + + The Z3_parser_context API allows you to parse SMTLIB2 commands incrementally, + maintaining state (declarations, assertions) between parse calls. This is useful + for interactive applications or when processing commands in chunks. + +Author: + + GitHub Copilot + +--*/ + +#include +#include +#include + +/** + \brief exit gracefully in case of error. +*/ +void exitf(const char* message) +{ + fprintf(stderr,"Error: %s.\n", message); + exit(1); +} + +/** + \brief Simpler error handler. + */ +void error_handler(Z3_context c, Z3_error_code e) +{ + printf("Error code: %d\n", e); + exitf("incorrect use of Z3"); +} + +/** + \brief Create a logical context with model construction enabled. +*/ +Z3_context mk_context() +{ + Z3_config cfg = Z3_mk_config(); + Z3_set_param_value(cfg, "model", "true"); + Z3_context ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + Z3_set_error_handler(ctx, error_handler); + return ctx; +} + +/** + \brief Create a solver. +*/ +Z3_solver mk_solver(Z3_context ctx) +{ + Z3_solver s = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, s); + return s; +} + +/** + \brief Delete a solver. +*/ +void del_solver(Z3_context ctx, Z3_solver s) +{ + Z3_solver_dec_ref(ctx, s); +} + +/** + \brief Basic example of using Z3_parser_context. + + This example demonstrates: + 1. Creating a parser context + 2. Parsing declarations incrementally + 3. Parsing assertions incrementally + 4. Using the parsed formulas in a solver +*/ +void parser_context_basic_example() +{ + printf("\n=== Basic Parser Context Example ===\n"); + + Z3_context ctx = mk_context(); + Z3_parser_context parser = Z3_mk_parser_context(ctx); + Z3_parser_context_inc_ref(ctx, parser); + + // First, declare some constants + printf("Parsing declarations...\n"); + Z3_ast_vector decls = Z3_parser_context_from_string(ctx, parser, + "(declare-const x Int)\n" + "(declare-const y Int)"); + Z3_ast_vector_inc_ref(ctx, decls); + printf("Parsed %d formulas from declarations\n", Z3_ast_vector_size(ctx, decls)); + Z3_ast_vector_dec_ref(ctx, decls); + + // Now parse some assertions using the previously declared symbols + printf("\nParsing first set of assertions...\n"); + Z3_ast_vector assertions1 = Z3_parser_context_from_string(ctx, parser, + "(assert (> x 0))\n" + "(assert (< y 10))"); + Z3_ast_vector_inc_ref(ctx, assertions1); + + printf("Got %d assertions:\n", Z3_ast_vector_size(ctx, assertions1)); + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, assertions1); i++) { + Z3_ast assertion = Z3_ast_vector_get(ctx, assertions1, i); + printf(" %s\n", Z3_ast_to_string(ctx, assertion)); + } + + // Parse more assertions incrementally + printf("\nParsing second set of assertions...\n"); + Z3_ast_vector assertions2 = Z3_parser_context_from_string(ctx, parser, + "(assert (< x y))"); + Z3_ast_vector_inc_ref(ctx, assertions2); + + printf("Got %d more assertion:\n", Z3_ast_vector_size(ctx, assertions2)); + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, assertions2); i++) { + Z3_ast assertion = Z3_ast_vector_get(ctx, assertions2, i); + printf(" %s\n", Z3_ast_to_string(ctx, assertion)); + } + + // Now use these assertions in a solver + printf("\nSolving the constraints...\n"); + Z3_solver solver = mk_solver(ctx); + + // Add all assertions to the solver + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, assertions1); i++) { + Z3_solver_assert(ctx, solver, Z3_ast_vector_get(ctx, assertions1, i)); + } + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, assertions2); i++) { + Z3_solver_assert(ctx, solver, Z3_ast_vector_get(ctx, assertions2, i)); + } + + Z3_lbool result = Z3_solver_check(ctx, solver); + if (result == Z3_L_TRUE) { + printf("SAT\n"); + Z3_model model = Z3_solver_get_model(ctx, solver); + Z3_model_inc_ref(ctx, model); + printf("Model:\n%s\n", Z3_model_to_string(ctx, model)); + Z3_model_dec_ref(ctx, model); + } else if (result == Z3_L_FALSE) { + printf("UNSAT\n"); + } else { + printf("UNKNOWN\n"); + } + + // Cleanup + del_solver(ctx, solver); + Z3_ast_vector_dec_ref(ctx, assertions2); + Z3_ast_vector_dec_ref(ctx, assertions1); + Z3_parser_context_dec_ref(ctx, parser); + Z3_del_context(ctx); +} + +/** + \brief Example showing how to add custom sorts and declarations to parser context. + + This demonstrates using Z3_parser_context_add_sort and Z3_parser_context_add_decl + to make external symbols available to the parser. +*/ +void parser_context_custom_decls_example() +{ + printf("\n=== Parser Context with Custom Declarations Example ===\n"); + + Z3_context ctx = mk_context(); + Z3_parser_context parser = Z3_mk_parser_context(ctx); + Z3_parser_context_inc_ref(ctx, parser); + + // Create a custom sort programmatically + Z3_symbol color_name = Z3_mk_string_symbol(ctx, "Color"); + Z3_sort color_sort = Z3_mk_uninterpreted_sort(ctx, color_name); + + // Add the sort to the parser context + printf("Adding custom sort 'Color' to parser context...\n"); + Z3_parser_context_add_sort(ctx, parser, color_sort); + + // Create a custom function declaration programmatically + Z3_symbol is_red_name = Z3_mk_string_symbol(ctx, "is_red"); + Z3_sort bool_sort = Z3_mk_bool_sort(ctx); + Z3_func_decl is_red = Z3_mk_func_decl(ctx, is_red_name, 1, &color_sort, bool_sort); + + // Add the function to the parser context + printf("Adding custom function 'is_red' to parser context...\n"); + Z3_parser_context_add_decl(ctx, parser, is_red); + + // Now we can parse SMTLIB2 strings that use these custom symbols + printf("\nParsing with custom symbols...\n"); + Z3_ast_vector formulas = Z3_parser_context_from_string(ctx, parser, + "(declare-const c1 Color)\n" + "(declare-const c2 Color)\n" + "(assert (is_red c1))\n" + "(assert (not (is_red c2)))"); + Z3_ast_vector_inc_ref(ctx, formulas); + + printf("Parsed %d formulas:\n", Z3_ast_vector_size(ctx, formulas)); + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, formulas); i++) { + Z3_ast formula = Z3_ast_vector_get(ctx, formulas, i); + printf(" %s\n", Z3_ast_to_string(ctx, formula)); + } + + // Cleanup + Z3_ast_vector_dec_ref(ctx, formulas); + Z3_parser_context_dec_ref(ctx, parser); + Z3_del_context(ctx); +} + +/** + \brief Example demonstrating declaration and usage patterns. + + Shows how to declare symbols explicitly before using them. +*/ +void parser_context_declarations_example() +{ + printf("\n=== Parser Context Declarations Example ===\n"); + + Z3_context ctx = mk_context(); + Z3_parser_context parser = Z3_mk_parser_context(ctx); + Z3_parser_context_inc_ref(ctx, parser); + + // First, explicitly declare constants + printf("Explicitly declaring constants 'a' and 'b'...\n"); + Z3_ast_vector decls = Z3_parser_context_from_string(ctx, parser, + "(declare-const a Int)\n" + "(declare-const b Int)"); + Z3_ast_vector_inc_ref(ctx, decls); + printf("Declarations parsed successfully\n"); + Z3_ast_vector_dec_ref(ctx, decls); + + // Now use the declared constants + printf("\nParsing assertions using declared constants...\n"); + Z3_ast_vector formulas = Z3_parser_context_from_string(ctx, parser, + "(assert (> a 5))\n" + "(assert (< b 10))"); + + Z3_ast_vector_inc_ref(ctx, formulas); + printf("Successfully parsed %d assertions:\n", Z3_ast_vector_size(ctx, formulas)); + for (unsigned i = 0; i < Z3_ast_vector_size(ctx, formulas); i++) { + printf(" %s\n", Z3_ast_to_string(ctx, Z3_ast_vector_get(ctx, formulas, 0))); + } + Z3_ast_vector_dec_ref(ctx, formulas); + + // Cleanup + Z3_parser_context_dec_ref(ctx, parser); + Z3_del_context(ctx); +} + +/** + \brief Main function demonstrating all parser context examples. +*/ +int main() +{ + printf("Z3 Parser Context Examples\n"); + printf("==========================\n"); + printf("\nThese examples demonstrate the Z3_parser_context API,\n"); + printf("which allows incremental parsing of SMTLIB2 commands.\n"); + + parser_context_basic_example(); + parser_context_custom_decls_example(); + parser_context_declarations_example(); + + printf("\n=== All examples completed successfully ===\n"); + + return 0; +} diff --git a/examples/cpp_parser_context/CMakeLists.txt b/examples/cpp_parser_context/CMakeLists.txt new file mode 100644 index 000000000..ddf59aa02 --- /dev/null +++ b/examples/cpp_parser_context/CMakeLists.txt @@ -0,0 +1,47 @@ +################################################################################ +# Example C++ parser context project +################################################################################ +project(Z3_CPP_PARSER_CONTEXT_EXAMPLE CXX) +cmake_minimum_required(VERSION 3.4) +find_package(Z3 + REQUIRED + CONFIG + # `NO_DEFAULT_PATH` is set so that -DZ3_DIR has to be passed to find Z3. + # This should prevent us from accidentally picking up an installed + # copy of Z3. This is here to benefit Z3's build system when building + # this project. When making your own project you probably shouldn't + # use this option. + NO_DEFAULT_PATH +) + +################################################################################ +# Z3 C++ API bindings require C++11 +################################################################################ +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +message(STATUS "Z3_FOUND: ${Z3_FOUND}") +message(STATUS "Found Z3 ${Z3_VERSION_STRING}") +message(STATUS "Z3_DIR: ${Z3_DIR}") + +add_executable(cpp_parser_context_example cpp_parser_context_example.cpp) +target_include_directories(cpp_parser_context_example PRIVATE ${Z3_CXX_INCLUDE_DIRS}) +target_link_libraries(cpp_parser_context_example PRIVATE ${Z3_LIBRARIES}) + +target_compile_options(cpp_parser_context_example PRIVATE ${Z3_COMPONENT_CXX_FLAGS}) + +if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows") + # On Windows we need to copy the Z3 libraries + # into the same directory as the executable + # so that they can be found. + foreach (z3_lib ${Z3_LIBRARIES}) + message(STATUS "Adding copy rule for ${z3_lib}") + add_custom_command(TARGET cpp_parser_context_example + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + $ + $ + ) + endforeach() +endif() diff --git a/examples/cpp_parser_context/README b/examples/cpp_parser_context/README new file mode 100644 index 000000000..286346b56 --- /dev/null +++ b/examples/cpp_parser_context/README @@ -0,0 +1,18 @@ +Example demonstrating Z3_parser_context for incremental SMTLIB2 parsing. + +To build the example using the Python build system, execute: + make examples +in the build directory. + +This will create the executable cpp_parser_context_example. + +To build using CMake, from the examples/cpp_parser_context directory: + mkdir build + cd build + cmake -DZ3_DIR= .. + make + +On Windows, you can just execute the binary. +On macOS and Linux, you must install z3 first using + sudo make install +OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) with the build directory to find the Z3 shared library. diff --git a/examples/cpp_parser_context/cpp_parser_context_example.cpp b/examples/cpp_parser_context/cpp_parser_context_example.cpp new file mode 100644 index 000000000..16d446070 --- /dev/null +++ b/examples/cpp_parser_context/cpp_parser_context_example.cpp @@ -0,0 +1,324 @@ +/*++ +Copyright (c) 2024 Microsoft Corporation + +Module Name: + + parser_context_example.cpp + +Abstract: + + Example demonstrating the use of Z3_parser_context for incremental parsing. + + The Z3_parser_context API allows you to parse SMTLIB2 commands incrementally, + maintaining state (declarations, assertions) between parse calls. This is useful + for interactive applications or when processing commands in chunks. + +Author: + + GitHub Copilot + +--*/ + +#include +#include + +/** + \brief Helper class to manage Z3_parser_context lifecycle. + + Since there is no C++ wrapper for Z3_parser_context in z3++.h, + this class provides RAII-style management. +*/ +class parser_context { + Z3_context m_ctx; + Z3_parser_context m_parser; + +public: + parser_context(Z3_context ctx) : m_ctx(ctx) { + m_parser = Z3_mk_parser_context(ctx); + Z3_parser_context_inc_ref(ctx, m_parser); + } + + ~parser_context() { + Z3_parser_context_dec_ref(m_ctx, m_parser); + } + + // Delete copy constructor and assignment operator + parser_context(const parser_context&) = delete; + parser_context& operator=(const parser_context&) = delete; + + operator Z3_parser_context() const { return m_parser; } + + /** + \brief Parse a string of SMTLIB2 commands. + */ + Z3_ast_vector parse_string(const char* str) { + return Z3_parser_context_from_string(m_ctx, m_parser, str); + } + + /** + \brief Add a sort to the parser context. + */ + void add_sort(Z3_sort s) { + Z3_parser_context_add_sort(m_ctx, m_parser, s); + } + + /** + \brief Add a function declaration to the parser context. + */ + void add_decl(Z3_func_decl f) { + Z3_parser_context_add_decl(m_ctx, m_parser, f); + } +}; + +/** + \brief Helper class to manage Z3_ast_vector lifecycle. +*/ +class ast_vector { + Z3_context m_ctx; + Z3_ast_vector m_vec; + +public: + ast_vector(Z3_context ctx, Z3_ast_vector vec) : m_ctx(ctx), m_vec(vec) { + Z3_ast_vector_inc_ref(ctx, vec); + } + + ~ast_vector() { + Z3_ast_vector_dec_ref(m_ctx, m_vec); + } + + // Delete copy constructor and assignment operator + ast_vector(const ast_vector&) = delete; + ast_vector& operator=(const ast_vector&) = delete; + + operator Z3_ast_vector() const { return m_vec; } + + unsigned size() const { + return Z3_ast_vector_size(m_ctx, m_vec); + } + + Z3_ast get(unsigned i) const { + return Z3_ast_vector_get(m_ctx, m_vec, i); + } +}; + +/** + \brief Basic example of using Z3_parser_context. + + This example demonstrates: + 1. Creating a parser context + 2. Parsing declarations incrementally + 3. Parsing assertions incrementally + 4. Using the parsed formulas in a solver +*/ +void parser_context_basic_example() { + std::cout << "\n=== Basic Parser Context Example ===" << std::endl; + + Z3_config cfg = Z3_mk_config(); + Z3_set_param_value(cfg, "model", "true"); + Z3_context ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + + { + parser_context parser(ctx); + + // First, declare some constants + std::cout << "Parsing declarations..." << std::endl; + { + ast_vector decls(ctx, parser.parse_string( + "(declare-const x Int)\n" + "(declare-const y Int)")); + std::cout << "Parsed " << decls.size() << " formulas from declarations" << std::endl; + } + + // Now parse some assertions using the previously declared symbols + std::cout << "\nParsing first set of assertions..." << std::endl; + ast_vector assertions1(ctx, parser.parse_string( + "(assert (> x 0))\n" + "(assert (< y 10))")); + + std::cout << "Got " << assertions1.size() << " assertions:" << std::endl; + for (unsigned i = 0; i < assertions1.size(); i++) { + std::cout << " " << Z3_ast_to_string(ctx, assertions1.get(i)) << std::endl; + } + + // Parse more assertions incrementally + std::cout << "\nParsing second set of assertions..." << std::endl; + ast_vector assertions2(ctx, parser.parse_string( + "(assert (< x y))")); + + std::cout << "Got " << assertions2.size() << " more assertion:" << std::endl; + for (unsigned i = 0; i < assertions2.size(); i++) { + std::cout << " " << Z3_ast_to_string(ctx, assertions2.get(i)) << std::endl; + } + + // Now use these assertions in a solver + std::cout << "\nSolving the constraints..." << std::endl; + Z3_solver solver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, solver); + + // Add all assertions to the solver + for (unsigned i = 0; i < assertions1.size(); i++) { + Z3_solver_assert(ctx, solver, assertions1.get(i)); + } + for (unsigned i = 0; i < assertions2.size(); i++) { + Z3_solver_assert(ctx, solver, assertions2.get(i)); + } + + Z3_lbool result = Z3_solver_check(ctx, solver); + if (result == Z3_L_TRUE) { + std::cout << "SAT" << std::endl; + Z3_model model = Z3_solver_get_model(ctx, solver); + Z3_model_inc_ref(ctx, model); + std::cout << "Model:\n" << Z3_model_to_string(ctx, model) << std::endl; + Z3_model_dec_ref(ctx, model); + } else if (result == Z3_L_FALSE) { + std::cout << "UNSAT" << std::endl; + } else { + std::cout << "UNKNOWN" << std::endl; + } + + // Cleanup + Z3_solver_dec_ref(ctx, solver); + } // parser and vectors destructors run here + + Z3_del_context(ctx); +} + +/** + \brief Example showing how to add custom sorts and declarations to parser context. + + This demonstrates using Z3_parser_context_add_sort and Z3_parser_context_add_decl + to make external symbols available to the parser. +*/ +void parser_context_custom_decls_example() { + std::cout << "\n=== Parser Context with Custom Declarations Example ===" << std::endl; + + Z3_config cfg = Z3_mk_config(); + Z3_context ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + + { + parser_context parser(ctx); + + // Create a custom sort programmatically + Z3_symbol color_name = Z3_mk_string_symbol(ctx, "Color"); + Z3_sort color_sort = Z3_mk_uninterpreted_sort(ctx, color_name); + + // Add the sort to the parser context + std::cout << "Adding custom sort 'Color' to parser context..." << std::endl; + parser.add_sort(color_sort); + + // Create a custom function declaration programmatically + Z3_symbol is_red_name = Z3_mk_string_symbol(ctx, "is_red"); + Z3_sort bool_sort = Z3_mk_bool_sort(ctx); + Z3_func_decl is_red = Z3_mk_func_decl(ctx, is_red_name, 1, &color_sort, bool_sort); + + // Add the function to the parser context + std::cout << "Adding custom function 'is_red' to parser context..." << std::endl; + parser.add_decl(is_red); + + // Now we can parse SMTLIB2 strings that use these custom symbols + std::cout << "\nParsing with custom symbols..." << std::endl; + ast_vector formulas(ctx, parser.parse_string( + "(declare-const c1 Color)\n" + "(declare-const c2 Color)\n" + "(assert (is_red c1))\n" + "(assert (not (is_red c2)))")); + + std::cout << "Parsed " << formulas.size() << " formulas:" << std::endl; + for (unsigned i = 0; i < formulas.size(); i++) { + std::cout << " " << Z3_ast_to_string(ctx, formulas.get(i)) << std::endl; + } + } // parser and formulas destructors run here, before Z3_del_context + + Z3_del_context(ctx); +} + +/** + \brief Example demonstrating a practical use case: building an interactive theorem prover. + + This shows how parser_context can maintain state across multiple user interactions. +*/ +void parser_context_interactive_example() { + std::cout << "\n=== Interactive Session Example ===" << std::endl; + + Z3_config cfg = Z3_mk_config(); + Z3_set_param_value(cfg, "model", "true"); + Z3_context ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + + { + parser_context parser(ctx); + Z3_solver solver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, solver); + + // Simulate an interactive session with multiple commands + std::cout << "Session command 1: Define the problem domain..." << std::endl; + { + ast_vector formulas(ctx, parser.parse_string( + "(declare-const a Int)\n" + "(declare-const b Int)\n" + "(declare-const c Int)")); + for (unsigned i = 0; i < formulas.size(); i++) { + Z3_solver_assert(ctx, solver, formulas.get(i)); + } + } + + std::cout << "Session command 2: Add first constraint..." << std::endl; + { + ast_vector formulas(ctx, parser.parse_string( + "(assert (= (+ a b) c))")); + for (unsigned i = 0; i < formulas.size(); i++) { + Z3_solver_assert(ctx, solver, formulas.get(i)); + } + } + + std::cout << "Session command 3: Add more constraints..." << std::endl; + { + ast_vector formulas(ctx, parser.parse_string( + "(assert (> a 0))\n" + "(assert (> b 0))\n" + "(assert (= c 10))")); + for (unsigned i = 0; i < formulas.size(); i++) { + Z3_solver_assert(ctx, solver, formulas.get(i)); + } + } + + std::cout << "\nSession command 4: Check satisfiability..." << std::endl; + Z3_lbool result = Z3_solver_check(ctx, solver); + if (result == Z3_L_TRUE) { + std::cout << "SAT - Found a solution!" << std::endl; + Z3_model model = Z3_solver_get_model(ctx, solver); + Z3_model_inc_ref(ctx, model); + std::cout << "Model:\n" << Z3_model_to_string(ctx, model) << std::endl; + Z3_model_dec_ref(ctx, model); + } else if (result == Z3_L_FALSE) { + std::cout << "UNSAT - No solution exists" << std::endl; + } else { + std::cout << "UNKNOWN" << std::endl; + } + + // Cleanup + Z3_solver_dec_ref(ctx, solver); + } // parser destructors run here + + Z3_del_context(ctx); +} + +/** + \brief Main function demonstrating all parser context examples. +*/ +int main() { + std::cout << "Z3 Parser Context Examples" << std::endl; + std::cout << "==========================" << std::endl; + std::cout << "\nThese examples demonstrate the Z3_parser_context API," << std::endl; + std::cout << "which allows incremental parsing of SMTLIB2 commands." << std::endl; + + parser_context_basic_example(); + parser_context_custom_decls_example(); + parser_context_interactive_example(); + + std::cout << "\n=== All examples completed successfully ===" << std::endl; + + return 0; +} diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 7b4d444ea..928671927 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -117,8 +117,10 @@ def init_project_def(): add_js() # Examples add_cpp_example('cpp_example', 'c++') + add_cpp_example('cpp_parser_context_example', 'cpp_parser_context') add_cpp_example('z3_tptp', 'tptp') add_c_example('c_example', 'c') + add_c_example('c_parser_context_example', 'c_parser_context') add_c_example('maxsat') add_dotnet_example('dotnet_example', 'dotnet') add_java_example('java_example', 'java')