Skippers
Skipping whitespace is a common task
A very common pattern is allowing arbitrary white space between elements of a given grammar.
This could be acheived like this:
// a list of 0 to N characters in the whitespace char set // that emits nothing to the destination. // ows stands for Optional White Space auto ows = ignore( *char_(" \r\n\t") ); // a list of integers, that ignores any whitespace before it. auto pattern = *(ows >> int_);
However, this can quickly become tedious, and makes parsers hard to read:
auto alnum = char_set::range('a', 'z') | char_set::range('A', 'Z') | char_set::range('0', '9'); auto ows = ignore(*char_(" \r\n\t")); auto name = *char_(alnum); auto player = ows >> name >> // first name ows >> name >> // last name ows >> uint_; // score parse(player, "John Doe 123");
Introducing Skippers
Thankfully Abulafia provides us with skippers, which automate the task of applying whitespace before each sub-parser.
auto alnum = char_set::range('a', 'z') | char_set::range('A', 'Z') | char_set::range('0', '9'); auto name = lexeme(*char_(alnum)); auto whitespace = char_(" \r\n\t"); auto player = name >> name >> uint_; // first name, last name, score parse(apply_skipper(player, whitespace), "John Doe 123");
apply_skipper()
will tell abulafia that every parser underneath it will be prefixed with an ignored repetition of the skipper pattern (whitespace
in our example).
On the other side of the coin, lexeme()
tells abulafia that the parser is to be considered as a logical unit, effectively disabling the skipper. Without it, the first name would be parsed as "JohnDoe123", since the white space between the letters would get skipped.