KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > css > parser > Scanner


1 /*
2
3    Copyright 2000-2004 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.css.parser;
19
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.Reader JavaDoc;
23
24 import org.apache.batik.util.io.NormalizingReader;
25 import org.apache.batik.util.io.StreamNormalizingReader;
26 import org.apache.batik.util.io.StringNormalizingReader;
27
28 /**
29  * This class represents a CSS scanner - an object which decodes CSS lexical
30  * units.
31  *
32  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
33  * @version $Id: Scanner.java,v 1.17 2005/03/27 08:58:31 cam Exp $
34  */

35 public class Scanner {
36
37     /**
38      * The reader.
39      */

40     protected NormalizingReader reader;
41
42     /**
43      * The current char.
44      */

45     protected int current;
46
47     /**
48      * The recording buffer.
49      */

50     protected char[] buffer = new char[128];
51
52     /**
53      * The current position in the buffer.
54      */

55     protected int position;
56
57     /**
58      * The type of the current lexical unit.
59      */

60     protected int type;
61
62     /**
63      * The start offset of the last lexical unit.
64      */

65     protected int start;
66
67     /**
68      * The end offset of the last lexical unit.
69      */

70     protected int end;
71
72     /**
73      * The characters to skip to create the string which represents the
74      * current token.
75      */

76     protected int blankCharacters;
77
78     /**
79      * Creates a new Scanner object.
80      * @param r The reader to scan.
81      */

82     public Scanner(Reader JavaDoc r) throws ParseException {
83         try {
84             reader = new StreamNormalizingReader(r);
85             current = nextChar();
86         } catch (IOException JavaDoc e) {
87             throw new ParseException(e);
88         }
89     }
90
91     /**
92      * Creates a new Scanner object.
93      * @param is The input stream to scan.
94      * @param enc The encoding to use to decode the input stream, or null.
95      */

96     public Scanner(InputStream JavaDoc is, String JavaDoc enc) throws ParseException {
97         try {
98             reader = new StreamNormalizingReader(is, enc);
99             current = nextChar();
100         } catch (IOException JavaDoc e) {
101             throw new ParseException(e);
102         }
103     }
104
105     /**
106      * Creates a new Scanner object.
107      * @param s The string to scan.
108      */

109     public Scanner(String JavaDoc s) throws ParseException {
110         try {
111             reader = new StringNormalizingReader(s);
112             current = nextChar();
113         } catch (IOException JavaDoc e) {
114             throw new ParseException(e);
115         }
116     }
117
118     /**
119      * Returns the current line.
120      */

121     public int getLine() {
122         return reader.getLine();
123     }
124
125     /**
126      * Returns the current column.
127      */

128     public int getColumn() {
129         return reader.getColumn();
130     }
131
132     /**
133      * Returns the buffer used to store the chars.
134      */

135     public char[] getBuffer() {
136         return buffer;
137     }
138
139     /**
140      * Returns the start offset of the last lexical unit.
141      */

142     public int getStart() {
143         return start;
144     }
145
146     /**
147      * Returns the end offset of the last lexical unit.
148      */

149     public int getEnd() {
150         return end;
151     }
152
153     /**
154      * Clears the buffer.
155      */

156     public void clearBuffer() {
157         if (position <= 0) {
158             position = 0;
159         } else {
160             buffer[0] = buffer[position-1];
161             position = 1;
162         }
163     }
164
165     /**
166      * The current lexical unit type like defined in LexicalUnits.
167      */

168     public int getType() {
169         return type;
170     }
171
172     /**
173      * Returns the string representation of the current lexical unit.
174      */

175     public String JavaDoc getStringValue() {
176         return new String JavaDoc(buffer, start, end - start);
177     }
178
179     /**
180      * Scans a @rule value. This method assumes that the current
181      * lexical unit is a at keyword.
182      */

183     public void scanAtRule() throws ParseException {
184         try {
185             // waiting for EOF, ';' or '{'
186
loop: for (;;) {
187                 switch (current) {
188                 case '{':
189                     int brackets = 1;
190                     for (;;) {
191                         nextChar();
192                         switch (current) {
193                         case '}':
194                             if (--brackets > 0) {
195                                 break;
196                             }
197                         case -1:
198                             break loop;
199                         case '{':
200                             brackets++;
201                         }
202                     }
203                 case -1:
204                 case ';':
205                     break loop;
206                 }
207                 nextChar();
208             }
209             end = position;
210         } catch (IOException JavaDoc e) {
211             throw new ParseException(e);
212         }
213     }
214     
215     /**
216      * Returns the next token.
217      */

218     public int next() throws ParseException {
219         blankCharacters = 0;
220         start = position - 1;
221         nextToken();
222         end = position - endGap();
223         return type;
224     }
225
226     /**
227      * Returns the end gap of the current lexical unit.
228      */

229     protected int endGap() {
230         int result = (current == -1) ? 0 : 1;
231         switch (type) {
232         case LexicalUnits.FUNCTION:
233         case LexicalUnits.STRING:
234         case LexicalUnits.S:
235         case LexicalUnits.PERCENTAGE:
236             result += 1;
237             break;
238         case LexicalUnits.COMMENT:
239         case LexicalUnits.HZ:
240         case LexicalUnits.EM:
241         case LexicalUnits.EX:
242         case LexicalUnits.PC:
243         case LexicalUnits.PT:
244         case LexicalUnits.PX:
245         case LexicalUnits.CM:
246         case LexicalUnits.MM:
247         case LexicalUnits.IN:
248         case LexicalUnits.MS:
249             result += 2;
250             break;
251         case LexicalUnits.KHZ:
252         case LexicalUnits.DEG:
253         case LexicalUnits.RAD:
254             result += 3;
255             break;
256         case LexicalUnits.GRAD:
257             result += 4;
258         }
259         return result + blankCharacters;
260     }
261
262     /**
263      * Returns the next token.
264      */

265     protected void nextToken() throws ParseException {
266         try {
267             switch (current) {
268             case -1:
269                 type = LexicalUnits.EOF;
270                 return;
271             case '{':
272                 nextChar();
273                 type = LexicalUnits.LEFT_CURLY_BRACE;
274                 return;
275             case '}':
276                 nextChar();
277                 type = LexicalUnits.RIGHT_CURLY_BRACE;
278                 return;
279             case '=':
280                 nextChar();
281                 type = LexicalUnits.EQUAL;
282                 return;
283             case '+':
284                 nextChar();
285                 type = LexicalUnits.PLUS;
286                 return;
287             case ',':
288                 nextChar();
289                 type = LexicalUnits.COMMA;
290                 return;
291             case ';':
292                 nextChar();
293                 type = LexicalUnits.SEMI_COLON;
294                 return;
295             case '>':
296                 nextChar();
297                 type = LexicalUnits.PRECEDE;
298                 return;
299             case '[':
300                 nextChar();
301                 type = LexicalUnits.LEFT_BRACKET;
302                 return;
303             case ']':
304                 nextChar();
305                 type = LexicalUnits.RIGHT_BRACKET;
306                 return;
307             case '*':
308                 nextChar();
309                 type = LexicalUnits.ANY;
310                 return;
311             case '(':
312                 nextChar();
313                 type = LexicalUnits.LEFT_BRACE;
314                 return;
315             case ')':
316                 nextChar();
317                 type = LexicalUnits.RIGHT_BRACE;
318                 return;
319             case ':':
320                 nextChar();
321                 type = LexicalUnits.COLON;
322                 return;
323             case ' ':
324             case '\t':
325             case '\r':
326             case '\n':
327             case '\f':
328                 do {
329                     nextChar();
330                 } while (ScannerUtilities.isCSSSpace((char)current));
331                 type = LexicalUnits.SPACE;
332                 return;
333             case '/':
334                 nextChar();
335                 if (current != '*') {
336                     type = LexicalUnits.DIVIDE;
337                     return;
338                 }
339                 // Comment
340
nextChar();
341                 start = position - 1;
342                 do {
343                     while (current != -1 && current != '*') {
344                         nextChar();
345                     }
346                     do {
347                         nextChar();
348                     } while (current != -1 && current == '*');
349                 } while (current != -1 && current != '/');
350                 if (current == -1) {
351                     throw new ParseException("eof",
352                                              reader.getLine(),
353                                              reader.getColumn());
354                 }
355                 nextChar();
356                 type = LexicalUnits.COMMENT;
357                 return;
358             case '\'': // String1
359
type = string1();
360                 return;
361             case '"': // String2
362
type = string2();
363                 return;
364             case '<':
365                 nextChar();
366                 if (current != '!') {
367                     throw new ParseException("character",
368                                              reader.getLine(),
369                                              reader.getColumn());
370                 }
371                 nextChar();
372                 if (current == '-') {
373                     nextChar();
374                     if (current == '-') {
375                         nextChar();
376                         type = LexicalUnits.CDO;
377                         return;
378                     }
379                 }
380                 throw new ParseException("character",
381                                          reader.getLine(),
382                                          reader.getColumn());
383             case '-':
384                 nextChar();
385                 if (current != '-') {
386                     type = LexicalUnits.MINUS;
387                     return;
388                 }
389                 nextChar();
390                 if (current == '>') {
391                     nextChar();
392                     type = LexicalUnits.CDC;
393                     return;
394                 }
395                 throw new ParseException("character",
396                                          reader.getLine(),
397                                          reader.getColumn());
398             case '|':
399                 nextChar();
400                 if (current == '=') {
401                     nextChar();
402                     type = LexicalUnits.DASHMATCH;
403                     return;
404                 }
405                 throw new ParseException("character",
406                                          reader.getLine(),
407                                          reader.getColumn());
408             case '~':
409                 nextChar();
410                 if (current == '=') {
411                     nextChar();
412                     type = LexicalUnits.INCLUDES;
413                     return;
414                 }
415                 throw new ParseException("character",
416                                          reader.getLine(),
417                                          reader.getColumn());
418             case '#':
419                 nextChar();
420                 if (ScannerUtilities.isCSSNameCharacter((char)current)) {
421                     start = position - 1;
422                     do {
423                         nextChar();
424                         if (current == '\\') {
425                             nextChar();
426                             escape();
427                         }
428                     } while (current != -1 &&
429                              ScannerUtilities.isCSSNameCharacter
430                                  ((char)current));
431                     type = LexicalUnits.HASH;
432                     return;
433                 }
434                 throw new ParseException("character",
435                                          reader.getLine(),
436                                          reader.getColumn());
437             case '@':
438                 nextChar();
439                 switch (current) {
440                 case 'c':
441                 case 'C':
442                     start = position - 1;
443                     if (isEqualIgnoreCase(nextChar(), 'h') &&
444                         isEqualIgnoreCase(nextChar(), 'a') &&
445                         isEqualIgnoreCase(nextChar(), 'r') &&
446                         isEqualIgnoreCase(nextChar(), 's') &&
447                         isEqualIgnoreCase(nextChar(), 'e') &&
448                         isEqualIgnoreCase(nextChar(), 't')) {
449                         nextChar();
450                         type = LexicalUnits.CHARSET_SYMBOL;
451                         return;
452                     }
453                     break;
454                 case 'f':
455                 case 'F':
456                     start = position - 1;
457                     if (isEqualIgnoreCase(nextChar(), 'o') &&
458                         isEqualIgnoreCase(nextChar(), 'n') &&
459                         isEqualIgnoreCase(nextChar(), 't') &&
460                         isEqualIgnoreCase(nextChar(), '-') &&
461                         isEqualIgnoreCase(nextChar(), 'f') &&
462                         isEqualIgnoreCase(nextChar(), 'a') &&
463                         isEqualIgnoreCase(nextChar(), 'c') &&
464                         isEqualIgnoreCase(nextChar(), 'e')) {
465                         nextChar();
466                         type = LexicalUnits.FONT_FACE_SYMBOL;
467                         return;
468                     }
469                     break;
470                 case 'i':
471                 case 'I':
472                     start = position - 1;
473                     if (isEqualIgnoreCase(nextChar(), 'm') &&
474                         isEqualIgnoreCase(nextChar(), 'p') &&
475                         isEqualIgnoreCase(nextChar(), 'o') &&
476                         isEqualIgnoreCase(nextChar(), 'r') &&
477                         isEqualIgnoreCase(nextChar(), 't')) {
478                         nextChar();
479                         type = LexicalUnits.IMPORT_SYMBOL;
480                         return;
481                     }
482                     break;
483                 case 'm':
484                 case 'M':
485                     start = position - 1;
486                     if (isEqualIgnoreCase(nextChar(), 'e') &&
487                         isEqualIgnoreCase(nextChar(), 'd') &&
488                         isEqualIgnoreCase(nextChar(), 'i') &&
489                         isEqualIgnoreCase(nextChar(), 'a')) {
490                         nextChar();
491                         type = LexicalUnits.MEDIA_SYMBOL;
492                         return;
493                     }
494                     break;
495                 case 'p':
496                 case 'P':
497                     start = position - 1;
498                     if (isEqualIgnoreCase(nextChar(), 'a') &&
499                         isEqualIgnoreCase(nextChar(), 'g') &&
500                         isEqualIgnoreCase(nextChar(), 'e')) {
501                         nextChar();
502                         type = LexicalUnits.PAGE_SYMBOL;
503                         return;
504                     }
505                     break;
506                 default:
507                     if (!ScannerUtilities.isCSSIdentifierStartCharacter
508                         ((char)current)) {
509                         throw new ParseException("identifier.character",
510                                                  reader.getLine(),
511                                                  reader.getColumn());
512                     }
513                     start = position - 1;
514                 }
515                 do {
516                     nextChar();
517                     if (current == '\\') {
518                         nextChar();
519                         escape();
520                     }
521                 } while (current != -1 &&
522                          ScannerUtilities.isCSSNameCharacter((char)current));
523                 type = LexicalUnits.AT_KEYWORD;
524                 return;
525             case '!':
526                 do {
527                     nextChar();
528                 } while (current != -1 &&
529                          ScannerUtilities.isCSSSpace((char)current));
530                 if (isEqualIgnoreCase(current, 'i') &&
531                     isEqualIgnoreCase(nextChar(), 'm') &&
532                     isEqualIgnoreCase(nextChar(), 'p') &&
533                     isEqualIgnoreCase(nextChar(), 'o') &&
534                     isEqualIgnoreCase(nextChar(), 'r') &&
535                     isEqualIgnoreCase(nextChar(), 't') &&
536                     isEqualIgnoreCase(nextChar(), 'a') &&
537                     isEqualIgnoreCase(nextChar(), 'n') &&
538                     isEqualIgnoreCase(nextChar(), 't')) {
539                     nextChar();
540                     type = LexicalUnits.IMPORTANT_SYMBOL;
541                     return;
542                 }
543                 if (current == -1) {
544                     throw new ParseException("eof",
545                                              reader.getLine(),
546                                              reader.getColumn());
547                 } else {
548                     throw new ParseException("character",
549                                              reader.getLine(),
550                                              reader.getColumn());
551                 }
552             case '0': case '1': case '2': case '3': case '4':
553             case '5': case '6': case '7': case '8': case '9':
554                 type = number();
555                 return;
556             case '.':
557                 switch (nextChar()) {
558                 case '0': case '1': case '2': case '3': case '4':
559                 case '5': case '6': case '7': case '8': case '9':
560                     type = dotNumber();
561                     return;
562                 default:
563                     type = LexicalUnits.DOT;
564                     return;
565                 }
566             case 'u':
567             case 'U':
568                 nextChar();
569                 switch (current) {
570                 case '+':
571                     boolean range = false;
572                     for (int i = 0; i < 6; i++) {
573                         nextChar();
574                         switch (current) {
575                         case '?':
576                             range = true;
577                             break;
578                         default:
579                             if (range &&
580                             !ScannerUtilities.isCSSHexadecimalCharacter
581                                 ((char)current)) {
582                                 throw new ParseException("character",
583                                                          reader.getLine(),
584                                                          reader.getColumn());
585                             }
586                         }
587                     }
588                     nextChar();
589                     if (range) {
590                         type = LexicalUnits.UNICODE_RANGE;
591                         return;
592                     }
593                     if (current == '-') {
594                         nextChar();
595                         if (!ScannerUtilities.isCSSHexadecimalCharacter
596                             ((char)current)) {
597                             throw new ParseException("character",
598                                                      reader.getLine(),
599                                                      reader.getColumn());
600                         }
601                         nextChar();
602                         if (!ScannerUtilities.isCSSHexadecimalCharacter
603                             ((char)current)) {
604                             type = LexicalUnits.UNICODE_RANGE;
605                             return;
606                         }
607                         nextChar();
608                         if (!ScannerUtilities.isCSSHexadecimalCharacter
609                             ((char)current)) {
610                             type = LexicalUnits.UNICODE_RANGE;
611                             return;
612                         }
613                         nextChar();
614                         if (!ScannerUtilities.isCSSHexadecimalCharacter
615                             ((char)current)) {
616                             type = LexicalUnits.UNICODE_RANGE;
617                             return;
618                         }
619                         nextChar();
620                         if (!ScannerUtilities.isCSSHexadecimalCharacter
621                             ((char)current)) {
622                             type = LexicalUnits.UNICODE_RANGE;
623                             return;
624                         }
625                         nextChar();
626                         if (!ScannerUtilities.isCSSHexadecimalCharacter
627                             ((char)current)) {
628                             type = LexicalUnits.UNICODE_RANGE;
629                             return;
630                         }
631                         nextChar();
632                         type = LexicalUnits.UNICODE_RANGE;
633                         return;
634                     }
635                 case 'r':
636                 case 'R':
637                     nextChar();
638                     switch (current) {
639                     case 'l':
640                     case 'L':
641                         nextChar();
642                         switch (current) {
643                         case '(':
644                             do {
645                                 nextChar();
646                             } while (current != -1 &&
647                                      ScannerUtilities.isCSSSpace
648                                      ((char)current));
649                             switch (current) {
650                             case '\'':
651                                 string1();
652                                 blankCharacters += 2;
653                                 while (current != -1 &&
654                                        ScannerUtilities.isCSSSpace
655                                        ((char)current)) {
656                                     blankCharacters++;
657                                     nextChar();
658                                 }
659                                 if (current == -1) {
660                                     throw new ParseException
661                                         ("eof",
662                                          reader.getLine(),
663                                          reader.getColumn());
664                                 }
665                                 if (current != ')') {
666                                     throw new ParseException
667                                         ("character",
668                                          reader.getLine(),
669                                          reader.getColumn());
670                                 }
671                                 nextChar();
672                                 type = LexicalUnits.URI;
673                                 return;
674                             case '"':
675                                 string2();
676                                 blankCharacters += 2;
677                                 while (current != -1 &&
678                                        ScannerUtilities.isCSSSpace
679                                        ((char)current)) {
680                                     blankCharacters++;
681                                     nextChar();
682                                 }
683                                 if (current == -1) {
684                                     throw new ParseException
685                                         ("eof",
686                                          reader.getLine(),
687                                          reader.getColumn());
688                                 }
689                                 if (current != ')') {
690                                     throw new ParseException
691                                         ("character",
692                                          reader.getLine(),
693                                          reader.getColumn());
694                                 }
695                                 nextChar();
696                                 type = LexicalUnits.URI;
697                                 return;
698                             case ')':
699                                 throw new ParseException("character",
700                                                          reader.getLine(),
701                                                          reader.getColumn());
702                             default:
703                                 if (!ScannerUtilities.isCSSURICharacter
704                                     ((char)current)) {
705                                     throw new ParseException
706                                         ("character",
707                                          reader.getLine(),
708                                          reader.getColumn());
709                                 }
710                                 start = position - 1;
711                                 do {
712                                     nextChar();
713                                 } while (current != -1 &&
714                                       ScannerUtilities.isCSSURICharacter
715                                          ((char)current));
716                                 blankCharacters++;
717                                 while (current != -1 &&
718                                        ScannerUtilities.isCSSSpace
719                                        ((char)current)) {
720                                     blankCharacters++;
721                                     nextChar();
722                                 }
723                                 if (current == -1) {
724                                     throw new ParseException
725                                         ("eof",
726                                          reader.getLine(),
727                                          reader.getColumn());
728                                 }
729                                 if (current != ')') {
730                                     throw new ParseException
731                                         ("character",
732                                          reader.getLine(),
733                                          reader.getColumn());
734                                 }
735                                 nextChar();
736                                 type = LexicalUnits.URI;
737                                 return;
738                             }
739                         }
740                     }
741                 }
742                 while (current != -1 &&
743                        ScannerUtilities.isCSSNameCharacter((char)current)) {
744                     nextChar();
745                 }
746                 if (current == '(') {
747                     nextChar();
748                     type = LexicalUnits.FUNCTION;
749                     return;
750                 }
751                 type = LexicalUnits.IDENTIFIER;
752                 return;
753             default:
754                 if (ScannerUtilities.isCSSIdentifierStartCharacter
755                     ((char)current)) {
756                     // Identifier
757
do {
758                         nextChar();
759                         if (current == '\\') {
760                             nextChar();
761                             escape();
762                         }
763                     } while (current != -1 &&
764                              ScannerUtilities.isCSSNameCharacter
765                              ((char)current));
766                     if (current == '(') {
767                         nextChar();
768                         type = LexicalUnits.FUNCTION;
769                         return;
770                     }
771                     type = LexicalUnits.IDENTIFIER;
772                     return;
773                 }
774                 nextChar();
775                 throw new ParseException("identifier.character",
776                                          reader.getLine(),
777                                          reader.getColumn());
778             }
779         } catch (IOException JavaDoc e) {
780             throw new ParseException(e);
781         }
782     }
783
784     /**
785      * Scans a single quoted string.
786      */

787     protected int string1() throws IOException JavaDoc {
788         start = position; // fix bug #29416
789
loop: for (;;) {
790             switch (nextChar()) {
791             case -1:
792                 throw new ParseException("eof",
793                                          reader.getLine(),
794                                          reader.getColumn());
795             case '\'':
796                 break loop;
797             case '"':
798                 break;
799             case '\\':
800                 switch (nextChar()) {
801                 case '\n':
802                 case '\f':
803                     break;
804                 default:
805                     escape();
806                 }
807                 break;
808             default:
809                 if (!ScannerUtilities.isCSSStringCharacter((char)current)) {
810                     throw new ParseException("character",
811                                              reader.getLine(),
812                                              reader.getColumn());
813                 }
814             }
815         }
816         nextChar();
817         return LexicalUnits.STRING;
818     }
819
820     /**
821      * Scans a double quoted string.
822      */

823     protected int string2() throws IOException JavaDoc {
824         start = position; // fix bug #29416
825
loop: for (;;) {
826             switch (nextChar()) {
827             case -1:
828                 throw new ParseException("eof",
829                                          reader.getLine(),
830                                          reader.getColumn());
831             case '\'':
832                 break;
833             case '"':
834                 break loop;
835             case '\\':
836                 switch (nextChar()) {
837                 case '\n':
838                 case '\f':
839                     break;
840                 default:
841                     escape();
842                 }
843                 break;
844             default:
845                 if (!ScannerUtilities.isCSSStringCharacter((char)current)) {
846                     throw new ParseException("character",
847                                              reader.getLine(),
848                                              reader.getColumn());
849                 }
850             }
851         }
852         nextChar();
853         return LexicalUnits.STRING;
854     }
855
856     /**
857      * Scans a number.
858      */

859     protected int number() throws IOException JavaDoc {
860         loop: for (;;) {
861             switch (nextChar()) {
862             case '.':
863                 switch (nextChar()) {
864                 case '0': case '1': case '2': case '3': case '4':
865                 case '5': case '6': case '7': case '8': case '9':
866                     return dotNumber();
867                 }
868                 throw new ParseException("character",
869                                          reader.getLine(),
870                                          reader.getColumn());
871             default:
872                 break loop;
873             case '0': case '1': case '2': case '3': case '4':
874             case '5': case '6': case '7': case '8': case '9':
875             }
876         }
877         return numberUnit(true);
878     }
879
880     /**
881      * Scans the decimal part of a number.
882      */

883     protected int dotNumber() throws IOException JavaDoc {
884         loop: for (;;) {
885             switch (nextChar()) {
886             default:
887                 break loop;
888             case '0': case '1': case '2': case '3': case '4':
889             case '5': case '6': case '7': case '8': case '9':
890             }
891         }
892         return numberUnit(false);
893     }
894
895     /**
896      * Scans the unit of a number.
897      */

898     protected int numberUnit(boolean integer) throws IOException JavaDoc {
899         switch (current) {
900         case '%':
901             nextChar();
902             return LexicalUnits.PERCENTAGE;
903         case 'c':
904         case 'C':
905             switch(nextChar()) {
906             case 'm':
907             case 'M':
908                 nextChar();
909                 if (current != -1 &&
910                     ScannerUtilities.isCSSNameCharacter((char)current)) {
911                     do {
912                         nextChar();
913                     } while (current != -1 &&
914                              ScannerUtilities.isCSSNameCharacter
915                              ((char)current));
916                     return LexicalUnits.DIMENSION;
917                 }
918                 return LexicalUnits.CM;
919             default:
920                 while (current != -1 &&
921                        ScannerUtilities.isCSSNameCharacter((char)current)) {
922                     nextChar();
923                 }
924                 return LexicalUnits.DIMENSION;
925             }
926         case 'd':
927         case 'D':
928             switch(nextChar()) {
929             case 'e':
930             case 'E':
931                 switch(nextChar()) {
932                 case 'g':
933                 case 'G':
934                     nextChar();
935                     if (current != -1 &&
936                         ScannerUtilities.isCSSNameCharacter((char)current)) {
937                         do {
938                             nextChar();
939                         } while (current != -1 &&
940                                  ScannerUtilities.isCSSNameCharacter
941                                  ((char)current));
942                         return LexicalUnits.DIMENSION;
943                     }
944                     return LexicalUnits.DEG;
945                 }
946             default:
947                 while (current != -1 &&
948                        ScannerUtilities.isCSSNameCharacter((char)current)) {
949                     nextChar();
950                 }
951                 return LexicalUnits.DIMENSION;
952             }
953         case 'e':
954         case 'E':
955             switch(nextChar()) {
956             case 'm':
957             case 'M':
958                 nextChar();
959                 if (current != -1 &&
960                     ScannerUtilities.isCSSNameCharacter((char)current)) {
961                     do {
962                         nextChar();
963                     } while (current != -1 &&
964                              ScannerUtilities.isCSSNameCharacter
965                              ((char)current));
966                     return LexicalUnits.DIMENSION;
967                 }
968                 return LexicalUnits.EM;
969             case 'x':
970             case 'X':
971                 nextChar();
972                 if (current != -1 &&
973                     ScannerUtilities.isCSSNameCharacter((char)current)) {
974                     do {
975                         nextChar();
976                     } while (current != -1 &&
977                              ScannerUtilities.isCSSNameCharacter
978                              ((char)current));
979                     return LexicalUnits.DIMENSION;
980                 }
981                 return LexicalUnits.EX;
982             default:
983                 while (current != -1 &&
984                        ScannerUtilities.isCSSNameCharacter((char)current)) {
985                     nextChar();
986                 }
987                 return LexicalUnits.DIMENSION;
988             }
989         case 'g':
990         case 'G':
991             switch(nextChar()) {
992             case 'r':
993             case 'R':
994                 switch(nextChar()) {
995                 case 'a':
996                 case 'A':
997                     switch(nextChar()) {
998                     case 'd':
999                     case 'D':
1000                        nextChar();
1001                        if (current != -1 &&
1002                            ScannerUtilities.isCSSNameCharacter
1003                            ((char)current)) {
1004                            do {
1005                                nextChar();
1006                            } while (current != -1 &&
1007                                     ScannerUtilities.isCSSNameCharacter
1008                                     ((char)current));
1009                            return LexicalUnits.DIMENSION;
1010                        }
1011                        return LexicalUnits.GRAD;
1012                    }
1013                }
1014            default:
1015                while (current != -1 &&
1016                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1017                    nextChar();
1018                }
1019                return LexicalUnits.DIMENSION;
1020            }
1021        case 'h':
1022        case 'H':
1023            nextChar();
1024            switch(current) {
1025            case 'z':
1026            case 'Z':
1027                nextChar();
1028                if (current != -1 &&
1029                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1030                    do {
1031                        nextChar();
1032                    } while (current != -1 &&
1033                             ScannerUtilities.isCSSNameCharacter
1034                             ((char)current));
1035                    return LexicalUnits.DIMENSION;
1036                }
1037                return LexicalUnits.HZ;
1038            default:
1039                while (current != -1 &&
1040                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1041                    nextChar();
1042                }
1043                return LexicalUnits.DIMENSION;
1044            }
1045        case 'i':
1046        case 'I':
1047            switch(nextChar()) {
1048            case 'n':
1049            case 'N':
1050                nextChar();
1051                if (current != -1 &&
1052                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1053                    do {
1054                        nextChar();
1055                    } while (current != -1 &&
1056                             ScannerUtilities.isCSSNameCharacter
1057                             ((char)current));
1058                    return LexicalUnits.DIMENSION;
1059                }
1060                return LexicalUnits.IN;
1061            default:
1062                while (current != -1 &&
1063                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1064                    nextChar();
1065                }
1066                return LexicalUnits.DIMENSION;
1067            }
1068        case 'k':
1069        case 'K':
1070            switch(nextChar()) {
1071            case 'h':
1072            case 'H':
1073                switch(nextChar()) {
1074                case 'z':
1075                case 'Z':
1076                    nextChar();
1077                    if (current != -1 &&
1078                        ScannerUtilities.isCSSNameCharacter((char)current)) {
1079                        do {
1080                            nextChar();
1081                        } while (current != -1 &&
1082                                 ScannerUtilities.isCSSNameCharacter
1083                                 ((char)current));
1084                        return LexicalUnits.DIMENSION;
1085                    }
1086                    return LexicalUnits.KHZ;
1087                }
1088            default:
1089                while (current != -1 &&
1090                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1091                    nextChar();
1092                }
1093                return LexicalUnits.DIMENSION;
1094            }
1095        case 'm':
1096        case 'M':
1097            switch(nextChar()) {
1098            case 'm':
1099            case 'M':
1100                nextChar();
1101                if (current != -1 &&
1102                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1103                    do {
1104                        nextChar();
1105                    } while (current != -1 &&
1106                             ScannerUtilities.isCSSNameCharacter
1107                             ((char)current));
1108                    return LexicalUnits.DIMENSION;
1109                }
1110                return LexicalUnits.MM;
1111            case 's':
1112            case 'S':
1113                nextChar();
1114                if (current != -1 &&
1115                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1116                    do {
1117                        nextChar();
1118                    } while (current != -1 &&
1119                             ScannerUtilities.isCSSNameCharacter
1120                             ((char)current));
1121                    return LexicalUnits.DIMENSION;
1122                }
1123                return LexicalUnits.MS;
1124            default:
1125                while (current != -1 &&
1126                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1127                    nextChar();
1128                }
1129                return LexicalUnits.DIMENSION;
1130            }
1131        case 'p':
1132        case 'P':
1133            switch(nextChar()) {
1134            case 'c':
1135            case 'C':
1136                nextChar();
1137                if (current != -1 &&
1138                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1139                    do {
1140                        nextChar();
1141                    } while (current != -1 &&
1142                             ScannerUtilities.isCSSNameCharacter
1143                             ((char)current));
1144                    return LexicalUnits.DIMENSION;
1145                }
1146                return LexicalUnits.PC;
1147            case 't':
1148            case 'T':
1149                nextChar();
1150                if (current != -1 &&
1151                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1152                    do {
1153                        nextChar();
1154                    } while (current != -1 &&
1155                             ScannerUtilities.isCSSNameCharacter
1156                             ((char)current));
1157                    return LexicalUnits.DIMENSION;
1158                }
1159                return LexicalUnits.PT;
1160            case 'x':
1161            case 'X':
1162                nextChar();
1163                if (current != -1 &&
1164                    ScannerUtilities.isCSSNameCharacter((char)current)) {
1165                    do {
1166                        nextChar();
1167                    } while (current != -1 &&
1168                             ScannerUtilities.isCSSNameCharacter
1169                             ((char)current));
1170                    return LexicalUnits.DIMENSION;
1171                }
1172                return LexicalUnits.PX;
1173            default:
1174                while (current != -1 &&
1175                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1176                    nextChar();
1177                }
1178                return LexicalUnits.DIMENSION;
1179            }
1180        case 'r':
1181        case 'R':
1182            switch(nextChar()) {
1183            case 'a':
1184            case 'A':
1185                switch(nextChar()) {
1186                case 'd':
1187                case 'D':
1188                    nextChar();
1189                    if (current != -1 &&
1190                        ScannerUtilities.isCSSNameCharacter((char)current)) {
1191                        do {
1192                            nextChar();
1193                        } while (current != -1 &&
1194                                 ScannerUtilities.isCSSNameCharacter
1195                                 ((char)current));
1196                        return LexicalUnits.DIMENSION;
1197                    }
1198                    return LexicalUnits.RAD;
1199                }
1200            default:
1201                while (current != -1 &&
1202                       ScannerUtilities.isCSSNameCharacter((char)current)) {
1203                    nextChar();
1204                }
1205                return LexicalUnits.DIMENSION;
1206            }
1207        case 's':
1208        case 'S':
1209            nextChar();
1210            return LexicalUnits.S;
1211        default:
1212            if (current != -1 &&
1213                ScannerUtilities.isCSSIdentifierStartCharacter
1214                ((char)current)) {
1215                do {
1216                    nextChar();
1217                } while (current != -1 &&
1218                         ScannerUtilities.isCSSNameCharacter((char)current));
1219                return LexicalUnits.DIMENSION;
1220            }
1221            return (integer) ? LexicalUnits.INTEGER : LexicalUnits.REAL;
1222        }
1223    }
1224
1225    /**
1226     * Scans an escape sequence, if one.
1227     */

1228    protected void escape() throws IOException JavaDoc {
1229        if (ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1230            nextChar();
1231            if (!ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1232                if (ScannerUtilities.isCSSSpace((char)current)) {
1233                    nextChar();
1234                }
1235                return;
1236            }
1237            nextChar();
1238            if (!ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1239                if (ScannerUtilities.isCSSSpace((char)current)) {
1240                    nextChar();
1241                }
1242                return;
1243            }
1244            nextChar();
1245            if (!ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1246                if (ScannerUtilities.isCSSSpace((char)current)) {
1247                    nextChar();
1248                }
1249                return;
1250            }
1251            nextChar();
1252            if (!ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1253                if (ScannerUtilities.isCSSSpace((char)current)) {
1254                    nextChar();
1255                }
1256                return;
1257            }
1258            nextChar();
1259            if (!ScannerUtilities.isCSSHexadecimalCharacter((char)current)) {
1260                if (ScannerUtilities.isCSSSpace((char)current)) {
1261                    nextChar();
1262                }
1263                return;
1264            }
1265        }
1266        if ((current >= ' ' && current <= '~') || current >= 128) {
1267            nextChar();
1268            return;
1269        }
1270        throw new ParseException("character",
1271                                 reader.getLine(),
1272                                 reader.getColumn());
1273    }
1274
1275    /**
1276     * Compares the given int with the given character, ignoring case.
1277     */

1278    protected static boolean isEqualIgnoreCase(int i, char c) {
1279        return (i == -1) ? false : Character.toLowerCase((char)i) == c;
1280    }
1281
1282    /**
1283     * Sets the value of the current char to the next character or -1 if the
1284     * end of stream has been reached.
1285     */

1286    protected int nextChar() throws IOException JavaDoc {
1287        current = reader.read();
1288
1289        if (current == -1) {
1290            return current;
1291        }
1292
1293        if (position == buffer.length) {
1294            char[] t = new char[position * 3 / 2];
1295            for (int i = 0; i < position; i++) {
1296                t[i] = buffer[i];
1297            }
1298            buffer = t;
1299        }
1300
1301        return buffer[position++] = (char)current;
1302    }
1303}
1304
Popular Tags