Ejemplo n.º 1
0
 public function parse(Input $input)
 {
     if (!$input->complete()) {
         return $input->errorHere("Unable to process {$input->get()}")->addParser($this);
     }
     return $input->nonCapturingMatchHere()->addParser($this);
 }
Ejemplo n.º 2
0
 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);
 }
Ejemplo n.º 3
0
 /**
  * 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);
 }
Ejemplo n.º 4
0
 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);
 }
Ejemplo n.º 5
0
 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);
 }
Ejemplo n.º 6
0
 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;
 }
Ejemplo n.º 7
0
 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);
 }
Ejemplo n.º 8
0
 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);
     }
 }
Ejemplo n.º 9
0
 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);
     }
 }
Ejemplo n.º 10
0
 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());
 }
Ejemplo n.º 11
0
 /**
  * Parse the given input
  *
  * @param Input $input
  *
  * @return mixed result
  */
 public function parse(Input $input)
 {
     return $input->nonCapturingMatchHere(true)->addParser($this);
 }