Skip to content

Conversation

@dnwpark
Copy link

@dnwpark dnwpark commented Dec 1, 2025

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

@yhirose
Copy link
Owner

yhirose commented Dec 1, 2025

@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!

@dnwpark
Copy link
Author

dnwpark commented Dec 4, 2025

@yhirose please take another look!

@dnwpark
Copy link
Author

dnwpark commented Dec 4, 2025

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants