Skip to content

acd1034/monadic-parser-combinator

Repository files navigation

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);
}

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.

Releases

No releases published

Packages

No packages published