1 : <?php
2 :
3 :
4 :
5 :
6 :
7 :
8 :
9 :
10 :
11 :
12 :
13 :
14 :
15 :
16 :
17 :
18 :
19 :
20 :
21 :
22 :
23 :
24 :
25 :
26 :
27 :
28 :
29 :
30 :
31 :
32 :
33 : class CLexer
34 : {
35 :
36 : private $single_characters = array(
37 : '(' => TOKEN_OPEN_NORMAL_BRACKET,
38 : ')' => TOKEN_CLOSE_NORMAL_BRACKET,
39 : '{' => TOKEN_OPEN_CURLY_BRACKET,
40 : '}' => TOKEN_CLOSE_CURLY_BRACKET,
41 : '[' => TOKEN_OPEN_SQUARE_BRACKET,
42 : ']' => TOKEN_CLOSE_SQUARE_BRACKET,
43 : '=' => TOKEN_EQUALS,
44 : '.' => TOKEN_PERIOD,
45 : ',' => TOKEN_COMMA,
46 : ';' => TOKEN_SEMICOLON,
47 : '*' => TOKEN_ASTERIX
48 : );
49 :
50 : private $reserved_words = array(
51 : 'auto', 'break', 'case', 'continue', 'default', 'do', 'else', 'enum', 'extern',
52 : 'for', 'goto', 'if', 'inline', 'register', 'restrict', 'return', 'sizeof', 'static',
53 : 'struct', 'switch', 'typedef', 'union', 'volatile', 'while'
54 : );
55 :
56 : private $token_words = array(
57 : 'const' => TOKEN_CONST,
58 : );
59 :
60 : private $reserved_values = array('NULL');
61 :
62 :
63 :
64 :
65 :
66 : public function resetState()
67 3 : {}
68 :
69 :
70 :
71 :
72 :
73 : public function process($source)
74 : {
75 3 : $offset = 0;
76 3 : $length = strlen($source);
77 3 : $tokens = array();
78 :
79 :
80 3 : $source = preg_replace('!/\*[^*].*?\*/!s', '', $source);
81 :
82 3 : $curr_line = 1;
83 3 : while ($offset < $length) {
84 :
85 3 : if (preg_match('/\G(\n|\r|\n\r)/', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
86 3 : $curr_line++;
87 3 : $offset = $matches[0][1] + strlen($matches[0][0]);
88 :
89 3 : continue;
90 : }
91 :
92 :
93 :
94 3 : foreach ($this->single_characters as $char => $token_type) {
95 3 : if ($source[$offset] == $char) {
96 3 : $tokens[] = new Token($token_type, $char);
97 3 : $offset++;
98 :
99 3 : continue 2;
100 : }
101 3 : }
102 :
103 :
104 :
105 :
106 :
107 3 : if (preg_match('/\G(#[a-z]+.*?)\n/s', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
108 0 : $tokens[] = new Token(TOKEN_C_PREPROCESSOR, $matches[0][0]);
109 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
110 :
111 0 : continue;
112 : }
113 :
114 :
115 3 : if (preg_match('/\G\/\*\*(.+?)\*\//s', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
116 0 : $tokens[] = new Token(TOKEN_DOCBLOCK, $matches[0][0]);
117 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
118 :
119 0 : continue;
120 : }
121 :
122 :
123 3 : if (preg_match('/\G\/\*(.+?)\*\//s', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
124 0 : $tokens[] = new Token(TOKEN_COMMENT, $matches[0][0]);
125 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
126 :
127 0 : continue;
128 : }
129 :
130 :
131 3 : if (preg_match('/\G\/\/.*\n/', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
132 0 : $tokens[] = new Token(TOKEN_COMMENT, rtrim($matches[0][0]));
133 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
134 :
135 0 : continue;
136 : }
137 :
138 :
139 3 : if (preg_match('/\G"([^\"]|\.)*"/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
140 0 : $tokens[] = new Token(TOKEN_STRING, $matches[0][0]);
141 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
142 :
143 0 : continue;
144 : }
145 :
146 :
147 3 : if (preg_match('/\G\'([^\\\']|\.)*\'/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
148 0 : $tokens[] = new Token(TOKEN_STRING, $matches[0][0]);
149 0 : $offset = $matches[0][1] + strlen($matches[0][0]);
150 :
151 0 : continue;
152 : }
153 :
154 :
155 3 : foreach ($this->reserved_words as $word) {
156 3 : if (preg_match('/\G' . $word . '/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
157 3 : $tokens[] = new Token(TOKEN_RESERVED_WORD, $word);
158 3 : $offset = $matches[0][1] + strlen($matches[0][0]);
159 :
160 3 : continue;
161 : }
162 3 : }
163 :
164 :
165 3 : foreach ($this->reserved_values as $value) {
166 3 : if (preg_match('/\G' . $value . '/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
167 2 : $tokens[] = new Token(TOKEN_RESERVED_VALUE, $value);
168 2 : $offset = $matches[0][1] + strlen($matches[0][0]);
169 :
170 2 : continue;
171 : }
172 3 : }
173 :
174 :
175 3 : foreach ($this->token_words as $word => $token_type) {
176 3 : if (preg_match('/\G' . $word . '/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
177 2 : $tokens[] = new Token($token_type, $word);
178 2 : $offset = $matches[0][1] + strlen($matches[0][0]);
179 :
180 2 : continue;
181 : }
182 3 : }
183 :
184 :
185 : $number_expressions = array(
186 3 : '/\G0x[0-9A-F]+/i',
187 : '/\G[0-9]+/'
188 3 : );
189 3 : foreach ($number_expressions as $expression) {
190 3 : if (preg_match($expression, $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
191 1 : $tokens[] = new Token(TOKEN_NUMBER, $matches[0][0]);
192 1 : $offset = $matches[0][1] + strlen($matches[0][0]);
193 :
194 1 : continue;
195 : }
196 3 : }
197 :
198 :
199 3 : if (preg_match('/\G[a-z$_][a-z0-9$_]*/i', $source, $matches, PREG_OFFSET_CAPTURE, $offset)) {
200 3 : $tokens[] = new Token(TOKEN_IDENTIFIER, $matches[0][0]);
201 3 : $offset = $matches[0][1] + strlen($matches[0][0]);
202 :
203 3 : continue;
204 : }
205 :
206 :
207 3 : $offset++;
208 3 : }
209 :
210 :
211 :
212 3 : return $tokens;
213 : }
214 :
215 :
216 : }
217 :
218 :
219 : ?>
|