yhirose / cpp-peglib

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

Optional matches in semantic actions #67

Closed zomgrolf closed 5 years ago

zomgrolf commented 5 years ago

Consider the following rule: S <- A? B+ C?. How can I tell inside a semantic action for S, whether A has or hasn't been matched? Assuming the SemanticValues object has k>1 elements, I don't see an easy way to distinguish between matching an A and k-1 Bs and just having k Bs...

My current workaround is to ensure that semantic actions for A, B and C return pairs of actual values and some tags I could use to disambiguate semantic values in the action for S -- but I'd love to get rid of that boilerplate code, if possible...

Would it be feasible to extend SemanticValues to allow me to check where does the given value come from (or perhaps extend peg::any to allow me to check, if it holds a value of the given type, without triggering an exception...)?

yhirose commented 5 years ago

@zomgrolf, I have implemented it in a memory efficient way.

parser parser(R"(
    S <- A? B* C?
    A <- 'a'
    B <- 'b'
    C <- 'c'
)");

parser["S"] = [](const SemanticValues& sv) {
    using namespace udl;
    REQUIRE(sv.size() == 1);
    REQUIRE(sv.tags.size() == 1);
    REQUIRE(sv.tags[0] == "C"_);
};

auto ret = parser.parse("c");
REQUIRE(ret == true);
zomgrolf commented 5 years ago

Awesome, thanks!