/**
  * @param In $inputStream
  * @param bool $keepCrlf If true, the line ending CRLF will be returned in the string
  * @param int $offset An offset tracker for the stream
  * @param int $maxLineLength The max line length. If it is reached, an exception will be thrown
  * @return string
  *
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidDataException If the line doesn't end with a CRLF, or if $maxLineLength is reached (if EOF or unix EOL is found)
  * @throws \Avalonia\Component\Message\Exception\MapperMaxLineLengthException If the line isn't ended before $maxLineLength
  *
  * Read an HTTP line
  */
 protected function readHttpLine(In $inputStream, bool $keepCrlf = false, int &$offset = null, int $maxLineLength = self::DEFAULT_MAX_LINE_LENGTH) : string
 {
     $buffer = '';
     $lastChar = '';
     $bufferLength = 0;
     $offset = $offset ?: 0;
     do {
         if ($inputStream->eof()) {
             throw (new MapperInvalidDataEofFoundException("The given line has no end. Found EOF before CRLF."))->setRemainingBufferData($buffer);
         }
         if ($maxLineLength <= $bufferLength) {
             throw new MapperMaxLineLengthException("Http line max length reached.");
         }
         $char = $inputStream->readCharacter();
         $buffer .= $char;
         $bufferLength++;
         $offset++;
         if (static::LF === $char) {
             if (static::CR !== $lastChar) {
                 throw new MapperInvalidDataException("The given line ends with a LF, not with a CRLF");
             }
             if (!$keepCrlf) {
                 $buffer = substr($buffer, 0, -2);
             }
             return $buffer;
         }
         $lastChar = $char;
     } while (true);
 }
Example #2
0
 /**
  * Load parser from a file that contains the grammar.
  * Example:
  *     %skip  space     \s
  *
  *     %token word      [a-zA-Z]+
  *     %token number    [0-9]+(\.[0-9]+)?
  *     %token open_par  \(
  *     %token close_par \)
  *     %token equal     =
  *     %token plus      \+
  *     %token minus     \-
  *     %token divide    \/
  *     %token times     \*
  *
  *     #equation:
  *         formula() ::equal:: <number>
  *
  *     formula:
  *         factor()
  *         (
  *             ::plus::  formula() #addition
  *           | ::minus:: formula() #substraction
  *         )?
  *
  *     factor:
  *         operand()
  *         (
  *             ::times::  factor() #product
  *           | ::divide:: factor() #division
  *         )?
  *
  *     operand:
  *           <word>
  *         | ::minus::? <number> #number
  *         | ::open_par:: formula() ::close_par::
  *
  * Use tabs or spaces, it does not matter.
  * Instructions follow the form: %<instruction>. Only %skip and %token are
  * supported.
  * Rules follow the form: <rule name>:<new line>[<space><rule><new line>]*.
  * Contexts are useful to set specific skips and tokens. We give a full
  * example with context + unification (for fun) to parse <a>b</a>:
  *     %skip   space         \s
  *     %token  lt             <        ->  in_tag
  *     %token  inner          [^<]*
  *
  *     %skip   in_tag:space   \s
  *     %token  in_tag:slash   /
  *     %token  in_tag:tagname [^>]+
  *     %token  in_tag:gt      >        ->  default
  *
  *     #foo:
  *         ::lt:: <tagname[0]> ::gt::
  *         <inner>
  *         ::lt:: ::slash:: ::tagname[0]:: ::gt::
  *
  * @param   \Hoa\Stream\IStream\In  $stream    Stream that contains the
  *                                             grammar.
  * @return  \Hoa\Compiler\Llk\Parser
  * @throws  \Hoa\Compiler\Exception
  */
 public static function load(Stream\IStream\In $stream)
 {
     $pp = $stream->readAll();
     if (empty($pp)) {
         $message = 'The grammar is empty';
         if ($stream instanceof Stream\IStream\Pointable) {
             if (0 < $stream->tell()) {
                 $message .= ': the stream ' . $stream->getStreamName() . ' is pointable and not rewinded, maybe it ' . 'could be the reason';
             } else {
                 $message .= ': nothing to read on the stream ' . $stream->getStreamName();
             }
         }
         throw new Compiler\Exception($message . '.', 0);
     }
     static::parsePP($pp, $tokens, $rawRules);
     $ruleAnalyzer = new Rule\Analyzer($tokens);
     $rules = $ruleAnalyzer->analyzeRules($rawRules);
     return new Parser($tokens, $rules);
 }