KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > cypress > CssLexer


1 /*
2 ** Cypress - CSS Parser
3 ** Copyright (c) 2001, 2002, 2003 by Gerald Bauer
4 **
5 ** This program is free software.
6 **
7 ** You may redistribute it and/or modify it under the terms of the GNU
8 ** Lesser General Public License as published by the Free Software Foundation.
9 ** Version 2.1 of the license should be included with this distribution in
10 ** the file LICENSE, as well as License.html. If the license is not
11 ** included with this distribution, you may find a copy at the FSF web
12 ** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
13 ** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
14 **
15 ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
16 ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
17 ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
18 ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
19 ** REDISTRIBUTION OF THIS SOFTWARE.
20 **
21 */

22
23 package cypress;
24
25 import java.io.IOException JavaDoc;
26 import java.io.Reader JavaDoc;
27
28 /**
29  * CSS scanner - an object which decodes CSS lexical units.
30  */

31 public class CssLexer
32 {
33
34    /**
35     * The characters to skip to create the string which represents the current
36     * token.
37     */

38    protected int _blankCharacters;
39
40    /**
41     * The recording buffer.
42     */

43    protected char[] _buffer = new char[128];
44
45    /**
46     * The current column.
47     */

48    protected int _column;
49
50    /**
51     * The current char.
52     */

53    protected int _current;
54
55    /**
56     * The end offset of the last lexical unit.
57     */

58    protected int _end;
59
60    /**
61     * The current line.
62     */

63    protected int _line = 1;
64
65    /**
66     * The current position in the buffer.
67     */

68    protected int _position;
69
70    /**
71     * The reading buffer.
72     */

73    protected char[] _readBuffer;
74
75    /**
76     * The current read buffer count.
77     */

78    protected int _readCount;
79
80    /**
81     * The current position in the read buffer.
82     */

83    protected int _readPosition;
84
85    protected Reader JavaDoc _reader;
86
87    /**
88     * The start offset of the last lexical unit.
89     */

90    protected int _start;
91
92    /**
93     * The type of the current lexical unit.
94     */

95    protected int _type;
96
97    /**
98     * Creates a new Scanner object.
99     *
100     *@param r The reader to scan.
101     *@exception CssParseException Description of the Exception
102     */

103    public CssLexer( Reader JavaDoc r ) throws CssParseException
104    {
105       try
106       {
107          _reader = r;
108          _readBuffer = new char[4096];
109          _current = nextChar();
110       }
111       catch( IOException JavaDoc e )
112       {
113          throw new CssParseException( e );
114       }
115    }
116
117    /**
118     * Creates a new Scanner object.
119     *
120     *@param r The reader to scan.
121     *@param s Description of the Parameter
122     *@exception CssParseException Description of the Exception
123     */

124    public CssLexer( String JavaDoc s ) throws CssParseException
125    {
126       try
127       {
128          _reader = null;
129          _readBuffer = s.toCharArray();
130          _readPosition = 0;
131          _readCount = _readBuffer.length;
132          collapseCRNL( 0 );
133          if( _readCount == 0 )
134             _current = -1;
135          else
136             _current = nextChar();
137       }
138       catch( IOException JavaDoc e )
139       {
140          throw new CssParseException( e );
141       }
142    }
143
144    /**
145     * Returns the buffer used to store the chars.
146     */

147    public char[] getBuffer()
148    {
149       return _buffer;
150    }
151
152    /**
153     * Returns the current column.
154     */

155    public int getColumn()
156    {
157       return _column;
158    }
159
160    /**
161     * Returns the end offset of the last lexical unit.
162     */

163    public int getEnd()
164    {
165       return _end;
166    }
167
168    /**
169     * Returns the current line.
170     */

171    public int getLine()
172    {
173       return _line;
174    }
175
176    /**
177     * Returns the start offset of the last lexical unit.
178     */

179    public int getStart()
180    {
181       return _start;
182    }
183
184    /**
185     * Returns the string representation of the current lexical unit.
186     */

187    public String JavaDoc getStringValue()
188    {
189       return new String JavaDoc( _buffer, _start, _end - _start );
190    }
191
192    /**
193     * The current lexical unit type like defined in Css.Token
194     */

195    public int getType()
196    {
197       return _type;
198    }
199
200    /**
201     * Compares the given int with the given character, ignoring case.
202     */

203    protected static boolean isEqualIgnoreCase( int i, char c )
204    {
205       return ( i == -1 ) ? false : Character.toLowerCase( ( char ) i ) == c;
206    }
207
208    /**
209     * Clears the buffer.
210     */

211    public void clearBuffer()
212    {
213       if( _position <= 0 )
214          _position = 0;
215       else
216       {
217          _buffer[0] = _buffer[_position - 1];
218          _position = 1;
219       }
220    }
221
222    /**
223     * Returns the next token.
224     */

225    public int next() throws CssParseException
226    {
227       _blankCharacters = 0;
228       _start = _position - 1;
229       nextToken();
230       _end = _position - endGap();
231       return _type;
232    }
233
234    /**
235     * Scans the decimal part of a number.
236     */

237    protected int dotNumber() throws IOException JavaDoc
238    {
239       loop :
240       for( ; ; )
241       {
242          switch ( nextChar() )
243          {
244             default:
245                break loop;
246             case '0':
247             case '1':
248             case '2':
249             case '3':
250             case '4':
251             case '5':
252             case '6':
253             case '7':
254             case '8':
255             case '9':
256          }
257       }
258       return numberUnit( false );
259    }
260
261    /**
262     * Returns the end gap of the current lexical unit.
263     */

264    protected int endGap()
265    {
266       int result = ( _current == -1 ) ? 0 : 1;
267       switch ( _type )
268       {
269          case Css.Token.FUNCTION:
270          case Css.Token.STRING:
271          case Css.Token.S:
272          case Css.Token.PERCENTAGE:
273             result += 1;
274             break;
275          case Css.Token.COMMENT:
276          case Css.Token.HZ:
277          case Css.Token.EM:
278          case Css.Token.EX:
279          case Css.Token.PC:
280          case Css.Token.PT:
281          case Css.Token.PX:
282          case Css.Token.CM:
283          case Css.Token.MM:
284          case Css.Token.IN:
285          case Css.Token.MS:
286             result += 2;
287             break;
288          case Css.Token.KHZ:
289          case Css.Token.DEG:
290          case Css.Token.RAD:
291             result += 3;
292             break;
293          case Css.Token.GRAD:
294             result += 4;
295       }
296       return result + _blankCharacters;
297    }
298
299    /**
300     * Scans an escape sequence, if one.
301     */

302    protected void escape() throws IOException JavaDoc
303    {
304       if( CssCharUtils.isHexadecimal( ( char ) _current ) )
305       {
306          nextChar();
307          if( !CssCharUtils.isHexadecimal( ( char ) _current ) )
308          {
309             if( CssCharUtils.isSpace( ( char ) _current ) )
310                nextChar();
311             return;
312          }
313          nextChar();
314          if( !CssCharUtils.isHexadecimal( ( char ) _current ) )
315          {
316             if( CssCharUtils.isSpace( ( char ) _current ) )
317                nextChar();
318             return;
319          }
320          nextChar();
321          if( !CssCharUtils.isHexadecimal( ( char ) _current ) )
322          {
323             if( CssCharUtils.isSpace( ( char ) _current ) )
324                nextChar();
325             return;
326          }
327          nextChar();
328          if( !CssCharUtils.isHexadecimal( ( char ) _current ) )
329          {
330             if( CssCharUtils.isSpace( ( char ) _current ) )
331                nextChar();
332             return;
333          }
334          nextChar();
335          if( !CssCharUtils.isHexadecimal( ( char ) _current ) )
336          {
337             if( CssCharUtils.isSpace( ( char ) _current ) )
338                nextChar();
339             return;
340          }
341       }
342       if( ( _current >= ' ' && _current <= '~' ) || _current >= 128 )
343       {
344          nextChar();
345          return;
346       }
347       throw new CssParseException( "character", _line, _column );
348    }
349
350    /**
351     * Sets the value of the current char to the next character or -1 if the end
352     * of stream has been reached.
353     */

354    protected int nextChar() throws IOException JavaDoc
355    {
356       if( _readPosition == _readCount && !fillReadBuffer() )
357          return _current = -1;
358
359       if( _current != 10 )
360          _column++;
361       else
362       {
363          _line++;
364          _column = 1;
365       }
366
367       _current = _readBuffer[_readPosition++];
368
369       if( _position == _buffer.length )
370       {
371          char[] t = new char[_position * 3 / 2];
372          System.arraycopy( _buffer, 0, t, 0, _position );
373          _buffer = t;
374       }
375
376       return _buffer[_position++] = ( char ) _current;
377    }
378
379    /**
380     * Returns the next token.
381     */

382    protected void nextToken() throws CssParseException
383    {
384       try
385       {
386          switch ( _current )
387          {
388             case -1:
389                _type = Css.Token.EOF;
390                return;
391             case '{':
392                nextChar();
393                _type = Css.Token.LEFT_CURLY_BRACE;
394                return;
395             case '}':
396                nextChar();
397                _type = Css.Token.RIGHT_CURLY_BRACE;
398                return;
399             case '=':
400                nextChar();
401                _type = Css.Token.EQUAL;
402                return;
403             case '+':
404                nextChar();
405                _type = Css.Token.PLUS;
406                return;
407             case ',':
408                nextChar();
409                _type = Css.Token.COMMA;
410                return;
411             case ';':
412                nextChar();
413                _type = Css.Token.SEMI_COLON;
414                return;
415             case '>':
416                nextChar();
417                _type = Css.Token.PRECEDE;
418                return;
419             case '[':
420                nextChar();
421                _type = Css.Token.LEFT_BRACKET;
422                return;
423             case ']':
424                nextChar();
425                _type = Css.Token.RIGHT_BRACKET;
426                return;
427             case '*':
428                nextChar();
429                _type = Css.Token.ANY;
430                return;
431             case '(':
432                nextChar();
433                _type = Css.Token.LEFT_BRACE;
434                return;
435             case ')':
436                nextChar();
437                _type = Css.Token.RIGHT_BRACE;
438                return;
439             case ':':
440                nextChar();
441                _type = Css.Token.COLON;
442                return;
443             case ' ':
444             case '\t':
445             case '\r':
446             case '\n':
447             case '\f':
448                do
449                {
450                   nextChar();
451                }while ( CssCharUtils.isSpace( ( char ) _current ) );
452                _type = Css.Token.SPACE;
453                return;
454             case '/':
455                nextChar();
456                if( _current != '*' )
457                {
458                   _type = Css.Token.DIVIDE;
459                   return;
460                }
461                // Comment
462
nextChar();
463                _start = _position - 1;
464                do
465                {
466                   while( _current != -1 && _current != '*' )
467                   {
468                      nextChar();
469                   }
470
471                   do
472                   {
473                      nextChar();
474                   }while ( _current != -1 && _current == '*' );
475                }while ( _current != -1 && _current != '/' );
476
477                if( _current == -1 )
478                   throw new CssParseException( "eof", _line, _column );
479                nextChar();
480                _type = Css.Token.COMMENT;
481                return;
482             case '\'':
483                // String1
484
_type = string1();
485                return;
486             case '"':
487                // String2
488
_type = string2();
489                return;
490             case '<':
491                nextChar();
492                if( _current != '!' )
493                   throw new CssParseException( "character", _line, _column );
494                nextChar();
495                if( _current == '-' )
496                {
497                   nextChar();
498                   if( _current == '-' )
499                   {
500                      nextChar();
501                      _type = Css.Token.CDO;
502                      return;
503                   }
504                }
505                throw new CssParseException( "character", _line, _column );
506             case '-':
507                nextChar();
508                if( _current != '-' )
509                {
510                   _type = Css.Token.MINUS;
511                   return;
512                }
513                nextChar();
514                if( _current == '>' )
515                {
516                   nextChar();
517                   _type = Css.Token.CDC;
518                   return;
519                }
520                throw new CssParseException( "character", _line, _column );
521             case '|':
522                nextChar();
523                if( _current == '=' )
524                {
525                   nextChar();
526                   _type = Css.Token.DASHMATCH;
527                   return;
528                }
529                throw new CssParseException( "character", _line, _column );
530             case '~':
531                nextChar();
532                if( _current == '=' )
533                {
534                   nextChar();
535                   _type = Css.Token.INCLUDES;
536                   return;
537                }
538                throw new CssParseException( "character", _line, _column );
539             case '#':
540                nextChar();
541                if( CssCharUtils.isName( ( char ) _current ) )
542                {
543                   _start = _position - 1;
544                   do
545                   {
546                      nextChar();
547                      if( _current == '\\' )
548                      {
549                         nextChar();
550                         escape();
551                      }
552                   }while ( _current != -1 &&
553                         CssCharUtils.isName( ( char ) _current ) );
554                   _type = Css.Token.HASH;
555                   return;
556                }
557                throw new CssParseException( "character", _line, _column );
558             case '!':
559                do
560                {
561                   nextChar();
562                }while ( _current != -1 && CssCharUtils.isSpace( ( char ) _current ) );
563                if( isEqualIgnoreCase( _current, 'i' ) &&
564                      isEqualIgnoreCase( nextChar(), 'm' ) &&
565                      isEqualIgnoreCase( nextChar(), 'p' ) &&
566                      isEqualIgnoreCase( nextChar(), 'o' ) &&
567                      isEqualIgnoreCase( nextChar(), 'r' ) &&
568                      isEqualIgnoreCase( nextChar(), 't' ) &&
569                      isEqualIgnoreCase( nextChar(), 'a' ) &&
570                      isEqualIgnoreCase( nextChar(), 'n' ) &&
571                      isEqualIgnoreCase( nextChar(), 't' ) )
572                {
573                   nextChar();
574                   _type = Css.Token.IMPORTANT_SYMBOL;
575                   return;
576                }
577                if( _current == -1 )
578                   throw new CssParseException( "eof", _line, _column );
579                else
580                   throw new CssParseException( "character", _line, _column );
581             case '0':
582             case '1':
583             case '2':
584             case '3':
585             case '4':
586             case '5':
587             case '6':
588             case '7':
589             case '8':
590             case '9':
591                _type = number();
592                return;
593             case '.':
594                switch ( nextChar() )
595                {
596                   case '0':
597                   case '1':
598                   case '2':
599                   case '3':
600                   case '4':
601                   case '5':
602                   case '6':
603                   case '7':
604                   case '8':
605                   case '9':
606                      _type = dotNumber();
607                      return;
608                   default:
609                      _type = Css.Token.DOT;
610                      return;
611                }
612             case 'u':
613             case 'U':
614                nextChar();
615                switch ( _current )
616                {
617                   case 'r':
618                   case 'R':
619                      nextChar();
620                      switch ( _current )
621                      {
622                         case 'l':
623                         case 'L':
624                            nextChar();
625                            switch ( _current )
626                            {
627                               case '(':
628                                  do
629                                  {
630                                     nextChar();
631                                  }while ( _current != -1 &&
632                                        CssCharUtils.isSpace( ( char ) _current ) );
633                                  switch ( _current )
634                                  {
635                                     case '\'':
636                                        string1();
637                                        _blankCharacters += 2;
638                                        while( _current != -1 &&
639                                              CssCharUtils.isSpace( ( char ) _current ) )
640                                        {
641                                           _blankCharacters++;
642                                           nextChar();
643                                        }
644                                        if( _current == -1 )
645                                        {
646                                           throw new CssParseException( "eof", _line, _column );
647                                        }
648                                        if( _current != ')' )
649                                        {
650                                           throw new CssParseException( "character", _line, _column );
651                                        }
652                                        nextChar();
653                                        _type = Css.Token.URI;
654                                        return;
655                                     case '"':
656                                        string2();
657                                        _blankCharacters += 2;
658                                        while( _current != -1 &&
659                                              CssCharUtils.isSpace( ( char ) _current ) )
660                                        {
661                                           _blankCharacters++;
662                                           nextChar();
663                                        }
664                                        if( _current == -1 )
665                                           throw new CssParseException( "eof", _line, _column );
666
667                                        if( _current != ')' )
668                                           throw new CssParseException( "character", _line, _column );
669
670                                        nextChar();
671                                        _type = Css.Token.URI;
672                                        return;
673                                     case ')':
674                                        throw new CssParseException( "character", _line, _column );
675                                     default:
676                                        if( !CssCharUtils.isUri( ( char ) _current ) )
677                                           throw new CssParseException( "character", _line, _column );
678                                        _start = _position - 1;
679                                        do
680                                        {
681                                           nextChar();
682                                        }while ( _current != -1 &&
683                                              CssCharUtils.isUri( ( char ) _current ) );
684                                        _blankCharacters++;
685                                        while( _current != -1 &&
686                                              CssCharUtils.isSpace( ( char ) _current ) )
687                                        {
688                                           _blankCharacters++;
689                                           nextChar();
690                                        }
691                                        if( _current == -1 )
692                                           throw new CssParseException( "eof", _line, _column );
693
694                                        if( _current != ')' )
695                                           throw new CssParseException( "character", _line, _column );
696
697                                        nextChar();
698                                        _type = Css.Token.URI;
699                                        return;
700                                  }
701                            }
702                      }
703                }
704                while( _current != -1 &&
705                      CssCharUtils.isName( ( char ) _current ) )
706                {
707                   nextChar();
708                }
709
710                if( _current == '(' )
711                {
712                   nextChar();
713                   _type = Css.Token.FUNCTION;
714                   return;
715                }
716                _type = Css.Token.IDENTIFIER;
717                return;
718             default:
719                if( CssCharUtils.isIdentifierStart( ( char ) _current ) )
720                {
721                   // Identifier
722
do
723                   {
724                      nextChar();
725                      if( _current == '\\' )
726                      {
727                         nextChar();
728                         escape();
729                      }
730                   }while ( _current != -1 &&
731                         CssCharUtils.isName( ( char ) _current ) );
732                   if( _current == '(' )
733                   {
734                      nextChar();
735                      _type = Css.Token.FUNCTION;
736                      return;
737                   }
738                   _type = Css.Token.IDENTIFIER;
739                   return;
740                }
741                nextChar();
742                throw new CssParseException( "character", _line, _column );
743          }
744       }
745       catch( IOException JavaDoc e )
746       {
747          throw new CssParseException( e );
748       }
749    }
750
751    /**
752     * Scans a number.
753     */

754    protected int number() throws IOException JavaDoc
755    {
756       loop :
757       for( ; ; )
758       {
759          switch ( nextChar() )
760          {
761             case '.':
762                switch ( nextChar() )
763                {
764                   case '0':
765                   case '1':
766                   case '2':
767                   case '3':
768                   case '4':
769                   case '5':
770                   case '6':
771                   case '7':
772                   case '8':
773                   case '9':
774                      return dotNumber();
775                }
776                throw new CssParseException( "character", _line, _column );
777             default:
778                break loop;
779             case '0':
780             case '1':
781             case '2':
782             case '3':
783             case '4':
784             case '5':
785             case '6':
786             case '7':
787             case '8':
788             case '9':
789          }
790       }
791       return numberUnit( true );
792    }
793
794    /**
795     * Scans the unit of a number.
796     */

797    protected int numberUnit( boolean integer ) throws IOException JavaDoc
798    {
799       switch ( _current )
800       {
801          case '%':
802             nextChar();
803             return Css.Token.PERCENTAGE;
804          case 'c':
805          case 'C':
806             switch ( nextChar() )
807             {
808                case 'm':
809                case 'M':
810                   nextChar();
811                   if( _current != -1 &&
812                         CssCharUtils.isName( ( char ) _current ) )
813                   {
814                      do
815                      {
816                         nextChar();
817                      }while ( _current != -1 &&
818                            CssCharUtils.isName( ( char ) _current ) );
819                      return Css.Token.DIMENSION;
820                   }
821                   return Css.Token.CM;
822                default:
823                   while( _current != -1 &&
824                         CssCharUtils.isName( ( char ) _current ) )
825                   {
826                      nextChar();
827                   }
828                   return Css.Token.DIMENSION;
829             }
830          case 'd':
831          case 'D':
832             switch ( nextChar() )
833             {
834                case 'e':
835                case 'E':
836                   switch ( nextChar() )
837                   {
838                      case 'g':
839                      case 'G':
840                         nextChar();
841                         if( _current != -1 &&
842                               CssCharUtils.isName( ( char ) _current ) )
843                         {
844                            do
845                            {
846                               nextChar();
847                            }while ( _current != -1 &&
848                                  CssCharUtils.isName( ( char ) _current ) );
849                            return Css.Token.DIMENSION;
850                         }
851                         return Css.Token.DEG;
852                   }
853                default:
854                   while( _current != -1 &&
855                         CssCharUtils.isName( ( char ) _current ) )
856                   {
857                      nextChar();
858                   }
859                   return Css.Token.DIMENSION;
860             }
861          case 'e':
862          case 'E':
863             switch ( nextChar() )
864             {
865                case 'm':
866                case 'M':
867                   nextChar();
868                   if( _current != -1 &&
869                         CssCharUtils.isName( ( char ) _current ) )
870                   {
871                      do
872                      {
873                         nextChar();
874                      }while ( _current != -1 &&
875                            CssCharUtils.isName( ( char ) _current ) );
876                      return Css.Token.DIMENSION;
877                   }
878                   return Css.Token.EM;
879                case 'x':
880                case 'X':
881                   nextChar();
882                   if( _current != -1 &&
883                         CssCharUtils.isName( ( char ) _current ) )
884                   {
885                      do
886                      {
887                         nextChar();
888                      }while ( _current != -1 &&
889                            CssCharUtils.isName( ( char ) _current ) );
890                      return Css.Token.DIMENSION;
891                   }
892                   return Css.Token.EX;
893                default:
894                   while( _current != -1 &&
895                         CssCharUtils.isName( ( char ) _current ) )
896                   {
897                      nextChar();
898                   }
899                   return Css.Token.DIMENSION;
900             }
901          case 'g':
902          case 'G':
903             switch ( nextChar() )
904             {
905                case 'r':
906                case 'R':
907                   switch ( nextChar() )
908                   {
909                      case 'a':
910                      case 'A':
911                         switch ( nextChar() )
912                         {
913                            case 'd':
914                            case 'D':
915                               nextChar();
916                               if( _current != -1 &&
917                                     CssCharUtils.isName( ( char ) _current ) )
918                               {
919                                  do
920                                  {
921                                     nextChar();
922                                  }while ( _current != -1 &&
923                                        CssCharUtils.isName( ( char ) _current ) );
924                                  return Css.Token.DIMENSION;
925                               }
926                               return Css.Token.GRAD;
927                         }
928                   }
929                default:
930                   while( _current != -1 &&
931                         CssCharUtils.isName( ( char ) _current ) )
932                   {
933                      nextChar();
934                   }
935                   return Css.Token.DIMENSION;
936             }
937          case 'h':
938          case 'H':
939             nextChar();
940             switch ( _current )
941             {
942                case 'z':
943                case 'Z':
944                   nextChar();
945                   if( _current != -1 &&
946                         CssCharUtils.isName( ( char ) _current ) )
947                   {
948                      do
949                      {
950                         nextChar();
951                      }while ( _current != -1 &&
952                            CssCharUtils.isName( ( char ) _current ) );
953                      return Css.Token.DIMENSION;
954                   }
955                   return Css.Token.HZ;
956                default:
957                   while( _current != -1 &&
958                         CssCharUtils.isName( ( char ) _current ) )
959                   {
960                      nextChar();
961                   }
962                   return Css.Token.DIMENSION;
963             }
964          case 'i':
965          case 'I':
966             switch ( nextChar() )
967             {
968                case 'n':
969                case 'N':
970                   nextChar();
971                   if( _current != -1 &&
972                         CssCharUtils.isName( ( char ) _current ) )
973                   {
974                      do
975                      {
976                         nextChar();
977                      }while ( _current != -1 &&
978                            CssCharUtils.isName( ( char ) _current ) );
979                      return Css.Token.DIMENSION;
980                   }
981                   return Css.Token.IN;
982                default:
983                   while( _current != -1 &&
984                         CssCharUtils.isName( ( char ) _current ) )
985                   {
986                      nextChar();
987                   }
988                   return Css.Token.DIMENSION;
989             }
990          case 'k':
991          case 'K':
992             switch ( nextChar() )
993             {
994                case 'h':
995                case 'H':
996                   switch ( nextChar() )
997                   {
998                      case 'z':
999                      case 'Z':
1000                        nextChar();
1001                        if( _current != -1 &&
1002                              CssCharUtils.isName( ( char ) _current ) )
1003                        {
1004                           do
1005                           {
1006                              nextChar();
1007                           }while ( _current != -1 &&
1008                                 CssCharUtils.isName( ( char ) _current ) );
1009                           return Css.Token.DIMENSION;
1010                        }
1011                        return Css.Token.KHZ;
1012                  }
1013               default:
1014                  while( _current != -1 &&
1015                        CssCharUtils.isName( ( char ) _current ) )
1016                  {
1017                     nextChar();
1018                  }
1019                  return Css.Token.DIMENSION;
1020            }
1021         case 'm':
1022         case 'M':
1023            switch ( nextChar() )
1024            {
1025               case 'm':
1026               case 'M':
1027                  nextChar();
1028                  if( _current != -1 &&
1029                        CssCharUtils.isName( ( char ) _current ) )
1030                  {
1031                     do
1032                     {
1033                        nextChar();
1034                     }while ( _current != -1 &&
1035                           CssCharUtils.isName( ( char ) _current ) );
1036                     return Css.Token.DIMENSION;
1037                  }
1038                  return Css.Token.MM;
1039               case 's':
1040               case 'S':
1041                  nextChar();
1042                  if( _current != -1 &&
1043                        CssCharUtils.isName( ( char ) _current ) )
1044                  {
1045                     do
1046                     {
1047                        nextChar();
1048                     }while ( _current != -1 &&
1049                           CssCharUtils.isName( ( char ) _current ) );
1050                     return Css.Token.DIMENSION;
1051                  }
1052                  return Css.Token.MS;
1053               default:
1054                  while( _current != -1 &&
1055                        CssCharUtils.isName( ( char ) _current ) )
1056                  {
1057                     nextChar();
1058                  }
1059                  return Css.Token.DIMENSION;
1060            }
1061         case 'p':
1062         case 'P':
1063            switch ( nextChar() )
1064            {
1065               case 'c':
1066               case 'C':
1067                  nextChar();
1068                  if( _current != -1 &&
1069                        CssCharUtils.isName( ( char ) _current ) )
1070                  {
1071                     do
1072                     {
1073                        nextChar();
1074                     }while ( _current != -1 &&
1075                           CssCharUtils.isName( ( char ) _current ) );
1076                     return Css.Token.DIMENSION;
1077                  }
1078                  return Css.Token.PC;
1079               case 't':
1080               case 'T':
1081                  nextChar();
1082                  if( _current != -1 &&
1083                        CssCharUtils.isName( ( char ) _current ) )
1084                  {
1085                     do
1086                     {
1087                        nextChar();
1088                     }while ( _current != -1 &&
1089                           CssCharUtils.isName( ( char ) _current ) );
1090                     return Css.Token.DIMENSION;
1091                  }
1092                  return Css.Token.PT;
1093               case 'x':
1094               case 'X':
1095                  nextChar();
1096                  if( _current != -1 &&
1097                        CssCharUtils.isName( ( char ) _current ) )
1098                  {
1099                     do
1100                     {
1101                        nextChar();
1102                     }while ( _current != -1 &&
1103                           CssCharUtils.isName( ( char ) _current ) );
1104                     return Css.Token.DIMENSION;
1105                  }
1106                  return Css.Token.PX;
1107               default:
1108                  while( _current != -1 &&
1109                        CssCharUtils.isName( ( char ) _current ) )
1110                  {
1111                     nextChar();
1112                  }
1113                  return Css.Token.DIMENSION;
1114            }
1115         case 'r':
1116         case 'R':
1117            switch ( nextChar() )
1118            {
1119               case 'a':
1120               case 'A':
1121                  switch ( nextChar() )
1122                  {
1123                     case 'd':
1124                     case 'D':
1125                        nextChar();
1126                        if( _current != -1 &&
1127                              CssCharUtils.isName( ( char ) _current ) )
1128                        {
1129                           do
1130                           {
1131                              nextChar();
1132                           }while ( _current != -1 &&
1133                                 CssCharUtils.isName( ( char ) _current ) );
1134                           return Css.Token.DIMENSION;
1135                        }
1136                        return Css.Token.RAD;
1137                  }
1138               default:
1139                  while( _current != -1 &&
1140                        CssCharUtils.isName( ( char ) _current ) )
1141                  {
1142                     nextChar();
1143                  }
1144                  return Css.Token.DIMENSION;
1145            }
1146         case 's':
1147         case 'S':
1148            nextChar();
1149            return Css.Token.S;
1150         default:
1151            if( _current != -1 &&
1152                  CssCharUtils.isIdentifierStart( ( char ) _current ) )
1153            {
1154               do
1155               {
1156                  nextChar();
1157               }while ( _current != -1 &&
1158                     CssCharUtils.isName( ( char ) _current ) );
1159               return Css.Token.DIMENSION;
1160            }
1161            return ( integer ) ? Css.Token.INTEGER : Css.Token.REAL;
1162      }
1163   }
1164
1165   /**
1166    * Scans a single quoted string.
1167    */

1168   protected int string1() throws IOException JavaDoc
1169   {
1170      nextChar();
1171      _start = _position - 1;
1172      loop :
1173      for( ; ; )
1174      {
1175         switch ( nextChar() )
1176         {
1177            case -1:
1178               throw new CssParseException( "eof", _line, _column );
1179            case '\'':
1180               break loop;
1181            case '"':
1182               break;
1183            case '\\':
1184               switch ( nextChar() )
1185               {
1186                  case '\n':
1187                  case '\f':
1188                     break;
1189                  default:
1190                     escape();
1191               }
1192               break;
1193            default:
1194               if( !CssCharUtils.isString( ( char ) _current ) )
1195                  throw new CssParseException( "character", _line, _column );
1196         }
1197      }
1198      nextChar();
1199      return Css.Token.STRING;
1200   }
1201
1202   /**
1203    * Scans a double quoted string.
1204    */

1205   protected int string2() throws IOException JavaDoc
1206   {
1207      nextChar();
1208      _start = _position - 1;
1209      loop :
1210      for( ; ; )
1211      {
1212         switch ( nextChar() )
1213         {
1214            case -1:
1215               throw new CssParseException( "eof", _line, _column );
1216            case '\'':
1217               break;
1218            case '"':
1219               break loop;
1220            case '\\':
1221               switch ( nextChar() )
1222               {
1223                  case '\n':
1224                  case '\f':
1225                     break;
1226                  default:
1227                     escape();
1228               }
1229               break;
1230            default:
1231               if( !CssCharUtils.isString( ( char ) _current ) )
1232                  throw new CssParseException( "character", _line, _column );
1233         }
1234      }
1235      nextChar();
1236      return Css.Token.STRING;
1237   }
1238
1239   private void collapseCRNL( int src )
1240   {
1241      // Now collapse cr/nl...
1242
while( src < _readCount )
1243      {
1244         if( _readBuffer[src] != 13 )
1245            src++;
1246         else
1247         {
1248            _readBuffer[src] = 10;
1249            src++;
1250            if( src >= _readCount )
1251               break;
1252
1253            if( _readBuffer[src] == 10 )
1254            {
1255               // We now need to collapse some of the chars to
1256
// eliminate cr/nl pairs. This is where we do it...
1257
int dst = src;
1258               // start writing where this 10 is
1259
src++;
1260               // skip reading this 10.
1261
while( src < _readCount )
1262               {
1263                  if( _readBuffer[src] == 13 )
1264                  {
1265                     _readBuffer[dst++] = 10;
1266                     src++;
1267                     if( src >= _readCount )
1268                        break;
1269
1270                     if( _readBuffer[src] == 10 )
1271                        src++;
1272
1273                     continue;
1274                  }
1275                  _readBuffer[dst++] = _readBuffer[src++];
1276               }
1277               _readCount = dst;
1278               break;
1279            }
1280         }
1281      }
1282   }
1283
1284   private boolean fillReadBuffer() throws IOException JavaDoc
1285   {
1286      if( _readCount != 0 )
1287      {
1288         if( _readPosition == _readCount )
1289         {
1290            _readBuffer[0] = _readBuffer[_readCount - 1];
1291            _readCount = 1;
1292            _readPosition = 1;
1293         }
1294         else
1295         {
1296            // we keep the last char in our readBuffer.
1297
System.arraycopy( _readBuffer, _readPosition - 1, _readBuffer, 0,
1298                  _readCount - _readPosition + 1 );
1299            _readCount = ( _readCount - _readPosition ) + 1;
1300            _readPosition = 1;
1301         }
1302      }
1303
1304      // No reader so can't extend...
1305
if( _reader == null )
1306         return ( _readCount != _readPosition );
1307
1308      // remember where the fill starts...
1309
int src = _readCount - 1;
1310      if( src < 0 )
1311         src = 0;
1312
1313      // Refill the readBuffer...
1314
int read = _reader.read( _readBuffer, _readCount,
1315            _readBuffer.length - _readCount );
1316      if( read == -1 )
1317         return _readCount != _readPosition;
1318
1319      _readCount += read;
1320      // add in chars read.
1321
collapseCRNL( src );
1322      // Now collapse cr/nl...
1323

1324      return _readCount != _readPosition;
1325   }
1326}
1327
Popular Tags