CSSParser.java revision 0
4248N/A * Copyright 1999-2000 Sun Microsystems, Inc. All Rights Reserved. 2668N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2668N/A * This code is free software; you can redistribute it and/or modify it 2668N/A * under the terms of the GNU General Public License version 2 only, as 2668N/A * published by the Free Software Foundation. Sun designates this 2668N/A * particular file as subject to the "Classpath" exception as provided 2668N/A * by Sun in the LICENSE file that accompanied this code. 2668N/A * This code is distributed in the hope that it will be useful, but WITHOUT 2668N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2668N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2668N/A * version 2 for more details (a copy is included in the LICENSE file that 2668N/A * You should have received a copy of the GNU General Public License version 2668N/A * 2 along with this work; if not, write to the Free Software Foundation, 2668N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2668N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2668N/A * CA 95054 USA or visit www.sun.com if you need additional information or 2668N/A * A CSS parser. This works by way of a delegate that implements the 2668N/A * CSSParserCallback interface. The delegate is notified of the following 2668N/A * <li>Import statement: <code>handleImport</code> 3883N/A * <li>Selectors <code>handleSelector</code>. This is invoked for each 2668N/A * string. For example if the Reader contained p, bar , a {}, the delegate 2668N/A * would be notified 4 times, for 'p,' 'bar' ',' and 'a'. 2668N/A * <li>When a rule starts, <code>startRule</code> 2668N/A * <li>Properties in the rule via the <code>handleProperty</code>. This 2668N/A * cause the delegate to be notified once with a value of 'font size'. 2668N/A * <li>Values in the rule via the <code>handleValue</code>, this is notified 2668N/A * <li>When a rule ends, <code>endRule</code> 2668N/A * This will parse much more than CSS 1, and loosely implements the 3883N/A * recommendation for <i>Forward-compatible parsing</i> in section 3883N/A * 7.1 of the CSS spec found at: 2668N/A * If an error results in parsing, a RuntimeException will be thrown. 2668N/A * This will preserve case. If the callback wishes to treat certain poritions 2668N/A * case insensitively (such as selectors), it should use toLowerCase, or 2668N/A // Parsing something like the following: 2668N/A // (@rule | ruleset | block)* 2668N/A // @rule (block | identifier)*; (block with {} ends @rule) 2668N/A // block matching [] () {} (that is, [()] is a block, [(){}{[]}] 2668N/A // is a block, ()[] is two blocks) 2668N/A // identifier "*" | '*' | anything but a [](){} and whitespace 2668N/A // ruleset selector decblock 2668N/A // selector (identifier | (block, except block '{}') )* 2668N/A // declblock declaration* block* 2668N/A // declaration (identifier* stopping when identifier ends with :) 2668N/A // (identifier* stopping when identifier ends with ;) 2668N/A // comments /* */ can appear any where, and are stripped. 2668N/A // identifier - letters, digits, dashes and escaped characters 2668N/A // block starts with { ends with matching }, () [] and {} always occur 2668N/A // in matching pairs, '' and "" also occur in pairs, except " may be 2668N/A // Indicates the type of token being parsed. 2668N/A /** Set to true if one character has been read ahead. */ 2668N/A /** The read ahead character. */ 2668N/A /** Temporary place to hold identifiers. */ 2668N/A /** Used to indicate blocks. */ 2668N/A /** Number of valid blocks. */ 2668N/A /** Holds the incoming CSS rules. */ 2668N/A /** Set to true when the first non @ rule is encountered. */ 2668N/A /** nextToken() inserts the string here. */ 2668N/A /** Current number of chars in tokenBufferLength. */ 2668N/A /** Set to true if any whitespace is read. */ 2668N/A /** Called when an @import is encountered. */ 2668N/A // There is currently no way to distinguish between '"foo,"' and 2668N/A // 'foo,'. But this generally isn't valid CSS. If it becomes 2668N/A // a problem, handleSelector will have to be told if the string is 2668N/A // Property names are mapped to lower case before being passed to 2668N/A * Gets the next statement, returning false if the end is reached. A 2668N/A * statement is either an @rule, or a ruleset. 2674N/A * Parses an @ rule, stopping at a matching brace pair, or ;. 2674N/A // PENDING: make this more effecient. 2668N/A // Skip a tailing ';', not really to spec. 2668N/A * Parses the next rule set, which is a selector followed by a 2668N/A * Parses a set of selectors, returning false if the end of the stream 2668N/A // Not too sure about this, how we handle this isn't very 2668N/A * Parses a declaration block. Which a number of declarations followed 2668N/A * Parses a single declaration, which is an identifier a : and another 2668N/A * identifier. This returns the last token seen. 2668N/A // identifier+: identifier* ;|} 2668N/A // Make the property name to lowercase 2668N/A * Parses identifiers until <code>extraChar</code> is encountered, 2668N/A * returning the ending token, which will be IDENTIFIER if extraChar 2668N/A // No need to throw for these two, we return token and 2668N/A * Parses till a matching block close is encountered. This is only 2668N/A * appropriate to be called at the top level (no nesting). * Gets an identifier, returning true if the length of the string is greater than 0, * stopping when <code>stopChar</code>, whitespace, or one of {}()[] is // NOTE: this could be combined with readTill, as they contain somewhat // similiar functionality. // 1 for '\', 2 for valid escape char [0-9a-fA-F], 3 for // stop character (white space, ()[]{}) 0 otherwise case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case '\'':
case '"':
case '[':
case ']':
case '{':
case '}':
case ' ':
case '\n':
case '\t':
case '\r':
// Make this simpler, reprocess the character. * Reads till a <code>stopChar</code> is encountered, escaping characters // 1 for '\', 2 for valid escape char [0-9a-fA-F], 0 otherwise case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
// Prematurely reached the end! * Parses a comment block. * Called when a block start is encountered ({[. * Called when an end block is encountered )]} // Invalid state, should do something. * @return true if currently in a block. * Skips any white space, returning the character after the white space. * Reads a character from the stream. // Uncomment the following to do case insensitive parsing. return (int)Character.toLowerCase((char)retValue); * Supports one character look ahead, this will throw if called twice throw new RuntimeException(
"Can not handle look ahead of more than one character");