Back to index

lightning-sunbird  0.9+nobinonly
nsCSSScanner.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   L. David Baron <dbaron@dbaron.org>
00024  *   Daniel Glazman <glazman@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #ifndef nsCSSScanner_h___
00040 #define nsCSSScanner_h___
00041 
00042 #include "nsString.h"
00043 #include "nsCOMPtr.h"
00044 class nsIUnicharInputStream;
00045 
00046 // XXX turn this off for minimo builds
00047 #define CSS_REPORT_PARSE_ERRORS
00048 
00049 // for #ifdef CSS_REPORT_PARSE_ERRORS
00050 #include "nsXPIDLString.h"
00051 class nsIURI;
00052 
00053 // Token types
00054 enum nsCSSTokenType {
00055   // A css identifier (e.g. foo)
00056   eCSSToken_Ident,          // mIdent
00057 
00058   // A css at keyword (e.g. @foo)
00059   eCSSToken_AtKeyword,      // mIdent
00060 
00061   // A css number without a percentage or dimension; with percentage;
00062   // without percentage but with a dimension
00063   eCSSToken_Number,         // mNumber
00064   eCSSToken_Percentage,     // mNumber
00065   eCSSToken_Dimension,      // mNumber + mIdent
00066 
00067   // A css string (e.g. "foo" or 'foo')
00068   eCSSToken_String,         // mSymbol + mIdent + mSymbol
00069 
00070   // Whitespace (e.g. " " or "/* abc */")
00071   eCSSToken_WhiteSpace,     // mIdent
00072 
00073   // A css symbol (e.g. ':', ';', '+', etc.)
00074   eCSSToken_Symbol,         // mSymbol
00075 
00076   // A css1 id (e.g. #foo3)
00077   eCSSToken_ID,             // mIdent
00078   // Just like eCSSToken_ID, except the part following the '#' is not
00079   // a valid CSS identifier (eg. starts with a digit, is the empty
00080   // string, etc).
00081   eCSSToken_Ref,            // mIdent
00082 
00083   eCSSToken_Function,       // mIdent
00084 
00085   eCSSToken_URL,            // mIdent
00086   eCSSToken_InvalidURL,     // doesn't matter
00087 
00088   eCSSToken_HTMLComment,    // "<!--" or "-->"
00089 
00090   eCSSToken_Includes,       // "~="
00091   eCSSToken_Dashmatch,      // "|="
00092   eCSSToken_Beginsmatch,    // "^="
00093   eCSSToken_Endsmatch,      // "$="
00094   eCSSToken_Containsmatch,  // "*="
00095 
00096   // A special token indicating that there was an error in tokenization.
00097   // It's always an unterminated string.
00098   eCSSToken_Error           // mSymbol + mIdent
00099 };
00100 
00101 struct nsCSSToken {
00102   nsCSSTokenType  mType;
00103   PRPackedBool    mIntegerValid;
00104   nsAutoString    mIdent;
00105   float           mNumber;
00106   PRInt32         mInteger;
00107   PRUnichar       mSymbol;
00108 
00109   nsCSSToken();
00110 
00111   PRBool IsDimension() {
00112     return PRBool((eCSSToken_Dimension == mType) ||
00113                   ((eCSSToken_Number == mType) && (mNumber == 0.0f)));
00114   }
00115 
00116   PRBool IsSymbol(PRUnichar aSymbol) {
00117     return PRBool((eCSSToken_Symbol == mType) && (mSymbol == aSymbol));
00118   }
00119 
00120   void AppendToString(nsString& aBuffer);
00121 };
00122 
00123 // CSS Scanner API. Used to tokenize an input stream using the CSS
00124 // forward compatible tokenization rules. This implementation is
00125 // private to this package and is only used internally by the css
00126 // parser.
00127 class nsCSSScanner {
00128   public:
00129   nsCSSScanner();
00130   ~nsCSSScanner();
00131 
00132   // Init the scanner.
00133   // |aLineNumber == 1| is the beginning of a file, use |aLineNumber == 0|
00134   // when the line number is unknown.
00135   void Init(nsIUnicharInputStream* aInput, nsIURI* aURI, PRUint32 aLineNumber);
00136   void Close();
00137 
00138   static PRBool InitGlobals();
00139   static void ReleaseGlobals();
00140 
00141 #ifdef CSS_REPORT_PARSE_ERRORS
00142   NS_HIDDEN_(void) AddToError(const nsSubstring& aErrorText);
00143   NS_HIDDEN_(void) OutputError();
00144   NS_HIDDEN_(void) ClearError();
00145 
00146   // aMessage must take no parameters
00147   NS_HIDDEN_(void) ReportUnexpected(const char* aMessage);
00148   NS_HIDDEN_(void) ReportUnexpectedParams(const char* aMessage,
00149                                           const PRUnichar **aParams,
00150                                           PRUint32 aParamsLength);
00151   // aMessage must take no parameters
00152   NS_HIDDEN_(void) ReportUnexpectedEOF(const char* aLookingFor);
00153   // aMessage must take 1 parameter (for the string representation of the
00154   // unexpected token)
00155   NS_HIDDEN_(void) ReportUnexpectedToken(nsCSSToken& tok,
00156                                          const char *aMessage);
00157   // aParams's first entry must be null, and we'll fill in the token
00158   NS_HIDDEN_(void) ReportUnexpectedTokenParams(nsCSSToken& tok,
00159                                                const char* aMessage,
00160                                                const PRUnichar **aParams,
00161                                                PRUint32 aParamsLength);
00162 #endif
00163 
00164   PRUint32 GetLineNumber() { return mLineNumber; }
00165 
00166   // Get the next token. Return PR_FALSE on EOF. aTokenResult
00167   // is filled in with the data for the token.
00168   PRBool Next(nsresult& aErrorCode, nsCSSToken& aTokenResult);
00169 
00170   // Get the next token that may be a string or unquoted URL or whitespace
00171   PRBool NextURL(nsresult& aErrorCode, nsCSSToken& aTokenResult);
00172 
00173   static inline PRBool
00174   IsIdentStart(PRInt32 aChar, const PRUint8* aLexTable)
00175   {
00176     return aChar >= 0 &&
00177       (aChar >= 256 || (aLexTable[aChar] & START_IDENT) != 0);
00178   }
00179 
00180   static inline PRBool
00181   StartsIdent(PRInt32 aFirstChar, PRInt32 aSecondChar,
00182               const PRUint8* aLexTable)
00183   {
00184     return IsIdentStart(aFirstChar, aLexTable) ||
00185       (aFirstChar == '-' && IsIdentStart(aSecondChar, aLexTable));
00186   }
00187 
00188   static inline const PRUint8* GetLexTable() {
00189     return gLexTable;
00190   }
00191   
00192 protected:
00193   PRInt32 Read(nsresult& aErrorCode);
00194   PRInt32 Peek(nsresult& aErrorCode);
00195   void Unread();
00196   void Pushback(PRUnichar aChar);
00197   PRBool LookAhead(nsresult& aErrorCode, PRUnichar aChar);
00198   PRBool EatWhiteSpace(nsresult& aErrorCode);
00199   PRBool EatNewline(nsresult& aErrorCode);
00200 
00201   void ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput);
00202   PRBool ParseIdent(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
00203   PRBool ParseAtKeyword(nsresult& aErrorCode, PRInt32 aChar,
00204                         nsCSSToken& aResult);
00205   PRBool ParseNumber(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
00206   PRBool ParseRef(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
00207   PRBool ParseString(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aResult);
00208 #if 0
00209   PRBool ParseEOLComment(nsresult& aErrorCode, nsCSSToken& aResult);
00210   PRBool ParseCComment(nsresult& aErrorCode, nsCSSToken& aResult);
00211 #endif
00212   PRBool SkipCComment(nsresult& aErrorCode);
00213 
00214   PRBool GatherIdent(nsresult& aErrorCode, PRInt32 aChar, nsString& aIdent);
00215 
00216   nsCOMPtr<nsIUnicharInputStream> mInput;
00217   PRUnichar* mBuffer;
00218   PRInt32 mOffset;
00219   PRInt32 mCount;
00220   PRUnichar* mPushback;
00221   PRInt32 mPushbackCount;
00222   PRInt32 mPushbackSize;
00223   PRInt32 mLastRead;
00224   PRUnichar mLocalPushback[4];
00225 
00226   PRUint32 mLineNumber;
00227 #ifdef CSS_REPORT_PARSE_ERRORS
00228   nsXPIDLCString mFileName;
00229   nsCOMPtr<nsIURI> mURI;  // Cached so we know to not refetch mFileName
00230   PRUint32 mErrorLineNumber, mColNumber, mErrorColNumber;
00231   nsFixedString mError;
00232   PRUnichar mErrorBuf[200];
00233 #endif
00234 
00235   static const PRUint8 IS_DIGIT;
00236   static const PRUint8 IS_HEX_DIGIT;
00237   static const PRUint8 START_IDENT;
00238   static const PRUint8 IS_IDENT;
00239   static const PRUint8 IS_WHITESPACE;
00240 
00241   static PRUint8 gLexTable[256];
00242   static void BuildLexTable();
00243   static PRBool CheckLexTable(PRInt32 aChar, PRUint8 aBit, PRUint8* aLexTable);
00244 };
00245 
00246 #endif /* nsCSSScanner_h___ */