mpc
Haskell-like feature supports in C++
mpc: Monadic Parser Combinator in C++

Linux build status Linux build (Release) status Github license

This library aims to implement Haskell-like features (functor, applicative, monad, etc.) and monadic parser combinators for C++20.

Quick Example

A sample code to parse and evaluate an expression

#include <charconv>
#include <mpc/parser.hpp>
// Preparation for implementing an expression parser
inline const auto spaces = mpc::many % mpc::space;
inline constexpr auto token = mpc::partial([](auto&& parser) {
return mpc::discard2nd(MPC_FORWARD(parser), spaces);
});
inline constexpr auto char_token = mpc::compose(token, mpc::char1);
inline constexpr auto readint = //
mpc::partial([](mpc::similar_to<mpc::String> auto&& s) {
std::string str(s.begin(), s.end());
std::int64_t num{};
if (auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), num);
ec == std::errc{}) {
return num;
} else
throw "Conversion from chars to integer failed";
});
inline constexpr auto numop = //
mpc::partial([](const char c, auto&& x, auto&& y) {
switch (c) {
case '+':
return MPC_FORWARD(x) + MPC_FORWARD(y);
case '-':
return MPC_FORWARD(x) - MPC_FORWARD(y);
case '*':
return MPC_FORWARD(x) * MPC_FORWARD(y);
case '/':
return MPC_FORWARD(x) / MPC_FORWARD(y);
default:
throw "Unexpected operator";
}
});
int main() {
// Implementation of an expression parser
// expr = term ("+" term | "-" term)*
// term = factor ("*" factor | "/" factor)*
// factor = number
// number = [0-9]+
using namespace mpc::operators::alternatives;
const auto number = token % (mpc::many1 % mpc::digit);
const auto factor = mpc::fmap(readint, number);
const auto termop = mpc::fmap(numop, char_token % '*' or char_token % '/');
const auto term = mpc::chainl1(factor, termop);
const auto exprop = mpc::fmap(numop, char_token % '+' or char_token % '-');
const auto expr = mpc::chainl1(term, exprop);
// Test
std::string_view sv = "1*2/3 + 3/4*5 - 5*6/7";
std::int64_t ans = 1*2/3 + 3/4*5 - 5*6/7 ;
auto result = mpc::eval_StateT % expr % mpc::String(sv.begin(), sv.end());
assert(result.index() == 1);
assert(*mpc::snd(result) == ans);
}
constexpr partial< detail::fmap_op > fmap
fmap :: (a -> b) -> f a -> f b
Definition: applicative.hpp:161
constexpr partial< detail::compose_op > compose
Function composition.
Definition: compose.hpp:35
constexpr partial< detail::discard2nd_op > discard2nd
discard2nd :: f a -> f b -> f a
Definition: applicative.hpp:105
constexpr auto many1
Definition: parser.hpp:85
constexpr auto chainl1
Definition: parser.hpp:149
constexpr auto many
Definition: parser.hpp:110
Implements a perfect-forwarding call wrapper.
Definition: partial.hpp:63
  • Link to another example

Supported Compilers

This library will work on the following compilers:

  • GCC 11.2.0 (or later)
  • Clang 13.0.0 (or later)
  • Apple clang 13.1.0 (or later)

Library Dependencies

This library depends on no external libraries.