public function parse(Input $input) { if (!$input->complete()) { return $input->errorHere("Unable to process {$input->get()}")->addParser($this); } return $input->nonCapturingMatchHere()->addParser($this); }
public function parse(Input $input) { $aggregatedResult = []; $isPositive = false; $count = 0; $lastOffset = $input->getOffset(); while ($this->max === null || $count < $this->max) { $result = parent::parse($input)->addParser($this); if ($result->positiveMatch) { $isPositive = true; } if ($result->errorMessage) { if ($count < $this->min) { return $input->errorHere("Expected {$this->min} elements, but found {$count}"); } elseif ($result->positiveMatch) { // If a branch got far enough to assert itself but still returned an error then we need to propagate return $result; } // Most errors are normal, they just signal the end of the repetition. break; } if ($input->getOffset() == $lastOffset) { throw new GrammarException('At ' . $input->getPositionDescription() . ": parser {$result->getParserStack()} did not consume any input, this is a bug with the grammar. Make sure there are no zero width matches in a Many. The result in was {$result}"); } if ($result->hasData) { $aggregatedResult[] = $result->data; } $lastOffset++; $count++; } if ($count < $this->min) { return $input->errorHere("Expected {$this->min} elements, but found {$count}", $isPositive)->addParser($this); } return $input->matchHere($aggregatedResult, $isPositive); }
/** * Parse the given input * * @param Input $input * * @return mixed result */ public function parse(Input $input) { if ($input->peek(0) === $this->char) { $input->consume(1); return $input->matchHere($this->char); } return $input->errorHere("{$this->char} was not found.")->addParser($this); }
public function parse(Input $input) { $initialOffset = $input->getOffset(); foreach ($this->getParsers() as $parser) { // Keep trying each of the parsers until one matches. $result = $parser->parse($input); // Stop on the first match if (!$result->errorMessage || $result->hasData) { return $result->addParser($this); } // To be safe we rewind the input after each attempt. $input->setOffset($initialOffset); } return $input->matchHere(null)->addParser($this); }
public function parse(Input $input) { $initialOffset = $input->getOffset(); foreach ($this->getParsers() as $parser) { // Keep trying each of the parsers until one matches. $result = $parser->parse($input); // Errors and positive results will stop us from searching. if (!$result->errorMessage || $result->positiveMatch) { return $result->addParser($this); } // To be safe we rewind the input after each attempt. $input->setOffset($initialOffset); } return $input->errorHere("Could not find any options that match {$input->get()}")->addParser($this); }
private function matches(Input $input) { $initialOffset = $input->getOffset(); foreach ($this->getParsers() as $parser) { // Keep trying each of the parsers until one matches. $result = $parser->parse($input); // Errors and positive results will stop us from searching. if ($result->match) { if ($initialOffset === $input->getOffset()) { throw new GrammarException('There was a zero width match inside a Not parser.'); } $input->setOffset($initialOffset); return true; } // To be safe we rewind the input after each attempt. $input->setOffset($initialOffset); } return false; }
public function setOffset($offset) { $diff = abs($this->getOffset() - $offset); if ($offset < $this->getOffset()) { $this->getParserData()['rewound'] += $diff; $this->log(Parser::getInlineParserStack() . " - rewind({$diff})"); } elseif ($offset > $this->getOffset()) { $this->getParserData()['consumed'] += $diff; $this->log(Parser::getInlineParserStack() . " - consume({$diff}, '{$this->get($diff)}')"); } parent::setOffset($offset); }
public function parse(Input $input) { if (!$input->match($this->expression, $matches)) { return $input->errorHere("Expected regex '{$this->expression}' to match '{$input->get()}', it does not.")->addParser($this); } $output = $input->getAndConsume(strlen($matches[0])); if (!$this->capturing) { return $input->nonCapturingMatchHere($output)->addParser($this); } else { return $input->matchHere($output)->addParser($this); } }
public function parse(Input $input) { $aggregatedData = []; $isPositive = false; $initialOffset = $input->getOffset(); foreach ($this->getParsers() as $parser) { $result = $parser->parse($input); if ($result->hasData) { $aggregatedData[] = $result->data; } // Any single positive match in the sequence makes the whole sequence positive. if ($result->positiveMatch) { $isPositive = true; } // Any single error causes the whole sequence to error if ($result->errorMessage) { $result->positiveMatch = $isPositive; if ($aggregatedData) { $result->errorMessage .= "\nPrevious tokens:\n"; foreach ($aggregatedData as $token) { if (is_callable([$token, '__toString'])) { $result->errorMessage .= ' - ' . $token->__toString() . "\n"; } else { $result->errorMessage .= ' - ' . print_r($token, true) . "\n"; } } } return $result->addParser($this); } } if ($aggregatedData === []) { return $input->nonCapturingMatchHere($isPositive, $initialOffset)->addParser($this); } else { return $input->matchHere($aggregatedData, $isPositive, $initialOffset)->addParser($this); } }
public function testPeek() { $input = new Input('1234'); $this->assertEquals('1', $input->peek(0)); $this->assertEquals('2', $input->peek(1)); $this->assertEquals('3', $input->peek(2)); $this->assertEquals('4', $input->peek(3)); $this->assertEquals(0, $input->getOffset()); }
/** * Parse the given input * * @param Input $input * * @return mixed result */ public function parse(Input $input) { return $input->nonCapturingMatchHere(true)->addParser($this); }