root/as2/E3Engine/Scanner.as

リビジョン 299, 7.2 kB (コミッタ: yossy, コミット時期: 4 年 前)

Imported Lab code.

Line 
1 class Scanner implements IScanner
2 {
3         private var source:String;
4         private var index:Number;
5        
6         private var linesCount:Number;
7        
8         public function Scanner (source:String)
9         {
10                 this.source = source;
11                 rewind();
12         }
13        
14         public function rewind () : Void
15         {
16                 index = 0;
17                 linesCount = 0;
18         }
19        
20         public function getLineNumber () : Number
21         {
22                 return linesCount+1;
23         }
24         public function getLine () : String
25         {
26                 return (source.split("\n"))[linesCount];
27         }
28        
29         private function getChar () : String
30         {
31                 return source.charAt(index);
32         }
33         private function nextChar () : String
34         {
35                 if (getChar() == "\n") {
36                         linesCount++;
37                 }
38                
39                 return source.charAt(++index);
40         }
41        
42         private function isSpace (c:String) : Boolean
43         {
44                 return (c==" " || c=="\t" || c=="\r" || c=="\n");
45         }
46         private function isAlphabet (c:String) : Boolean
47         {
48                 var code:Number = c.charCodeAt(0);
49                 return ((65 <= code && code <= 90) || (97 <= code && code <= 122));
50         }
51         private function isNumber (c:String) : Boolean
52         {
53                 var code:Number = c.charCodeAt(0);
54                 return (48 <= code && code <= 57);
55         }
56         private function isAlphabetOrNumber (c:String) : Boolean
57         {
58                 var code:Number = c.charCodeAt(0);
59                 return ((48 <= code && code <= 57) || (65 <= code && code <= 90) || (97 <= code && code <= 122));
60         }
61         private function isHex (c:String) : Boolean
62         {
63                 var code:Number = c.charCodeAt(0);
64                 return ((48 <= code && code <= 57) || (65 <= code && code <= 70) || (97 <= code && code <= 102));
65         }
66         private function isIdentifier (c:String) : Boolean
67         {
68                 var code:Number = c.charCodeAt(0);
69                 return (code==36 || code==95 || (48 <= code && code <= 57) || (65 <= code && code <= 90) || (97 <= code && code <= 122));
70         }
71        
72         public function getToken () : Token
73         {
74                 var c:String = getChar();
75                
76                 while (isSpace(c)) {
77                         c = nextChar();
78                 }
79                
80                 if (!c) return null;
81                
82                 if (isAlphabet(c) || c=='$' || c=='_') {
83                         var value:String = c;
84                         while ((c = nextChar()) && isIdentifier(c)) {
85                                 value += c;
86                         }
87                         var type:String = value.toLowerCase();
88                         switch (type) {
89                                 case 'break':
90                                 case 'case':
91                                 // case 'catch':
92                                 case 'continue':
93                                 case 'default':
94                                 case 'delete':
95                                 case 'do':
96                                 case 'else':
97                                 // case 'finally':
98                                 case 'for':
99                                 case 'function':
100                                 case 'if':
101                                 // case 'in':
102                                 case 'instanceof':
103                                 case 'new':
104                                 case 'return':
105                                 case 'switch':
106                                 case 'this':
107                                 // case 'throw':
108                                 // case 'try':
109                                 case 'typeof':
110                                 case 'var':
111                                 // case 'void':
112                                 case 'while':
113                                 case 'with':
114                                 //
115                                 // original
116                                 //
117                                 case 'coroutine':
118                                 case 'suspend':
119                                 case 'yield':
120                                 case 'loop':
121                                 {
122                                         return new Token(type, null);
123                                 }
124                                
125                                 case 'null':    return new Token('null', null);
126                                 case 'undefined':       return new Token('undefined', undefined);
127                                 case 'true':    return new Token('bool', true);
128                                 case 'false':   return new Token('bool', false);
129                                
130                                 default:
131                                 {
132                                         return new Token('identifier', value);
133                                 }
134                         }
135                 }
136                
137                 if (isNumber(c)) {
138                         var value:String = c;
139                         if (c == '0') {
140                                 if ((c = nextChar()) && c == 'x' || c == 'X') {
141                                         value += c;
142                                         while ((c = nextChar()) && isHex(c)) {
143                                                 value += c;
144                                         }
145                                 }
146                                 else if (isNumber(c)) {
147                                         value += c;
148                                         while ((c = nextChar()) && isNumber(c)) {
149                                                 value += c;
150                                         }
151                                 }
152                         }
153                         else {
154                                 while ((c = nextChar()) && isNumber(c)) {
155                                         value += c;
156                                 }
157                         }
158                         if (c == '.') {
159                                 value += c;
160                                 while ((c = nextChar()) && isNumber(c)) {
161                                         value += c;
162                                 }
163                                 return new Token('number', parseFloat(value));
164                         }
165                         else {
166                                 return new Token('number', parseInt(value));
167                         }
168                 }
169                
170                 if (c == "'") {
171                         var value:String = '';
172                         while ((c = nextChar()) && c != "'") {
173                                 if (c == '\\') {
174                                         c = nextChar();
175                                         if (c == 'n') {
176                                                 value += "\n";
177                                                 c = nextChar();
178                                                 continue;
179                                         }
180                                         if (c == '\\') {
181                                                 value += "\\";
182                                                 c = nextChar();
183                                                 continue;
184                                         }
185                                 }
186                                 value += c;
187                         }
188                         if (c != "'") {
189                                 throw new SyntaxError('String literal is not closed.');
190                         }
191                         nextChar();
192                         return new Token('string', value);
193                 }
194                 if (c == '"') {
195                         var value:String = "";
196                         while ((c = nextChar()) && c != '"') {
197                                 if (c == '\\') {
198                                         c = nextChar();
199                                         if (c == 'n') {
200                                                 value += "\n";
201                                                 c = nextChar();
202                                                 continue;
203                                         }
204                                         if (c == '\\') {
205                                                 value += "\\";
206                                                 c = nextChar();
207                                                 continue;
208                                         }
209                                 }
210                                 value += c;
211                         }
212                         if (c != '"') {
213                                 throw new SyntaxError('String literal is not closed.');
214                         }
215                         nextChar();
216                         return new Token('string', value);
217                 }
218                
219                 if (c == '/') {
220                         if (c = nextChar()) {
221                                 if (c == '=') {
222                                         nextChar();
223                                         return new Token('/=', null);
224                                 }
225                                 else if (c == '/') {
226                                         while ((c = nextChar()) && c != "\n") {
227                                         }
228                                         nextChar();
229                                         return getToken();
230                                 }
231                                 else if(c == '*') {
232                                         for (c=nextChar(); c; ) {
233                                                 if (c == '*') {
234                                                         if ((c = nextChar()) && c == '/') {
235                                                                 break;
236                                                         }
237                                                         continue;
238                                                 }
239                                                 c = nextChar();
240                                         }
241                                         nextChar();
242                                         return getToken();
243                                 }
244                         }
245                         return new Token('/', null);
246                 }
247                
248                 /*
249                         *
250                         *=
251                         %
252                         %=
253                         ^
254                         ^=
255                 */
256                 if (c == '*' || c == '%' || c == '^') {
257                         var type:String = c;
258                         if ((c = nextChar()) && c == '=') {
259                                 nextChar();
260                                 return new Token(type+'=', null);
261                         }
262                         return new Token(type, null);
263                 }
264                
265                 /*
266                         +
267                         ++
268                         +=
269                         -
270                         --
271                         -=
272                         &
273                         &&
274                         &=
275                         |
276                         ||
277                         |=
278                 */
279                 if (c == '+' || c == '-' || c == '|' || c == '&') {
280                         var type:String = c;
281                         if (c = nextChar()) {
282                                 if (c == type) {
283                                         nextChar();
284                                         return new Token(type+type, null);
285                                 }
286                                 if (c == '=') {
287                                         nextChar();
288                                         return new Token(type+'=', null);
289                                 }
290                         }
291                         return new Token(type, null);
292                 }
293                
294                 /*
295                         =
296                         ==
297                         ===
298                         !
299                         !=
300                         !==
301                 */
302                 if (c == '=' || c == '!') {
303                         var type:String = c;
304                         if ((c = nextChar()) && c == '=') {
305                                 if ((c = nextChar()) && c == '=') {
306                                         nextChar();
307                                         return new Token(type+'==', null);
308                                 }
309                                 return new Token(type+'=', null);
310                         }
311                         return new Token(type, null);
312                 }
313                
314                 /*
315                         >
316                         >=
317                         >>
318                         >>=
319                         >>>
320                         >>>=
321                         <
322                         <=
323                         <<
324                         <<=
325                 */
326                 if (c == '>' || c == '<') {
327                         var type:String = c;
328                         if (c = nextChar()) {
329                                 if (c == '=') {
330                                         nextChar();
331                                         return new Token(type+'=', null);
332                                 }
333                                 if (c == type) {
334                                         if (c = nextChar()) {
335                                                 if (type == '>' && c == '>') {
336                                                         if ((c = nextChar()) && c == '=') {
337                                                                 nextChar();
338                                                                 return new Token('>>>=', null);
339                                                         }
340                                                         return new Token('>>>', null);
341                                                 }
342                                                 if (c == '=') {
343                                                         nextChar();
344                                                         return new Token(type+type+'=', null);
345                                                 }
346                                         }
347                                         return new Token(type+type, null);
348                                 }
349                         }
350                         return new Token(type, null);
351                 }
352                
353                 switch (c) {
354                         case '{':
355                         case '}':
356                         case '(':
357                         case ')':
358                         case '[':
359                         case ']':
360                         case '.':
361                         case ';':
362                         case ',':
363                         case '~':
364                         case '?':
365                         case ':':
366                         {
367                                 nextChar();
368                                 return new Token(c, null);
369                         }
370                         default:
371                         {
372                                 throw new SyntaxError('Unknown character : "'+c+'" at index '+index+'.');
373                         }
374                 }
375                
376                 return null;
377         }
378 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。