diff --git a/.github/workflows/boosttest.yml b/.github/workflows/boosttest.yml index 7844c7f..28aa7a0 100644 --- a/.github/workflows/boosttest.yml +++ b/.github/workflows/boosttest.yml @@ -112,9 +112,6 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make unit_test && ./unit_test macOS_Ventura: @@ -130,9 +127,6 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make unit_test && ./unit_test macOS_Monterey: @@ -148,7 +142,4 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make unit_test && ./unit_test diff --git a/.github/workflows/build_without_submodule.yml b/.github/workflows/build_without_submodule.yml index 42dc243..caad01e 100644 --- a/.github/workflows/build_without_submodule.yml +++ b/.github/workflows/build_without_submodule.yml @@ -10,7 +10,7 @@ jobs: strategy: max-parallel: 4 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: default build run: | mkdir build diff --git a/.github/workflows/integrated_test.yml b/.github/workflows/integrated_test.yml index 17c7820..a6d38da 100644 --- a/.github/workflows/integrated_test.yml +++ b/.github/workflows/integrated_test.yml @@ -39,7 +39,7 @@ jobs: strategy: max-parallel: 4 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Install required packages @@ -62,9 +62,6 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make monaa && ../examples/integrated_test.sh macOS_Ventura: @@ -80,9 +77,6 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make monaa && ../examples/integrated_test.sh macOS_Monterey: @@ -98,7 +92,4 @@ jobs: - name: build and test run: | mkdir -p build - export PATH="/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" - LDFLAGS="-L/usr/local/opt/bison/lib -L/usr/local/opt/flex/lib" - export CPPFLAGS="-I/usr/local/opt/flex/include" cd build && cmake .. && make monaa && ../examples/integrated_test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 155f585..7e26cbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-deprecated-register") +cmake_minimum_required(VERSION 3.30) -project(MONAA CXX) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-deprecated-register") -cmake_minimum_required(VERSION 3.1) -set(CMAKE_CXX_FLAGS "-Wall -std=c++14") +project(MONAA LANGUAGES CXX) +set(CMAKE_CXX_FLAGS "-Wall") # Hack to disable -march=native if it is not supported include(CheckCXXCompilerFlag) check_cxx_compiler_flag("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) @@ -16,13 +16,9 @@ set(VERSION_MAJOR 0) set(VERSION_MINOR 5) set(VERSION_PATCH 4) -if(${CMAKE_VERSION} VERSION_LESS "3.12.0") - add_definitions( - "-DMONAA_VERSION=\"${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}\"") -else() - add_compile_definitions( - MONAA_VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") -endif() +add_compile_definitions( + MONAA_VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" + PROJECT_ROOT_DIR="${CMAKE_SOURCE_DIR}") # On macOS, search Homebrew for keg-only versions of Bison and Flex. Xcode does # not provide new enough versions for us to use. @@ -94,8 +90,7 @@ target_include_directories(monaa PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) -set_property(TARGET monaa - PROPERTY CXX_STANDARD 14) +target_compile_features(monaa PRIVATE cxx_std_20) ## Config for TRE2TA add_executable(tre2ta EXCLUDE_FROM_ALL @@ -114,8 +109,7 @@ target_include_directories(tre2ta PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) -set_property(TARGET tre2ta - PROPERTY CXX_STANDARD 14) +target_compile_features(tre2ta PRIVATE cxx_std_20) ## Config for libmonaa add_library(libmonaa STATIC EXCLUDE_FROM_ALL @@ -172,6 +166,7 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/rapidcheck/CMakeLists.txt") add_test(NAME unit_test COMMAND $ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + target_compile_features(unit_test PRIVATE cxx_std_20) endif() # add a target to generate API documentation with Doxygen diff --git a/README.md b/README.md index d8dc1c7..491192e 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ MONAA is tested on Arch Linux, Ubuntu (20.04, 22.04, 24.04), and macOS (12 Monte ### Requirements -* C++ compiler supporting C++14 and the corresponding libraries. +* C++ compiler supporting C++20 and the corresponding libraries. * Boost (>= 1.59) * Eigen -* CMake +* CMake (>= 3.30) * Bison (>= 3.0) * Flex @@ -117,7 +117,7 @@ Syntax of Timed Regular Expressions | expr expr (Concatenation) | expr | expr (Disjunction) | expr & expr (Conjunction) - | expr % (s,t) (Time Restriction) + | expr % (s,t) | expr % [s,t) | expr % (s,t] | expr % [s,t] | expr % (>s) | expr % (>=s) | expr % (s) | expr % (>=s) | expr % ( class WordContainer { +template +class WordContainer { protected: //! @brief The actual container of the timed word. Container vec; @@ -24,7 +25,7 @@ public: simulation is directly passed), this can be ignored. @param [in] isBinary A flag if the input is in a binary file. */ - WordContainer(FILE *file, bool isBinary = false) + WordContainer(FILE *file, bool isBinary = false) : vec(file, isBinary) {} /*! @brief Access an element of the container. diff --git a/monaa/main.cc b/monaa/main.cc index 14b4dca..d23275a 100644 --- a/monaa/main.cc +++ b/monaa/main.cc @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) { if (vm.count("version")) { std::cout << "MONAA (a MONitoring tool Acceralated by Automata) " << MONAA_VERSION << "\n" - << "Copyright (C) 2017-2022 Masaki Waga.\n\n" + << "Copyright (C) 2017-2024 Masaki Waga.\n\n" << "This program is free software; you can redistribute it and/or modify\n" << "it under the terms of the GNU General Public License as published by\n" << "the Free Software Foundation; either version 3 of the License, or\n" diff --git a/monaa/tre2ta.cc b/monaa/tre2ta.cc index 7633032..e5c21a3 100644 --- a/monaa/tre2ta.cc +++ b/monaa/tre2ta.cc @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) { std::cout << "MONAA (a MONitoring tool Acceralated by Automata) " << MONAA_VERSION << "\n" - << "Copyright (C) 2017-2019 Masaki Waga.\n\n" + << "Copyright (C) 2017-2024 Masaki Waga.\n\n" << "This program is free software; you can redistribute it and/or " "modify\n" << "it under the terms of the GNU General Public License as published " diff --git a/monaa/tre_lexer.l b/monaa/tre_lexer.l index 01861da..9ea05b8 100644 --- a/monaa/tre_lexer.l +++ b/monaa/tre_lexer.l @@ -33,6 +33,13 @@ using token = MONAA::TREParser::token; "%" return token::WITHIN; "(" return token::LPAREN; ")" return token::RPAREN; +"[" return token::LSQPAREN; +"]" return token::RSQPAREN; +"<" return token::LT; +">" return token::GT; +"<=" return token::LE; +">=" return token::GE; +"=" return token::EQ; "," return token::COMMA; [a-zA-Z$] { @@ -45,8 +52,7 @@ using token = MONAA::TREParser::token; return token::INT; } +[[:blank:]]+ "\n" return token::END; %% - - diff --git a/monaa/tre_parser.yy b/monaa/tre_parser.yy index 8f68db5..44f1800 100644 --- a/monaa/tre_parser.yy +++ b/monaa/tre_parser.yy @@ -1,9 +1,10 @@ +/* -*- mode: bison; -*- */ %skeleton "lalr1.cc" %require "3.0" %debug %defines %define api.namespace {MONAA} -%define parser_class_name {TREParser} +%define api.parser.class {TREParser} %code requires{ #include @@ -41,7 +42,14 @@ WITHIN "%" LPAREN "(" RPAREN ")" + LSQPAREN "[" + RSQPAREN "]" COMMA "," + GT ">" + GE ">=" + LE "<=" + LT "<" + EQ "=" ; %locations @@ -68,6 +76,15 @@ expr : ATOM { $$ = std::make_shared(TRE::op::atom, $1); } /* We support only open intervals now */ interval : LPAREN INT COMMA INT RPAREN { $$ = std::make_shared($2, $4); } + | LSQPAREN INT COMMA INT RPAREN { $$ = std::make_shared(Bounds($2, 1), Bounds($4, 0)); } + | LPAREN INT COMMA INT RSQPAREN { $$ = std::make_shared(Bounds($2, 0), Bounds($4, 1)); } + | LSQPAREN INT COMMA INT RSQPAREN { $$ = std::make_shared(Bounds($2, 1), Bounds($4, 1)); } + | LT INT { $$ = std::make_shared(Bounds(0, 1), Bounds($2, 0)); } + | LE INT { $$ = std::make_shared(Bounds(0, 1), Bounds($2, 1)); } + | EQ INT { $$ = std::make_shared(Bounds($2, 1), Bounds($2, 1)); } + | GE INT { $$ = std::make_shared(Bounds($2, 1), Bounds(std::numeric_limits::infinity(), 0)); } + | GT INT { $$ = std::make_shared($2); } + | LPAREN interval RPAREN { $$ = $2; } %% diff --git a/test/lazy_deque_test.cc b/test/lazy_deque_test.cc index 0156e84..6524e11 100644 --- a/test/lazy_deque_test.cc +++ b/test/lazy_deque_test.cc @@ -1,5 +1,8 @@ -#include +#include #include + +#include + #include "../libmonaa/lazy_deque.hh" BOOST_AUTO_TEST_SUITE(LazyDequeTest) @@ -9,7 +12,7 @@ class DQASCIIFixture { FILE* file; public: // "a 1.1 b 3.2 c 5.3 d 7.4 e 9.5 f 11.6 g 13.7 h 15.8" - DQASCIIFixture() : file(fopen("../test/ascii_test.txt", "r")), dqAscii(file) {} + DQASCIIFixture() : file(fopen(std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("ascii_test.txt").c_str(), "r")), dqAscii(file) {} LazyDeque dqAscii; }; @@ -18,7 +21,7 @@ class DQBinaryFixture { FILE* file; public: // "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" - DQBinaryFixture() : file(fopen("../test/binary_test.bin", "r")), dqBinary(file, true) {} + DQBinaryFixture() : file(fopen(std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("binary_test.bin").c_str(), "r")), dqBinary(file, true) {} LazyDeque dqBinary; }; diff --git a/test/timedFJS_test.cc b/test/timedFJS_test.cc index 9929f37..d99766f 100644 --- a/test/timedFJS_test.cc +++ b/test/timedFJS_test.cc @@ -1,4 +1,5 @@ #define BOOST_GRAPH_USE_SPIRIT_PARSER // for header only +#include #include #include "../libmonaa/monaa.hh" @@ -27,7 +28,8 @@ BOOST_AUTO_TEST_CASE(timedFJS) { TA.maxConstraints = {1}; - FILE* file(fopen("../test/timed_word.txt", "r")); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("timed_word.txt"); + FILE* file(fopen(inputPath.c_str(), "r")); WordVector > w(file, false); AnsVec ans; monaa(w, TA, ans); @@ -61,7 +63,8 @@ BOOST_AUTO_TEST_CASE(timedFJSa0_1b0_1) { TA.maxConstraints = {1}; - FILE* file(fopen("../test/ascii_test.txt", "r")); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("ascii_test.txt"); + FILE* file(fopen(inputPath.c_str(), "r")); WordVector > w(file, false); AnsVec ans; monaa(w, TA, ans); @@ -76,13 +79,15 @@ BOOST_AUTO_TEST_CASE(timedFJSa0_1b0_1) { } BOOST_AUTO_TEST_CASE(timedFJSTorque) { - std::ifstream taStream("../test/torque.dot"); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("torque.dot"); + std::ifstream taStream(inputPath); BoostTimedAutomaton BoostTA; TimedAutomaton TA; parseBoostTA(taStream, BoostTA); convBoostTA(BoostTA, TA); - FILE* file(fopen("../test/torque_short.txt", "r")); + inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("torque_short.txt"); + FILE* file(fopen(inputPath.c_str(), "r")); WordVector > w(file, false); AnsVec ans; diff --git a/test/timed_automaton_parser_test.cc b/test/timed_automaton_parser_test.cc index 3bfd8cf..0d7273b 100644 --- a/test/timed_automaton_parser_test.cc +++ b/test/timed_automaton_parser_test.cc @@ -1,13 +1,15 @@ #define BOOST_GRAPH_USE_SPIRIT_PARSER // for header only +#include #include -#include "../monaa/timed_automaton_parser.hh" +#include "timed_automaton_parser.hh" BOOST_AUTO_TEST_SUITE(timedAutomatonParserTests) BOOST_AUTO_TEST_CASE(parseBoostPhi7TATest) { BoostTimedAutomaton BoostTA; - std::ifstream file("../test/phi7.dot"); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("phi7.dot"); + std::ifstream file(inputPath); parseBoostTA(file, BoostTA); BOOST_TEST(!BoostTA[0].isMatch); @@ -27,7 +29,8 @@ BOOST_AUTO_TEST_CASE(parseBoostPhi7TATest) BOOST_AUTO_TEST_CASE(parseBoostTATest) { BoostTimedAutomaton BoostTA; - std::ifstream file("../test/timed_automaton.dot"); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("timed_automaton.dot"); + std::ifstream file(inputPath); parseBoostTA(file, BoostTA); BOOST_TEST(!BoostTA[0].isMatch); @@ -51,7 +54,8 @@ BOOST_AUTO_TEST_CASE(parseBoostTATest) BOOST_AUTO_TEST_CASE(parseBoostTASimpleTest) { BoostTimedAutomaton BoostTA; - std::ifstream file("../test/small.dot"); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("small.dot"); + std::ifstream file(inputPath); parseBoostTA(file, BoostTA); std::array initResult = {{true, false, false, false}}; @@ -93,7 +97,8 @@ BOOST_AUTO_TEST_CASE(convBoostTATest) { BoostTimedAutomaton BoostTA; TimedAutomaton TA; - std::ifstream file("../test/timed_automaton.dot"); + std::filesystem::path inputPath = std::filesystem::path{PROJECT_ROOT_DIR}.append("test").append("timed_automaton.dot"); + std::ifstream file(inputPath); parseBoostTA(file, BoostTA); convBoostTA(BoostTA, TA); diff --git a/test/tre_driver_test.cc b/test/tre_driver_test.cc index c9449c1..8e87ef2 100644 --- a/test/tre_driver_test.cc +++ b/test/tre_driver_test.cc @@ -39,6 +39,78 @@ BOOST_FIXTURE_TEST_CASE(simpleTimedParse, SimpleTimedExpression) result << *(driver.getResult()); BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((1, 0),(2, 0)))"); } + +BOOST_AUTO_TEST_CASE(closeTimedParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%[2,4]"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((2, 1),(4, 1)))"); +} + +BOOST_AUTO_TEST_CASE(leftOpenTimedParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(2,4]"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((2, 0),(4, 1)))"); +} + +BOOST_AUTO_TEST_CASE(rightOpenTimedParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%[2,4)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((2, 1),(4, 0)))"); +} + +BOOST_AUTO_TEST_CASE(ltParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(< 3)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((0, 1),(3, 0)))"); +} + +BOOST_AUTO_TEST_CASE(leParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(<= 3)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((0, 1),(3, 1)))"); +} + +BOOST_AUTO_TEST_CASE(eqParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(= 3)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((3, 1),(3, 1)))"); +} + +BOOST_AUTO_TEST_CASE(geParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(>= 3)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((3, 1),(inf, 0)))"); +} + +BOOST_AUTO_TEST_CASE(gtParse) { + TREDriver driver; + std::stringstream stream, result; + stream << "(aba)%(> 3)"; + BOOST_TEST_REQUIRE(driver.parse(stream)); + result << *(driver.getResult()); + BOOST_CHECK_EQUAL(result.str(), "((a(ba))%((3, 0),(inf, 0)))"); +} BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()