yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
879 stars 112 forks source link

About macro and actions #263

Closed 95A31 closed 1 year ago

95A31 commented 1 year ago

Hello, I am using the macro sequence(x) <- x ("," x)* to match text of the form x,x,...,x. Ideally, I would like to have an action to manage it (see below) but, from my understanding, macros are just syntactic sugar. There is a way to have an action associated with a macro, or something to mimic that?

    parser["sequence"] = [](SemanticValues const & vs)
    {
        std::vector<std::any> * const sequence =  new std::vector<std::any>();
        for (const auto & v : vs)
        {
            sequence->push_back(v);
        }
       return std::any(sequence);
    };
yhirose commented 1 year ago

@95A31, your assumption is correct, and there is no way to associate an action handler with a macro rule. Only thing that we could do is as below. But I think it's probably not what you want. Sorry about that...

#include <cstdlib>
#include <iostream>
#include <peglib.h>

using namespace peg;

int main(void) {
  parser parser(R"(
START       <- SEQUENCE_A
SEQUENCE_A  <- SEQUENCE('A')
SEQUENCE(X) <- X (',' X)*
  )");

  parser["SEQUENCE_A"] = [](const SemanticValues &vs) {
    std::cout << "SEQUENCE_A" << std::endl;
  };

  if (parser.parse("A,A")) { return 0; }

  std::cout << "syntax error..." << std::endl;
  return -1;
}
95A31 commented 1 year ago

For future reference: in the end I reworked the grammar by adding a rule sequence_of_x <- sequence(x) for every x , and using a template function as follow:

parser["sequence_of_int"] = [](peg::SemanticValues const & vs)
{
    return sequence_action<int>(vs);
};

template<typename T>
std::vector<T> sequence_action(peg::SemanticValues const & vs)
{
    auto const count = vs.size();
    std::vector<T> sequence(count);
    for (auto i = 0; i < count; i +=1)
    {
        sequence.at(i) = std::move(std::any_cast<T>(vs.at(i)));
    }
    return sequence;
}