cpp-peglib icon indicating copy to clipboard operation
cpp-peglib copied to clipboard

Add peg::Error to allow parsing to fail during action.

Open dnwpark opened this issue 1 month ago • 3 comments

Predicates are useful, but often determining whether something can be parsed often involves actually doing redundant work.

For example, you may have a rule INT <- < [0-9]+ >, and want to ensure that the number can be supported by int:

parser['INT'].predicate = [](
    const peg::SemanticValues& vs,
    const std::any& /*dt*/,
    std::string& msg
    )
{
    int value;
    auto [ptr, err] = std::from_chars(
        vs.token().data(),
        vs.token().data() + vs.token().size(),
        value
        );

    return err == std::errc();
}

Once the predicate passes, a second call to std::from_chars will be necessary within the action.


This PR adds peg::Error, which may be returned from an action and is treated as if the parse was invalid. The above check can be included in the action:

parser['INT'] = [](const peg::SemanticValues& vs)
{
    int value;
    auto [ptr, err] = std::from_chars(
        vs.token().data(),
        vs.token().data() + vs.token().size(),
        value
        );

    if (err != std::errc()) {
        return peg::Error("Number out of range.");
    }

    return value;
}

dnwpark avatar Dec 01 '25 21:12 dnwpark

@dnwpark thanks for the pull request. Could you add some unit test cases for this change? Then, I'll take a look at it. Thanks!

yhirose avatar Dec 01 '25 22:12 yhirose

@yhirose please take another look!

dnwpark avatar Dec 04 '25 20:12 dnwpark

I also ran into an issue where if I have a grammar such as

WORD <- LETTER*
LETTER <- [a-z]

with the action:

parser["LETTER"] = [&](const SemanticValues &vs) -> std::any {
  if (vs.token() == "x") {
    return Error("Not allowing 'x'");
  }
  return vs.token();
};

When parsing a word like "extra", the interaction with zero or more causes the message to be "expected end of input". This only occurs if the erroring action is the last rule.

I am not sure how to fix this, or if this should even be considered a defect.

dnwpark avatar Dec 04 '25 20:12 dnwpark