vanderlee/Comprehend

View on GitHub
src/Parser/Structure/Sequence.php

Summary

Maintainability
A
45 mins
Test Coverage
<?php

namespace Vanderlee\Comprehend\Parser\Structure;

use InvalidArgumentException;
use Vanderlee\Comprehend\Core\Context;
use Vanderlee\Comprehend\Match\Success;
use Vanderlee\Comprehend\Parser\Parser;

/**
 * Description of SequenceParser.
 *
 * @author Martijn
 */
class Sequence extends IterableParser
{
    use SpacingTrait;

    public function __construct(...$arguments)
    {
        if (empty($arguments)) {
            throw new InvalidArgumentException('No arguments');
        }

        $this->parsers = self::getArguments($arguments, false);
    }

    protected function parse(&$input, $offset, Context $context)
    {
        $childMatches = [];

        $this->pushSpacer($context);

        $total = 0;
        /** @var Parser $parser */
        foreach ($this->parsers as $parser) {
            if ($total > 0) {
                $skip = $context->skipSpacing($input, $offset + $total);
                if ($skip === false) {
                    return $this->failure($input, $offset, $total);
                }
                $total += $skip;
            }
            $match = $parser->parse($input, $offset + $total, $context);
            $total += $match->length;

            if (!($match instanceof Success)) {  // must match
                $this->popSpacer($context);

                return $this->failure($input, $offset, $total);
            }

            $childMatches[] = $match;
        }

        $this->popSpacer($context);

        return $this->success($input, $offset, $total, $childMatches);
    }

    /**
     * Add one or more parsers to the end of this sequence.
     *
     * @param string[]|int[]|Parser[] $arguments
     *
     * @return $this
     */
    public function add(...$arguments)
    {
        $this->parsers = array_merge($this->parsers, self::getArguments($arguments));

        return $this;
    }

    public function __toString()
    {
        return '( ' . implode(' ', $this->parsers) . ' )';
    }
}