12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972 |
- /*
- * Copyright 2000-2013 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- /* -*-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.internal.parser;
-
- import java.io.*;
- import java.net.*;
- import java.util.ArrayList;
- import java.util.Locale;
- import java.util.Map;
- import java.util.UUID;
-
- 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.internal.handler.*;
-
- import com.vaadin.sass.internal.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);
- }
-
- public InputSource getInputSource(){
- return source;
- }
-
- /**
- * 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));
-
- return null;
- }
-
- 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 ?");
- }
- }
- }
- //use UTF-8 as the default encoding.
- String encoding = source.getEncoding();
- InputStream input = source.getByteStream();
- if (!input.markSupported()) {
- // If mark is not supported, wrap it in a stream which supports mark
- input = new BufferedInputStream(input);
- source.setByteStream(input);
- }
- // Mark either the original stream or the wrapped stream
- input.mark(100);
- if(encoding == null){
- encoding = "ASCII";
-
- char c = ' ';
-
- 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_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 : "|=" >
- | < CARETMATCH : "^=" >
- | < DOLLARMATCH : "$=" >
- | < STARMATCH : "*=" >
- | < INCLUDES : "~=" >
- | < EQ : "=" >
- | < PLUS : "+" >
- | < MINUS : "-" >
- | < COMMA : "," >
- | < SEMICOLON : ";" >
- | < PRECEDES : ">" >
- | < SIBLING : "~" >
- | < SUCCEEDS : "<" >
- | < DIV : "/" >
- | < LBRACKET : "[" >
- | < RBRACKET : "]" >
- | < ANY : "*" >
- | < MOD : "%" >
- | < PARENT : "&" >
- | < DOT : "." >
- | < LPARAN : "(" >
- | < RPARAN : ")">
- | < COMPARE : "==" >
- | < OR : "||" >
- | < AND : "&&" >
- | < NOT_EQ : "!=" >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < COLON : ":" >
- }
-
- < DEFAULT >
- TOKEN :
- {
- < INTERPOLATION : "#{"< VARIABLE > "}">
- }
-
- <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">
- |<FROM : "from">
- }
-
- /* 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:
- {
- < MICROSOFT_RULE : "filter"|"-ms-filter" >
- }
-
- < DEFAULT >
- TOKEN:
- {
- < IF : "if" >
- }
-
- <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" >
- | < LEM : <NUMBER> "lem" >
- | < REM : <NUMBER> "rem" >
- | < 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" >
- | < KEY_FRAME_SYM: "@keyframes" | "@-moz-keyframes" | "@-o-keyframes" | "@-webkit-keyframes" | "@-ms-keyframes">
- | < 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 :
- {
- < REMOVE : "remove" (< S >)? "(" >
- | < APPEND : "append" (< S >)? "(" >
- | < CONTAINS : "contains" (< S >)? "(" >
- }
-
- <DEFAULT>
- TOKEN :
- {
- < FUNCTION : <IDENT>(< S >)* "(" >
- }
-
- <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> comments()
- | 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;
- }
- {
- (
- ( debuggingDirective() | mixinDirective() | controlDirective() | includeDirective() | styleRule() | media()
- | page() | fontFace() | keyframes() | LOOKAHEAD(variable()) variable() | listModifyDirective()
- | { l = getLocator(); } ret=skipStatement()
- {
- if ((ret == null) || (ret.length() == 0)) {
- return;
- }
- if (ret.charAt(0) == '@') {
- documentHandler.unrecognizedRule(ret);
- } else {
- reportWarningSkipText(l, 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 keyframes() :
- {
- Token n;
- boolean start = false;
- String keyframeName = null;
- String animationname = "";
- }
- {
- try {
- n=<KEY_FRAME_SYM> ( <S> )* {keyframeName = n.image;}
- (n = <IDENT>{animationname += n.image; }|n = < INTERPOLATION >{ animationname += n.image; })+(<S>)*
- {start = true; documentHandler.startKeyFrames(keyframeName, animationname); }
- <LBRACE> ( <S> )* ( keyframeSelector() )* <RBRACE> ( <S> )*
- } catch (ParseException e) {
- reportError(getLocator(), e);
- skipStatement();
- } finally {
- if (start) {
- documentHandler.endKeyFrames();
- }
- }
- }
-
- void keyframeSelector():
- {
- Token n;
- boolean start = false;
- }
- {
- try{
- (n = <FROM> | n = <TO> | n = <PERCENTAGE>) (<S>)* <LBRACE> (<S>)*
- {
- start = true;
- documentHandler.startKeyframeSelector(n.image);
- }
- (ifContentStatement() | controlDirective() | microsoftExtension() )*
- <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.endKeyframeSelector();
- }
- }
- }
-
- /**
- * @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> )* ( debuggingDirective() | 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();
- if ((ret != null) && (ret.charAt(0) == '@')) {
- documentHandler.unrecognizedRule(ret);
- } else {
- reportWarningSkipText(getLocator(), 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=<UNKNOWN>
- ) {
- String ret;
- Locator loc = getLocator();
- ret=skipStatement();
- if ((ret != null) && (n.image.charAt(0) == '@')) {
- documentHandler.unrecognizedRule(ret);
- } else {
- reportWarningSkipText(loc, ret);
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- char combinator() :
- {
- char connector = ' ';
- }
- {
- (connector = combinatorChar()
- | <S> (connector = combinatorChar())?) { return connector; }
- }
-
- /**to refactor combinator and reuse in selector().*/
- char combinatorChar() :
- {Token t;}
- {
- (t = <PLUS> | t = <PRECEDES> | t = <SIBLING>) (<S>)*
- {
- return t.image.charAt(0);
- }
- }
-
- void microsoftExtension() :
- {
- Token n;
- String name = "";
- String value = "";
- }
-
- {
- // This is not really taking the syntax of filter rules into account
- n = < MICROSOFT_RULE > (< S >)* { name = n.image; }
- < COLON >
- ((n = < IDENT > { value += n.image; })
- | (n = < NUMBER > { value += n.image; })
- | (n = < STRING > { value += n.image; })
- | (n = < COMMA > { value += n.image; })
- | (n = < INTERPOLATION > { value += n.image; })
- | (n = < COLON > { value += n.image; })
- | (n = < FUNCTION > { value += n.image; })
- | (n = < RPARAN > { value += n.image; })
- | (n = < EQ > { value += n.image; })
- | (n = < DOT > { value += n.image; })
- | (n = < S > { if(value.lastIndexOf(' ') != value.length()-1)
- { value += n.image; } }
- ) )+
- < SEMICOLON >
- (< S >)*
- { documentHandler.microsoftDirective(name, value); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String property() :
- {Token t;String s = "";
- }
- {
- (t = <IDENT>{s += t.image; }|t = < INTERPOLATION >{ s += t.image; })+(< S >)*
- {
- return s;
- }
- }
-
- 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;
- ArrayList<String> l = null;
- Token save;
- Locator loc;
- }
- {
- try {
- l=selectorList() { save = token; } <LBRACE> (<S>)*
- {
- start = true;
- documentHandler.startSelector(l);
- }
- ( ifContentStatement() | controlDirective() | microsoftExtension() )*
- <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();
- }
- }
- }
-
- ArrayList<String> selectorList() :
- {
- ArrayList<String> selectors = new ArrayList<String>();
- String selector;
- }
- {
- selector=selector() ( <COMMA> (<S>)* { selectors.add(selector); }
- selector=selector() )*
- { selectors.add(selector);
- return selectors;
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String selector() :
- {
- String selector = null;
- char comb;
- }
- {
- try {
- // the selector can begin either a simple_selector, or a combinatorChar(+, >, ~).
- // when beginning with combinatorChar, the next one should be a simple_selector().
- (selector=simple_selector(null, ' ') | (comb=combinatorChar() selector=simple_selector(selector, comb)))
- ( 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
- */
- String simple_selector(String selector, char comb) :
- {
- String simple_current = null;
- String 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 = "";
- }
- if (cond != null) {
- simple_current = simple_current + cond;
- }
- StringBuilder builder = new StringBuilder();
- switch (comb) {
- case ' ':
- if(selector!=null){
- builder.append(selector).append(" ");
- }
- break;
- case '+':
- case '>':
- case '~':
- if(selector!=null){
- builder.append(selector).append(" ");
- }
- builder.append(comb).append(" ");
- break;
- default:
- throw new ParseException("invalid state. send a bug report");
- }
- builder.append(simple_current);
- selector = builder.toString();
-
- if (pseudoElt != null) {
- selector = selector + pseudoElt;
- }
- return selector;
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String _class(String pred) :
- {Token t;
- String s = ".";
- }
- {
- "." (t = <IDENT>{s += t.image; }|t = < INTERPOLATION >{ s += t.image; })+
- {
-
- if (pred == null) {
- return s;
- } else {
- return pred + s;
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String element_name() :
- {Token t; String s = "";}
- {
- (t = <IDENT>{s += t.image; }|t = < INTERPOLATION >{ s += t.image; })+
- {
- return s;
- }
- | "*"
- { return "*"; }
- | "&"
- { return "&"; }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String attrib(String 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; }
- | <CARETMATCH> { cases = 4; }
- | <DOLLARMATCH> { cases = 5; }
- | <STARMATCH> { cases = 6; } ) ( <S> )*
- ( val=<IDENT> { attValue = val.image; }
- | val=<STRING> { attValue = val.image; }
- )
- ( <S> )* )?
- "]"
- {
- String name = convertIdent(att.image);
- String c;
- switch (cases) {
- case 0:
- c = name;
- break;
- case 1:
- c = name + "=" + attValue;
- break;
- case 2:
- c = name + "~=" + attValue;
- break;
- case 3:
- c = name + "|=" +attValue;
- break;
- case 4:
- c = name + "^=" +attValue;
- break;
- case 5:
- c = name + "$=" +attValue;
- break;
- case 6:
- c = name + "*=" +attValue;
- break;
- default:
- // never reached.
- c = null;
- }
- c = "[" + c + "]";
- if (pred == null) {
- return c;
- } else {
- return pred + c;
- }
- }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String pseudo(String pred) :
- {Token n;
- Token param;
- String d;
- 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 {
- String c = s;
- if (pred == null) {
- return c;
- } else {
- return pred + c;
- }
- }
- }
- | ( n=<FUNCTION> ( <S> )* d=skipStatementUntilRightParan() <RPARAN>
- {
- // accept anything between function and a right parenthesis
- String f = convertIdent(n.image);
- String colons = isPseudoElement ? "::" : ":";
- String pseudofn = colons + f + d + ")";
- if (pred == null) {
- return pseudofn;
- } else {
- return pred + pseudofn;
- }
- }
- )
- )
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String hash(String pred) :
- {Token n; }
- {
- n=<HASH>
- {
- String d = n.image;
- if (pred == null) {
- return d;
- } else {
- return pred + d;
- }
- }
- }
-
- void variable() :
- {
- String name;
- LexicalUnitImpl 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 controlDirective() :
- {}
- {
- ifDirective() | eachDirective()
- }
-
- void ifContentStatement() :
- {}
- {
- includeDirective() | media() | extendDirective() | styleRuleOrDeclarationOrNestedProperties()
- | keyframes() | LOOKAHEAD(variable()) variable() | listModifyDirective()
- }
-
- void ifDirective() :
- {
- Token n = null;
- String s = null;
- String evaluator = "";
- }
- {
- < IF_SYM >
- ( s = booleanExpressionToken() { evaluator += s;} )+
- < LBRACE >(< S >)*
- { documentHandler.startIfElseDirective();
- documentHandler.ifDirective(evaluator);
- }
- ( ifContentStatement() )*
- < RBRACE >(< S >)*
- (elseDirective())*
- { documentHandler.endIfElseDirective(); }
- }
-
- void elseDirective() :
- {
- String evaluator = "";
- Token n = null;
- String s = null;
- }
- {
- < ELSE_SYM >(< S >)*
- ( < IF > ( s = booleanExpressionToken() { evaluator += s; } )+ )?
- < LBRACE >(< S >)*
- { if(!evaluator.trim().equals("")){ documentHandler.ifDirective(evaluator); }
- else{ documentHandler.elseDirective(); }
- }
- ( ifContentStatement() )*
- < RBRACE >(< S >)*
- }
-
- String booleanExpressionToken() :
- {
- Token n = null;
- String s = null;
- }
- {
- (
- LOOKAHEAD(containsDirective())
- s = containsDirective()
- |n = < VARIABLE >
- |n = < IDENT >
- |n = < NUMBER >
- |n = < LPARAN >
- |n = < RPARAN >
- |n = < PLUS >
- |n = < MINUS >
- |n = < DIV >
- |n = < ANY >
- |n = < COMPARE >
- |n = < EQ >
- |n = < PRECEDES >
- |n = < SUCCEEDS >
- |n = < OR >
- |n = < AND >
- |n = < S >
- |n = < NOT_EQ >
- ){
- if(n!=null){return n.image;}
- else{return s;}
- }
- }
-
- void eachDirective() :
- {
- Token var;
- ArrayList<String> list = null;
- String listVariable = null;
- }
- {
- < EACH_SYM >
- (< S >)*
- var = < VARIABLE > (< S >)* < EACH_IN > (< S >)*
- (list = stringList()
- {documentHandler.startEachDirective(var.image, list);}
- |listVariable = variableName()
- {documentHandler.startEachDirective(var.image, listVariable);}
- )
- < LBRACE >(< S >)*
- ( ifContentStatement() )*
- < RBRACE >(< S >)*
- { documentHandler.endEachDirective();}
- }
-
- ArrayList<String > stringList():
- {
- ArrayList<String > strings = new ArrayList<String >();
- Token input;
- }
- {
- (input = < IDENT > (< S >)*)
- { strings.add(input.image); }
-
- (< COMMA >(< S >)* input = < IDENT > { strings.add(input.image); } (< S >)*)*
- { return strings; }
-
- }
-
- 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);}
- ( ifContentStatement() | controlDirective() | fontFace() | page())*
- <RBRACE>(<S>)*
- {documentHandler.endMixinDirective(name, args);}
- }
-
- ArrayList<VariableNode> arglist() :
- {
- ArrayList<VariableNode> args = new ArrayList<VariableNode>();
- VariableNode arg;
- boolean hasNonOptionalArgument = false;
- }
- {
- arg=mixinArg() ( <COMMA> (<S>)* { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); }
- arg=mixinArg() )*
- { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg);
- return args;
- }
- }
-
- JAVACODE
- boolean checkMixinForNonOptionalArguments(VariableNode arg, boolean hasNonOptionalArguments)
{
- boolean currentArgHasArguments = arg.getExpr() != null && arg.getExpr().getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE && arg.getExpr().getNextLexicalUnit() != null;
-
if(currentArgHasArguments)
{
- if(hasNonOptionalArguments)
{
throw new ParseException("Sass Error: Required argument $"+ arg.getName() +" must come before any optional arguments.");
- }
- return hasNonOptionalArguments;
- }else
{
return true;
- }
- }
-
- VariableNode mixinArg() :
- {
- String name;
- Token variable = null;
- LexicalUnitImpl first = null;
- LexicalUnitImpl prev = null;
- LexicalUnitImpl next = null;
- }
- {
- name=variableName() (< COLON > (< S >)*
-
- (
first = nonVariableTerm(null)
{
- prev = first;
}
- (LOOKAHEAD(3)(< COMMA >(< S >)*)? prev = nonVariableTerm(prev))*
)
- | (variable = < VARIABLE >{ first = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn,
- prev, variable.image);}
-
- )
- )?
- {
- VariableNode arg = new VariableNode(name, first, false);
- return arg;
- }
- }
-
- ArrayList<LexicalUnitImpl> argValuelist() :
- {
- ArrayList<LexicalUnitImpl> args = new ArrayList<LexicalUnitImpl>();
- LexicalUnitImpl first = null;
- LexicalUnitImpl next = null;
- LexicalUnitImpl prev = null;
- }
- {
- first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})*
- ( <COMMA> (<S>)*
- first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})*
- )*
- {return args;}
- }
-
- void includeDirective() :
- {
- String name;
- ArrayList<LexicalUnitImpl> args=null;
- }
- {
- <INCLUDE_SYM>
- (<S>)*
- (name = property()|name = variableName(){ name = "$"+name;}
- |(name = functionName()
- args = argValuelist()) <RPARAN>)(";"(<S>)*)+
- {documentHandler.includeDirective(name, args);}
- }
-
- String interpolation() :
- {
- Token n;
- }
- {
- n = < INTERPOLATION >
- {
- return n.image;
- }
- }
-
- void listModifyDirective() :
- {
- String list = null;
- String remove = null;
- String separator = null;
- String variable = null;
- Token n = null;
- Token type = null;
- }
- {
- //refactor, remove those 3 LOOKAHEAD(5).
- n = < VARIABLE >{ variable = n.image; }(< S >)* ":" (< S >)*
- (type = < APPEND> | type = <REMOVE> | type=<CONTAINS> )(< S >)*
- (list = listModifyDirectiveArgs(0))
- (< RPARAN >)? < COMMA >(< S >)*
- (remove = listModifyDirectiveArgs(1))
- ( < COMMA >(< S >)* n = < IDENT >{ separator = n.image; } (< S >)*)?
- < RPARAN >
- {
- switch (type.kind) {
- case APPEND:
- documentHandler.appendDirective(variable,list,remove,separator);
- break;
- case REMOVE:
- documentHandler.removeDirective(variable,list,remove,separator);
- break;
- case CONTAINS:
- if(variable == null){
- variable = "$var_"+UUID.randomUUID();
- }
- documentHandler.containsDirective(variable,list,remove,separator);
- break;
- default:
- break;
- }
- }
- (< S >)*< SEMICOLON >(<S>)*
- }
-
-
- /**
- * @exception ParseException exception during the parse
- */
- void appendDirective() :
- {
- String list = null;
- String remove = null;
- String separator = null;
- String variable = null;
- Token n = null;
- }
- {
- n = < VARIABLE >{ variable = n.image; }(< S >)* ":" (< S >)*
- < APPEND >(< S >)*
- (list = listModifyDirectiveArgs(0))
- (< RPARAN >)? < COMMA >(< S >)*
- (remove = listModifyDirectiveArgs(1))
- ( < COMMA >(< S >)* n = < IDENT >{ separator = n.image; } (< S >)*)?
- < RPARAN >
-
- { documentHandler.appendDirective(variable,list,remove,separator); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- void removeDirective() :
- {
- String list = null;
- String remove = null;
- String separator = null;
- String variable = null;
- Token n = null;
- }
- {
- n = < VARIABLE >{ variable = n.image; }(< S >)* ":" (< S >)*
- < REMOVE >(< S >)*
- (list = listModifyDirectiveArgs(0))
- (< RPARAN >)? < COMMA >(< S >)*
- (remove = listModifyDirectiveArgs(1))
- ( < COMMA >(< S >)* n = < IDENT >{ separator = n.image; } (< S >)*)?
- < RPARAN >
-
- { documentHandler.removeDirective(variable,list,remove,separator); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- String containsDirective() :
- {
- String list = null;
- String remove = null;
- String separator = null;
- String variable = null;
- Token n = null;
- }
- {
- (n = < VARIABLE >{ variable = n.image; }(< S >)* ":" (< S >)*)?
- < CONTAINS >(< S >)*
- (list = listModifyDirectiveArgs(0))
- (< RPARAN >)? < COMMA >(< S >)*
- (remove = listModifyDirectiveArgs(1))
- ( < COMMA >(< S >)* n = < IDENT >{ separator = n.image; } (< S >)*)?
- < RPARAN >
-
- { /*
- *if it is not in the form like "$contains : contains($items, .v-button);"
- *for example in @if, like "@if (contains(a b c, b))", then create a temp
- *variable for contains(a b c, b);
- */
- if(variable == null){
- variable = "$var_"+UUID.randomUUID();
- }
- documentHandler.containsDirective(variable,list,remove,separator);
- return variable;
- }
- }
-
- JAVACODE
- String listModifyDirectiveArgs(int nest)
- {
- String list = "";
- int nesting = nest;
- Token t = null;
-
- while(true)
- {
- t = getToken(1);
- String s = t.image;
- if(t.kind == VARIABLE||t.kind == IDENT)
{
- list += s;
- }else if(s.toLowerCase().equals("auto")||s.toLowerCase().equals("space")||s.toLowerCase().equals("comma"))
{
- int i = 2;
- Token temp = getToken(i);
- boolean isLast = true;
- while(temp.kind != SEMICOLON)
- {
if(temp.kind != RPARAN || temp.kind != S)
- {
isLast = false;
}
- i++;
- temp = getToken(i);
- }
-
- if(isLast)
{
return list;
- }
- }
else if(t.kind == STRING)
{
list += s.substring(1,s.length()).substring(0,s.length()-2);
-
- }else if(t.kind == LPARAN)
{
nesting++;
- if(nesting > nest+1)
{
throw new CSSParseException("Only one ( ) pair per parameter allowed", getLocator());
- }
- }else if(t.kind == RPARAN)
{
nesting--;
- if(nesting == 0)
{
- return list;
- }
- } else if(t.kind == COMMA)
{
- if(nesting == nest)
{
- return list;
}else
{
- list += ",";
}
-
- }else if(t.kind == S)
{
- list += " ";
} else if(t.kind == LBRACE)
{
- throw new CSSParseException("Invalid token,'{' found", getLocator());
}
-
getNextToken();
- }
- }
-
- Node returnDirective() :
- {
- String raw;
- }
- {
- raw = skipStatement()
- {return null;}
- }
-
- void debuggingDirective() :
- {}
- {
- debugDirective() | warnDirective()
- }
-
- void debugDirective() :
- {}
- {
- <DEBUG_SYM>
- {
- String content = skipStatementUntilSemiColon();
- // TODO should evaluate the content expression, call documentHandler.debugDirective() etc.
- System.out.println(content);
- }
- (<S>)*
- }
-
- void warnDirective() :
- {}
- {
- <WARN_SYM>
- {
- String content = skipStatementUntilSemiColon();
- // TODO should evaluate the content expression, call documentHandler.warnDirective() etc.
- System.err.println(content);
- }
- (<S>)*
- }
-
- 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 whileDirective() :
- {
- String condition;
- String body;
- }
- {
- condition = skipStatementUntilLeftBrace()
- body = skipStatement()
- { return documentHandler.whileDirective(condition, body);}
- }
-
- void extendDirective() :
- {ArrayList<String> 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 styleRuleOrDeclarationOrNestedProperties() :
- {
- }
- {
- try {
- // differentiate between the colon of a pseudo and the colon of nested properties and the colon of a simple property
- // first check if it is a normal styleRule, if not check if it is declarationOrNestedProperties(), if still fails, most likely, it is
- // is styleRule with pseudo selector with contains functions. have to do it in this way, because both the styleRule and declarationOrNestedProperties()
- // have 'skipStatementUntilXXX', which cannot be LOOKAHEAD properly.
- ( debuggingDirective() | LOOKAHEAD(selectorList()<LBRACE>) styleRule() | LOOKAHEAD(3)declarationOrNestedProperties() | styleRule())
- } catch (JumpException e) {
- skipAfterExpression();
- // 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 declarationOrNestedProperties() :
- { boolean important = false;
- String name;
- LexicalUnitImpl exp;
- Token save;
- String comment = null;
- }
- {
- 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;}
- {
- /* (comments copied from basic_arithmetics.scss)
- *supports:
- * 1. standard arithmetic operations (+, -, *, /, %)
- * 2. / is treated as css operator, unless one of its operands is variable or there is another binary arithmetic operator
- *limits:
- * 1. cannot mix arithmetic and css operations, e.g. "margin: 1px + 3px 2px" will fail
- * 2. space between add and minus operator and their following operand is mandatory. e.g. "1 + 2" is valid, "1+2" is not
- * 3. parenthesis is not supported now.
- */
- n="," ( <S> )* { return LexicalUnitImpl.createComma(n.beginLine,
- n.beginColumn,
- prev); }
- |n="/" ( <S> )* { return LexicalUnitImpl.createSlash(n.beginLine,
- n.beginColumn,
- prev); }
- | n="*" ( <S> )* { return LexicalUnitImpl.createMultiply(n.beginLine,
- n.beginColumn,
- prev); }
- | n="%" ( <S> )* { return LexicalUnitImpl.createModulo(n.beginLine,
- n.beginColumn,
- prev); }
- /*
- * for '+', since it can be either a binary operator or an unary operator,
- * which is ambiguous. To avoid this, the binary operator '+' always has
- * a space before the following term. so '2+3' is not a valid binary expression,
- * but '2 + 3' is. The same for '-' operator.
- */
-
- | n="+" ( <S> )+{ return LexicalUnitImpl.createAdd(n.beginLine,
- n.beginColumn,
- prev); }
- | n="-" ( <S> )+{ return LexicalUnitImpl.createMinus(n.beginLine,
- n.beginColumn,
- prev); }
- }
-
- /**
- * @exception ParseException exception during the parse
- */
- LexicalUnitImpl expr() :
- {
- LexicalUnitImpl first, res;
- char op;
- }
- {
- first=term(null){ res = first; }
- ( LOOKAHEAD(2) ( 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 = ' ';
- }
- {
- (result = nonVariableTerm(prev)| result = variableTerm(prev))
- {
- return result;
- }
- }
-
- LexicalUnitImpl variableTerm(LexicalUnitImpl prev) :
{
- LexicalUnitImpl result = null;
- String varName = "";
}
{
- varName = variableName()
- {result = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn,
- prev, varName); return result;}
}
-
- LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) :
{
LexicalUnitImpl result = null;
- Token n = null;
- char op = ' ';
- String varName;
- String s = "";
- }
- {
- ( ( (
- 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=<LEM>
- { result = LexicalUnitImpl.createLEM(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | n=<REM>
- { result = LexicalUnitImpl.createREM(n.beginLine, n.beginColumn,
- prev, number(op, n, 3)); }
- | 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>
- {
- 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));}
- | (< DOT >{ s+="."; })?n=<IDENT>
- { 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> )*
- {
- 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);
- }else if("expression(".equals(fname)){
- String body = skipStatementUntilSemiColon();
- return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
- null, "expression("+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();
- 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':
- buf.append('\\');
- while (index < len) {
- buf.append(s.charAt(index++));
- }
- 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());
- }
-
- JAVACODE
- void comments(){
- if (token.specialToken != null){
- Token tmp_t = token.specialToken;
- while (tmp_t.specialToken != null) tmp_t = tmp_t.specialToken;
- while (tmp_t != null) {
- documentHandler.comment(tmp_t.image);
- tmp_t = tmp_t.next;
- }
- }
- }
-
- /*
- * @@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() | debuggingDirective() | styleRule() | media() | page() | fontFace() | ret=skipStatement()
- {
- if ((ret == null) || (ret.length() == 0)) {
- return;
- }
- if (ret.charAt(0) == '@') {
- documentHandler.unrecognizedRule(ret);
- } else {
- throw new CSSParseException("unrecognize rule: " + ret,
- getLocator());
- }
- }
- )
- }
-
- void _parseImportRule() :
- {
- }
- {
- ( <S> )* importDeclaration()
- }
-
- void _parseMediaRule() :
- {
- }
- {
- ( <S> )* media()
- }
-
- void _parseDeclarationBlock() :
- {
- }
- {
- ( <S> )*
- ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
- }
-
- ArrayList<String> _parseSelectors() :
- { ArrayList<String> 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:
- */
|