Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge latest from Develop branch #41

Merged
merged 14 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ Checks:
- -clang-analyzer-optin.core.EnumCastOutOfRange # interferes with enum bitfield flags
- android-*
- bugprone-*
- -bugprone-easily-swappable-parameters # many functions have easily swappable parameters
- cert-*
- -cert-dcl21-cpp # this check is deprecated, it is no longer part of the CERT standard
- concurrency-*
- cppcoreguidelines-*
- -cppcoreguidelines-avoid-magic-numbers # revisit after new instruction scheme, maybe only disable for unicode tables
- -cppcoreguidelines-avoid-do-while # if removing do-while does not cause serious performance issues remove this check
- -cppcoreguidelines-avoid-goto # if removing goto does not cause serious performance issues remove this check
- -cppcoreguidelines-pro-bounds-* # requires gsl::at and std::span to suppress, would prefer Standard Library hardening approach
- -cppcoreguidelines-pro-type-union-access # remove after developing new instruction encoding scheme that doesn't use union
- darwin-*
Expand All @@ -21,7 +21,6 @@ Checks:
- -google-readability-braces-around-statements # adversely affects line count
- -google-runtime-int # revisit after new instruction scheme
- hicpp-*
- -hicpp-avoid-goto # if removing goto does not cause serious performance issues remove this check
- -hicpp-braces-around-statements # adversely affects line count
- llvm-namespace-comment
- misc-*
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Release v0.4.0 (Under Development)

* Implemented new 64-bit instruction encoding scheme that is simpler and more efficient. String data is no longer embedded in the instruction stream, ensuring constant instruction length of 8 bytes.
* Merged `lug::program_encoder` and `lug::rule_encoder` into the `lug::encoder` base class after overhauling how choice/jump offsets are calculated, significantly reducing binary size bloat.
* Extracted common base class of `lug::basic_parser` into `lug::parser_base` to reduce template bloat.
* Reduced template bloat for parser directives (improving compiler error messages) and optimized nested directives.
* Merged parser stack frames together into a single stack using `std::variant`.
* Removed use of `goto` in parsing machine main loop.
* Changed grammar program generation to force inline the start rule.
* Implemented tail call optimization.

## Release v0.3.0 (July 4, 2024)

* Added list repetition operator `e1 >> e2` to the DSL that is shorthand for `e1 > *(e2 > e1)`.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
cmake_minimum_required(VERSION 3.10)

project(
lug VERSION 0.3.0
lug VERSION 0.4.0
DESCRIPTION "Embedded DSL for PE grammar parser combinators in C++"
HOMEPAGE_URL "https://github.com/jwtowner/lug"
LANGUAGES CXX)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See LICENSE file for copyright and license details

# distribution version
VERSION = 0.3.0
VERSION = 0.4.0

# paths
PREFIX = /usr/local
Expand Down
40 changes: 19 additions & 21 deletions lug/detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,29 +292,36 @@ class scope_exit
template <class Fn, class = std::enable_if_t<std::is_invocable_v<Fn>>>
scope_exit(Fn) -> scope_exit<std::decay_t<Fn>>;

template <class Error, class T, class U, class V>
inline void assure_in_range(T x, U minval, V maxval)
template <class Error, class T, class U, class V, class = std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U> && std::is_integral_v<V>>>
constexpr void assure_in_range(T x, U minval, V maxval)
{
if (!((minval <= x) && (x <= maxval)))
throw Error();
}

template <class Error, class T, class U>
[[nodiscard]] inline auto checked_add(T x, U y)
template <class T, class Error, class S, class U, class V, class = std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<S> && std::is_integral_v<U> && std::is_integral_v<V>>>
[[nodiscard]] constexpr T checked_cast(S x, U minval, V maxval)
{
if (((std::numeric_limits<decltype(x + y)>::max)() - x) < y)
throw Error();
return x + y;
detail::assure_in_range<Error>(x, minval, maxval);
return static_cast<T>(x);
}

template <class T, class Error, class S, class = std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<S>>>
[[nodiscard]] constexpr T checked_cast(S x)
{
return detail::checked_cast<T, Error>(x, (std::numeric_limits<std::decay_t<T>>::min)(), (std::numeric_limits<std::decay_t<T>>::max)());
}

template <std::size_t... Indices, class Tuple>
[[nodiscard]] constexpr auto make_tuple_view(Tuple&& t) noexcept
template <class Error, class T, class U, class = std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>>>
[[nodiscard]] constexpr auto checked_add(T x, U y)
{
return std::forward_as_tuple(std::get<Indices>(std::forward<Tuple>(t))...);
if (((std::numeric_limits<decltype(x + y)>::max)() - x) < y)
throw Error();
return x + y;
}

template<class InputIt, class UnaryPredicate>
[[nodiscard]] inline InputIt escaping_find_if(InputIt first, InputIt last, UnaryPredicate pred)
[[nodiscard]] constexpr InputIt escaping_find_if(InputIt first, InputIt last, UnaryPredicate pred)
{
for ( ; first != last; ++first) {
const int status = pred(*first);
Expand All @@ -326,17 +333,8 @@ template<class InputIt, class UnaryPredicate>
return last;
}

template <class Sequence, class T>
inline std::size_t push_back_unique(Sequence& s, T&& x)
{
if (auto i = std::find(std::cbegin(s), std::cend(s), x); i != std::cend(s))
return static_cast<std::size_t>(std::distance(std::cbegin(s), i));
s.push_back(std::forward<T>(x));
return s.size() - 1;
}

template <class Sequence>
[[nodiscard]] inline auto pop_back(Sequence& s) -> typename Sequence::value_type
[[nodiscard]] constexpr auto pop_back(Sequence& s) -> typename Sequence::value_type
{
typename Sequence::value_type result{std::move(s.back())}; // NOLINT(misc-const-correctness)
s.pop_back();
Expand Down
3 changes: 2 additions & 1 deletion lug/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ class reenterant_parse_error : public lug_error { public: reenterant_parse_error
class reenterant_read_error : public lug_error { public: reenterant_read_error() : lug_error{"attempted to read or modify input source while reading"} {} };
class parse_context_error : public lug_error { public: parse_context_error() : lug_error{"operation valid only inside calling context of parser::parse" } {} };
class accept_context_error : public lug_error{ public: accept_context_error() : lug_error{"operation valid only inside calling context of parser::accept"} {} };
class attribute_stack_error : public lug_error{ public: attribute_stack_error() : lug_error{"incompatible or invalid stack frame"} {} };
class attribute_stack_error : public lug_error{ public: attribute_stack_error() : lug_error{"incompatible or invalid attribute stack frame"} {} };
class bad_string_expression : public lug_error { public: explicit bad_string_expression(std::string const& s = "invalid string or bracket expression") : lug_error{s} {} };
class bad_character_class : public bad_string_expression { public: bad_character_class() : bad_string_expression{"invalid character class"} {} };
class bad_character_range : public bad_string_expression { public: bad_character_range() : bad_string_expression{"character range is reversed"} {} };
class bad_grammar : public lug_error { public: bad_grammar() : lug_error{"invalid or empty grammar"} {} };
class bad_opcode : public lug_error { public: bad_opcode() : lug_error{"invalid opcode"} {} };
class bad_stack : public lug_error{ public: bad_stack() : lug_error{"empty or invalid parser stack error"} {} };

} // namespace lug

Expand Down
Loading