1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443 |
- /* -*-java-extended-*-
- * Copyright (c) 1999 World Wide Web Consortium
- * (Massachusetts Institute of Technology, Institut National de Recherche
- * en Informatique et en Automatique, Keio University).
- * All Rights Reserved. http://www.w3.org/Consortium/Legal/
- *
- * $Id: Parser.jj,v 1.15 2000/10/27 21:09:37 plehegar Exp $
- */
-
- options {
- IGNORE_CASE = true;
- STATIC = false;
- USER_CHAR_STREAM = true;
- /* DEBUG_TOKEN_MANAGER = true;
- DEBUG_PARSER = true; */
- }
-
- PARSER_BEGIN(Parser)
-
- package com.vaadin.sass.parser;
-
- import java.io.*;
- import java.net.*;
- import java.util.ArrayList;
- import java.util.Locale;
- import java.util.Map;
-
- import org.w3c.css.sac.ConditionFactory;
- import org.w3c.css.sac.Condition;
- import org.w3c.css.sac.SelectorFactory;
- import org.w3c.css.sac.SelectorList;
- import org.w3c.css.sac.Selector;
- import org.w3c.css.sac.SimpleSelector;
- import org.w3c.css.sac.DocumentHandler;
- import org.w3c.css.sac.InputSource;
- import org.w3c.css.sac.ErrorHandler;
- import org.w3c.css.sac.CSSException;
- import org.w3c.css.sac.CSSParseException;
- import org.w3c.css.sac.Locator;
- import org.w3c.css.sac.LexicalUnit;
-
- import org.w3c.flute.parser.selectors.SelectorFactoryImpl;
- import org.w3c.flute.parser.selectors.ConditionFactoryImpl;
-
- import org.w3c.flute.util.Encoding;
-
- import com.vaadin.sass.handler.*;
-
- import com.vaadin.sass.tree.*;
-
- /**
- * A CSS2 parser
- *
- * @author Philippe Le H�garet
- * @version $Revision: 1.15 $
- */
- public class Parser implements org.w3c.css.sac.Parser {
-
- // replaces all \t, \n, etc with this StringBuffer.
- static final StringBuilder SPACE = new StringBuilder(" ");
-
- // the document handler for the parser
- protected SCSSDocumentHandlerImpl documentHandler;
- // the error handler for the parser
- protected ErrorHandler errorHandler;
- // the input source for the parser
- protected InputSource source;
-
- protected ConditionFactory conditionFactory;
- protected SelectorFactory selectorFactory;
-
- // temporary place holder for pseudo-element ...
- private String pseudoElt;
-
- /**
- * Creates a new Parser
- */
- public Parser() {
- this((CharStream) null);
- }
-
- /**
- * @@TODO
- * @exception CSSException Not yet implemented
- */
- public void setLocale(Locale locale) throws CSSException {
- throw new CSSException(CSSException.SAC_NOT_SUPPORTED_ERR);
- }
-
- /**
- * Set the document handler for this parser
- */
- public void setDocumentHandler(DocumentHandler handler) {
- this.documentHandler = (SCSSDocumentHandlerImpl) handler;
- }
-
- public void setSelectorFactory(SelectorFactory selectorFactory) {
- this.selectorFactory = selectorFactory;
- }
-
- public void setConditionFactory(ConditionFactory conditionFactory) {
- this.conditionFactory = conditionFactory;
- }
-
- /**
- * Set the error handler for this parser
- */
- public void setErrorHandler(ErrorHandler error) {
- this.errorHandler = error;
- }
-
- /**
- * Main parse methods
- *
- * @param source the source of the style sheet.
- * @exception IOException the source can't be parsed.
- * @exception CSSException the source is not CSS valid.
- */
- public void parseStyleSheet(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
-
- parserUnit();
- }
-
- /**
- * Convenient method for URIs.
- *
- * @param systemId the fully resolved URI of the style sheet.
- * @exception IOException the source can't be parsed.
- * @exception CSSException the source is not CSS valid.
- */
- public void parseStyleSheet(String systemId)
- throws CSSException, IOException {
- parseStyleSheet(new InputSource(systemId));
- }
-
- /**
- * This method parses only one rule (style rule or at-rule, except @charset).
- *
- * @param source the source of the rule.
- * @exception IOException the source can't be parsed.
- * @exception CSSException the source is not CSS valid.
- */
- public void parseRule(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
- _parseRule();
- }
-
- /**
- * This method parses a style declaration (including the surrounding curly
- * braces).
- *
- * @param source the source of the style declaration.
- * @exception IOException the source can't be parsed.
- * @exception CSSException the source is not CSS valid.
- */
- public void parseStyleDeclaration(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
- _parseDeclarationBlock();
- }
-
- /**
- * This methods returns "http://www.w3.org/TR/REC-CSS2".
- * @return the string "http://www.w3.org/TR/REC-CSS2".
- */
- public String getParserVersion() {
- return "http://www.w3.org/TR/REC-CSS2";
- }
-
- /**
- * Parse methods used by DOM Level 2 implementation.
- */
- public void parseImportRule(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
- _parseImportRule();
- }
-
- public void parseMediaRule(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
- _parseMediaRule();
- }
-
- public SelectorList parseSelectors(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- if (selectorFactory == null) {
- selectorFactory = new SelectorFactoryImpl();
- }
- if (conditionFactory == null) {
- conditionFactory = new ConditionFactoryImpl();
- }
- return _parseSelectors();
- }
-
- public LexicalUnit parsePropertyValue(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- return expr();
- }
-
- public boolean parsePriority(InputSource source)
- throws CSSException, IOException {
- this.source = source;
- ReInit(getCharStreamWithLurk(source));
-
- return prio();
- }
-
- /**
- * Convert the source into a Reader. Used only by DOM Level 2 parser methods.
- */
- private Reader getReader(InputSource source) throws IOException {
- if (source.getCharacterStream() != null) {
- return source.getCharacterStream();
- } else if (source.getByteStream() != null) {
- // My DOM level 2 implementation doesn't use this case.
- if (source.getEncoding() == null) {
- // unknown encoding, use ASCII as default.
- return new InputStreamReader(source.getByteStream(), "ASCII");
- } else {
- return new InputStreamReader(source.getByteStream(),
- source.getEncoding());
- }
- } else {
- // systemId
- // @@TODO
- throw new CSSException("not yet implemented");
- }
- }
-
- /**
- * Convert the source into a CharStream with encoding informations.
- * The encoding can be found in the InputSource or in the CSS document.
- * Since this method marks the reader and make a reset after looking for
- * the charset declaration, you'll find the charset declaration into the
- * stream.
- */
- private CharStream getCharStreamWithLurk(InputSource source)
- throws CSSException, IOException {
- if (source.getCharacterStream() != null) {
- // all encoding are supposed to be resolved by the user
- // return the reader
- return new Generic_CharStream(source.getCharacterStream(), 1, 1);
- } else if (source.getByteStream() == null) {
- // @@CONTINUE ME. see also getReader() with systemId
- try {
- source.setByteStream(new URL(source.getURI()).openStream());
- } catch (Exception e) {
- try {
- source.setByteStream(new FileInputStream(source.getURI()));
- } catch (IOException ex) {
- throw new CSSException("invalid url ?");
- }
- }
- }
- String encoding = "ASCII";
- InputStream input = source.getByteStream();
- char c = ' ';
-
- if (!input.markSupported()) {
- input = new BufferedInputStream(input);
- source.setByteStream(input);
- }
- input.mark(100);
- c = (char) input.read();
-
- if (c == '@') {
- // hum, is it a charset ?
- int size = 100;
- byte[] buf = new byte[size];
- input.read(buf, 0, 7);
- String keyword = new String(buf, 0, 7);
- if (keyword.equals("charset")) {
- // Yes, this is the charset declaration !
-
- // here I don't use the right declaration : white space are ' '.
- while ((c = (char) input.read()) == ' ') {
- // find the first quote
- }
- char endChar = c;
- int i = 0;
-
- if ((endChar != '"') && (endChar != '\'')) {
- // hum this is not a quote.
- throw new CSSException("invalid charset declaration");
- }
-
- while ((c = (char) input.read()) != endChar) {
- buf[i++] = (byte) c;
- if (i == size) {
- byte[] old = buf;
- buf = new byte[size + 100];
- System.arraycopy(old, 0, buf, 0, size);
- size += 100;
- }
- }
- while ((c = (char) input.read()) == ' ') {
- // find the next relevant character
- }
- if (c != ';') {
- // no semi colon at the end ?
- throw new CSSException("invalid charset declaration: "
- + "missing semi colon");
- }
- encoding = new String(buf, 0, i);
- if (source.getEncoding() != null) {
- // compare the two encoding informations.
- // For example, I don't accept to have ASCII and after UTF-8.
- // Is it really good ? That is the question.
- if (!encoding.equals(source.getEncoding())) {
- throw new CSSException("invalid encoding information.");
- }
- }
- } // else no charset declaration available
- }
- // ok set the real encoding of this source.
- source.setEncoding(encoding);
- // set the real reader of this source.
- source.setCharacterStream(new InputStreamReader(source.getByteStream(),
- Encoding.getJavaEncoding(encoding)));
- // reset the stream (leave the charset declaration in the stream).
- input.reset();
-
- return new Generic_CharStream(source.getCharacterStream(), 1, 1);
- }
-
- private LocatorImpl currentLocator;
- private Locator getLocator() {
- if (currentLocator == null) {
- currentLocator = new LocatorImpl(this);
- return currentLocator;
- }
- return currentLocator.reInit(this);
- }
- private LocatorImpl getLocator(Token save) {
- if (currentLocator == null) {
- currentLocator = new LocatorImpl(this, save);
- return currentLocator;
- }
- return currentLocator.reInit(this, save);
- }
-
- private void reportError(Locator l, Exception e) {
- if (errorHandler != null) {
- if (e instanceof ParseException) {
- // construct a clean error message.
- ParseException pe = (ParseException) e;
- if (pe.specialConstructor) {
- StringBuffer errorM = new StringBuffer();
- if (pe.currentToken != null) {
- errorM.append("encountered \"")
- .append(pe.currentToken.next);
- }
- errorM.append('"');
- if (pe.expectedTokenSequences.length != 0) {
- errorM.append(". Was expecting one of: ");
- for (int i = 0; i < pe.expectedTokenSequences.length; i++) {
- for (int j = 0; j < pe.expectedTokenSequences[i].length; j++) {
- int kind = pe.expectedTokenSequences[i][j];
- if (kind != S) {
- errorM.append(pe.tokenImage[kind]);
- errorM.append(' ');
- }
- }
- }
- }
- errorHandler.error(new CSSParseException(errorM.toString(),
- l, e));
- } else {
- errorHandler.error(new CSSParseException(e.getMessage(),
- l, e));
- }
- } else if (e == null) {
- errorHandler.error(new CSSParseException("error", l, null));
- } else {
- errorHandler.error(new CSSParseException(e.getMessage(), l, e));
- }
- }
- }
-
- private void reportWarningSkipText(Locator l, String text) {
- if (errorHandler != null && text != null) {
- errorHandler.warning(new CSSParseException("Skipping: " + text, l));
- }
- }
- }
-
- PARSER_END(Parser)
-
- /*
- * The tokenizer
- */
-
- <DEFAULT>
- TOKEN :
- {
- < S : ( [ " ", "\t" , "\n" , "\r", "\f" ] )+ >
- { image = Parser.SPACE; }
- }
-
- <DEFAULT>
- MORE:
- {
- "#{" : IN_INTERPOLATION
- }
-
- <IN_INTERPOLATION>
- MORE:
- {
- < ~["}"]> : IN_INTERPOLATION
- }
-
- <IN_INTERPOLATION>
- SPECIAL_TOKEN:
- {
- <INTERPOLATION: "}"> : DEFAULT
- }
-
- <DEFAULT>
- MORE :
- {
- "//" : IN_SINGLE_LINE_COMMENT
- }
-
- <IN_SINGLE_LINE_COMMENT>
- MORE :
- {
- < ~["\n","\r"] > : IN_SINGLE_LINE_COMMENT
- }
-
- <IN_SINGLE_LINE_COMMENT>
- SKIP :
- {
- < "\n"|"\r"|"\r\n" > : DEFAULT
- }
-
-
- <DEFAULT>
- MORE :
- {
- <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
- |
- "/*" : IN_MULTI_LINE_COMMENT
- }
- <IN_FORMAL_COMMENT>
- SPECIAL_TOKEN :
- {
- <FORMAL_COMMENT: "*/" > : DEFAULT
- }
-
- <IN_MULTI_LINE_COMMENT>
- SKIP :
- {
- <MULTI_LINE_COMMENT: "*/" > : DEFAULT
- }
-
- <IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
- MORE :
- {
- < ~[] >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < CDO : "<!--" >
- | < CDC : "-->" >
- | < LBRACE : "{" >
- | < RBRACE : "}">
- | < DASHMATCH : "|=" >
- | < INCLUDES : "~=" >
- | < EQ : "=" >
- | < PLUS : "+" >
- | < MINUS : "-" >
- | < COMMA : "," >
- | < SEMICOLON : ";" >
- | < PRECEDES : ">" >
- | < DIV : "/" >
- | < LBRACKET : "[" >
- | < RBRACKET : "]" >
- | < ANY : "*" >
- | < PARENT : "&" >
- | < DOT : "." >
- | < LPARAN : "(" >
- | < RPARAN : ")">
- }
-
- <DEFAULT>
- TOKEN :
- {
- < COLON : ":" >
- }
-
- <DEFAULT>
- TOKEN : /* basic tokens */
- {
- < NONASCII : ["\200"-"\377"] >
- | < #H : ["0"-"9", "a"-"f"] >
- | < #UNICODE : "\\" <H> ( <H> )? /* I can't say {1,6} */
- ( <H> )? ( <H> )?
- ( <H> )? ( <H> )?
- ( [ " ", "\t" , "\n" , "\r", "\f" ] )? >
- | < #ESCAPE : <UNICODE> | ( "\\" [ " "-"~","\200"-"\377" ] ) >
- | < #NMSTART : ("-")?[ "a"-"z"] | <NONASCII> | <ESCAPE> >
- | < #NMCHAR : ["a"-"z", "0"-"9", "-", "_"] | <NONASCII> | <ESCAPE> >
- | < #STRINGCHAR : [ "\t"," ","!","#","$","%","&","("-"~" ]
- | "\\\n" | "\\\r\n" | "\\\r" | "\\\f"
- | <NONASCII> | <ESCAPE> >
- | < #D : ["0"-"9"] >
- | < #NAME : ( <NMCHAR> )+ >
- }
-
-
- <DEFAULT>
- TOKEN :
- {
- <TO : "to">
- |<THROUGH : "through">
- |<EACH_IN : "in">
- }
-
- /* DERECTIVES */
- <DEFAULT>
- TOKEN :
- {
- <MIXIN_SYM : "@mixin">
- | <INCLUDE_SYM : "@include">
- | <FUNCTION_SYM : "@function">
- | <RETURN_SYM : "@return">
- | <DEBUG_SYM : "@debug">
- | <WARN_SYM : "@warn">
- | <FOR_SYM : "@for">
- | <EACH_SYM : "@each">
- | <WHILE_SYM : "@while">
- | <IF_SYM : "@if">
- | <ELSE_SYM : "@else">
- | <EXTEND_SYM : "@extend">
- | <MOZ_DOCUMENT_SYM : "@-moz-document">
- | <SUPPORTS_SYM : "@supports">
- }
-
- <DEFAULT>
- TOKEN:
- {
- < GUARDED_SYM : "!" ( <S> )? "default">
- }
-
- <DEFAULT>
- TOKEN :
- {
- < STRING : ( "\"" ( <STRINGCHAR> | "'" )* "\"" ) |
- ( "'" ( <STRINGCHAR> | "\"" )* "'" ) >
- | < IDENT : <NMSTART> ( <NMCHAR> )* >
- | < NUMBER : ( <D> )+ | ( <D> )* "." ( <D> )+ >
- | < #_URL : [ "!","#","$","%","&","*"-"~" ] | <NONASCII> | <ESCAPE> >
- | < URL : "url(" ( <S> )*
- ( <STRING> | ( <_URL> )* ) ( <S> )* ")" >
- }
-
- <DEFAULT>
- TOKEN:
- {
- < VARIABLE : "$" <IDENT>>
- }
-
- <DEFAULT>
- TOKEN :
- {
- < PERCENTAGE : <NUMBER> "%" >
- | < PT : <NUMBER> "pt" >
- | < MM : <NUMBER> "mm" >
- | < CM : <NUMBER> "cm" >
- | < PC : <NUMBER> "pc" >
- | < IN : <NUMBER> "in" >
- | < PX : <NUMBER> "px" >
- | < EMS : <NUMBER> "em" >
- | < EXS : <NUMBER> "ex" >
- | < DEG : <NUMBER> "deg" >
- | < RAD : <NUMBER> "rad" >
- | < GRAD : <NUMBER> "grad" >
- | < MS : <NUMBER> "ms" >
- | < SECOND : <NUMBER> "s" >
- | < HZ : <NUMBER> "Hz" >
- | < KHZ : <NUMBER> "kHz" >
- | < DIMEN : <NUMBER> <IDENT> >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < HASH : "#" <NAME> >
- }
-
- /* RESERVED ATRULE WORDS */
- <DEFAULT>
- TOKEN :
- {
- < IMPORT_SYM : "@import">
- | < MEDIA_SYM : "@media" >
- | < CHARSET_SYM : "@charset" >
- | < PAGE_SYM : "@page" >
- | < FONT_FACE_SYM: "@font-face" >
- | < ATKEYWORD : "@" <IDENT> >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < IMPORTANT_SYM : "!" ( <S> )? "important" >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < #RANGE0 : <H> <H> <H> <H> <H> >
- | < #RANGE1 : <H> <H> <H> <H> <H> ( "?" )? >
- | < #RANGE2 : <H> <H> <H> <H> ( "?" )? ( "?" )? >
- | < #RANGE3 : <H> <H> <H> ( "?" )? ( "?" )? ( "?" )? >
- | < #RANGE4 : <H> <H> ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
- | < #RANGE5 : <H> ( "?" )? ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
- | < #RANGE6 : "?" ( "?" )? ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
- | < #RANGE : <RANGE0> | <RANGE1> | <RANGE2>
- | <RANGE3> | <RANGE4> | <RANGE5> | <RANGE6> >
- | < #UNI : <H> ( <H> )? ( <H> )? ( <H> )? ( <H> )? ( <H> )? >
- | < UNICODERANGE : "U+" <RANGE>
- | "U+" <UNI> "-" <UNI> >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < FUNCTION : <IDENT> "(" >
- }
-
- <DEFAULT, IN_MULTI_LINE_COMMENT>
- TOKEN :
- { /* avoid token manager error */
- < UNKNOWN : ~[] >
- }
-
- /*
- * The grammar of CSS2
- */
-
- /**
- * The main entry for the parser.
- *
- * @exception ParseException exception during the parse
- */
- void parserUnit() :
- {}
- {
- try {
- { documentHandler.startDocument(source); }
- ( charset() )?
- ( <S> | ignoreStatement() )*
- ( importDeclaration() ( ignoreStatement() ( <S> )* )* )*
- afterImportDeclaration()
- <EOF>
- } finally {
- documentHandler.endDocument(source);
- }
- }
-
- void charset() :
- { Token n; }
- {
- try {
- <CHARSET_SYM> ( <S> )* n=<STRING> ( <S> )* ";"
- } catch (ParseException e) {
- reportError(getLocator(e.currentToken.next), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- } catch (Exception e) {
- reportError(getLocator(), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- }
- }
-
- void afterImportDeclaration() :
- {String ret;
- Locator l;
- }
- {
- ( ( variable() | mixinDirective() | includeDirective() | styleRule() | media()| page() | fontFace()
- | { l = getLocator(); } ret=skipStatement()
- {
- if ((ret == null) || (ret.length() == 0)) {
- return;
- }
- reportWarningSkipText(l, ret);
- if (ret.charAt(0) == '@') {
- documentHandler.ignorableAtRule(ret);
- }
- }
- )
- ( ignoreStatement() ( <S> )* )* )*
- }
-
- void ignoreStatement() :
- {}
- {
- <CDO> | <CDC> | atRuleDeclaration()
- }
-
- /**
- * The import statement
- *
- * @exception ParseException exception during the parse
- */
- void importDeclaration() :
- {Token n;
- String uri;
- MediaListImpl ml = new MediaListImpl();
- boolean isURL = false;
- }
- {
- try {
- <IMPORT_SYM>
- ( <S> )* ( n=<STRING> { uri = convertStringIndex(n.image, 1,
- n.image.length() -1); }
- | n=<URL>
- {
- isURL=true;
- uri = n.image.substring(4, n.image.length()-1).trim();
- if ((uri.charAt(0) == '"')
- || (uri.charAt(0) == '\'')) {
- uri = uri.substring(1, uri.length()-1);
- }
- }
- )
- ( <S> )* ( mediaStatement(ml) )? ";"
- ( <S> )*
- {
- if (ml.getLength() == 0) {
- // see section 6.3 of the CSS2 recommandation.
- ml.addItem("all");
- }
- documentHandler.importStyle(uri, ml, isURL);
- }
- } catch (ParseException e) {
- reportError(getLocator(), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- void media() :
- {
- boolean start = false;
- String ret;
- MediaListImpl ml = new MediaListImpl();
- }
- {
- try {
- <MEDIA_SYM> ( <S> )*
- mediaStatement(ml)
- { start = true; documentHandler.startMedia(ml); }
- <LBRACE> ( <S> )* ( styleRule() | skipUnknownRule() )* <RBRACE> ( <S> )*
- } catch (ParseException e) {
- reportError(getLocator(), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- } finally {
- if (start) {
- documentHandler.endMedia(ml);
- }
- }
- }
-
- void mediaStatement(MediaListImpl ml) :
- {
- String m;
- }
- {
- m=medium() ( <COMMA> ( <S> )* { ml.addItem(m); } m=medium() )*
- { ml.addItem(m); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String medium() : /* tv, projection, screen, ... */
- {Token n;}
- {
- n=<IDENT> ( <S> )* { return convertIdent(n.image); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- void page() :
- {
- boolean start = false;
- Token n = null;
- String page = null;
- String pseudo = null;
- }
- {
- try {
- <PAGE_SYM> ( <S> )* ( n=<IDENT> ( <S> )* )?
- ( pseudo=pseudo_page() )?
- {
- if (n != null) {
- page = convertIdent(n.image);
- }
- }
- <LBRACE> (<S>)*
- {
- start = true;
- documentHandler.startPage(page, pseudo);
- }
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- <RBRACE> (<S>)*
- } catch (ParseException e) {
- if (errorHandler != null) {
- LocatorImpl li = new LocatorImpl(this,
- e.currentToken.next.beginLine,
- e.currentToken.next.beginColumn-1);
- reportError(li, e);
- skipStatement();
- // reportWarningSkipText(li, skipStatement());
- } else {
- skipStatement();
- }
- } finally {
- if (start) {
- documentHandler.endPage(page, pseudo);
- }
- }
- }
-
- String pseudo_page() :
- { Token n; }
- {
- ":" n=<IDENT> ( <S> )* { return convertIdent(n.image); }
- }
-
- void fontFace() :
- {
- boolean start = false;
- }
- {
- try {
- <FONT_FACE_SYM> ( <S> )*
- <LBRACE> (<S>)*
- { start = true; documentHandler.startFontFace(); }
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- <RBRACE> (<S>)*
- } catch (ParseException e) {
- reportError(getLocator(), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- } finally {
- if (start) {
- documentHandler.endFontFace();
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- void atRuleDeclaration() :
- {Token n;
- String ret;
- }
- {
- n=<ATKEYWORD>
- {
- ret=skipStatement();
- reportWarningSkipText(getLocator(), ret);
- if ((ret != null) && (ret.charAt(0) == '@')) {
- documentHandler.ignorableAtRule(ret);
- }
- }
- }
-
- void skipUnknownRule() :
- { Token n;}
- {
- ( n=<ATKEYWORD>
- | n=<CDO>
- | n=<CHARSET_SYM>
- | n=<COMMA>
- | n=<DASHMATCH>
- | n=<FONT_FACE_SYM>
- | n=<FUNCTION>
- | n=<IMPORTANT_SYM>
- | n=<IMPORT_SYM>
- | n=<INCLUDES>
- | n=<LBRACE>
- | n=<MEDIA_SYM>
- | n=<NONASCII>
- | n=<NUMBER>
- | n=<PAGE_SYM>
- | n=<PERCENTAGE>
- | n=<STRING>
- | n=<UNICODERANGE>
- | n=<URL>
- | n=";"
- | n="+"
- | n=">"
- | n="-"
- | n=<UNKNOWN>
- ) {
- String ret;
- Locator loc = getLocator();
- ret=skipStatement();
- reportWarningSkipText(loc, ret);
- if ((ret != null) && (n.image.charAt(0) == '@')) {
- documentHandler.ignorableAtRule(ret);
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- char combinator() :
- {
- char connector = ' ';
- }
- {
- "+" ( <S> )* { return '+'; }
- | ">" ( <S> )* { return '>'; }
- | <S> ( ( "+" { connector = '+'; }
- | ">" { connector = '>'; } )
- ( <S> )* )? { return connector; }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String property() :
- {Token n; }
- {
- n=<IDENT> ( <S> )* { return convertIdent(n.image); }
- }
-
- String variableName() :
- {Token n;}
- {
- n=<VARIABLE> (<S>)* {return convertIdent(n.image.substring(1));}
- }
-
- String functionName() :
- {Token n;}
- {
- n=<FUNCTION> ( <S> )* {return convertIdent(n.image.substring(0, n.image.length()-1));}
- }
- /**
- * @exception ParseException exception during the parse
- */
- void styleRule() :
- {
- boolean start = false;
- SelectorList l = null;
- Token save;
- Locator loc;
- }
- {
- try {
- l=selectorList() { save = token; } <LBRACE> (<S>)*
- {
- start = true;
- documentHandler.startSelector(l);
- }
- ( includeDirective() | media() | extendDirective()| variable() | LOOKAHEAD(3) declarationOrNestedProperties() | styleRule())*
- <RBRACE> (<S>)*
- } catch (ThrowedParseException e) {
- if (errorHandler != null) {
- LocatorImpl li = new LocatorImpl(this,
- e.e.currentToken.next.beginLine,
- e.e.currentToken.next.beginColumn-1);
- reportError(li, e.e);
- }
- } catch (ParseException e) {
- reportError(getLocator(), e);
- skipStatement();
- // reportWarningSkipText(getLocator(), skipStatement());
- } catch (TokenMgrError e) {
- reportWarningSkipText(getLocator(), skipStatement());
- } finally {
- if (start) {
- documentHandler.endSelector(l);
- }
- }
- }
-
- SelectorList selectorList() :
- {
- SelectorListImpl selectors = new SelectorListImpl();
- Selector selector;
- }
- {
- selector=selector() ( <COMMA> (<S>)* { selectors.addSelector(selector); }
- selector=selector() )*
- { selectors.addSelector(selector);
- return selectors;
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Selector selector() :
- {
- Selector selector;
- char comb;
- }
- {
- try {
- selector=simple_selector(null, ' ')
- ( LOOKAHEAD(2) comb=combinator()
- selector=simple_selector(selector, comb) )* (<S>)*
- {
- return selector;
- }
- } catch (ParseException e) {
- /*
- Token t = getToken(1);
- StringBuffer s = new StringBuffer();
- s.append(getToken(0).image);
- while ((t.kind != COMMA) && (t.kind != SEMICOLON)
- && (t.kind != LBRACE) && (t.kind != EOF)) {
- s.append(t.image);
- getNextToken();
- t = getToken(1);
- }
- reportWarningSkipText(getLocator(), s.toString());
- */
- Token t = getToken(1);
- while ((t.kind != COMMA) && (t.kind != SEMICOLON)
- && (t.kind != LBRACE) && (t.kind != EOF)) {
- getNextToken();
- t = getToken(1);
- }
-
- throw new ThrowedParseException(e);
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Selector simple_selector(Selector selector, char comb) :
- {
- SimpleSelector simple_current = null;
- Condition cond = null;
-
- pseudoElt = null;
- }
- {
- ( simple_current=element_name()
- ( cond=hash(cond) | cond=_class(cond)
- | cond=attrib(cond) | cond=pseudo(cond) )*
- | cond=hash(cond) ( cond=_class(cond)
- | cond=attrib(cond) | cond=pseudo(cond) )*
- | cond=_class(cond) ( cond=hash(cond) | cond=_class(cond)
- | cond=attrib(cond) | cond=pseudo(cond) )*
- | cond=pseudo(cond) ( cond=hash(cond) | cond=_class(cond)
- | cond=attrib(cond) | cond=pseudo(cond) )*
- | cond=attrib(cond) ( cond=hash(cond) | cond=_class(cond)
- | cond=attrib(cond) | cond=pseudo(cond) )*
- )
- {
- if (simple_current == null) {
- simple_current = selectorFactory.createElementSelector(null, null);
- }
- if (cond != null) {
- simple_current = selectorFactory.createConditionalSelector(simple_current,
- cond);
- }
- if (selector != null) {
- switch (comb) {
- case ' ':
- selector = selectorFactory.createDescendantSelector(selector,
- simple_current);
- break;
- case '+':
- selector =
- selectorFactory.createDirectAdjacentSelector((short) 1,
- selector,
- simple_current);
- break;
- case '>':
- selector = selectorFactory.createChildSelector(selector,
- simple_current);
- break;
- default:
- throw new ParseException("invalid state. send a bug report");
- }
- } else {
- selector= simple_current;
- }
- if (pseudoElt != null) {
- selector = selectorFactory.createChildSelector(selector,
- selectorFactory.createPseudoElementSelector(null, pseudoElt));
- }
- return selector;
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Condition _class(Condition pred) :
- {Token n;
- Condition c;
- }
- {
- "." n=<IDENT>
- {
- c = conditionFactory.createClassCondition(null, n.image);
- if (pred == null) {
- return c;
- } else {
- return conditionFactory.createAndCondition(pred, c);
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- SimpleSelector element_name() :
- {Token n; }
- {
- n=<IDENT>
- {
- return selectorFactory.createElementSelector(null, convertIdent(n.image));
- }
- | "*"
- { return selectorFactory.createElementSelector(null, "*"); }
- | "&"
- { return selectorFactory.createElementSelector(null, "&"); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Condition attrib(Condition pred) :
- {
- int cases = 0;
- Token att = null;
- Token val = null;
- String attValue = null;
- }
- {
- "[" ( <S> )* att=<IDENT> ( <S> )*
- ( ( "=" { cases = 1; }
- | <INCLUDES> { cases = 2; }
- | <DASHMATCH> { cases = 3; } ) ( <S> )*
- ( val=<IDENT> { attValue = val.image; }
- | val=<STRING> { attValue = convertStringIndex(val.image, 1,
- val.image.length() -1);}
- )
- ( <S> )* )?
- "]"
- {
- String name = convertIdent(att.image);
- Condition c;
- switch (cases) {
- case 0:
- c = conditionFactory.createAttributeCondition(name, null, false, null);
- break;
- case 1:
- c = conditionFactory.createAttributeCondition(name, null, false,
- attValue);
- break;
- case 2:
- c = conditionFactory.createOneOfAttributeCondition(name, null, false,
- attValue);
- break;
- case 3:
- c = conditionFactory.createBeginHyphenAttributeCondition(name, null,
- false,
- attValue);
- break;
- default:
- // never reached.
- c = null;
- }
- if (pred == null) {
- return c;
- } else {
- return conditionFactory.createAndCondition(pred, c);
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Condition pseudo(Condition pred) :
- {Token n;
- Token language;
- boolean isPseudoElement = false;
- }
- {
- ":" (":"{isPseudoElement=true;})?( n=<IDENT>
- {
- String s = convertIdent(n.image);
- if (isPseudoElement) {
- if (pseudoElt != null) {
- throw new CSSParseException("duplicate pseudo element definition "
- + s, getLocator());
- } else {
- pseudoElt = s;
- return pred;
- }
- } else {
- Condition c =
- conditionFactory.createPseudoClassCondition(null, s);
- if (pred == null) {
- return c;
- } else {
- return conditionFactory.createAndCondition(pred, c);
- }
- }
- }
- | ( n=<FUNCTION> ( <S> )* language=<IDENT> ( <S> )* ")"
- {
- String f = convertIdent(n.image);
- if (f.equals("lang(")) {
- Condition d =
- conditionFactory.createLangCondition(convertIdent(language.image));
- if (pred == null) {
- return d;
- } else {
- return conditionFactory.createAndCondition(pred, d);
- }
- } else {
- throw new CSSParseException("invalid pseudo function name "
- + f, getLocator());
- }
- }
- )
- )
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- Condition hash(Condition pred) :
- {Token n; }
- {
- n=<HASH>
- {
- Condition d =
- conditionFactory.createIdCondition(n.image.substring(1));
- if (pred == null) {
- return d;
- } else {
- return conditionFactory.createAndCondition(pred, d);
- }
- }
- }
-
- void variable() :
- {
- String name;
- LexicalUnit exp = null;
- boolean guarded = false;
- String raw;
- }
- {
- try{
- name = variableName()
- ":" ( <S> )* exp=expr() ( guarded=guarded() )?(";"(<S>)*)+
- //raw=skipStatementUntilSemiColon()
- {
- documentHandler.variable(name, exp, guarded);
- }
- }catch (JumpException e) {
- skipAfterExpression();
- } catch (NumberFormatException e) {
- if (errorHandler != null) {
- errorHandler.error(new CSSParseException("Invalid number "
- + e.getMessage(),
- getLocator(),
- e));
- }
- reportWarningSkipText(getLocator(), skipAfterExpression());
- } catch (ParseException e) {
- if (errorHandler != null) {
- if (e.currentToken != null) {
- LocatorImpl li = new LocatorImpl(this,
- e.currentToken.next.beginLine,
- e.currentToken.next.beginColumn-1);
- reportError(li, e);
- } else {
- reportError(getLocator(), e);
- }
- skipAfterExpression();
- } else {
- skipAfterExpression();
- }
- }
- }
-
- void mixinDirective() :
- {
- String name;
- ArrayList<VariableNode> args = null;
- String body;
- }
- {
- <MIXIN_SYM>
- (<S>)*
- (name = property()
- |(name = functionName()
- args = arglist()) <RPARAN> (<S>)*) <LBRACE> (<S>)*
- {documentHandler.startMixinDirective(name, args);}
- ( includeDirective() | media() | extendDirective()| variable() | LOOKAHEAD(3) declarationOrNestedProperties() | styleRule())*
- //(includeDirective() | media() | LOOKAHEAD(declaration()) declaration()";"(<S>)* | styleRule())*
- <RBRACE>(<S>)*
- {documentHandler.endMixinDirective(name, args);}
- }
-
- ArrayList<VariableNode> arglist() :
- {
- ArrayList<VariableNode> args = new ArrayList<VariableNode>();
- VariableNode arg;
- }
- {
- arg=mixinArg() ( <COMMA> (<S>)* { args.add(arg); }
- arg=mixinArg() )*
- { args.add(arg);
- return args;
- }
- }
-
- VariableNode mixinArg() :
- {
- String name;
- LexicalUnit value = null;
- }
- {
- name=variableName() (":" (<S>)* value=term(null) )?
- {
- VariableNode arg = new VariableNode(name, value, false);
- return arg;
- }
- }
-
- ArrayList<LexicalUnit> argValuelist() :
- {
- ArrayList<LexicalUnit> args = new ArrayList<LexicalUnit>();
- LexicalUnit argValue;
- }
- {
- argValue= term(null) { args.add(argValue); }
- ( <COMMA> (<S>)* argValue = term(null)
- {args.add(argValue);}
- )*
- {return args;}
- }
-
- void includeDirective() :
- {
- String name;
- ArrayList<LexicalUnit> args=null;
- }
- {
- <INCLUDE_SYM>
- (<S>)*
- (name = property()
- |(name = functionName()
- args = argValuelist()) <RPARAN>)(";"(<S>)*)+
- {documentHandler.includeDirective(name, args);}
- }
-
- Node functionDirective() :
- {
- String name;
- String args = null;
- String body;
- int[] stops = {RPARAN};
- }
- {
- (name=functionName() args = skipStatementUntilRightParan() <RPARAN>)
- (<S>)*
- body = skipStatement()
- {
- return null;
- }
- }
-
- Node returnDirective() :
- {
- String raw;
- }
- {
- raw = skipStatement()
- {return null;}
- }
-
- JAVACODE
- void debugDirective(){
- }
-
- JAVACODE
- void warnDirective(){
- }
-
- Node forDirective() :
- {
- String var;
- String from;
- String to;
- boolean exclusive;
- String body;
- Token tok;
- }
- {
- var = variableName()
- {
- int[] toThrough = {TO, THROUGH};
- from = skipStatementUntil(toThrough);
- }
- (tok = <TO> {exclusive = true;}
- | tok = <THROUGH> {exclusive = false;})
- to = skipStatementUntilLeftBrace()
- (<S>)*
- body = skipStatement()
- {return documentHandler.forDirective(var, from, to, exclusive, body);}
- }
-
- Node eachDirective() :
- {
- String var;
- String list;
- String body;
- }
- {
- var = variableName()
- <EACH_IN> (<S>)*
- list = skipStatementUntilLeftBrace()
- body = skipStatement()
- {
- return documentHandler.eachDirective(var, list, body);
- }
- }
-
- Node whileDirective() :
- {
- String condition;
- String body;
- }
- {
- condition = skipStatementUntilLeftBrace()
- body = skipStatement()
- { return documentHandler.whileDirective(condition, body);}
- }
-
- JAVACODE
- Node ifDirective(){
- return documentHandler.ifDirective();
- }
-
- JAVACODE
- void elseDirective(){
- // throw new ParseException("Invalid CSS: @else must come after @if");
- }
-
- void extendDirective() :
- {SelectorList list;}
- {
- <EXTEND_SYM>
- (<S>)*
- list = selectorList()
- (";"(<S>)*)+
- {documentHandler.extendDirective(list);}
- }
-
- JAVACODE
- Node importDirective(){
- return null;
- }
-
- JAVACODE
- Node charsetDirective(){
- return null;
- }
-
- JAVACODE
- Node mozDocumentDirective(){
- return null;
- }
-
- JAVACODE
- Node supportsDirective(){
- return null;
- }
-
-
- void nestedProperties():
- {String name;
- LexicalUnit exp;}
- {
- name=property()
- ":" ( <S> )*
- <LBRACE> (<S>)*
- {
- documentHandler.startNestedProperties(name);
- }
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- <RBRACE>
- {
- documentHandler.endNestedProperties(name);
- }
- (<S>)*
- }
- /**
- * @exception ParseException exception during the parse
- */
- void declarationOrNestedProperties() :
- { boolean important = false;
- String name;
- LexicalUnit exp;
- Token save;
- }
- {
- try {
- name=property()
- { save = token; }
- ":" ( <S> )*
- (exp=expr() ( important=prio() )?
- {
- Token next = getToken(1);
- if(next.kind == SEMICOLON || next.kind == RBRACE){
- while(next.kind == SEMICOLON){
- skipStatement();
- next = getToken(1);
- }
- if(token.specialToken!=null){
- documentHandler.property(name, exp, important, token.specialToken.image);
- }else{
- documentHandler.property(name, exp, important, null);
- }
- }
- }
- |<LBRACE> (<S>)*
- {
- documentHandler.startNestedProperties(name);
- }
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- <RBRACE>(<S>)*
- {
- documentHandler.endNestedProperties(name);
- }
- )
-
- } catch (JumpException e) {
- skipAfterExpression();
- // reportWarningSkipText(getLocator(), skipAfterExpression());
- } catch (NumberFormatException e) {
- if (errorHandler != null) {
- errorHandler.error(new CSSParseException("Invalid number "
- + e.getMessage(),
- getLocator(),
- e));
- }
- reportWarningSkipText(getLocator(), skipAfterExpression());
- } catch (ParseException e) {
- if (errorHandler != null) {
- if (e.currentToken != null) {
- LocatorImpl li = new LocatorImpl(this,
- e.currentToken.next.beginLine,
- e.currentToken.next.beginColumn-1);
- reportError(li, e);
- } else {
- reportError(getLocator(), e);
- }
- skipAfterExpression();
- /*
- LocatorImpl loc = (LocatorImpl) getLocator();
- loc.column--;
- reportWarningSkipText(loc, skipAfterExpression());
- */
- } else {
- skipAfterExpression();
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- void declaration() :
- { boolean important = false;
- String name;
- LexicalUnit exp;
- Token save;
- }
- {
- try {
- name=property()
- { save = token; }
- ":" ( <S> )* exp=expr() ( important=prio() )?
- {
- documentHandler.property(name, exp, important);
- }
- } catch (JumpException e) {
- skipAfterExpression();
- // reportWarningSkipText(getLocator(), skipAfterExpression());
- } catch (NumberFormatException e) {
- if (errorHandler != null) {
- errorHandler.error(new CSSParseException("Invalid number "
- + e.getMessage(),
- getLocator(),
- e));
- }
- reportWarningSkipText(getLocator(), skipAfterExpression());
- } catch (ParseException e) {
- if (errorHandler != null) {
- if (e.currentToken != null) {
- LocatorImpl li = new LocatorImpl(this,
- e.currentToken.next.beginLine,
- e.currentToken.next.beginColumn-1);
- reportError(li, e);
- } else {
- reportError(getLocator(), e);
- }
- skipAfterExpression();
- /*
- LocatorImpl loc = (LocatorImpl) getLocator();
- loc.column--;
- reportWarningSkipText(loc, skipAfterExpression());
- */
- } else {
- skipAfterExpression();
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- boolean prio() :
- {}
- {
- <IMPORTANT_SYM> ( <S> )* { return true; }
- }
-
- boolean guarded() :
- {}
- {
- <GUARDED_SYM> (<S>)* {return true;}
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- LexicalUnitImpl operator(LexicalUnitImpl prev) :
- {Token n;}
- {
- n="/" ( <S> )* { return LexicalUnitImpl.createSlash(n.beginLine,
- n.beginColumn,
- prev); }
- | n="," ( <S> )* { return LexicalUnitImpl.createComma(n.beginLine,
- n.beginColumn,
- prev); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- LexicalUnit expr() :
- {
- LexicalUnitImpl first, res;
- char op;
- }
- {
- first=term(null){ res = first; }
- ( LOOKAHEAD(2) ( res=operator(res) )? res=term(res))*
- { return first; }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- char unaryOperator() :
- {}
- {
- "-" { return '-'; }
- | "+" { return '+'; }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- LexicalUnitImpl term(LexicalUnitImpl prev) :
- { LexicalUnitImpl result = null;
- Token n = null;
- char op = ' ';
- String varName;
- }
- {
- (( ( ( op=unaryOperator() )?
- (
- n=<NUMBER>
- { result = LexicalUnitImpl.createNumber(n.beginLine, n.beginColumn,
- prev, number(op, n, 0)); }
- | n=<PERCENTAGE>
- { result = LexicalUnitImpl.createPercentage(n.beginLine, n.beginColumn,
- prev, number(op, n, 1)); }
- | n=<PT>
- { result = LexicalUnitImpl.createPT(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<CM>
- { result = LexicalUnitImpl.createCM(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<MM>
- { result = LexicalUnitImpl.createMM(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<PC>
- { result = LexicalUnitImpl.createPC(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<IN>
- { result = LexicalUnitImpl.createIN(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<PX>
- { result = LexicalUnitImpl.createPX(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<EMS>
- { result = LexicalUnitImpl.createEMS(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<EXS>
- { result = LexicalUnitImpl.createEXS(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<DEG>
- { result = LexicalUnitImpl.createDEG(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | n=<RAD>
- { result = LexicalUnitImpl.createRAD(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | n=<GRAD>
- { result = LexicalUnitImpl.createGRAD(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | n=<SECOND>
- { result = LexicalUnitImpl.createS(n.beginLine, n.beginColumn,
- prev, number(op, n, 1)); }
- | n=<MS>
- { result = LexicalUnitImpl.createMS(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<HZ>
- { result = LexicalUnitImpl.createHZ(n.beginLine, n.beginColumn,
- prev, number(op, n, 2)); }
- | n=<KHZ>
- { result = LexicalUnitImpl.createKHZ(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | n=<DIMEN>
- {
- String s = n.image;
- int i = 0;
- while (i < s.length()
- && (Character.isDigit(s.charAt(i)) || (s.charAt(i) == '.'))) {
- i++;
- }
- result = LexicalUnitImpl.createDimen(n.beginLine, n.beginColumn, prev,
- Float.valueOf(s.substring(0, i)).floatValue(),
- s.substring(i));
- }
- | result=function(op, prev) ) )
- | ( n=<STRING>
- { result =
- LexicalUnitImpl.createString(n.beginLine, n.beginColumn, prev,
- convertStringIndex(n.image, 1,
- n.image.length() -1));}
- | n=<IDENT>
- { String s = convertIdent(n.image);
- if ("inherit".equals(s)) {
- result = LexicalUnitImpl.createInherit(n.beginLine, n.beginColumn,
- prev);
- } else {
- result = LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
- prev, convertIdent(n.image));
- }
-
- /* /
- Auto correction code used in the CSS Validator but must not
- be used by a conformant CSS2 parser.
- * Common error :
- * H1 {
- * color : black
- * background : white
- * }
- *
- Token t = getToken(1);
- Token semicolon = new Token();
- semicolon.kind = SEMICOLON;
- semicolon.image = ";";
- if (t.kind == COLON) {
- // @@SEEME. (generate a warning?)
- // @@SEEME if expression is a single ident,
- generate an error ?
- rejectToken(semicolon);
-
- result = prev;
- }
- / */
- }
- | result=hexcolor(prev)
- | result=url(prev)
- | result=unicode(prev)
- ) ) ( <S> )*
- | varName = variableName()
- {result = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn,
- prev, varName);})
- {
- return result;
- }
- }
-
- /**
- * Handle all CSS2 functions.
- * @exception ParseException exception during the parse
- */
- LexicalUnitImpl function(char operator, LexicalUnitImpl prev) :
- {Token n;
- LexicalUnit params = null;
- }
- {
- n=<FUNCTION> ( <S> )*
- {
- String fname = convertIdent(n.image);
- if("alpha(".equals(fname)){
- String body = skipStatementUntilSemiColon();
- return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
- null, "alpha("+body);
- }
- }
- ( params=expr() )? ")"
- {
- if (operator != ' ') {
- throw new CSSParseException("invalid operator before a function.",
- getLocator());
- }
- String f = convertIdent(n.image);
- LexicalUnitImpl l = (LexicalUnitImpl) params;
- boolean loop = true;
- if ("rgb(".equals(f)) {
- // this is a RGB declaration (e.g. rgb(255, 50%, 0) )
- int i = 0;
- while (loop && l != null && i < 5) {
- switch (i) {
- case 0:
- case 2:
- case 4:
- if ((l.getLexicalUnitType() != LexicalUnit.SAC_INTEGER)
- && (l.getLexicalUnitType() != LexicalUnit.SAC_PERCENTAGE)) {
- loop = false;
- }
- break;
- case 1:
- case 3:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
- loop = false;
- }
- break;
- default:
- throw new ParseException("implementation error");
- }
- if (loop) {
- l = (LexicalUnitImpl) l.getNextLexicalUnit();
- i ++;
- }
- }
- if ((i == 5) && loop && (l == null)) {
- return LexicalUnitImpl.createRGBColor(n.beginLine,
- n.beginColumn,
- prev, params);
- } else {
- if (errorHandler != null) {
- String errorText;
- Locator loc;
- if (i < 5) {
- if (params == null) {
- loc = new LocatorImpl(this, n.beginLine,
- n.beginColumn-1);
- errorText = "not enough parameters.";
- } else if (l == null) {
- loc = new LocatorImpl(this, n.beginLine,
- n.beginColumn-1);
- errorText = "not enough parameters: "
- + params.toString();
- } else {
- loc = new LocatorImpl(this, l.getLineNumber(),
- l.getColumnNumber());
- errorText = "invalid parameter: "
- + l.toString();
- }
- } else {
- loc = new LocatorImpl(this, l.getLineNumber(),
- l.getColumnNumber());
- errorText = "too many parameters: "
- + l.toString();
- }
- errorHandler.error(new CSSParseException(errorText, loc));
- }
-
- throw new JumpException();
- }
- } else if ("counter".equals(f)) {
- int i = 0;
- while (loop && l != null && i < 3) {
- switch (i) {
- case 0:
- case 2:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
- loop = false;
- }
- break;
- case 1:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
- loop = false;
- }
- break;
- default:
- throw new ParseException("implementation error");
- }
- l = (LexicalUnitImpl) l.getNextLexicalUnit();
- i ++;
- }
- if (((i == 1) || (i == 3)) && loop && (l == null)) {
- return LexicalUnitImpl.createCounter(n.beginLine, n.beginColumn,
- prev, params);
- }
-
- } else if ("counters(".equals(f)) {
-
- int i = 0;
- while (loop && l != null && i < 5) {
- switch (i) {
- case 0:
- case 4:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
- loop = false;
- }
- break;
- case 2:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_STRING_VALUE) {
- loop = false;
- }
- break;
- case 1:
- case 3:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
- loop = false;
- }
- break;
- default:
- throw new ParseException("implementation error");
- }
- l = (LexicalUnitImpl) l.getNextLexicalUnit();
- i ++;
- }
- if (((i == 3) || (i == 5)) && loop && (l == null)) {
- return LexicalUnitImpl.createCounters(n.beginLine, n.beginColumn,
- prev, params);
- }
- } else if ("attr(".equals(f)) {
- if ((l != null)
- && (l.getNextLexicalUnit() == null)
- && (l.getLexicalUnitType() == LexicalUnit.SAC_IDENT)) {
- return LexicalUnitImpl.createAttr(l.getLineNumber(),
- l.getColumnNumber(),
- prev, l.getStringValue());
- }
- } else if ("rect(".equals(f)) {
- int i = 0;
- while (loop && l != null && i < 7) {
- switch (i) {
- case 0:
- case 2:
- case 4:
- case 6:
- switch (l.getLexicalUnitType()) {
- case LexicalUnit.SAC_INTEGER:
- if (l.getIntegerValue() != 0) {
- loop = false;
- }
- break;
- case LexicalUnit.SAC_IDENT:
- if (!l.getStringValue().equals("auto")) {
- loop = false;
- }
- break;
- case LexicalUnit.SAC_EM:
- case LexicalUnit.SAC_EX:
- case LexicalUnit.SAC_PIXEL:
- case LexicalUnit.SAC_CENTIMETER:
- case LexicalUnit.SAC_MILLIMETER:
- case LexicalUnit.SAC_INCH:
- case LexicalUnit.SAC_POINT:
- case LexicalUnit.SAC_PICA:
- // nothing
- break;
- default:
- loop = false;
- }
- break;
- case 1:
- case 3:
- case 5:
- if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
- loop = false;
- }
- break;
- default:
- throw new ParseException("implementation error");
- }
- l = (LexicalUnitImpl) l.getNextLexicalUnit();
- i ++;
- }
- if ((i == 7) && loop && (l == null)) {
- return LexicalUnitImpl.createRect(n.beginLine, n.beginColumn,
- prev, params);
- }
- }
- return LexicalUnitImpl.createFunction(n.beginLine, n.beginColumn, prev,
- f.substring(0,
- f.length() -1),
- params);
- }
- }
-
- LexicalUnitImpl unicode(LexicalUnitImpl prev) :
- { Token n;
- }
- {
- n=<UNICODERANGE>
- {
- LexicalUnitImpl params = null;
- String s = n.image.substring(2);
- int index = s.indexOf('-');
- if (index == -1) {
- params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
- params, Integer.parseInt(s, 16));
- } else {
- String s1 = s.substring(0, index);
- String s2 = s.substring(index);
-
- params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
- params, Integer.parseInt(s1, 16));
- params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
- params, Integer.parseInt(s2, 16));
- }
-
- return LexicalUnitImpl.createUnicodeRange(n.beginLine, n.beginColumn,
- prev, params);
- }
- }
-
- LexicalUnitImpl url(LexicalUnitImpl prev) :
- { Token n;
- }
- {
- n=<URL>
- {
- String urlname = n.image.substring(4, n.image.length()-1).trim();
- if (urlname.charAt(0) == '"'
- || urlname.charAt(0) == '\'') {
- urlname = urlname.substring(1, urlname.length()-1);
- }
- return LexicalUnitImpl.createURL(n.beginLine, n.beginColumn, prev, urlname);
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- LexicalUnitImpl hexcolor(LexicalUnitImpl prev) :
- {Token n;
- }
- {
- n=<HASH>
- {
- int r;
- LexicalUnitImpl first, params = null;
- String s = n.image.substring(1);
-
- if(s.length()!=3 && s.length()!=6) {
- first = null;
- throw new CSSParseException("invalid hexadecimal notation for RGB: " + s,
- getLocator());
- }
- return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
- prev, n.image);
- }
- }
-
- JAVACODE
- float number(char operator, Token n, int lengthUnit) {
- String image = n.image;
- float f = 0;
-
- if (lengthUnit != 0) {
- image = image.substring(0, image.length() - lengthUnit);
- }
- f = Float.valueOf(image).floatValue();
- return (operator == '-')? -f: f;
- }
-
- JAVACODE
- String skipStatementUntilSemiColon(){
- int[] semicolon = {SEMICOLON};
- return skipStatementUntil(semicolon);
- }
-
- JAVACODE
- String skipStatementUntilLeftBrace(){
- int[] lBrace = {LBRACE};
- return skipStatementUntil(lBrace);
- }
-
- JAVACODE
- String skipStatementUntilRightParan(){
- int[] rParan = {RPARAN};
- return skipStatementUntil(rParan);
- }
-
- JAVACODE
- String skipStatementUntil(int[] symbols){
- StringBuffer s = new StringBuffer();
- boolean stop = false;
- Token tok;
- while(!stop){
- tok = getToken(1);
- if(tok.kind == EOF) {
- return null;
- }
- for(int sym : symbols){
- if(tok.kind == sym){
- stop = true;
- break;
- }
- }
- if(!stop){
- if (tok.image != null) {
- s.append(tok.image);
- }
- getNextToken();
- }
- }
- return s.toString().trim();
- }
-
- JAVACODE
- String skipStatement() {
- StringBuffer s = new StringBuffer();
- Token tok = getToken(0);
- if (tok.image != null) {
- s.append(tok.image);
- }
- while (true) {
- tok = getToken(1);
- if (tok.kind == EOF) {
- return null;
- }
- s.append(tok.image);
- if (tok.kind == LBRACE) {
- getNextToken();
- s.append(skip_to_matching_brace());
- getNextToken();
- tok = getToken(1);
- break;
- } else if (tok.kind == RBRACE) {
- getNextToken();
- tok = getToken(1);
- break;
- } else if (tok.kind == SEMICOLON) {
- getNextToken();
- tok = getToken(1);
- break;
- }
- getNextToken();
- }
-
- // skip white space
- while (true) {
- if (tok.kind != S) {
- break;
- }
- tok = getNextToken();
- tok = getToken(1);
- }
-
- return s.toString().trim();
- }
-
- JAVACODE
- String skip_to_matching_brace() {
- StringBuffer s = new StringBuffer();
- Token tok;
- int nesting = 1;
- while (true) {
- tok = getToken(1);
- if (tok.kind == EOF) {
- break;
- }
- s.append(tok.image);
- if (tok.kind == LBRACE) {
- nesting++;
- } else if (tok.kind == RBRACE) {
- nesting--;
- if (nesting == 0) {
- break;
- }
- }
- getNextToken();
- }
- return s.toString();
- }
-
- /*
- * Here I handle all CSS2 unicode character stuffs.
- * I convert all \XXXXXX character into a single character.
- * Don't forget that the parser has recognize the token before.
- * (So IDENT won't contain newline and stuffs like this).
- */
- JAVACODE
- String convertStringIndex(String s, int start, int len) {
- StringBuffer buf = new StringBuffer(len);
- int index = start;
-
- while (index < len) {
- char c = s.charAt(index);
- if (c == '\\') {
- if (++index < len) {
- c = s.charAt(index);
- switch (c) {
- 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':
- int numValue = Character.digit(c, 16);
- int count = 0;
- int p = 16;
-
- while (index + 1 < len && count < 6) {
- c = s.charAt(index+1);
-
- if (Character.digit(c, 16) != -1) {
- numValue = (numValue * 16) + Character.digit(c, 16);
- p *= 16;
- index++;
- } else {
- if (c == ' ') {
- // skip the latest white space
- index++;
- }
- break;
- }
- }
- buf.append((char) numValue);
- break;
- case '\n':
- case '\f':
- break;
- case '\r':
- if (index + 1 < len) {
- if (s.charAt(index + 1) == '\n') {
- index ++;
- }
- }
- break;
- default:
- buf.append(c);
- }
- } else {
- throw new CSSParseException("invalid string " + s, getLocator());
- }
- } else {
- buf.append(c);
- }
- index++;
- }
-
- return buf.toString();
- }
-
- JAVACODE
- String convertIdent(String s) {
- return convertStringIndex(s, 0, s.length());
- }
-
- JAVACODE
- String convertString(String s) {
- return convertStringIndex(s, 0, s.length());
- }
-
- /*
- * @@HACK
- * I can't insert a token into the tokens flow.
- * It's jj_consume_token implementation dependant! :-(
- */
- JAVACODE
- void rejectToken(Token t) {
- Token fakeToken = new Token();
- t.next = token;
- fakeToken.next = t;
- token = fakeToken;
- }
-
- /**
- * skip after an expression
- */
- JAVACODE
- String skipAfterExpression() {
- Token t = getToken(1);
- StringBuffer s = new StringBuffer();
- s.append(getToken(0).image);
-
- while ((t.kind != RBRACE) && (t.kind != SEMICOLON) && (t.kind != EOF)) {
- s.append(t.image);
- getNextToken();
- t = getToken(1);
- }
-
- return s.toString();
- }
-
- /**
- * The following functions are useful for a DOM CSS implementation only and are
- * not part of the general CSS2 parser.
- */
-
- void _parseRule() :
- {String ret = null;
- }
- {
- ( <S> )*
- ( importDeclaration() | styleRule() | media() | page()
- | fontFace() | ret=skipStatement()
- {
- if ((ret == null) || (ret.length() == 0)) {
- return;
- }
- if (ret.charAt(0) == '@') {
- documentHandler.ignorableAtRule(ret);
- } else {
- throw new CSSParseException("unrecognize rule: " + ret,
- getLocator());
- }
- }
- )
- }
-
- void _parseImportRule() :
- {
- }
- {
- ( <S> )* importDeclaration()
- }
-
- void _parseMediaRule() :
- {
- }
- {
- ( <S> )* media()
- }
-
- void _parseDeclarationBlock() :
- {
- }
- {
- ( <S> )*
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- }
-
- SelectorList _parseSelectors() :
- { SelectorList p = null;
- }
- {
- try {
- ( <S> )* p = selectorList()
- { return p; }
- } catch (ThrowedParseException e) {
- throw (ParseException) e.e.fillInStackTrace();
- }
- }
-
- /*
- * Local Variables:
- * compile-command: javacc Parser.jj & javac Parser.java
- * End:
- */
|