コード例 #1
0
ファイル: Llk.php プロジェクト: lovenunu/Hoa-compiler
 /**
  * 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);
 }