mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			562 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			562 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
/* CSSParser.java --
 | 
						|
   Copyright (C) 2005 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package javax.swing.text.html;
 | 
						|
 | 
						|
import java.io.*;
 | 
						|
 | 
						|
/**
 | 
						|
 * Parses a CSS document. This works by way of a delegate that implements the
 | 
						|
 * CSSParserCallback interface. The delegate is notified of the following
 | 
						|
 * events:
 | 
						|
 * - Import statement: handleImport
 | 
						|
 * - Selectors handleSelector. This is invoked for each string. For example if
 | 
						|
 * the Reader contained p, bar , a {}, the delegate would be notified 4 times,
 | 
						|
 * for 'p,' 'bar' ',' and 'a'.
 | 
						|
 * - When a rule starts, startRule
 | 
						|
 * - Properties in the rule via the handleProperty. This
 | 
						|
 * is invoked one per property/value key, eg font size: foo;, would cause the
 | 
						|
 * delegate to be notified once with a value of 'font size'.
 | 
						|
 * - Values in the rule via the handleValue, this is notified for the total value.
 | 
						|
 * - When a rule ends, endRule
 | 
						|
 *
 | 
						|
 * @author Lillian Angel (langel@redhat.com)
 | 
						|
 */
 | 
						|
class CSSParser
 | 
						|
{
 | 
						|
 | 
						|
  /**
 | 
						|
   * Receives all information about the CSS document structure while parsing it.
 | 
						|
   * The methods are invoked by parser.
 | 
						|
   */
 | 
						|
  static interface CSSParserCallback
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Handles the import statment in the document.
 | 
						|
     *
 | 
						|
     * @param imp - the import string
 | 
						|
     */
 | 
						|
    public abstract void handleImport(String imp);
 | 
						|
 | 
						|
    /**
 | 
						|
     * Called when the start of a rule is encountered.
 | 
						|
     */
 | 
						|
    public abstract void startRule();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Called when the end of a rule is encountered.
 | 
						|
     */
 | 
						|
    public abstract void endRule();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Handles the selector of a rule.
 | 
						|
     *
 | 
						|
     * @param selector - the selector in the rule
 | 
						|
     */
 | 
						|
    public abstract void handleSelector(String selector);
 | 
						|
 | 
						|
    /**
 | 
						|
     * Handles the properties in the document.
 | 
						|
     *
 | 
						|
     * @param property - the property in the document.
 | 
						|
     */
 | 
						|
    public abstract void handleProperty(String property);
 | 
						|
 | 
						|
    /**
 | 
						|
     * Handles the values in the document.
 | 
						|
     *
 | 
						|
     * @param value - the value to handle.
 | 
						|
     */
 | 
						|
    public abstract void handleValue(String value);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * The identifier of the rule.
 | 
						|
   */
 | 
						|
  private static final int IDENTIFIER = 1;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The open bracket.
 | 
						|
   */
 | 
						|
  private static final int BRACKET_OPEN = 2;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The close bracket.
 | 
						|
   */
 | 
						|
  private static final int BRACKET_CLOSE = 3;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The open brace.
 | 
						|
   */
 | 
						|
  private static final int BRACE_OPEN = 4;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The close brace.
 | 
						|
   */
 | 
						|
  private static final int BRACE_CLOSE = 5;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The open parentheses.
 | 
						|
   */
 | 
						|
  private static final int PAREN_OPEN = 6;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The close parentheses.
 | 
						|
   */
 | 
						|
  private static final int PAREN_CLOSE = 7;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The end of the document.
 | 
						|
   */
 | 
						|
  private static final int END = -1;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The character mapping in the document.
 | 
						|
   */
 | 
						|
  // FIXME: What is this used for?
 | 
						|
  private static final char[] charMapping = null;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set to true if one character has been read ahead.
 | 
						|
   */
 | 
						|
  private boolean didPushChar;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The read ahead character.
 | 
						|
   */
 | 
						|
  private int pushedChar;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Used to indicate blocks.
 | 
						|
   */
 | 
						|
  private int[] unitStack;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Number of valid blocks.
 | 
						|
   */
 | 
						|
  private int stackCount;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Holds the incoming CSS rules.
 | 
						|
   */
 | 
						|
  private Reader reader;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set to true when the first non @ rule is encountered.
 | 
						|
   */
 | 
						|
  private boolean encounteredRuleSet;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The call back used to parse.
 | 
						|
   */
 | 
						|
  private CSSParser.CSSParserCallback callback;
 | 
						|
 | 
						|
  /**
 | 
						|
   * nextToken() inserts the string here.
 | 
						|
   */
 | 
						|
  private char[] tokenBuffer;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Current number of chars in tokenBufferLength.
 | 
						|
   */
 | 
						|
  private int tokenBufferLength;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set to true if any whitespace is read.
 | 
						|
   */
 | 
						|
  private boolean readWS;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructor
 | 
						|
   */
 | 
						|
  CSSParser()
 | 
						|
  {
 | 
						|
    tokenBuffer = new char[10];
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Appends a character to the token buffer.
 | 
						|
   *
 | 
						|
   * @param c - the character to append
 | 
						|
   */
 | 
						|
  private void append(char c)
 | 
						|
  {
 | 
						|
    if (tokenBuffer.length >= tokenBufferLength)
 | 
						|
      {
 | 
						|
        char[] temp = new char[tokenBufferLength * 2];
 | 
						|
        if (tokenBuffer != null)
 | 
						|
          System.arraycopy(tokenBuffer, 0, temp, 0, tokenBufferLength);
 | 
						|
 | 
						|
        temp[tokenBufferLength] = c;
 | 
						|
        tokenBuffer = temp;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      tokenBuffer[tokenBufferLength] = c;
 | 
						|
    tokenBufferLength++;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Fetches the next token.
 | 
						|
   *
 | 
						|
   * @param c - the character to fetch.
 | 
						|
   * @return the location
 | 
						|
   * @throws IOException - any i/o error encountered while reading
 | 
						|
   */
 | 
						|
  private int nextToken(char c) throws IOException
 | 
						|
  {
 | 
						|
    readWS = false;
 | 
						|
    int next = readWS();
 | 
						|
 | 
						|
    switch (next)
 | 
						|
      {
 | 
						|
      case '\"':
 | 
						|
        if (tokenBufferLength > 0)
 | 
						|
          tokenBufferLength--;
 | 
						|
        return IDENTIFIER;
 | 
						|
      case '\'':
 | 
						|
        if (tokenBufferLength > 0)
 | 
						|
          tokenBufferLength--;
 | 
						|
        return IDENTIFIER;
 | 
						|
      case '(':
 | 
						|
        return PAREN_OPEN;
 | 
						|
      case ')':
 | 
						|
        return PAREN_CLOSE;
 | 
						|
      case '{':
 | 
						|
        return BRACE_OPEN;
 | 
						|
      case '}':
 | 
						|
        return BRACE_CLOSE;
 | 
						|
      case '[':
 | 
						|
        return BRACKET_OPEN;
 | 
						|
      case ']':
 | 
						|
        return BRACKET_CLOSE;
 | 
						|
      case -1:
 | 
						|
        return END;
 | 
						|
      default:
 | 
						|
        pushChar(next);
 | 
						|
        getIdentifier(c);
 | 
						|
        return IDENTIFIER;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Reads a character from the stream.
 | 
						|
   *
 | 
						|
   * @return the number of characters read or -1 if end of stream is reached.
 | 
						|
   * @throws IOException - any i/o encountered while reading
 | 
						|
   */
 | 
						|
  private int readChar() throws IOException
 | 
						|
  {
 | 
						|
    if (didPushChar)
 | 
						|
      {
 | 
						|
        didPushChar = false;
 | 
						|
        return pushedChar;
 | 
						|
      }
 | 
						|
    return reader.read();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses the the contents of the reader using the
 | 
						|
   * callback.
 | 
						|
   *
 | 
						|
   * @param reader - the reader to read from
 | 
						|
   * @param callback - the callback instance
 | 
						|
   * @param parsingDeclaration - true if parsing a declaration
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  void parse(Reader reader, CSSParser.CSSParserCallback callback,
 | 
						|
             boolean parsingDeclaration)
 | 
						|
      throws IOException
 | 
						|
  {
 | 
						|
    this.reader = reader;
 | 
						|
    this.callback = callback;
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      if (!parsingDeclaration)
 | 
						|
        while(getNextStatement())
 | 
						|
          ;
 | 
						|
      else
 | 
						|
        parseDeclarationBlock();
 | 
						|
    }
 | 
						|
    catch (IOException ioe)
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Skips any white space, returning the character after the white space.
 | 
						|
   *
 | 
						|
   * @return the character after the whitespace
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private int readWS() throws IOException
 | 
						|
  {
 | 
						|
    int next = readChar();
 | 
						|
    while (Character.isWhitespace((char) next))
 | 
						|
      {
 | 
						|
        readWS = true;
 | 
						|
        int tempNext = readChar();
 | 
						|
        if (tempNext == END)
 | 
						|
          return next;
 | 
						|
        next = tempNext;
 | 
						|
      }
 | 
						|
 | 
						|
    // Its all whitespace
 | 
						|
    return END;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Gets the next statement, returning false if the end is reached.
 | 
						|
   * A statement is either an At-rule, or a ruleset.
 | 
						|
   *
 | 
						|
   * @return false if the end is reached
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private boolean getNextStatement() throws IOException
 | 
						|
  {
 | 
						|
    int c = nextToken((char) 0);
 | 
						|
    switch (c)
 | 
						|
      {
 | 
						|
        case PAREN_OPEN:
 | 
						|
        case BRACE_OPEN:
 | 
						|
        case BRACKET_OPEN:
 | 
						|
          parseTillClosed(c);
 | 
						|
          break;
 | 
						|
        case BRACKET_CLOSE:
 | 
						|
        case BRACE_CLOSE:
 | 
						|
        case PAREN_CLOSE:
 | 
						|
          throw new IOException("Not a proper statement.");
 | 
						|
        case IDENTIFIER:
 | 
						|
          if (tokenBuffer[0] == ('@'))
 | 
						|
            parseAtRule();
 | 
						|
          else
 | 
						|
            parseRuleSet();
 | 
						|
          break;
 | 
						|
        case END:
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses an @ rule, stopping at a matching brace pair, or ;.
 | 
						|
   *
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void parseAtRule() throws IOException
 | 
						|
  {
 | 
						|
    // An At-Rule begins with the "@" character followed immediately by a keyword.
 | 
						|
    // Following the keyword separated by a space is an At-rule statement appropriate
 | 
						|
    // to the At-keyword used. If the At-Rule is a simple declarative statement
 | 
						|
    // (charset, import, fontdef), it is terminated by a semi-colon (";".)
 | 
						|
    // If the At-Rule is a conditional or informative statement (media, page, font-face),
 | 
						|
    // it is followed by optional arguments and then a style declaration block inside matching
 | 
						|
    // curly braces ("{", "}".) At-Rules are sometimes nestable, depending on the context.
 | 
						|
    // If any part of an At-Rule is not understood, it should be ignored.
 | 
						|
 | 
						|
    // FIXME: Not Implemented
 | 
						|
    // call handleimport
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses the next rule set, which is a selector followed by a declaration
 | 
						|
   * block.
 | 
						|
   *
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void parseRuleSet() throws IOException
 | 
						|
  {
 | 
						|
    // call parseDeclarationBlock
 | 
						|
    // call parse selectors
 | 
						|
    // call parse identifiers
 | 
						|
    // call startrule/endrule
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses a set of selectors, returning false if the end of the stream is
 | 
						|
   * reached.
 | 
						|
   *
 | 
						|
   * @return false if the end of stream is reached
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private boolean parseSelectors() throws IOException
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
    // call handleselector
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses a declaration block. Which a number of declarations followed by a
 | 
						|
   * })].
 | 
						|
   *
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void parseDeclarationBlock() throws IOException
 | 
						|
  {
 | 
						|
    // call parseDeclaration
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses a single declaration, which is an identifier a : and another identifier.
 | 
						|
   * This returns the last token seen.
 | 
						|
   *
 | 
						|
   * @returns the last token
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private int parseDeclaration() throws IOException
 | 
						|
  {
 | 
						|
    // call handleValue
 | 
						|
    // FIXME: Not Implemented
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses identifiers until c is encountered, returning the ending token,
 | 
						|
   * which will be IDENTIFIER if c is found.
 | 
						|
   *
 | 
						|
   * @param c - the stop character
 | 
						|
   * @param wantsBlocks - true if blocks are wanted
 | 
						|
   * @return the ending token
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private int parseIdentifiers(char c, boolean wantsBlocks) throws IOException
 | 
						|
  {
 | 
						|
    // FIXME: Not implemented
 | 
						|
    // call handleproperty?
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses till a matching block close is encountered. This is only appropriate
 | 
						|
   * to be called at the top level (no nesting).
 | 
						|
   *
 | 
						|
   * @param i - FIXME
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void parseTillClosed(int i) throws IOException
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Gets an identifier, returning true if the length of the string is greater
 | 
						|
   * than 0, stopping when c, whitespace, or one of {}()[] is hit.
 | 
						|
   *
 | 
						|
   * @param c - the stop character
 | 
						|
   * @return returns true if the length of the string > 0
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private boolean getIdentifier(char c) throws IOException
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Reads till c is encountered, escaping characters as necessary.
 | 
						|
   *
 | 
						|
   * @param c - the stop character
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void readTill(char c) throws IOException
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Parses a comment block.
 | 
						|
   *
 | 
						|
   * @throws IOException - any i/o error from the reader
 | 
						|
   */
 | 
						|
  private void readComment() throws IOException
 | 
						|
  {
 | 
						|
    // Should ignore comments. Read until end of comment.
 | 
						|
    // FIXME: Not implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called when a block start is encountered ({[.
 | 
						|
   *
 | 
						|
   * @param start of block
 | 
						|
   */
 | 
						|
  private void startBlock(int start)
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called when an end block is encountered )]}
 | 
						|
   *
 | 
						|
   * @param end of block
 | 
						|
   */
 | 
						|
  private void endBlock(int end)
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks if currently in a block.
 | 
						|
   *
 | 
						|
   * @return true if currently in a block.
 | 
						|
   */
 | 
						|
  private boolean inBlock()
 | 
						|
  {
 | 
						|
    // FIXME: Not Implemented
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Supports one character look ahead, this will throw if called twice in a row.
 | 
						|
   *
 | 
						|
   * @param c - the character to push.
 | 
						|
   * @throws IOException - if called twice in a row
 | 
						|
   */
 | 
						|
  private void pushChar(int c) throws IOException
 | 
						|
  {
 | 
						|
    if (didPushChar)
 | 
						|
      throw new IOException("pushChar called twice.");
 | 
						|
    didPushChar = true;
 | 
						|
    pushedChar = c;
 | 
						|
  }
 | 
						|
}
 |