public function match(Parser $parser, Scanner $scanner) { $right = $scanner->getContext()->pop(); $op = $scanner->getContext()->pop(); $left = $scanner->getContext()->pop(); switch ($op) { case '+': $e = new E\Add($left, $right); break; case '-': $e = new E\Sub($left, $right); break; case '*': $e = new E\Mul($left, $right); break; case '/': $e = new E\Div($left, $right); break; case '^': $e = new E\Pow($left, $right); break; // default: '????'; return; } $scanner->getContext()->push($e); }
public function trigger(Scanner $scanner) { if ($scanner->type() !== Scanner::CHAR) { return false; } if (is_null($this->char)) { return true; } return $scanner->token() == $this->char; }
public function trigger(Scanner $scanner) { if ($scanner->type() !== Scanner::NUMBER) { return false; } if (is_null($this->num)) { return true; } return $scanner->token() == $this->num; }
public function trigger(Scanner $scanner) { if ($scanner->type() !== Scanner::WORD) { return false; } if (is_null($this->word)) { return true; } return $scanner->token() == $this->word; }
protected function doScan(Scanner $scan) { $state = $scan->getState(); foreach ($this->parsers as $p) { if (!$p->trigger($scan) || !$p->scan($scan)) { $scan->setState($state); return false; } } return true; }
public function match(Parser $parser, Scanner $scanner) { // only one argument implementation yet $start = $scanner->getContext()->pop(); $arguments = array(); while (($t = $scanner->getContext()->pop()) !== '(') { $arguments[] = $t; } $name = $scanner->getContext()->pop(); $scanner->getContext()->push(new E\Func($name, array_reverse($arguments))); }
protected function doScan(Scanner $scan) { $q = $scan->type(); $ok = false; $escape = false; $str = ''; while ($scan->next()) { if ($escape) { $escape = false; } else { if ($scan->token() === '\\') { $escape = true; continue; } if ($q === $scan->type()) { $ok = true; break; } } $str .= $scan->token(); } if ($ok && !$this->discard) { $scan->getContext()->push($str); } return $ok; }
public function match(Parser $parser, Scanner $scanner) { $value = $scanner->getContext()->pop(); $sign = $scanner->getContext()->pop(); switch ($sign) { case '+': $e = $value; break; case '-': $e = new E\Neg($value); break; default: $e = $value; if (!is_null($sign)) { $scanner->getContext()->push($sign); } break; } $scanner->getContext()->push($e); }
protected function doScan(Scanner $scan) { $start = $scan->getState(); $count = 0; while (true) { if ($this->max > 0 && $count >= $this->max) { break; } if (!$this->parser->trigger($scan) || !$this->parser->scan($scan)) { if ($this->min == 0 || $count >= $this->min) { break; } else { // $scan->setState($start); return false; } } $count++; } return true; }
public function testScan() { $scan = new I\Scanner(new I\StringReader("1+2"), $ctx = new I\Context()); $scan->next(); $this->assertSame('1', $scan->token()); $scan->next(); $this->assertSame('+', $scan->token()); $scan->next(); $this->assertSame('2', $scan->token()); }
public function trigger(Scanner $scan) { return in_array($scan->token(), $this->chars); }
public function match(Parser $parser, Scanner $scanner) { $value = $scanner->getContext()->pop(); $scanner->getContext()->push(new E\Literal($value)); }
protected function doScan(Scanner $scan) { $start = $scan->getState(); $int = $scan->token(); $scan->next(); if ($scan->token() !== '.') { $scan->setState($start); $res = is_null($this->number) || $this->number == $int; if ($res) { $scan->getContext()->push($int); // echo "$int | Parsed. Next token is not a point\n"; // } else { // echo "$int | Next token is not a point. Doesn't match {$this->number}\n"; } return $res; } if (!$scan->next() || $scan->type() !== Scanner::NUMBER) { $scan->setState($start); // echo "$int | Fail: not number after /\d+\./ \n"; return false; } $frac = $scan->token(); if (!is_null($this->number)) { if ("{$int}.{$frac}" != $this->number) { $scan->setState($start); // echo "$int.$frac | Parsed float doesn't match {$this->number}\n"; return false; } } $scan->getContext()->push("{$int}.{$frac}"); // echo "$int.$frac | Parsed\n"; return true; }