1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Tokenizer;
9:
10:
11: 12: 13:
14: class Tokenizer
15: {
16:
17: private $re;
18:
19:
20: private $types;
21:
22:
23: 24: 25: 26:
27: public function __construct(array $patterns, $flags = '')
28: {
29: $this->re = '~(' . implode(')|(', $patterns) . ')~A' . $flags;
30: $this->types = array_keys($patterns);
31: }
32:
33:
34: 35: 36: 37: 38: 39:
40: public function tokenize($input)
41: {
42: preg_match_all($this->re, $input, $tokens, PREG_SET_ORDER);
43: $len = 0;
44: $count = count($this->types);
45: foreach ($tokens as &$token) {
46: $type = null;
47: for ($i = 1; $i <= $count; $i++) {
48: if (!isset($token[$i])) {
49: break;
50: } elseif ($token[$i] != null) {
51: $type = $this->types[$i - 1];
52: break;
53: }
54: }
55: $token = new Token($token[0], $type, $len);
56: $len += strlen($token->value);
57: }
58: if ($len !== strlen($input)) {
59: list($line, $col) = $this->getCoordinates($input, $len);
60: $token = str_replace("\n", '\n', substr($input, $len, 10));
61: throw new Exception("Unexpected '$token' on line $line, column $col.");
62: }
63: return new Stream($tokens);
64: }
65:
66:
67: 68: 69: 70: 71: 72:
73: public static function getCoordinates($text, $offset)
74: {
75: $text = substr($text, 0, $offset);
76: return [substr_count($text, "\n") + 1, $offset - strrpos("\n" . $text, "\n") + 1];
77: }
78: }
79: