Reference for the parser combinator library.
For practical hands-on tips and tricks, see the guide.
These are the foundation of the whole thing. Fairly boring in terms of capabilities, but essential for everything to work. The core building blocks, if you will.
Parses any single character or symbol. Multibyte-safe, fails on empty input.
Using named constructor:
use Stratadox\Parser\Parsers\Any;
$parser = Any::symbol();Using function:
use function Stratadox\Parser\any;
$parser = any();Parsing a letter
use Stratadox\Parser\Parsers\Any;
$parser = Any::symbol();
$result = $parser->parse('a');
assert(true === $result->ok());
assert('a' === $result->data());
assert('' === $result->unparsed());Parsing only a letter
use Stratadox\Parser\Parsers\Any;
$parser = Any::symbol();
$result = $parser->parse('abc');
assert(true === $result->ok());
assert('a' === $result->data());
assert('bc' === $result->unparsed());Failing on empty content
use Stratadox\Parser\Parsers\Any;
$parser = Any::symbol();
$result = $parser->parse('');
assert(false === $result->ok());
assert('unexpected end' === $result->data());
assert('' === $result->unparsed());Parses the predefined string, or returns an error result indicating where the input starts becoming different. Multibyte safe. (Somehow, I think. If not, let me know.)
Using named constructor:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('aa');Using function:
use function Stratadox\Parser\text;
$parser = text('aa');Successful full parse:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('abc');
$result = $parser->parse('abc');
assert(true === $result->ok());
assert('abc' === $result->data());
assert('' === $result->unparsed());Successful partial parse:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('abc');
$result = $parser->parse('abcdef');
assert(true === $result->ok());
assert('abc' === $result->data());
assert('def' === $result->unparsed());Full failure:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('abc');
$result = $parser->parse('foo');
assert(false === $result->ok());
assert('unexpected f' === $result->data());
assert('foo' === $result->unparsed());Partial failure:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('abc');
$result = $parser->parse('abd');
assert(false === $result->ok());
assert('unexpected d' === $result->data());
assert('d' === $result->unparsed());Parses the (first match of the) given regular expression. Regex delimiters ("/") are not used. Accepts an optional modifier as optional second parameter.
Using named constructor:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('\d+');Using named constructor with modifier:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('[a-z]', 'i');Using function:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+');Using function with modifier:
use function Stratadox\Parser\pattern;
$parser = pattern('[a-z]', 'i');Successful parse:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('\d+');
$result = $parser->parse('42');
assert(true === $result->ok());
assert('42' === $result->data());
assert('' === $result->unparsed());With capturing group:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('foo(\d)');
$result = $parser->parse('foo4abc');
assert(true === $result->ok());
assert('4' === $result->data());
assert('abc' === $result->unparsed());With multiple capturing groups:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('foo(\d)(\d)');
$result = $parser->parse('foo42abc');
assert(true === $result->ok());
assert(['4', '2'] === $result->data());
assert('abc' === $result->unparsed());Base parsers and non-base parsers alike can be upgraded with these decorator parsers. These add to or modify ("decorate") the behavior of a single parser.
Makes a given parser repeatable, by parsing zero or more of its occurrences and yielding a list of the results.
Using named constructor:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a');Using named constructors:
use Stratadox\Parser\Parsers\Repeatable;
use Stratadox\Parser\Parsers\Text;
$parser = Repeatable::parser(Text::is('a'));Using method:
use function Stratadox\Parser\text;
$parser = text('a')->repeatable();Repeated text:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a');
$result = $parser->parse('aaa');
assert(true === $result->ok());
assert(['a', 'a', 'a'] === $result->data());Unrepeated text:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a');
$result = $parser->parse('a');
assert(true === $result->ok());
assert(['a'] === $result->data());Empty content:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a');
$result = $parser->parse('');
assert(true === $result->ok());
assert([] === $result->data());Shortcut that combines repeatable and join.
Using method:
use function Stratadox\Parser\text;
$parser = text('a')->repeatableString();Repeated text:
use function Stratadox\Parser\text;
$parser = text('a')->repeatableString();
$result = $parser->parse('aaa');
assert(true === $result->ok());
assert('aaa' === $result->data());Applies a function to the data of a successful result.
Using named constructor:
use Stratadox\Parser\Parsers\Map;
$parser = Map::the('foo', $closure);Using named constructors:
use Stratadox\Parser\Parsers\Map;
use Stratadox\Parser\Parsers\Text;
$parser = Map::the(Text::is('foo'), $closure);Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->map($closure);Transforming to upper case:
use Stratadox\Parser\Parsers\Map;
use Stratadox\Parser\Parsers\Text;
$parser = Map::the(Text::is('foo'), fn($result) => strtoupper($result));
$result = $parser->parse('foo');
assert(true === $result->ok());
assert('FOO' === $result->data());Not transforming failed results:
use Stratadox\Parser\Parsers\Map;
use Stratadox\Parser\Parsers\Text;
$parser = Map::the(Text::is('foo'), fn($result) => strtoupper($result));
$result = $parser->parse('bar');
assert(false === $result->ok());
assert('unexpected b' === $result->data());
assert('bar' === $result->unparsed());Applies a function to the result, regardless of whether it was successful or not.
Using named constructor:
use Stratadox\Parser\Parsers\FullyMap;
$parser = FullyMap::the('foo', $closure);Using named constructors:
use Stratadox\Parser\Parsers\FullyMap;
use Stratadox\Parser\Parsers\Text;
$parser = FullyMap::the(Text::is('foo'), $closure);Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->fullMap($closure);Changing the error:
use Stratadox\Parser\Parsers\FullyMap;
use Stratadox\Parser\Result;
use Stratadox\Parser\Results\Error;
$parser = FullyMap::the('foo', fn(Result $r) => $r->ok() ? $r : Error::in('baz'));
$result = $parser->parse('bar');
assert(false === $result->ok());
assert('unexpected b' === $result->data());
assert('baz' === $result->unparsed());Changing error into successful parse:
use Stratadox\Parser\Parsers\FullyMap;
use Stratadox\Parser\Result;
use Stratadox\Parser\Results\Error;
$parser = FullyMap::the(Text::is('foo'), fn(Result $r) => Ok::with('foo', $r->unparsed()));
$result = $parser->parse('bar');
assert(true === $result->ok());
assert('foo' === $result->data());
assert('bar' === $result->unparsed());Requires a successful parsing result, and then ignores it. (Miauw)
Using named constructor:
use Stratadox\Parser\Parsers\Ignore;
$parser = Ignore::the('foo');Using named constructors:
use Stratadox\Parser\Parsers\Ignore;
use Stratadox\Parser\Parsers\Text;
$parser = Ignore::the(Text::is('foo'));Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->ignore();Ignoring a successful parse:
use Stratadox\Parser\Parsers\Ignore;
use Stratadox\Parser\Parsers\Text;
$parser = Ignore::the(Text::is('foo'));
$result = $parser->parse('foo');
assert(true === $result->ok());
assert(false === $result->use());
assert(null === $result->data());
assert('' === $result->unparsed());Not ignoring a failed result:
use Stratadox\Parser\Parsers\Ignore;
use Stratadox\Parser\Parsers\Text;
$parser = Ignore::the(Text::is('foo'));
$result = $parser->parse('bar');
assert(false === $result->ok());
assert(false === $result->use());
assert('unexpected b' === $result->data());
assert('bar' === $result->unparsed());Returns the result if successful, or an empty "skip this" result otherwise.
Using named constructor:
use Stratadox\Parser\Parsers\Maybe;
$parser = Maybe::that('foo');Using named constructors:
use Stratadox\Parser\Parsers\Maybe;
use Stratadox\Parser\Parsers\Text;
$parser = Maybe::that(Text::is('foo'));Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->maybe();Using a successful result:
use Stratadox\Parser\Parsers\Maybe;
use Stratadox\Parser\Parsers\Text;
$parser = Maybe::that(Text::is('foo'));
$result = $parser->parse('foo bar');
assert(true === $result->ok());
assert(true === $result->use());
assert('foo' === $result->data());
assert(' bar' === $result->unparsed());Ignoring a failed result:
use Stratadox\Parser\Parsers\Maybe;
use Stratadox\Parser\Parsers\Text;
$parser = Maybe::that(Text::is('foo'));
$result = $parser->parse('bar bar');
assert(true === $result->ok());
assert(false === $result->use());
assert(null === $result->data());
assert('bar bar' === $result->unparsed());Ignores the parser, yielding a skip result whether the parser succeeds or not.
Using named constructor:
use Stratadox\Parser\Parsers\Optional;
use Stratadox\Parser\Parsers\Text;
$parser = Optional::ignored(Text::is('foo'));Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->optional();Ignoring optional occurrence:
use Stratadox\Parser\Parsers\Optional;
use Stratadox\Parser\Parsers\Text;
$parser = Optional::ignored(Text::is('foo'));
$result = $parser->parse('foo');
assert(true === $result->ok());
assert(false === $result->use());
assert(null === $result->data());
assert('' === $result->unparsed());Ignoring optional non-occurrence:
use Stratadox\Parser\Parsers\Optional;
use Stratadox\Parser\Parsers\Text;
$parser = Optional::ignored(Text::is('foo'));
$result = $parser->parse('bar');
assert(true === $result->ok());
assert(false === $result->use());
assert(null === $result->data());
assert('bar' === $result->unparsed());Transforms a successful result into a failure if another parser also matches the content.
Using named constructor:
use Stratadox\Parser\Parsers\Except;
use Stratadox\Parser\Parsers\Pattern;
$parser = Except::for('4', Pattern::match('\d'));Using method:
use function Stratadox\Parser\pattern;
$parser = pattern('\d')->except('4');Accepting any digit, but failing on 4:
use Stratadox\Parser\Parsers\Except;
use Stratadox\Parser\Parsers\Pattern;
$parser = Except::for('4', Pattern::match('\d'));
$result = $parser->parse('4');
assert(false === $result->ok());
assert('unexpected 4' === $result->data());
assert('4' === $result->unparsed());Accepting 5 as any digit except 4:
use Stratadox\Parser\Parsers\Except;
use Stratadox\Parser\Parsers\Pattern;
$parser = Except::for('4', Pattern::match('\d'));
$result = $parser->parse('5');
assert(true === $result->ok());
assert('5' === $result->data());
assert('' === $result->unparsed());Returns an error result if there is unparsed content remaining after parsing.
Using named constructor:
use Stratadox\Parser\Parsers\End;
use Stratadox\Parser\Parsers\Text;
$parser = End::with(Text::is('foo'));Using method:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('foo')->end();Accepting a full match:
use Stratadox\Parser\Parsers\End;
use Stratadox\Parser\Parsers\Pattern;
$parser = End::with(Pattern::match('\d'));
$result = $parser->parse('4');
assert(true === $result->ok());
assert('4' === $result->data());
assert('' === $result->unparsed());Refusing a partial match:
use Stratadox\Parser\Parsers\End;
use Stratadox\Parser\Parsers\Pattern;
$parser = End::with(Pattern::match('\d'));
$result = $parser->parse('42');
assert(false === $result->ok());
assert('unexpected 2' === $result->data());
assert('2' === $result->unparsed());Decorator that matches the entire result or nothing at all. Used to control where the error occurs. No effect on successful results.
Using named constructor:
use Stratadox\Parser\Parsers\AllOrNothing;
use Stratadox\Parser\Parsers\Text;
$parser = AllOrNothing::in(Text::is('foo'));Resetting the error to the first character:
use Stratadox\Parser\Parsers\AllOrNothing;
$parser = AllOrNothing::in('aaa');
$result = $parser->parse('aab');
assert(false === $result->ok());
assert('unexpected a' === $result->data());
assert('aab' === $result->unparsed());Parsers can be combined using these combinators. These parsers take a number of parsers, combining them into one.
Returns the first matching parser of the lot. If none of the parsers match, returns the error of one that got furthest.
Using named constructor:
use Stratadox\Parser\Parsers\Either;
$parser = Either::of('foo', 'bar', 'baz'));Using named constructors:
use Stratadox\Parser\Parsers\Either;
use Stratadox\Parser\Parsers\Text;
$parser = Either::of(Text::is('foo'), Text::is('bar'), Text::is('baz'));Using method:
use function Stratadox\Parser\text;
$parser = text('foo')->or('bar', 'baz');Using method chain:
use function Stratadox\Parser\text;
$parser = text('foo')->or('bar')->or('baz');Parsing as foo:
use Stratadox\Parser\Parsers\Either;
$parser = Either::of('foo', 'bar', 'baz'));
assert(true === $result->ok());
assert('foo' === $result->data());
assert('' === $result->unparsed());Parsing as bar:
use Stratadox\Parser\Parsers\Either;
$parser = Either::of('foo', 'bar', 'baz'));
assert(true === $result->ok());
assert('bar' === $result->data());
assert('' === $result->unparsed());Refusing abc:
use Stratadox\Parser\Parsers\Either;
$parser = Either::of('foo', 'bar', 'baz'));
$result = $parser->parse('abc');
assert(false === $result->ok());
assert('unexpected a' === $result->data());
assert('abc' === $result->unparsed());Puts several parsers one after the other. Leaves ignored results out of the returned list of results.
Using named constructor:
use Stratadox\Parser\Parsers\Sequence;
use Stratadox\Parser\Parsers\Text;
$parser = Sequence::of('a', 'b', 'c');Using named constructors:
use Stratadox\Parser\Parsers\Sequence;
use Stratadox\Parser\Parsers\Text;
$parser = Sequence::of(Text::is('a'), Text::is('b'), Text::is('c'));Using method:
use function Stratadox\Parser\text;
$parser = text('a')->andThen('b', 'c');Using method chain:
use function Stratadox\Parser\text;
$parser = text('a')->andThen('b')->andThen('c');Parsing abc as sequence:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c');
$result = $parser->parse('abcdef');
assert(true === $result->ok());
assert(['a', 'b', 'c'] === $result->data());
assert('def' === $result->unparsed());Refusing partial matches:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c');
$result = $parser->parse('abxyz');
assert(true === $result->ok());
assert('unexpected x' === $result->data());
assert('xyz' === $result->unparsed());Parsing sequences with ignored bits:
use Stratadox\Parser\Parsers\Ignore;
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of(Ignore::the('a'), 'b', 'c');
$result = $parser->parse('abcdef');
assert(true === $result->ok());
assert(['b', 'c'] === $result->data());
assert('def' === $result->unparsed());All the above can be mixed and combined at will. To make life easier, there's a bunch of combinator shortcuts for "everyday tasks".
Matches the parser's content between start and end.
Using named constructor:
use Stratadox\Parser\Helpers\Between;
use Stratadox\Parser\Parsers\Pattern;
$parser = Between::these('(', ')', Pattern::match('\d+'));Using named constructors:
use Stratadox\Parser\Helpers\Between;
use Stratadox\Parser\Parsers\Pattern;
use Stratadox\Parser\Parsers\Text;
$parser = Between::these(Text::is('('), Text::is(')'), Pattern::match('\d+'));Using method:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+')->between('(', ')');Using method with single parameter:
use function Stratadox\Parser\pattern;
$parser = pattern('[a-z]+')->between('"');Parsing an integer between braces:
use Stratadox\Parser\Helpers\Between;
use Stratadox\Parser\Parsers\Pattern;
$parser = Between::these('(', ')', Pattern::match('\d+'));
$result = $parser->parse('(123)');
assert(true === $result->ok());
assert('123' === $result->data());
assert('' === $result->unparsed());Refusing an integer without braces:
use Stratadox\Parser\Helpers\Between;
use Stratadox\Parser\Parsers\Pattern;
$parser = Between::these('(', ')', Pattern::match('\d+'));
$result = $parser->parse('123');
assert(true === $result->ok());
assert('unexpected 1' === $result->data());
assert('123' === $result->unparsed());Matches unescaped content between start and end.
Using named constructor:
use Stratadox\Parser\Helpers\Between;
$parser = Between::escaped($from, $to, $escape);Parsing a string with escaped quotes:
use Stratadox\Parser\Helpers\Between;
$parser = Between::escaped('"', '"', '!');
$result = $parser->parse('"foo!"bar!!"');
assert(true === $result->ok());
assert('foo"bar!' === $result->data());
assert('' === $result->unparsed());Using a different escape for the escape sequence:
use Stratadox\Parser\Helpers\Between;
$parser = Between::escaped('"', '"', '!?', '_');
$result = $parser->parse('"foo!?"bar_!?"');
assert(true === $result->ok());
assert('foo"bar!?' === $result->data());
assert('' === $result->unparsed());Splits content based on a separator. Yields one or more results.
Using named constructor:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::optional(',', Pattern::match('\d+'));Using method:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+')->split(',');Splitting integers with commas:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::optional(',', Pattern::match('\d+'));
$result = $parser->parse('12,16,1,5646');
assert(true === $result->ok());
assert(['12', '16', '1', '5646'] === $result->data());
assert('' === $result->unparsed());Splitting a single integer with (absent) commas:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::optional(',', Pattern::match('\d+'));
$result = $parser->parse('12');
assert(true === $result->ok());
assert(['12'] === $result->data());
assert('' === $result->unparsed());Splits content based on a separator. Yields two or more results.
Using named constructor:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::with(',', Pattern::match('\d+'));Using method:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+')->mustSplit(',');Splitting integers with commas:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::with(',', Pattern::match('\d+'));
$result = $parser->parse('12,16,1,5646');
assert(true === $result->ok());
assert(['12', '16', '1', '5646'] === $result->data());
assert('' === $result->unparsed());Refusing content without separator:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::with(',', Pattern::match('\d+'));
$result = $parser->parse('12');
assert(false === $result->ok());
assert('unexpected end' === $result->data());
assert('' === $result->unparsed());Splits content based on a separator, keeping the separator.
Yields a structure like {delimiter: [left, right]}, unless mapped differently.
Using named constructors:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Either;
use Stratadox\Parser\Parsers\Pattern;
use Stratadox\Parser\Parsers\Text;
$parser = Split::keep(
Either::of(Text::is('*'), Text::is('/')),
Pattern::match('\d+')
);Using named constructor with shortcuts:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::keep(['*', '/'], Pattern::match('\d+'));Using named constructor with shortcuts and mapping:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::keep(['*', '/'], Pattern::match('\d+'), $closure);Using method:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+')->keepSplit(['*', '/']);Using method with mapping:
use function Stratadox\Parser\pattern;
$parser = pattern('\d+')->keepSplit(['*', '/'], $closure);Splitting multiplication and division, keeping the operator:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::keep(['*', '/'], Pattern::match('\d+'));
$result = $parser->parse('1*2/3');
assert(true === $result->ok());
assert(['/' => [['*' => ['1', '2']], '3']] === $result->data());Splitting multiplication and division, mapping the result:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::keep(['*', '/'], Pattern::match('\d+'), fn($op, $l, $r) => [
'op' => $op,
'arg' => [$l, $r],
]);
$result = $parser->parse('1*2/3');
assert(true === $result->ok());
assert([
'op' => '/',
'arg' => [
[
'op' => '*',
'arg' => ['1', '2'],
],
'3',
],
] === $result->data());Refusing content without separator:
use Stratadox\Parser\Helpers\Split;
use Stratadox\Parser\Parsers\Pattern;
$parser = Split::keep(['*', '/'], Pattern::match('\d+'));
$result = $parser->parse('1');
assert(false === $result->ok());
assert('unexpected end' === $result->data());
assert('' === $result->unparsed());There's several additional helpers, which are essentially mapping shortcuts.
Implodes the array result into a string.
Using named constructor:
use Stratadox\Parser\Helpers\Join;
use Stratadox\Parser\Parsers\Sequence;
$parser = Join::the(Sequence::of('a', 'b', 'c'));Using named constructor with glue:
use Stratadox\Parser\Helpers\Join;
use Stratadox\Parser\Parsers\Sequence;
$parser = Join::with(';', Sequence::of('a', 'b', 'c'));Using method:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c')->join();Using method with glue:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c')->join(';');Joining a sequence:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c')->join(';');
$result = $parser->parse('abc');
assert(true === $result->ok());
assert('a;b;c' === $result->data());No transformations on text result:
use Stratadox\Parser\Parsers\Text;
$parser = Text::is('abc')->join(';');
$result = $parser->parse('abc');
assert(true === $result->ok());
assert('abc' === $result->data());Transforms an array result into its first item.
Using named constructor:
use Stratadox\Parser\Helpers\First;
use Stratadox\Parser\Parsers\Sequence;
$parser = First::of(Sequence::of('a', 'b', 'c'));Using method:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c')->first();Transforms an array result into its nth item.
Using named constructor:
use Stratadox\Parser\Helpers\Item;
use Stratadox\Parser\Parsers\Sequence;
$parser = Item::number(2, Sequence::of('a', 'b', 'c'));Using method:
use Stratadox\Parser\Parsers\Sequence;
$parser = Sequence::of('a', 'b', 'c')->item(2);Refuses empty results.
Using named constructor:
use Stratadox\Parser\Helpers\NonEmpty;
use Stratadox\Parser\Parsers\Pattern;
$parser = NonEmpty::result(Pattern::match('\d+'));Using method:
use Stratadox\Parser\Parsers\Pattern;
$parser = Pattern::match('\d+')->nonEmpty();Refuses array results with fewer than x entries.
Using named constructor:
use Stratadox\Parser\Helpers\AtLeast;
use Stratadox\Parser\Parsers\Repeatable;
$parser = AtLeast::results(5, Repeatable::parser('a'));Using method:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a')->atLeast(5);Refusing results with fewer than 5 entries:
use Stratadox\Parser\Helpers\AtLeast;
use Stratadox\Parser\Parsers\Repeatable;
$parser = AtLeast::results(5, Repeatable::parser('a'));
$result = $parser->parse('aaaa');
assert(false === $result->ok());
assert('unexpected end' === $result->data());Refuses array results with more than x entries.
Using named constructor:
use Stratadox\Parser\Helpers\AtMost;
use Stratadox\Parser\Parsers\Repeatable;
$parser = AtMost::results(5, Repeatable::parser('a'));Using method:
use Stratadox\Parser\Parsers\Repeatable;
$parser = Repeatable::parser('a')->atMost(5);Refusing results with more than 5 entries:
use Stratadox\Parser\Helpers\AtMost;
use Stratadox\Parser\Parsers\Repeatable;
$parser = AtMost::results(5, Repeatable::parser('a'));
$result = $parser->parse('aaaaaa');
assert(false === $result->ok());
assert('unexpected a' === $result->data());To enable lazy parsers (and/or to provide a structure), different containers are available.
Manages lazy loading, essential for recursive parsers.
Using named constructor:
use Stratadox\Parser\Containers\Lazy;
$lazy = Lazy::container();Parsing a recursive definition:
use Stratadox\Parser\Containers\Lazy;
$lazy = Lazy::container();
$lazy['parser'] = $lazy['parser']->between('(', ')')->or('z');
$result = $lazy['parser']->parse('(((z)))');
assert(true === $result->ok());
assert('z' === $result->data());A basic typed list of regular parsers.
Using named constructor:
use Stratadox\Parser\Containers\Eager;
$eager = Eager::container();It's just a simple container:
use Stratadox\Parser\Containers\Eager;
use Stratadox\Parser\Parsers\Text;
$eager = Eager::container();
$eager['parser'] = Text::is('foo');
$result = $eager['parser']->parse('foo');
assert(true === $result->ok());
assert('foo' === $result->data());Prevents infinite looping on left-recursion.
Using named constructor:
use Stratadox\Parser\Containers\Lazy;
use Stratadox\Parser\Containers\Limited;
$lazy = Limited::recursion(Lazy::container());Parsing despite left-recursion:
use Stratadox\Parser\Containers\Lazy;
use Stratadox\Parser\Containers\Limited;
$lazy = Limited::recursion(Lazy::container());
$lazy['parser'] = $lazy['parser']->andThen('a')->or('z')->split(',');
$result = $lazy['parser']->parse('z,z,z');
assert(true === $result->ok());
assert(['z', 'z', 'z'] === $result->data());Mixes lazy and eager containers.
Using named constructor:
use Stratadox\Parser\Containers\Grammar;
$grammar = Grammar::container();Using named constructor and $lazy syntax:
use Stratadox\Parser\Containers\Grammar;
use Stratadox\Parser\Containers\Lazy;
$grammar = Grammar::with($lazy = Lazy::container());use Stratadox\Parser\Containers\Grammar;
use Stratadox\Parser\Containers\Lazy;
use function Stratadox\Parser\text;
$grammar = Grammar::with($lazy = Lazy::container());
$grammar['a|b'] = text('a')->or('b');
$lazy['(a|b)'] = $grammar['(a|b)']->between('(', ')')->or($grammar['(a|b)']);
$result = $lazy['(a|b)']->parse('((((((b))))))');
assert(true === $result->ok());
assert('b' === $result->data());use Stratadox\Parser\Containers\Grammar;
use Stratadox\Parser\Containers\Lazy;
use function Stratadox\Parser\text;
$grammar = Grammar::with($lazy = Lazy::container());
$grammar['a|b'] = text('a')->or('b');
$lazy['(a|b)'] = $grammar['(a|b)']->between('(', ')')->or($grammar['(a|b)']);
$result = $lazy['(a|b)']->parse('(a)');
assert(true === $result->ok());
assert('a' === $result->data());