Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Parsica Laravel Package

parsica-php/parsica

Parsica is a PHP parser combinator library for building custom parsers from small reusable pieces. Compose complex grammars with a fluent API, parse strings into structured results, and handle errors cleanly—ideal for DSLs, config formats, and language tooling.

View on GitHub
Deep Wiki
Context7

title: Dealing with Space

Parsica comes with a number of useful parsers for dealing with different types of whitespace and newlines, as well with required or optional whitespace. We recommend browsing src/space.php to see what is available, so you don't need to build your own parsers for that.

Space consumers

When building a parser for say a language or a file format, you often have specific rules about space. Whitespace can be required or optional, and expressions can be valid or invalid if they contain newlines. All of these are could be valid or invalid depending on your case:

// with 0, 1, or more spaces
1+1
1 + 1
1   +   1

// multiline
1 +
2

// tabs
1 
  + 2

There's too much variation for Parsica to provide a single solution. However, you don't want to litter your code with space parsers everywhere:

<?php
$term = digitChar();
$operator = char('+');
$parser = collect(
        $term,
        skipSpace1(),
        $operator,
        skipSpace1(),
        $term,
        skipSpace1(),
    )->map(fn($o) => $o[0] + $o[4]);

$result = $parser->tryString("1  +\n  2\t");
assertSame(3, $result->output());

This is noisy. And if you want to change the rules about whitespace or build more complex parsers, you have to deal with this problem all the time, making it unmaintainable (or at least annoying).

The idea is to build a space consumer that you can reuse everywhere. The space consumer is a parser combinator that you wrap around another parser, and that returns the output of the inner parser, ignoring whitespace. A typical approach is to consistently ignore space after the thing you're interested in.

<?php
// $token behaves just like $parser, but requires the parsed 
// value to be followed by at least 1 space
$token = fn(Parser $parser) => keepFirst($parser, skipSpace1());

// Now we wrap our parsers
$term = $token(digitChar());
$operator = $token(char('+'));

// Our main parser now has the same "shape" as the expression we're trying to parse:
$parser = collect(
        $term,
        $operator,
        $term,
    )->map(fn($o) => $o[0] + $o[2]);

$result = $parser->tryString("1  +\n  2\t");
assertSame(3, $result->output());

Now, all the logic for skipping space is nicely contained in $token. If we wanted to disallow multiline expressions, we only need to replace skipSpace1() with skipHSpace1() in one place.

As an example, here's an excerpt from the JSON parser, using the ws (whitespace) as defined in the JSON spec:

final class MyJSON
{ 
    public static function ws(): Parser
    {
        return zeroOrMore(satisfy(isCharCode([0x20, 0x0A, 0x0D, 0x09])))->voidLeft(null)
            ->label('whitespace');
    }

    public static function token(Parser $parser): Parser
    {
        return keepFirst($parser, JSON::ws());
    }

    public static function object(): Parser
    {
        return map(
            between(
                JSON::token(char('{')),
                JSON::token(char('}')),
                sepBy(
                    JSON::token(char(',')),
                    JSON::member()
                )
            ),
            fn(array $members):object => (object)array_merge(...$members));
    }

    // see src/JSON/JSON.php for the full code
}

If you have multiple ways of handling space in one parser, you can of course define multiple space consumers and give them relevant names.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport