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