1

What is the most idiomatic way to do post-skipping? More specific I want to ensure there is no "non-skippable" (garbage) characters in my input after matching my top rule.

auto const blankOrComment
    = ascii::space
    | x3::lexeme ['#' >> *(x3::char_ - x3::eol) >> -x3::eol ]
    ;

auto const program = rule<AstProgram>("program")
    = *(as<AstDefinition> (definition > ";"))
    ;

auto const programEntry = x3::skip(blankOrComment) [program];

One idea, I consider quite ugly was to do a separate parse call for the blankOrComment afterwards, if the main iterator position is not the end iterator. The current better idea I have is to change the root rule:

auto const programEntry = x3::skip(blankOrComment) [program >> x3::omit[*blankOrComment]];

Is there a more idiomatic way?

sehe
  • 374,641
  • 47
  • 450
  • 633
senevoldsen
  • 337
  • 3
  • 8

1 Answers1

1

The simplest hack is to tack on >> eps: Live On Coliru

Note I'd strive to make the skipper more self-descriptive:

auto const skipper
    = space
    | '#' >> *(char_ - eol) >> (eol|eoi) 
    ;

Likewise you can make that postskip hack more self-descriptive:

    auto const post_skip = eps;
    auto const program = "program" >> post_skip;

Live On Coliru

#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>

namespace Parser {
    namespace x3 = boost::spirit::x3;

    namespace rules {
        using namespace x3;

        auto const skipper
            = space
            | '#' >> *(char_ - eol) >> (eol|eoi) 
            ;

        auto const post_skip = eps;
        auto const program = "program" >> post_skip;

    }

    auto const programEntry = x3::skip(rules::skipper) [rules::program];
}

int main() {
    using It = std::string::const_iterator;
    for (std::string const input : {
            "",
            " program ",
            "#hello\n program # comment\n",
    }) {
        It f = input.begin(), l = input.end();

        if(parse(f, l, Parser::programEntry)) {
            std::cout << "Parse success\n";
        } else {
            std::cout << "Parse failed\n";
        }

        std::cout << "Remaining: '" << std::string(f,l) << "'\n";
    }
}

Prints

Parse failed
Remaining: ''
Parse success
Remaining: ''
Parse success
Remaining: ''
sehe
  • 374,641
  • 47
  • 450
  • 633