You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Parser.jj 57KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443
  1. /* -*-java-extended-*-
  2. * Copyright (c) 1999 World Wide Web Consortium
  3. * (Massachusetts Institute of Technology, Institut National de Recherche
  4. * en Informatique et en Automatique, Keio University).
  5. * All Rights Reserved. http://www.w3.org/Consortium/Legal/
  6. *
  7. * $Id: Parser.jj,v 1.15 2000/10/27 21:09:37 plehegar Exp $
  8. */
  9. options {
  10. IGNORE_CASE = true;
  11. STATIC = false;
  12. USER_CHAR_STREAM = true;
  13. /* DEBUG_TOKEN_MANAGER = true;
  14. DEBUG_PARSER = true; */
  15. }
  16. PARSER_BEGIN(Parser)
  17. package com.vaadin.sass.parser;
  18. import java.io.*;
  19. import java.net.*;
  20. import java.util.ArrayList;
  21. import java.util.Locale;
  22. import java.util.Map;
  23. import org.w3c.css.sac.ConditionFactory;
  24. import org.w3c.css.sac.Condition;
  25. import org.w3c.css.sac.SelectorFactory;
  26. import org.w3c.css.sac.SelectorList;
  27. import org.w3c.css.sac.Selector;
  28. import org.w3c.css.sac.SimpleSelector;
  29. import org.w3c.css.sac.DocumentHandler;
  30. import org.w3c.css.sac.InputSource;
  31. import org.w3c.css.sac.ErrorHandler;
  32. import org.w3c.css.sac.CSSException;
  33. import org.w3c.css.sac.CSSParseException;
  34. import org.w3c.css.sac.Locator;
  35. import org.w3c.css.sac.LexicalUnit;
  36. import org.w3c.flute.parser.selectors.SelectorFactoryImpl;
  37. import org.w3c.flute.parser.selectors.ConditionFactoryImpl;
  38. import org.w3c.flute.util.Encoding;
  39. import com.vaadin.sass.handler.*;
  40. import com.vaadin.sass.tree.*;
  41. /**
  42. * A CSS2 parser
  43. *
  44. * @author Philippe Le H�garet
  45. * @version $Revision: 1.15 $
  46. */
  47. public class Parser implements org.w3c.css.sac.Parser {
  48. // replaces all \t, \n, etc with this StringBuffer.
  49. static final StringBuilder SPACE = new StringBuilder(" ");
  50. // the document handler for the parser
  51. protected SCSSDocumentHandlerImpl documentHandler;
  52. // the error handler for the parser
  53. protected ErrorHandler errorHandler;
  54. // the input source for the parser
  55. protected InputSource source;
  56. protected ConditionFactory conditionFactory;
  57. protected SelectorFactory selectorFactory;
  58. // temporary place holder for pseudo-element ...
  59. private String pseudoElt;
  60. /**
  61. * Creates a new Parser
  62. */
  63. public Parser() {
  64. this((CharStream) null);
  65. }
  66. /**
  67. * @@TODO
  68. * @exception CSSException Not yet implemented
  69. */
  70. public void setLocale(Locale locale) throws CSSException {
  71. throw new CSSException(CSSException.SAC_NOT_SUPPORTED_ERR);
  72. }
  73. /**
  74. * Set the document handler for this parser
  75. */
  76. public void setDocumentHandler(DocumentHandler handler) {
  77. this.documentHandler = (SCSSDocumentHandlerImpl) handler;
  78. }
  79. public void setSelectorFactory(SelectorFactory selectorFactory) {
  80. this.selectorFactory = selectorFactory;
  81. }
  82. public void setConditionFactory(ConditionFactory conditionFactory) {
  83. this.conditionFactory = conditionFactory;
  84. }
  85. /**
  86. * Set the error handler for this parser
  87. */
  88. public void setErrorHandler(ErrorHandler error) {
  89. this.errorHandler = error;
  90. }
  91. /**
  92. * Main parse methods
  93. *
  94. * @param source the source of the style sheet.
  95. * @exception IOException the source can't be parsed.
  96. * @exception CSSException the source is not CSS valid.
  97. */
  98. public void parseStyleSheet(InputSource source)
  99. throws CSSException, IOException {
  100. this.source = source;
  101. ReInit(getCharStreamWithLurk(source));
  102. if (selectorFactory == null) {
  103. selectorFactory = new SelectorFactoryImpl();
  104. }
  105. if (conditionFactory == null) {
  106. conditionFactory = new ConditionFactoryImpl();
  107. }
  108. parserUnit();
  109. }
  110. /**
  111. * Convenient method for URIs.
  112. *
  113. * @param systemId the fully resolved URI of the style sheet.
  114. * @exception IOException the source can't be parsed.
  115. * @exception CSSException the source is not CSS valid.
  116. */
  117. public void parseStyleSheet(String systemId)
  118. throws CSSException, IOException {
  119. parseStyleSheet(new InputSource(systemId));
  120. }
  121. /**
  122. * This method parses only one rule (style rule or at-rule, except @charset).
  123. *
  124. * @param source the source of the rule.
  125. * @exception IOException the source can't be parsed.
  126. * @exception CSSException the source is not CSS valid.
  127. */
  128. public void parseRule(InputSource source)
  129. throws CSSException, IOException {
  130. this.source = source;
  131. ReInit(getCharStreamWithLurk(source));
  132. if (selectorFactory == null) {
  133. selectorFactory = new SelectorFactoryImpl();
  134. }
  135. if (conditionFactory == null) {
  136. conditionFactory = new ConditionFactoryImpl();
  137. }
  138. _parseRule();
  139. }
  140. /**
  141. * This method parses a style declaration (including the surrounding curly
  142. * braces).
  143. *
  144. * @param source the source of the style declaration.
  145. * @exception IOException the source can't be parsed.
  146. * @exception CSSException the source is not CSS valid.
  147. */
  148. public void parseStyleDeclaration(InputSource source)
  149. throws CSSException, IOException {
  150. this.source = source;
  151. ReInit(getCharStreamWithLurk(source));
  152. if (selectorFactory == null) {
  153. selectorFactory = new SelectorFactoryImpl();
  154. }
  155. if (conditionFactory == null) {
  156. conditionFactory = new ConditionFactoryImpl();
  157. }
  158. _parseDeclarationBlock();
  159. }
  160. /**
  161. * This methods returns "http://www.w3.org/TR/REC-CSS2".
  162. * @return the string "http://www.w3.org/TR/REC-CSS2".
  163. */
  164. public String getParserVersion() {
  165. return "http://www.w3.org/TR/REC-CSS2";
  166. }
  167. /**
  168. * Parse methods used by DOM Level 2 implementation.
  169. */
  170. public void parseImportRule(InputSource source)
  171. throws CSSException, IOException {
  172. this.source = source;
  173. ReInit(getCharStreamWithLurk(source));
  174. if (selectorFactory == null) {
  175. selectorFactory = new SelectorFactoryImpl();
  176. }
  177. if (conditionFactory == null) {
  178. conditionFactory = new ConditionFactoryImpl();
  179. }
  180. _parseImportRule();
  181. }
  182. public void parseMediaRule(InputSource source)
  183. throws CSSException, IOException {
  184. this.source = source;
  185. ReInit(getCharStreamWithLurk(source));
  186. if (selectorFactory == null) {
  187. selectorFactory = new SelectorFactoryImpl();
  188. }
  189. if (conditionFactory == null) {
  190. conditionFactory = new ConditionFactoryImpl();
  191. }
  192. _parseMediaRule();
  193. }
  194. public SelectorList parseSelectors(InputSource source)
  195. throws CSSException, IOException {
  196. this.source = source;
  197. ReInit(getCharStreamWithLurk(source));
  198. if (selectorFactory == null) {
  199. selectorFactory = new SelectorFactoryImpl();
  200. }
  201. if (conditionFactory == null) {
  202. conditionFactory = new ConditionFactoryImpl();
  203. }
  204. return _parseSelectors();
  205. }
  206. public LexicalUnit parsePropertyValue(InputSource source)
  207. throws CSSException, IOException {
  208. this.source = source;
  209. ReInit(getCharStreamWithLurk(source));
  210. return expr();
  211. }
  212. public boolean parsePriority(InputSource source)
  213. throws CSSException, IOException {
  214. this.source = source;
  215. ReInit(getCharStreamWithLurk(source));
  216. return prio();
  217. }
  218. /**
  219. * Convert the source into a Reader. Used only by DOM Level 2 parser methods.
  220. */
  221. private Reader getReader(InputSource source) throws IOException {
  222. if (source.getCharacterStream() != null) {
  223. return source.getCharacterStream();
  224. } else if (source.getByteStream() != null) {
  225. // My DOM level 2 implementation doesn't use this case.
  226. if (source.getEncoding() == null) {
  227. // unknown encoding, use ASCII as default.
  228. return new InputStreamReader(source.getByteStream(), "ASCII");
  229. } else {
  230. return new InputStreamReader(source.getByteStream(),
  231. source.getEncoding());
  232. }
  233. } else {
  234. // systemId
  235. // @@TODO
  236. throw new CSSException("not yet implemented");
  237. }
  238. }
  239. /**
  240. * Convert the source into a CharStream with encoding informations.
  241. * The encoding can be found in the InputSource or in the CSS document.
  242. * Since this method marks the reader and make a reset after looking for
  243. * the charset declaration, you'll find the charset declaration into the
  244. * stream.
  245. */
  246. private CharStream getCharStreamWithLurk(InputSource source)
  247. throws CSSException, IOException {
  248. if (source.getCharacterStream() != null) {
  249. // all encoding are supposed to be resolved by the user
  250. // return the reader
  251. return new Generic_CharStream(source.getCharacterStream(), 1, 1);
  252. } else if (source.getByteStream() == null) {
  253. // @@CONTINUE ME. see also getReader() with systemId
  254. try {
  255. source.setByteStream(new URL(source.getURI()).openStream());
  256. } catch (Exception e) {
  257. try {
  258. source.setByteStream(new FileInputStream(source.getURI()));
  259. } catch (IOException ex) {
  260. throw new CSSException("invalid url ?");
  261. }
  262. }
  263. }
  264. String encoding = "ASCII";
  265. InputStream input = source.getByteStream();
  266. char c = ' ';
  267. if (!input.markSupported()) {
  268. input = new BufferedInputStream(input);
  269. source.setByteStream(input);
  270. }
  271. input.mark(100);
  272. c = (char) input.read();
  273. if (c == '@') {
  274. // hum, is it a charset ?
  275. int size = 100;
  276. byte[] buf = new byte[size];
  277. input.read(buf, 0, 7);
  278. String keyword = new String(buf, 0, 7);
  279. if (keyword.equals("charset")) {
  280. // Yes, this is the charset declaration !
  281. // here I don't use the right declaration : white space are ' '.
  282. while ((c = (char) input.read()) == ' ') {
  283. // find the first quote
  284. }
  285. char endChar = c;
  286. int i = 0;
  287. if ((endChar != '"') && (endChar != '\'')) {
  288. // hum this is not a quote.
  289. throw new CSSException("invalid charset declaration");
  290. }
  291. while ((c = (char) input.read()) != endChar) {
  292. buf[i++] = (byte) c;
  293. if (i == size) {
  294. byte[] old = buf;
  295. buf = new byte[size + 100];
  296. System.arraycopy(old, 0, buf, 0, size);
  297. size += 100;
  298. }
  299. }
  300. while ((c = (char) input.read()) == ' ') {
  301. // find the next relevant character
  302. }
  303. if (c != ';') {
  304. // no semi colon at the end ?
  305. throw new CSSException("invalid charset declaration: "
  306. + "missing semi colon");
  307. }
  308. encoding = new String(buf, 0, i);
  309. if (source.getEncoding() != null) {
  310. // compare the two encoding informations.
  311. // For example, I don't accept to have ASCII and after UTF-8.
  312. // Is it really good ? That is the question.
  313. if (!encoding.equals(source.getEncoding())) {
  314. throw new CSSException("invalid encoding information.");
  315. }
  316. }
  317. } // else no charset declaration available
  318. }
  319. // ok set the real encoding of this source.
  320. source.setEncoding(encoding);
  321. // set the real reader of this source.
  322. source.setCharacterStream(new InputStreamReader(source.getByteStream(),
  323. Encoding.getJavaEncoding(encoding)));
  324. // reset the stream (leave the charset declaration in the stream).
  325. input.reset();
  326. return new Generic_CharStream(source.getCharacterStream(), 1, 1);
  327. }
  328. private LocatorImpl currentLocator;
  329. private Locator getLocator() {
  330. if (currentLocator == null) {
  331. currentLocator = new LocatorImpl(this);
  332. return currentLocator;
  333. }
  334. return currentLocator.reInit(this);
  335. }
  336. private LocatorImpl getLocator(Token save) {
  337. if (currentLocator == null) {
  338. currentLocator = new LocatorImpl(this, save);
  339. return currentLocator;
  340. }
  341. return currentLocator.reInit(this, save);
  342. }
  343. private void reportError(Locator l, Exception e) {
  344. if (errorHandler != null) {
  345. if (e instanceof ParseException) {
  346. // construct a clean error message.
  347. ParseException pe = (ParseException) e;
  348. if (pe.specialConstructor) {
  349. StringBuffer errorM = new StringBuffer();
  350. if (pe.currentToken != null) {
  351. errorM.append("encountered \"")
  352. .append(pe.currentToken.next);
  353. }
  354. errorM.append('"');
  355. if (pe.expectedTokenSequences.length != 0) {
  356. errorM.append(". Was expecting one of: ");
  357. for (int i = 0; i < pe.expectedTokenSequences.length; i++) {
  358. for (int j = 0; j < pe.expectedTokenSequences[i].length; j++) {
  359. int kind = pe.expectedTokenSequences[i][j];
  360. if (kind != S) {
  361. errorM.append(pe.tokenImage[kind]);
  362. errorM.append(' ');
  363. }
  364. }
  365. }
  366. }
  367. errorHandler.error(new CSSParseException(errorM.toString(),
  368. l, e));
  369. } else {
  370. errorHandler.error(new CSSParseException(e.getMessage(),
  371. l, e));
  372. }
  373. } else if (e == null) {
  374. errorHandler.error(new CSSParseException("error", l, null));
  375. } else {
  376. errorHandler.error(new CSSParseException(e.getMessage(), l, e));
  377. }
  378. }
  379. }
  380. private void reportWarningSkipText(Locator l, String text) {
  381. if (errorHandler != null && text != null) {
  382. errorHandler.warning(new CSSParseException("Skipping: " + text, l));
  383. }
  384. }
  385. }
  386. PARSER_END(Parser)
  387. /*
  388. * The tokenizer
  389. */
  390. <DEFAULT>
  391. TOKEN :
  392. {
  393. < S : ( [ " ", "\t" , "\n" , "\r", "\f" ] )+ >
  394. { image = Parser.SPACE; }
  395. }
  396. <DEFAULT>
  397. MORE:
  398. {
  399. "#{" : IN_INTERPOLATION
  400. }
  401. <IN_INTERPOLATION>
  402. MORE:
  403. {
  404. < ~["}"]> : IN_INTERPOLATION
  405. }
  406. <IN_INTERPOLATION>
  407. SPECIAL_TOKEN:
  408. {
  409. <INTERPOLATION: "}"> : DEFAULT
  410. }
  411. <DEFAULT>
  412. MORE :
  413. {
  414. "//" : IN_SINGLE_LINE_COMMENT
  415. }
  416. <IN_SINGLE_LINE_COMMENT>
  417. MORE :
  418. {
  419. < ~["\n","\r"] > : IN_SINGLE_LINE_COMMENT
  420. }
  421. <IN_SINGLE_LINE_COMMENT>
  422. SKIP :
  423. {
  424. < "\n"|"\r"|"\r\n" > : DEFAULT
  425. }
  426. <DEFAULT>
  427. MORE :
  428. {
  429. <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
  430. |
  431. "/*" : IN_MULTI_LINE_COMMENT
  432. }
  433. <IN_FORMAL_COMMENT>
  434. SPECIAL_TOKEN :
  435. {
  436. <FORMAL_COMMENT: "*/" > : DEFAULT
  437. }
  438. <IN_MULTI_LINE_COMMENT>
  439. SKIP :
  440. {
  441. <MULTI_LINE_COMMENT: "*/" > : DEFAULT
  442. }
  443. <IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
  444. MORE :
  445. {
  446. < ~[] >
  447. }
  448. <DEFAULT>
  449. TOKEN :
  450. {
  451. < CDO : "<!--" >
  452. | < CDC : "-->" >
  453. | < LBRACE : "{" >
  454. | < RBRACE : "}">
  455. | < DASHMATCH : "|=" >
  456. | < INCLUDES : "~=" >
  457. | < EQ : "=" >
  458. | < PLUS : "+" >
  459. | < MINUS : "-" >
  460. | < COMMA : "," >
  461. | < SEMICOLON : ";" >
  462. | < PRECEDES : ">" >
  463. | < DIV : "/" >
  464. | < LBRACKET : "[" >
  465. | < RBRACKET : "]" >
  466. | < ANY : "*" >
  467. | < PARENT : "&" >
  468. | < DOT : "." >
  469. | < LPARAN : "(" >
  470. | < RPARAN : ")">
  471. }
  472. <DEFAULT>
  473. TOKEN :
  474. {
  475. < COLON : ":" >
  476. }
  477. <DEFAULT>
  478. TOKEN : /* basic tokens */
  479. {
  480. < NONASCII : ["\200"-"\377"] >
  481. | < #H : ["0"-"9", "a"-"f"] >
  482. | < #UNICODE : "\\" <H> ( <H> )? /* I can't say {1,6} */
  483. ( <H> )? ( <H> )?
  484. ( <H> )? ( <H> )?
  485. ( [ " ", "\t" , "\n" , "\r", "\f" ] )? >
  486. | < #ESCAPE : <UNICODE> | ( "\\" [ " "-"~","\200"-"\377" ] ) >
  487. | < #NMSTART : ("-")?[ "a"-"z"] | <NONASCII> | <ESCAPE> >
  488. | < #NMCHAR : ["a"-"z", "0"-"9", "-", "_"] | <NONASCII> | <ESCAPE> >
  489. | < #STRINGCHAR : [ "\t"," ","!","#","$","%","&","("-"~" ]
  490. | "\\\n" | "\\\r\n" | "\\\r" | "\\\f"
  491. | <NONASCII> | <ESCAPE> >
  492. | < #D : ["0"-"9"] >
  493. | < #NAME : ( <NMCHAR> )+ >
  494. }
  495. <DEFAULT>
  496. TOKEN :
  497. {
  498. <TO : "to">
  499. |<THROUGH : "through">
  500. |<EACH_IN : "in">
  501. }
  502. /* DERECTIVES */
  503. <DEFAULT>
  504. TOKEN :
  505. {
  506. <MIXIN_SYM : "@mixin">
  507. | <INCLUDE_SYM : "@include">
  508. | <FUNCTION_SYM : "@function">
  509. | <RETURN_SYM : "@return">
  510. | <DEBUG_SYM : "@debug">
  511. | <WARN_SYM : "@warn">
  512. | <FOR_SYM : "@for">
  513. | <EACH_SYM : "@each">
  514. | <WHILE_SYM : "@while">
  515. | <IF_SYM : "@if">
  516. | <ELSE_SYM : "@else">
  517. | <EXTEND_SYM : "@extend">
  518. | <MOZ_DOCUMENT_SYM : "@-moz-document">
  519. | <SUPPORTS_SYM : "@supports">
  520. }
  521. <DEFAULT>
  522. TOKEN:
  523. {
  524. < GUARDED_SYM : "!" ( <S> )? "default">
  525. }
  526. <DEFAULT>
  527. TOKEN :
  528. {
  529. < STRING : ( "\"" ( <STRINGCHAR> | "'" )* "\"" ) |
  530. ( "'" ( <STRINGCHAR> | "\"" )* "'" ) >
  531. | < IDENT : <NMSTART> ( <NMCHAR> )* >
  532. | < NUMBER : ( <D> )+ | ( <D> )* "." ( <D> )+ >
  533. | < #_URL : [ "!","#","$","%","&","*"-"~" ] | <NONASCII> | <ESCAPE> >
  534. | < URL : "url(" ( <S> )*
  535. ( <STRING> | ( <_URL> )* ) ( <S> )* ")" >
  536. }
  537. <DEFAULT>
  538. TOKEN:
  539. {
  540. < VARIABLE : "$" <IDENT>>
  541. }
  542. <DEFAULT>
  543. TOKEN :
  544. {
  545. < PERCENTAGE : <NUMBER> "%" >
  546. | < PT : <NUMBER> "pt" >
  547. | < MM : <NUMBER> "mm" >
  548. | < CM : <NUMBER> "cm" >
  549. | < PC : <NUMBER> "pc" >
  550. | < IN : <NUMBER> "in" >
  551. | < PX : <NUMBER> "px" >
  552. | < EMS : <NUMBER> "em" >
  553. | < EXS : <NUMBER> "ex" >
  554. | < DEG : <NUMBER> "deg" >
  555. | < RAD : <NUMBER> "rad" >
  556. | < GRAD : <NUMBER> "grad" >
  557. | < MS : <NUMBER> "ms" >
  558. | < SECOND : <NUMBER> "s" >
  559. | < HZ : <NUMBER> "Hz" >
  560. | < KHZ : <NUMBER> "kHz" >
  561. | < DIMEN : <NUMBER> <IDENT> >
  562. }
  563. <DEFAULT>
  564. TOKEN :
  565. {
  566. < HASH : "#" <NAME> >
  567. }
  568. /* RESERVED ATRULE WORDS */
  569. <DEFAULT>
  570. TOKEN :
  571. {
  572. < IMPORT_SYM : "@import">
  573. | < MEDIA_SYM : "@media" >
  574. | < CHARSET_SYM : "@charset" >
  575. | < PAGE_SYM : "@page" >
  576. | < FONT_FACE_SYM: "@font-face" >
  577. | < ATKEYWORD : "@" <IDENT> >
  578. }
  579. <DEFAULT>
  580. TOKEN :
  581. {
  582. < IMPORTANT_SYM : "!" ( <S> )? "important" >
  583. }
  584. <DEFAULT>
  585. TOKEN :
  586. {
  587. < #RANGE0 : <H> <H> <H> <H> <H> >
  588. | < #RANGE1 : <H> <H> <H> <H> <H> ( "?" )? >
  589. | < #RANGE2 : <H> <H> <H> <H> ( "?" )? ( "?" )? >
  590. | < #RANGE3 : <H> <H> <H> ( "?" )? ( "?" )? ( "?" )? >
  591. | < #RANGE4 : <H> <H> ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
  592. | < #RANGE5 : <H> ( "?" )? ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
  593. | < #RANGE6 : "?" ( "?" )? ( "?" )? ( "?" )? ( "?" )? ( "?" )? >
  594. | < #RANGE : <RANGE0> | <RANGE1> | <RANGE2>
  595. | <RANGE3> | <RANGE4> | <RANGE5> | <RANGE6> >
  596. | < #UNI : <H> ( <H> )? ( <H> )? ( <H> )? ( <H> )? ( <H> )? >
  597. | < UNICODERANGE : "U+" <RANGE>
  598. | "U+" <UNI> "-" <UNI> >
  599. }
  600. <DEFAULT>
  601. TOKEN :
  602. {
  603. < FUNCTION : <IDENT> "(" >
  604. }
  605. <DEFAULT, IN_MULTI_LINE_COMMENT>
  606. TOKEN :
  607. { /* avoid token manager error */
  608. < UNKNOWN : ~[] >
  609. }
  610. /*
  611. * The grammar of CSS2
  612. */
  613. /**
  614. * The main entry for the parser.
  615. *
  616. * @exception ParseException exception during the parse
  617. */
  618. void parserUnit() :
  619. {}
  620. {
  621. try {
  622. { documentHandler.startDocument(source); }
  623. ( charset() )?
  624. ( <S> | ignoreStatement() )*
  625. ( importDeclaration() ( ignoreStatement() ( <S> )* )* )*
  626. afterImportDeclaration()
  627. <EOF>
  628. } finally {
  629. documentHandler.endDocument(source);
  630. }
  631. }
  632. void charset() :
  633. { Token n; }
  634. {
  635. try {
  636. <CHARSET_SYM> ( <S> )* n=<STRING> ( <S> )* ";"
  637. } catch (ParseException e) {
  638. reportError(getLocator(e.currentToken.next), e);
  639. skipStatement();
  640. // reportWarningSkipText(getLocator(), skipStatement());
  641. } catch (Exception e) {
  642. reportError(getLocator(), e);
  643. skipStatement();
  644. // reportWarningSkipText(getLocator(), skipStatement());
  645. }
  646. }
  647. void afterImportDeclaration() :
  648. {String ret;
  649. Locator l;
  650. }
  651. {
  652. ( ( variable() | mixinDirective() | includeDirective() | styleRule() | media()| page() | fontFace()
  653. | { l = getLocator(); } ret=skipStatement()
  654. {
  655. if ((ret == null) || (ret.length() == 0)) {
  656. return;
  657. }
  658. reportWarningSkipText(l, ret);
  659. if (ret.charAt(0) == '@') {
  660. documentHandler.ignorableAtRule(ret);
  661. }
  662. }
  663. )
  664. ( ignoreStatement() ( <S> )* )* )*
  665. }
  666. void ignoreStatement() :
  667. {}
  668. {
  669. <CDO> | <CDC> | atRuleDeclaration()
  670. }
  671. /**
  672. * The import statement
  673. *
  674. * @exception ParseException exception during the parse
  675. */
  676. void importDeclaration() :
  677. {Token n;
  678. String uri;
  679. MediaListImpl ml = new MediaListImpl();
  680. boolean isURL = false;
  681. }
  682. {
  683. try {
  684. <IMPORT_SYM>
  685. ( <S> )* ( n=<STRING> { uri = convertStringIndex(n.image, 1,
  686. n.image.length() -1); }
  687. | n=<URL>
  688. {
  689. isURL=true;
  690. uri = n.image.substring(4, n.image.length()-1).trim();
  691. if ((uri.charAt(0) == '"')
  692. || (uri.charAt(0) == '\'')) {
  693. uri = uri.substring(1, uri.length()-1);
  694. }
  695. }
  696. )
  697. ( <S> )* ( mediaStatement(ml) )? ";"
  698. ( <S> )*
  699. {
  700. if (ml.getLength() == 0) {
  701. // see section 6.3 of the CSS2 recommandation.
  702. ml.addItem("all");
  703. }
  704. documentHandler.importStyle(uri, ml, isURL);
  705. }
  706. } catch (ParseException e) {
  707. reportError(getLocator(), e);
  708. skipStatement();
  709. // reportWarningSkipText(getLocator(), skipStatement());
  710. }
  711. }
  712. /**
  713. * @exception ParseException exception during the parse
  714. */
  715. void media() :
  716. {
  717. boolean start = false;
  718. String ret;
  719. MediaListImpl ml = new MediaListImpl();
  720. }
  721. {
  722. try {
  723. <MEDIA_SYM> ( <S> )*
  724. mediaStatement(ml)
  725. { start = true; documentHandler.startMedia(ml); }
  726. <LBRACE> ( <S> )* ( styleRule() | skipUnknownRule() )* <RBRACE> ( <S> )*
  727. } catch (ParseException e) {
  728. reportError(getLocator(), e);
  729. skipStatement();
  730. // reportWarningSkipText(getLocator(), skipStatement());
  731. } finally {
  732. if (start) {
  733. documentHandler.endMedia(ml);
  734. }
  735. }
  736. }
  737. void mediaStatement(MediaListImpl ml) :
  738. {
  739. String m;
  740. }
  741. {
  742. m=medium() ( <COMMA> ( <S> )* { ml.addItem(m); } m=medium() )*
  743. { ml.addItem(m); }
  744. }
  745. /**
  746. * @exception ParseException exception during the parse
  747. */
  748. String medium() : /* tv, projection, screen, ... */
  749. {Token n;}
  750. {
  751. n=<IDENT> ( <S> )* { return convertIdent(n.image); }
  752. }
  753. /**
  754. * @exception ParseException exception during the parse
  755. */
  756. void page() :
  757. {
  758. boolean start = false;
  759. Token n = null;
  760. String page = null;
  761. String pseudo = null;
  762. }
  763. {
  764. try {
  765. <PAGE_SYM> ( <S> )* ( n=<IDENT> ( <S> )* )?
  766. ( pseudo=pseudo_page() )?
  767. {
  768. if (n != null) {
  769. page = convertIdent(n.image);
  770. }
  771. }
  772. <LBRACE> (<S>)*
  773. {
  774. start = true;
  775. documentHandler.startPage(page, pseudo);
  776. }
  777. ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
  778. <RBRACE> (<S>)*
  779. } catch (ParseException e) {
  780. if (errorHandler != null) {
  781. LocatorImpl li = new LocatorImpl(this,
  782. e.currentToken.next.beginLine,
  783. e.currentToken.next.beginColumn-1);
  784. reportError(li, e);
  785. skipStatement();
  786. // reportWarningSkipText(li, skipStatement());
  787. } else {
  788. skipStatement();
  789. }
  790. } finally {
  791. if (start) {
  792. documentHandler.endPage(page, pseudo);
  793. }
  794. }
  795. }
  796. String pseudo_page() :
  797. { Token n; }
  798. {
  799. ":" n=<IDENT> ( <S> )* { return convertIdent(n.image); }
  800. }
  801. void fontFace() :
  802. {
  803. boolean start = false;
  804. }
  805. {
  806. try {
  807. <FONT_FACE_SYM> ( <S> )*
  808. <LBRACE> (<S>)*
  809. { start = true; documentHandler.startFontFace(); }
  810. ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
  811. <RBRACE> (<S>)*
  812. } catch (ParseException e) {
  813. reportError(getLocator(), e);
  814. skipStatement();
  815. // reportWarningSkipText(getLocator(), skipStatement());
  816. } finally {
  817. if (start) {
  818. documentHandler.endFontFace();
  819. }
  820. }
  821. }
  822. /**
  823. * @exception ParseException exception during the parse
  824. */
  825. void atRuleDeclaration() :
  826. {Token n;
  827. String ret;
  828. }
  829. {
  830. n=<ATKEYWORD>
  831. {
  832. ret=skipStatement();
  833. reportWarningSkipText(getLocator(), ret);
  834. if ((ret != null) && (ret.charAt(0) == '@')) {
  835. documentHandler.ignorableAtRule(ret);
  836. }
  837. }
  838. }
  839. void skipUnknownRule() :
  840. { Token n;}
  841. {
  842. ( n=<ATKEYWORD>
  843. | n=<CDO>
  844. | n=<CHARSET_SYM>
  845. | n=<COMMA>
  846. | n=<DASHMATCH>
  847. | n=<FONT_FACE_SYM>
  848. | n=<FUNCTION>
  849. | n=<IMPORTANT_SYM>
  850. | n=<IMPORT_SYM>
  851. | n=<INCLUDES>
  852. | n=<LBRACE>
  853. | n=<MEDIA_SYM>
  854. | n=<NONASCII>
  855. | n=<NUMBER>
  856. | n=<PAGE_SYM>
  857. | n=<PERCENTAGE>
  858. | n=<STRING>
  859. | n=<UNICODERANGE>
  860. | n=<URL>
  861. | n=";"
  862. | n="+"
  863. | n=">"
  864. | n="-"
  865. | n=<UNKNOWN>
  866. ) {
  867. String ret;
  868. Locator loc = getLocator();
  869. ret=skipStatement();
  870. reportWarningSkipText(loc, ret);
  871. if ((ret != null) && (n.image.charAt(0) == '@')) {
  872. documentHandler.ignorableAtRule(ret);
  873. }
  874. }
  875. }
  876. /**
  877. * @exception ParseException exception during the parse
  878. */
  879. char combinator() :
  880. {
  881. char connector = ' ';
  882. }
  883. {
  884. "+" ( <S> )* { return '+'; }
  885. | ">" ( <S> )* { return '>'; }
  886. | <S> ( ( "+" { connector = '+'; }
  887. | ">" { connector = '>'; } )
  888. ( <S> )* )? { return connector; }
  889. }
  890. /**
  891. * @exception ParseException exception during the parse
  892. */
  893. String property() :
  894. {Token n; }
  895. {
  896. n=<IDENT> ( <S> )* { return convertIdent(n.image); }
  897. }
  898. String variableName() :
  899. {Token n;}
  900. {
  901. n=<VARIABLE> (<S>)* {return convertIdent(n.image.substring(1));}
  902. }
  903. String functionName() :
  904. {Token n;}
  905. {
  906. n=<FUNCTION> ( <S> )* {return convertIdent(n.image.substring(0, n.image.length()-1));}
  907. }
  908. /**
  909. * @exception ParseException exception during the parse
  910. */
  911. void styleRule() :
  912. {
  913. boolean start = false;
  914. SelectorList l = null;
  915. Token save;
  916. Locator loc;
  917. }
  918. {
  919. try {
  920. l=selectorList() { save = token; } <LBRACE> (<S>)*
  921. {
  922. start = true;
  923. documentHandler.startSelector(l);
  924. }
  925. ( includeDirective() | media() | extendDirective()| variable() | LOOKAHEAD(3) declarationOrNestedProperties() | styleRule())*
  926. <RBRACE> (<S>)*
  927. } catch (ThrowedParseException e) {
  928. if (errorHandler != null) {
  929. LocatorImpl li = new LocatorImpl(this,
  930. e.e.currentToken.next.beginLine,
  931. e.e.currentToken.next.beginColumn-1);
  932. reportError(li, e.e);
  933. }
  934. } catch (ParseException e) {
  935. reportError(getLocator(), e);
  936. skipStatement();
  937. // reportWarningSkipText(getLocator(), skipStatement());
  938. } catch (TokenMgrError e) {
  939. reportWarningSkipText(getLocator(), skipStatement());
  940. } finally {
  941. if (start) {
  942. documentHandler.endSelector(l);
  943. }
  944. }
  945. }
  946. SelectorList selectorList() :
  947. {
  948. SelectorListImpl selectors = new SelectorListImpl();
  949. Selector selector;
  950. }
  951. {
  952. selector=selector() ( <COMMA> (<S>)* { selectors.addSelector(selector); }
  953. selector=selector() )*
  954. { selectors.addSelector(selector);
  955. return selectors;
  956. }
  957. }
  958. /**
  959. * @exception ParseException exception during the parse
  960. */
  961. Selector selector() :
  962. {
  963. Selector selector;
  964. char comb;
  965. }
  966. {
  967. try {
  968. selector=simple_selector(null, ' ')
  969. ( LOOKAHEAD(2) comb=combinator()
  970. selector=simple_selector(selector, comb) )* (<S>)*
  971. {
  972. return selector;
  973. }
  974. } catch (ParseException e) {
  975. /*
  976. Token t = getToken(1);
  977. StringBuffer s = new StringBuffer();
  978. s.append(getToken(0).image);
  979. while ((t.kind != COMMA) && (t.kind != SEMICOLON)
  980. && (t.kind != LBRACE) && (t.kind != EOF)) {
  981. s.append(t.image);
  982. getNextToken();
  983. t = getToken(1);
  984. }
  985. reportWarningSkipText(getLocator(), s.toString());
  986. */
  987. Token t = getToken(1);
  988. while ((t.kind != COMMA) && (t.kind != SEMICOLON)
  989. && (t.kind != LBRACE) && (t.kind != EOF)) {
  990. getNextToken();
  991. t = getToken(1);
  992. }
  993. throw new ThrowedParseException(e);
  994. }
  995. }
  996. /**
  997. * @exception ParseException exception during the parse
  998. */
  999. Selector simple_selector(Selector selector, char comb) :
  1000. {
  1001. SimpleSelector simple_current = null;
  1002. Condition cond = null;
  1003. pseudoElt = null;
  1004. }
  1005. {
  1006. ( simple_current=element_name()
  1007. ( cond=hash(cond) | cond=_class(cond)
  1008. | cond=attrib(cond) | cond=pseudo(cond) )*
  1009. | cond=hash(cond) ( cond=_class(cond)
  1010. | cond=attrib(cond) | cond=pseudo(cond) )*
  1011. | cond=_class(cond) ( cond=hash(cond) | cond=_class(cond)
  1012. | cond=attrib(cond) | cond=pseudo(cond) )*
  1013. | cond=pseudo(cond) ( cond=hash(cond) | cond=_class(cond)
  1014. | cond=attrib(cond) | cond=pseudo(cond) )*
  1015. | cond=attrib(cond) ( cond=hash(cond) | cond=_class(cond)
  1016. | cond=attrib(cond) | cond=pseudo(cond) )*
  1017. )
  1018. {
  1019. if (simple_current == null) {
  1020. simple_current = selectorFactory.createElementSelector(null, null);
  1021. }
  1022. if (cond != null) {
  1023. simple_current = selectorFactory.createConditionalSelector(simple_current,
  1024. cond);
  1025. }
  1026. if (selector != null) {
  1027. switch (comb) {
  1028. case ' ':
  1029. selector = selectorFactory.createDescendantSelector(selector,
  1030. simple_current);
  1031. break;
  1032. case '+':
  1033. selector =
  1034. selectorFactory.createDirectAdjacentSelector((short) 1,
  1035. selector,
  1036. simple_current);
  1037. break;
  1038. case '>':
  1039. selector = selectorFactory.createChildSelector(selector,
  1040. simple_current);
  1041. break;
  1042. default:
  1043. throw new ParseException("invalid state. send a bug report");
  1044. }
  1045. } else {
  1046. selector= simple_current;
  1047. }
  1048. if (pseudoElt != null) {
  1049. selector = selectorFactory.createChildSelector(selector,
  1050. selectorFactory.createPseudoElementSelector(null, pseudoElt));
  1051. }
  1052. return selector;
  1053. }
  1054. }
  1055. /**
  1056. * @exception ParseException exception during the parse
  1057. */
  1058. Condition _class(Condition pred) :
  1059. {Token n;
  1060. Condition c;
  1061. }
  1062. {
  1063. "." n=<IDENT>
  1064. {
  1065. c = conditionFactory.createClassCondition(null, n.image);
  1066. if (pred == null) {
  1067. return c;
  1068. } else {
  1069. return conditionFactory.createAndCondition(pred, c);
  1070. }
  1071. }
  1072. }
  1073. /**
  1074. * @exception ParseException exception during the parse
  1075. */
  1076. SimpleSelector element_name() :
  1077. {Token n; }
  1078. {
  1079. n=<IDENT>
  1080. {
  1081. return selectorFactory.createElementSelector(null, convertIdent(n.image));
  1082. }
  1083. | "*"
  1084. { return selectorFactory.createElementSelector(null, "*"); }
  1085. | "&"
  1086. { return selectorFactory.createElementSelector(null, "&"); }
  1087. }
  1088. /**
  1089. * @exception ParseException exception during the parse
  1090. */
  1091. Condition attrib(Condition pred) :
  1092. {
  1093. int cases = 0;
  1094. Token att = null;
  1095. Token val = null;
  1096. String attValue = null;
  1097. }
  1098. {
  1099. "[" ( <S> )* att=<IDENT> ( <S> )*
  1100. ( ( "=" { cases = 1; }
  1101. | <INCLUDES> { cases = 2; }
  1102. | <DASHMATCH> { cases = 3; } ) ( <S> )*
  1103. ( val=<IDENT> { attValue = val.image; }
  1104. | val=<STRING> { attValue = convertStringIndex(val.image, 1,
  1105. val.image.length() -1);}
  1106. )
  1107. ( <S> )* )?
  1108. "]"
  1109. {
  1110. String name = convertIdent(att.image);
  1111. Condition c;
  1112. switch (cases) {
  1113. case 0:
  1114. c = conditionFactory.createAttributeCondition(name, null, false, null);
  1115. break;
  1116. case 1:
  1117. c = conditionFactory.createAttributeCondition(name, null, false,
  1118. attValue);
  1119. break;
  1120. case 2:
  1121. c = conditionFactory.createOneOfAttributeCondition(name, null, false,
  1122. attValue);
  1123. break;
  1124. case 3:
  1125. c = conditionFactory.createBeginHyphenAttributeCondition(name, null,
  1126. false,
  1127. attValue);
  1128. break;
  1129. default:
  1130. // never reached.
  1131. c = null;
  1132. }
  1133. if (pred == null) {
  1134. return c;
  1135. } else {
  1136. return conditionFactory.createAndCondition(pred, c);
  1137. }
  1138. }
  1139. }
  1140. /**
  1141. * @exception ParseException exception during the parse
  1142. */
  1143. Condition pseudo(Condition pred) :
  1144. {Token n;
  1145. Token language;
  1146. boolean isPseudoElement = false;
  1147. }
  1148. {
  1149. ":" (":"{isPseudoElement=true;})?( n=<IDENT>
  1150. {
  1151. String s = convertIdent(n.image);
  1152. if (isPseudoElement) {
  1153. if (pseudoElt != null) {
  1154. throw new CSSParseException("duplicate pseudo element definition "
  1155. + s, getLocator());
  1156. } else {
  1157. pseudoElt = s;
  1158. return pred;
  1159. }
  1160. } else {
  1161. Condition c =
  1162. conditionFactory.createPseudoClassCondition(null, s);
  1163. if (pred == null) {
  1164. return c;
  1165. } else {
  1166. return conditionFactory.createAndCondition(pred, c);
  1167. }
  1168. }
  1169. }
  1170. | ( n=<FUNCTION> ( <S> )* language=<IDENT> ( <S> )* ")"
  1171. {
  1172. String f = convertIdent(n.image);
  1173. if (f.equals("lang(")) {
  1174. Condition d =
  1175. conditionFactory.createLangCondition(convertIdent(language.image));
  1176. if (pred == null) {
  1177. return d;
  1178. } else {
  1179. return conditionFactory.createAndCondition(pred, d);
  1180. }
  1181. } else {
  1182. throw new CSSParseException("invalid pseudo function name "
  1183. + f, getLocator());
  1184. }
  1185. }
  1186. )
  1187. )
  1188. }
  1189. /**
  1190. * @exception ParseException exception during the parse
  1191. */
  1192. Condition hash(Condition pred) :
  1193. {Token n; }
  1194. {
  1195. n=<HASH>
  1196. {
  1197. Condition d =
  1198. conditionFactory.createIdCondition(n.image.substring(1));
  1199. if (pred == null) {
  1200. return d;
  1201. } else {
  1202. return conditionFactory.createAndCondition(pred, d);
  1203. }
  1204. }
  1205. }
  1206. void variable() :
  1207. {
  1208. String name;
  1209. LexicalUnit exp = null;
  1210. boolean guarded = false;
  1211. String raw;
  1212. }
  1213. {
  1214. try{
  1215. name = variableName()
  1216. ":" ( <S> )* exp=expr() ( guarded=guarded() )?(";"(<S>)*)+
  1217. //raw=skipStatementUntilSemiColon()
  1218. {
  1219. documentHandler.variable(name, exp, guarded);
  1220. }
  1221. }catch (JumpException e) {
  1222. skipAfterExpression();
  1223. } catch (NumberFormatException e) {
  1224. if (errorHandler != null) {
  1225. errorHandler.error(new CSSParseException("Invalid number "
  1226. + e.getMessage(),
  1227. getLocator(),
  1228. e));
  1229. }
  1230. reportWarningSkipText(getLocator(), skipAfterExpression());
  1231. } catch (ParseException e) {
  1232. if (errorHandler != null) {
  1233. if (e.currentToken != null) {
  1234. LocatorImpl li = new LocatorImpl(this,
  1235. e.currentToken.next.beginLine,
  1236. e.currentToken.next.beginColumn-1);
  1237. reportError(li, e);
  1238. } else {
  1239. reportError(getLocator(), e);
  1240. }
  1241. skipAfterExpression();
  1242. } else {
  1243. skipAfterExpression();
  1244. }
  1245. }
  1246. }
  1247. void mixinDirective() :
  1248. {
  1249. String name;
  1250. ArrayList<VariableNode> args = null;
  1251. String body;
  1252. }
  1253. {
  1254. <MIXIN_SYM>
  1255. (<S>)*
  1256. (name = property()
  1257. |(name = functionName()
  1258. args = arglist()) <RPARAN> (<S>)*) <LBRACE> (<S>)*
  1259. {documentHandler.startMixinDirective(name, args);}
  1260. ( includeDirective() | media() | extendDirective()| variable() | LOOKAHEAD(3) declarationOrNestedProperties() | styleRule())*
  1261. //(includeDirective() | media() | LOOKAHEAD(declaration()) declaration()";"(<S>)* | styleRule())*
  1262. <RBRACE>(<S>)*
  1263. {documentHandler.endMixinDirective(name, args);}
  1264. }
  1265. ArrayList<VariableNode> arglist() :
  1266. {
  1267. ArrayList<VariableNode> args = new ArrayList<VariableNode>();
  1268. VariableNode arg;
  1269. }
  1270. {
  1271. arg=mixinArg() ( <COMMA> (<S>)* { args.add(arg); }
  1272. arg=mixinArg() )*
  1273. { args.add(arg);
  1274. return args;
  1275. }
  1276. }
  1277. VariableNode mixinArg() :
  1278. {
  1279. String name;
  1280. LexicalUnit value = null;
  1281. }
  1282. {
  1283. name=variableName() (":" (<S>)* value=term(null) )?
  1284. {
  1285. VariableNode arg = new VariableNode(name, value, false);
  1286. return arg;
  1287. }
  1288. }
  1289. ArrayList<LexicalUnit> argValuelist() :
  1290. {
  1291. ArrayList<LexicalUnit> args = new ArrayList<LexicalUnit>();
  1292. LexicalUnit argValue;
  1293. }
  1294. {
  1295. argValue= term(null) { args.add(argValue); }
  1296. ( <COMMA> (<S>)* argValue = term(null)
  1297. {args.add(argValue);}
  1298. )*
  1299. {return args;}
  1300. }
  1301. void includeDirective() :
  1302. {
  1303. String name;
  1304. ArrayList<LexicalUnit> args=null;
  1305. }
  1306. {
  1307. <INCLUDE_SYM>
  1308. (<S>)*
  1309. (name = property()
  1310. |(name = functionName()
  1311. args = argValuelist()) <RPARAN>)(";"(<S>)*)+
  1312. {documentHandler.includeDirective(name, args);}
  1313. }
  1314. Node functionDirective() :
  1315. {
  1316. String name;
  1317. String args = null;
  1318. String body;
  1319. int[] stops = {RPARAN};
  1320. }
  1321. {
  1322. (name=functionName() args = skipStatementUntilRightParan() <RPARAN>)
  1323. (<S>)*
  1324. body = skipStatement()
  1325. {
  1326. return null;
  1327. }
  1328. }
  1329. Node returnDirective() :
  1330. {
  1331. String raw;
  1332. }
  1333. {
  1334. raw = skipStatement()
  1335. {return null;}
  1336. }
  1337. JAVACODE
  1338. void debugDirective(){
  1339. }
  1340. JAVACODE
  1341. void warnDirective(){
  1342. }
  1343. Node forDirective() :
  1344. {
  1345. String var;
  1346. String from;
  1347. String to;
  1348. boolean exclusive;
  1349. String body;
  1350. Token tok;
  1351. }
  1352. {
  1353. var = variableName()
  1354. {
  1355. int[] toThrough = {TO, THROUGH};
  1356. from = skipStatementUntil(toThrough);
  1357. }
  1358. (tok = <TO> {exclusive = true;}
  1359. | tok = <THROUGH> {exclusive = false;})
  1360. to = skipStatementUntilLeftBrace()
  1361. (<S>)*
  1362. body = skipStatement()
  1363. {return documentHandler.forDirective(var, from, to, exclusive, body);}
  1364. }
  1365. Node eachDirective() :
  1366. {
  1367. String var;
  1368. String list;
  1369. String body;
  1370. }
  1371. {
  1372. var = variableName()
  1373. <EACH_IN> (<S>)*
  1374. list = skipStatementUntilLeftBrace()
  1375. body = skipStatement()
  1376. {
  1377. return documentHandler.eachDirective(var, list, body);
  1378. }
  1379. }
  1380. Node whileDirective() :
  1381. {
  1382. String condition;
  1383. String body;
  1384. }
  1385. {
  1386. condition = skipStatementUntilLeftBrace()
  1387. body = skipStatement()
  1388. { return documentHandler.whileDirective(condition, body);}
  1389. }
  1390. JAVACODE
  1391. Node ifDirective(){
  1392. return documentHandler.ifDirective();
  1393. }
  1394. JAVACODE
  1395. void elseDirective(){
  1396. // throw new ParseException("Invalid CSS: @else must come after @if");
  1397. }
  1398. void extendDirective() :
  1399. {SelectorList list;}
  1400. {
  1401. <EXTEND_SYM>
  1402. (<S>)*
  1403. list = selectorList()
  1404. (";"(<S>)*)+
  1405. {documentHandler.extendDirective(list);}
  1406. }
  1407. JAVACODE
  1408. Node importDirective(){
  1409. return null;
  1410. }
  1411. JAVACODE
  1412. Node charsetDirective(){
  1413. return null;
  1414. }
  1415. JAVACODE
  1416. Node mozDocumentDirective(){
  1417. return null;
  1418. }
  1419. JAVACODE
  1420. Node supportsDirective(){
  1421. return null;
  1422. }
  1423. void nestedProperties():
  1424. {String name;
  1425. LexicalUnit exp;}
  1426. {
  1427. name=property()
  1428. ":" ( <S> )*
  1429. <LBRACE> (<S>)*
  1430. {
  1431. documentHandler.startNestedProperties(name);
  1432. }
  1433. ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
  1434. <RBRACE>
  1435. {
  1436. documentHandler.endNestedProperties(name);
  1437. }
  1438. (<S>)*
  1439. }
  1440. /**
  1441. * @exception ParseException exception during the parse
  1442. */
  1443. void declarationOrNestedProperties() :
  1444. { boolean important = false;
  1445. String name;
  1446. LexicalUnit exp;
  1447. Token save;
  1448. }
  1449. {
  1450. try {
  1451. name=property()
  1452. { save = token; }
  1453. ":" ( <S> )*
  1454. (exp=expr() ( important=prio() )?
  1455. {
  1456. Token next = getToken(1);
  1457. if(next.kind == SEMICOLON || next.kind == RBRACE){
  1458. while(next.kind == SEMICOLON){
  1459. skipStatement();
  1460. next = getToken(1);
  1461. }
  1462. if(token.specialToken!=null){
  1463. documentHandler.property(name, exp, important, token.specialToken.image);
  1464. }else{
  1465. documentHandler.property(name, exp, important, null);
  1466. }
  1467. }
  1468. }
  1469. |<LBRACE> (<S>)*
  1470. {
  1471. documentHandler.startNestedProperties(name);
  1472. }
  1473. ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
  1474. <RBRACE>(<S>)*
  1475. {
  1476. documentHandler.endNestedProperties(name);
  1477. }
  1478. )
  1479. } catch (JumpException e) {
  1480. skipAfterExpression();
  1481. // reportWarningSkipText(getLocator(), skipAfterExpression());
  1482. } catch (NumberFormatException e) {
  1483. if (errorHandler != null) {
  1484. errorHandler.error(new CSSParseException("Invalid number "
  1485. + e.getMessage(),
  1486. getLocator(),
  1487. e));
  1488. }
  1489. reportWarningSkipText(getLocator(), skipAfterExpression());
  1490. } catch (ParseException e) {
  1491. if (errorHandler != null) {
  1492. if (e.currentToken != null) {
  1493. LocatorImpl li = new LocatorImpl(this,
  1494. e.currentToken.next.beginLine,
  1495. e.currentToken.next.beginColumn-1);
  1496. reportError(li, e);
  1497. } else {
  1498. reportError(getLocator(), e);
  1499. }
  1500. skipAfterExpression();
  1501. /*
  1502. LocatorImpl loc = (LocatorImpl) getLocator();
  1503. loc.column--;
  1504. reportWarningSkipText(loc, skipAfterExpression());
  1505. */
  1506. } else {
  1507. skipAfterExpression();
  1508. }
  1509. }
  1510. }
  1511. /**
  1512. * @exception ParseException exception during the parse
  1513. */
  1514. void declaration() :
  1515. { boolean important = false;
  1516. String name;
  1517. LexicalUnit exp;
  1518. Token save;
  1519. }
  1520. {
  1521. try {
  1522. name=property()
  1523. { save = token; }
  1524. ":" ( <S> )* exp=expr() ( important=prio() )?
  1525. {
  1526. documentHandler.property(name, exp, important);
  1527. }
  1528. } catch (JumpException e) {
  1529. skipAfterExpression();
  1530. // reportWarningSkipText(getLocator(), skipAfterExpression());
  1531. } catch (NumberFormatException e) {
  1532. if (errorHandler != null) {
  1533. errorHandler.error(new CSSParseException("Invalid number "
  1534. + e.getMessage(),
  1535. getLocator(),
  1536. e));
  1537. }
  1538. reportWarningSkipText(getLocator(), skipAfterExpression());
  1539. } catch (ParseException e) {
  1540. if (errorHandler != null) {
  1541. if (e.currentToken != null) {
  1542. LocatorImpl li = new LocatorImpl(this,
  1543. e.currentToken.next.beginLine,
  1544. e.currentToken.next.beginColumn-1);
  1545. reportError(li, e);
  1546. } else {
  1547. reportError(getLocator(), e);
  1548. }
  1549. skipAfterExpression();
  1550. /*
  1551. LocatorImpl loc = (LocatorImpl) getLocator();
  1552. loc.column--;
  1553. reportWarningSkipText(loc, skipAfterExpression());
  1554. */
  1555. } else {
  1556. skipAfterExpression();
  1557. }
  1558. }
  1559. }
  1560. /**
  1561. * @exception ParseException exception during the parse
  1562. */
  1563. boolean prio() :
  1564. {}
  1565. {
  1566. <IMPORTANT_SYM> ( <S> )* { return true; }
  1567. }
  1568. boolean guarded() :
  1569. {}
  1570. {
  1571. <GUARDED_SYM> (<S>)* {return true;}
  1572. }
  1573. /**
  1574. * @exception ParseException exception during the parse
  1575. */
  1576. LexicalUnitImpl operator(LexicalUnitImpl prev) :
  1577. {Token n;}
  1578. {
  1579. n="/" ( <S> )* { return LexicalUnitImpl.createSlash(n.beginLine,
  1580. n.beginColumn,
  1581. prev); }
  1582. | n="," ( <S> )* { return LexicalUnitImpl.createComma(n.beginLine,
  1583. n.beginColumn,
  1584. prev); }
  1585. }
  1586. /**
  1587. * @exception ParseException exception during the parse
  1588. */
  1589. LexicalUnit expr() :
  1590. {
  1591. LexicalUnitImpl first, res;
  1592. char op;
  1593. }
  1594. {
  1595. first=term(null){ res = first; }
  1596. ( LOOKAHEAD(2) ( res=operator(res) )? res=term(res))*
  1597. { return first; }
  1598. }
  1599. /**
  1600. * @exception ParseException exception during the parse
  1601. */
  1602. char unaryOperator() :
  1603. {}
  1604. {
  1605. "-" { return '-'; }
  1606. | "+" { return '+'; }
  1607. }
  1608. /**
  1609. * @exception ParseException exception during the parse
  1610. */
  1611. LexicalUnitImpl term(LexicalUnitImpl prev) :
  1612. { LexicalUnitImpl result = null;
  1613. Token n = null;
  1614. char op = ' ';
  1615. String varName;
  1616. }
  1617. {
  1618. (( ( ( op=unaryOperator() )?
  1619. (
  1620. n=<NUMBER>
  1621. { result = LexicalUnitImpl.createNumber(n.beginLine, n.beginColumn,
  1622. prev, number(op, n, 0)); }
  1623. | n=<PERCENTAGE>
  1624. { result = LexicalUnitImpl.createPercentage(n.beginLine, n.beginColumn,
  1625. prev, number(op, n, 1)); }
  1626. | n=<PT>
  1627. { result = LexicalUnitImpl.createPT(n.beginLine, n.beginColumn,
  1628. prev, number(op, n, 2)); }
  1629. | n=<CM>
  1630. { result = LexicalUnitImpl.createCM(n.beginLine, n.beginColumn,
  1631. prev, number(op, n, 2)); }
  1632. | n=<MM>
  1633. { result = LexicalUnitImpl.createMM(n.beginLine, n.beginColumn,
  1634. prev, number(op, n, 2)); }
  1635. | n=<PC>
  1636. { result = LexicalUnitImpl.createPC(n.beginLine, n.beginColumn,
  1637. prev, number(op, n, 2)); }
  1638. | n=<IN>
  1639. { result = LexicalUnitImpl.createIN(n.beginLine, n.beginColumn,
  1640. prev, number(op, n, 2)); }
  1641. | n=<PX>
  1642. { result = LexicalUnitImpl.createPX(n.beginLine, n.beginColumn,
  1643. prev, number(op, n, 2)); }
  1644. | n=<EMS>
  1645. { result = LexicalUnitImpl.createEMS(n.beginLine, n.beginColumn,
  1646. prev, number(op, n, 2)); }
  1647. | n=<EXS>
  1648. { result = LexicalUnitImpl.createEXS(n.beginLine, n.beginColumn,
  1649. prev, number(op, n, 2)); }
  1650. | n=<DEG>
  1651. { result = LexicalUnitImpl.createDEG(n.beginLine, n.beginColumn,
  1652. prev, number(op, n, 3)); }
  1653. | n=<RAD>
  1654. { result = LexicalUnitImpl.createRAD(n.beginLine, n.beginColumn,
  1655. prev, number(op, n, 3)); }
  1656. | n=<GRAD>
  1657. { result = LexicalUnitImpl.createGRAD(n.beginLine, n.beginColumn,
  1658. prev, number(op, n, 3)); }
  1659. | n=<SECOND>
  1660. { result = LexicalUnitImpl.createS(n.beginLine, n.beginColumn,
  1661. prev, number(op, n, 1)); }
  1662. | n=<MS>
  1663. { result = LexicalUnitImpl.createMS(n.beginLine, n.beginColumn,
  1664. prev, number(op, n, 2)); }
  1665. | n=<HZ>
  1666. { result = LexicalUnitImpl.createHZ(n.beginLine, n.beginColumn,
  1667. prev, number(op, n, 2)); }
  1668. | n=<KHZ>
  1669. { result = LexicalUnitImpl.createKHZ(n.beginLine, n.beginColumn,
  1670. prev, number(op, n, 3)); }
  1671. | n=<DIMEN>
  1672. {
  1673. String s = n.image;
  1674. int i = 0;
  1675. while (i < s.length()
  1676. && (Character.isDigit(s.charAt(i)) || (s.charAt(i) == '.'))) {
  1677. i++;
  1678. }
  1679. result = LexicalUnitImpl.createDimen(n.beginLine, n.beginColumn, prev,
  1680. Float.valueOf(s.substring(0, i)).floatValue(),
  1681. s.substring(i));
  1682. }
  1683. | result=function(op, prev) ) )
  1684. | ( n=<STRING>
  1685. { result =
  1686. LexicalUnitImpl.createString(n.beginLine, n.beginColumn, prev,
  1687. convertStringIndex(n.image, 1,
  1688. n.image.length() -1));}
  1689. | n=<IDENT>
  1690. { String s = convertIdent(n.image);
  1691. if ("inherit".equals(s)) {
  1692. result = LexicalUnitImpl.createInherit(n.beginLine, n.beginColumn,
  1693. prev);
  1694. } else {
  1695. result = LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
  1696. prev, convertIdent(n.image));
  1697. }
  1698. /* /
  1699. Auto correction code used in the CSS Validator but must not
  1700. be used by a conformant CSS2 parser.
  1701. * Common error :
  1702. * H1 {
  1703. * color : black
  1704. * background : white
  1705. * }
  1706. *
  1707. Token t = getToken(1);
  1708. Token semicolon = new Token();
  1709. semicolon.kind = SEMICOLON;
  1710. semicolon.image = ";";
  1711. if (t.kind == COLON) {
  1712. // @@SEEME. (generate a warning?)
  1713. // @@SEEME if expression is a single ident,
  1714. generate an error ?
  1715. rejectToken(semicolon);
  1716. result = prev;
  1717. }
  1718. / */
  1719. }
  1720. | result=hexcolor(prev)
  1721. | result=url(prev)
  1722. | result=unicode(prev)
  1723. ) ) ( <S> )*
  1724. | varName = variableName()
  1725. {result = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn,
  1726. prev, varName);})
  1727. {
  1728. return result;
  1729. }
  1730. }
  1731. /**
  1732. * Handle all CSS2 functions.
  1733. * @exception ParseException exception during the parse
  1734. */
  1735. LexicalUnitImpl function(char operator, LexicalUnitImpl prev) :
  1736. {Token n;
  1737. LexicalUnit params = null;
  1738. }
  1739. {
  1740. n=<FUNCTION> ( <S> )*
  1741. {
  1742. String fname = convertIdent(n.image);
  1743. if("alpha(".equals(fname)){
  1744. String body = skipStatementUntilSemiColon();
  1745. return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
  1746. null, "alpha("+body);
  1747. }
  1748. }
  1749. ( params=expr() )? ")"
  1750. {
  1751. if (operator != ' ') {
  1752. throw new CSSParseException("invalid operator before a function.",
  1753. getLocator());
  1754. }
  1755. String f = convertIdent(n.image);
  1756. LexicalUnitImpl l = (LexicalUnitImpl) params;
  1757. boolean loop = true;
  1758. if ("rgb(".equals(f)) {
  1759. // this is a RGB declaration (e.g. rgb(255, 50%, 0) )
  1760. int i = 0;
  1761. while (loop && l != null && i < 5) {
  1762. switch (i) {
  1763. case 0:
  1764. case 2:
  1765. case 4:
  1766. if ((l.getLexicalUnitType() != LexicalUnit.SAC_INTEGER)
  1767. && (l.getLexicalUnitType() != LexicalUnit.SAC_PERCENTAGE)) {
  1768. loop = false;
  1769. }
  1770. break;
  1771. case 1:
  1772. case 3:
  1773. if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
  1774. loop = false;
  1775. }
  1776. break;
  1777. default:
  1778. throw new ParseException("implementation error");
  1779. }
  1780. if (loop) {
  1781. l = (LexicalUnitImpl) l.getNextLexicalUnit();
  1782. i ++;
  1783. }
  1784. }
  1785. if ((i == 5) && loop && (l == null)) {
  1786. return LexicalUnitImpl.createRGBColor(n.beginLine,
  1787. n.beginColumn,
  1788. prev, params);
  1789. } else {
  1790. if (errorHandler != null) {
  1791. String errorText;
  1792. Locator loc;
  1793. if (i < 5) {
  1794. if (params == null) {
  1795. loc = new LocatorImpl(this, n.beginLine,
  1796. n.beginColumn-1);
  1797. errorText = "not enough parameters.";
  1798. } else if (l == null) {
  1799. loc = new LocatorImpl(this, n.beginLine,
  1800. n.beginColumn-1);
  1801. errorText = "not enough parameters: "
  1802. + params.toString();
  1803. } else {
  1804. loc = new LocatorImpl(this, l.getLineNumber(),
  1805. l.getColumnNumber());
  1806. errorText = "invalid parameter: "
  1807. + l.toString();
  1808. }
  1809. } else {
  1810. loc = new LocatorImpl(this, l.getLineNumber(),
  1811. l.getColumnNumber());
  1812. errorText = "too many parameters: "
  1813. + l.toString();
  1814. }
  1815. errorHandler.error(new CSSParseException(errorText, loc));
  1816. }
  1817. throw new JumpException();
  1818. }
  1819. } else if ("counter".equals(f)) {
  1820. int i = 0;
  1821. while (loop && l != null && i < 3) {
  1822. switch (i) {
  1823. case 0:
  1824. case 2:
  1825. if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
  1826. loop = false;
  1827. }
  1828. break;
  1829. case 1:
  1830. if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
  1831. loop = false;
  1832. }
  1833. break;
  1834. default:
  1835. throw new ParseException("implementation error");
  1836. }
  1837. l = (LexicalUnitImpl) l.getNextLexicalUnit();
  1838. i ++;
  1839. }
  1840. if (((i == 1) || (i == 3)) && loop && (l == null)) {
  1841. return LexicalUnitImpl.createCounter(n.beginLine, n.beginColumn,
  1842. prev, params);
  1843. }
  1844. } else if ("counters(".equals(f)) {
  1845. int i = 0;
  1846. while (loop && l != null && i < 5) {
  1847. switch (i) {
  1848. case 0:
  1849. case 4:
  1850. if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
  1851. loop = false;
  1852. }
  1853. break;
  1854. case 2:
  1855. if (l.getLexicalUnitType() != LexicalUnit.SAC_STRING_VALUE) {
  1856. loop = false;
  1857. }
  1858. break;
  1859. case 1:
  1860. case 3:
  1861. if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
  1862. loop = false;
  1863. }
  1864. break;
  1865. default:
  1866. throw new ParseException("implementation error");
  1867. }
  1868. l = (LexicalUnitImpl) l.getNextLexicalUnit();
  1869. i ++;
  1870. }
  1871. if (((i == 3) || (i == 5)) && loop && (l == null)) {
  1872. return LexicalUnitImpl.createCounters(n.beginLine, n.beginColumn,
  1873. prev, params);
  1874. }
  1875. } else if ("attr(".equals(f)) {
  1876. if ((l != null)
  1877. && (l.getNextLexicalUnit() == null)
  1878. && (l.getLexicalUnitType() == LexicalUnit.SAC_IDENT)) {
  1879. return LexicalUnitImpl.createAttr(l.getLineNumber(),
  1880. l.getColumnNumber(),
  1881. prev, l.getStringValue());
  1882. }
  1883. } else if ("rect(".equals(f)) {
  1884. int i = 0;
  1885. while (loop && l != null && i < 7) {
  1886. switch (i) {
  1887. case 0:
  1888. case 2:
  1889. case 4:
  1890. case 6:
  1891. switch (l.getLexicalUnitType()) {
  1892. case LexicalUnit.SAC_INTEGER:
  1893. if (l.getIntegerValue() != 0) {
  1894. loop = false;
  1895. }
  1896. break;
  1897. case LexicalUnit.SAC_IDENT:
  1898. if (!l.getStringValue().equals("auto")) {
  1899. loop = false;
  1900. }
  1901. break;
  1902. case LexicalUnit.SAC_EM:
  1903. case LexicalUnit.SAC_EX:
  1904. case LexicalUnit.SAC_PIXEL:
  1905. case LexicalUnit.SAC_CENTIMETER:
  1906. case LexicalUnit.SAC_MILLIMETER:
  1907. case LexicalUnit.SAC_INCH:
  1908. case LexicalUnit.SAC_POINT:
  1909. case LexicalUnit.SAC_PICA:
  1910. // nothing
  1911. break;
  1912. default:
  1913. loop = false;
  1914. }
  1915. break;
  1916. case 1:
  1917. case 3:
  1918. case 5:
  1919. if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
  1920. loop = false;
  1921. }
  1922. break;
  1923. default:
  1924. throw new ParseException("implementation error");
  1925. }
  1926. l = (LexicalUnitImpl) l.getNextLexicalUnit();
  1927. i ++;
  1928. }
  1929. if ((i == 7) && loop && (l == null)) {
  1930. return LexicalUnitImpl.createRect(n.beginLine, n.beginColumn,
  1931. prev, params);
  1932. }
  1933. }
  1934. return LexicalUnitImpl.createFunction(n.beginLine, n.beginColumn, prev,
  1935. f.substring(0,
  1936. f.length() -1),
  1937. params);
  1938. }
  1939. }
  1940. LexicalUnitImpl unicode(LexicalUnitImpl prev) :
  1941. { Token n;
  1942. }
  1943. {
  1944. n=<UNICODERANGE>
  1945. {
  1946. LexicalUnitImpl params = null;
  1947. String s = n.image.substring(2);
  1948. int index = s.indexOf('-');
  1949. if (index == -1) {
  1950. params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
  1951. params, Integer.parseInt(s, 16));
  1952. } else {
  1953. String s1 = s.substring(0, index);
  1954. String s2 = s.substring(index);
  1955. params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
  1956. params, Integer.parseInt(s1, 16));
  1957. params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn,
  1958. params, Integer.parseInt(s2, 16));
  1959. }
  1960. return LexicalUnitImpl.createUnicodeRange(n.beginLine, n.beginColumn,
  1961. prev, params);
  1962. }
  1963. }
  1964. LexicalUnitImpl url(LexicalUnitImpl prev) :
  1965. { Token n;
  1966. }
  1967. {
  1968. n=<URL>
  1969. {
  1970. String urlname = n.image.substring(4, n.image.length()-1).trim();
  1971. if (urlname.charAt(0) == '"'
  1972. || urlname.charAt(0) == '\'') {
  1973. urlname = urlname.substring(1, urlname.length()-1);
  1974. }
  1975. return LexicalUnitImpl.createURL(n.beginLine, n.beginColumn, prev, urlname);
  1976. }
  1977. }
  1978. /**
  1979. * @exception ParseException exception during the parse
  1980. */
  1981. LexicalUnitImpl hexcolor(LexicalUnitImpl prev) :
  1982. {Token n;
  1983. }
  1984. {
  1985. n=<HASH>
  1986. {
  1987. int r;
  1988. LexicalUnitImpl first, params = null;
  1989. String s = n.image.substring(1);
  1990. if(s.length()!=3 && s.length()!=6) {
  1991. first = null;
  1992. throw new CSSParseException("invalid hexadecimal notation for RGB: " + s,
  1993. getLocator());
  1994. }
  1995. return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn,
  1996. prev, n.image);
  1997. }
  1998. }
  1999. JAVACODE
  2000. float number(char operator, Token n, int lengthUnit) {
  2001. String image = n.image;
  2002. float f = 0;
  2003. if (lengthUnit != 0) {
  2004. image = image.substring(0, image.length() - lengthUnit);
  2005. }
  2006. f = Float.valueOf(image).floatValue();
  2007. return (operator == '-')? -f: f;
  2008. }
  2009. JAVACODE
  2010. String skipStatementUntilSemiColon(){
  2011. int[] semicolon = {SEMICOLON};
  2012. return skipStatementUntil(semicolon);
  2013. }
  2014. JAVACODE
  2015. String skipStatementUntilLeftBrace(){
  2016. int[] lBrace = {LBRACE};
  2017. return skipStatementUntil(lBrace);
  2018. }
  2019. JAVACODE
  2020. String skipStatementUntilRightParan(){
  2021. int[] rParan = {RPARAN};
  2022. return skipStatementUntil(rParan);
  2023. }
  2024. JAVACODE
  2025. String skipStatementUntil(int[] symbols){
  2026. StringBuffer s = new StringBuffer();
  2027. boolean stop = false;
  2028. Token tok;
  2029. while(!stop){
  2030. tok = getToken(1);
  2031. if(tok.kind == EOF) {
  2032. return null;
  2033. }
  2034. for(int sym : symbols){
  2035. if(tok.kind == sym){
  2036. stop = true;
  2037. break;
  2038. }
  2039. }
  2040. if(!stop){
  2041. if (tok.image != null) {
  2042. s.append(tok.image);
  2043. }
  2044. getNextToken();
  2045. }
  2046. }
  2047. return s.toString().trim();
  2048. }
  2049. JAVACODE
  2050. String skipStatement() {
  2051. StringBuffer s = new StringBuffer();
  2052. Token tok = getToken(0);
  2053. if (tok.image != null) {
  2054. s.append(tok.image);
  2055. }
  2056. while (true) {
  2057. tok = getToken(1);
  2058. if (tok.kind == EOF) {
  2059. return null;
  2060. }
  2061. s.append(tok.image);
  2062. if (tok.kind == LBRACE) {
  2063. getNextToken();
  2064. s.append(skip_to_matching_brace());
  2065. getNextToken();
  2066. tok = getToken(1);
  2067. break;
  2068. } else if (tok.kind == RBRACE) {
  2069. getNextToken();
  2070. tok = getToken(1);
  2071. break;
  2072. } else if (tok.kind == SEMICOLON) {
  2073. getNextToken();
  2074. tok = getToken(1);
  2075. break;
  2076. }
  2077. getNextToken();
  2078. }
  2079. // skip white space
  2080. while (true) {
  2081. if (tok.kind != S) {
  2082. break;
  2083. }
  2084. tok = getNextToken();
  2085. tok = getToken(1);
  2086. }
  2087. return s.toString().trim();
  2088. }
  2089. JAVACODE
  2090. String skip_to_matching_brace() {
  2091. StringBuffer s = new StringBuffer();
  2092. Token tok;
  2093. int nesting = 1;
  2094. while (true) {
  2095. tok = getToken(1);
  2096. if (tok.kind == EOF) {
  2097. break;
  2098. }
  2099. s.append(tok.image);
  2100. if (tok.kind == LBRACE) {
  2101. nesting++;
  2102. } else if (tok.kind == RBRACE) {
  2103. nesting--;
  2104. if (nesting == 0) {
  2105. break;
  2106. }
  2107. }
  2108. getNextToken();
  2109. }
  2110. return s.toString();
  2111. }
  2112. /*
  2113. * Here I handle all CSS2 unicode character stuffs.
  2114. * I convert all \XXXXXX character into a single character.
  2115. * Don't forget that the parser has recognize the token before.
  2116. * (So IDENT won't contain newline and stuffs like this).
  2117. */
  2118. JAVACODE
  2119. String convertStringIndex(String s, int start, int len) {
  2120. StringBuffer buf = new StringBuffer(len);
  2121. int index = start;
  2122. while (index < len) {
  2123. char c = s.charAt(index);
  2124. if (c == '\\') {
  2125. if (++index < len) {
  2126. c = s.charAt(index);
  2127. switch (c) {
  2128. case '0': case '1': case '2': case '3': case '4':
  2129. case '5': case '6': case '7': case '8': case '9':
  2130. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  2131. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  2132. int numValue = Character.digit(c, 16);
  2133. int count = 0;
  2134. int p = 16;
  2135. while (index + 1 < len && count < 6) {
  2136. c = s.charAt(index+1);
  2137. if (Character.digit(c, 16) != -1) {
  2138. numValue = (numValue * 16) + Character.digit(c, 16);
  2139. p *= 16;
  2140. index++;
  2141. } else {
  2142. if (c == ' ') {
  2143. // skip the latest white space
  2144. index++;
  2145. }
  2146. break;
  2147. }
  2148. }
  2149. buf.append((char) numValue);
  2150. break;
  2151. case '\n':
  2152. case '\f':
  2153. break;
  2154. case '\r':
  2155. if (index + 1 < len) {
  2156. if (s.charAt(index + 1) == '\n') {
  2157. index ++;
  2158. }
  2159. }
  2160. break;
  2161. default:
  2162. buf.append(c);
  2163. }
  2164. } else {
  2165. throw new CSSParseException("invalid string " + s, getLocator());
  2166. }
  2167. } else {
  2168. buf.append(c);
  2169. }
  2170. index++;
  2171. }
  2172. return buf.toString();
  2173. }
  2174. JAVACODE
  2175. String convertIdent(String s) {
  2176. return convertStringIndex(s, 0, s.length());
  2177. }
  2178. JAVACODE
  2179. String convertString(String s) {
  2180. return convertStringIndex(s, 0, s.length());
  2181. }
  2182. /*
  2183. * @@HACK
  2184. * I can't insert a token into the tokens flow.
  2185. * It's jj_consume_token implementation dependant! :-(
  2186. */
  2187. JAVACODE
  2188. void rejectToken(Token t) {
  2189. Token fakeToken = new Token();
  2190. t.next = token;
  2191. fakeToken.next = t;
  2192. token = fakeToken;
  2193. }
  2194. /**
  2195. * skip after an expression
  2196. */
  2197. JAVACODE
  2198. String skipAfterExpression() {
  2199. Token t = getToken(1);
  2200. StringBuffer s = new StringBuffer();
  2201. s.append(getToken(0).image);
  2202. while ((t.kind != RBRACE) && (t.kind != SEMICOLON) && (t.kind != EOF)) {
  2203. s.append(t.image);
  2204. getNextToken();
  2205. t = getToken(1);
  2206. }
  2207. return s.toString();
  2208. }
  2209. /**
  2210. * The following functions are useful for a DOM CSS implementation only and are
  2211. * not part of the general CSS2 parser.
  2212. */
  2213. void _parseRule() :
  2214. {String ret = null;
  2215. }
  2216. {
  2217. ( <S> )*
  2218. ( importDeclaration() | styleRule() | media() | page()
  2219. | fontFace() | ret=skipStatement()
  2220. {
  2221. if ((ret == null) || (ret.length() == 0)) {
  2222. return;
  2223. }
  2224. if (ret.charAt(0) == '@') {
  2225. documentHandler.ignorableAtRule(ret);
  2226. } else {
  2227. throw new CSSParseException("unrecognize rule: " + ret,
  2228. getLocator());
  2229. }
  2230. }
  2231. )
  2232. }
  2233. void _parseImportRule() :
  2234. {
  2235. }
  2236. {
  2237. ( <S> )* importDeclaration()
  2238. }
  2239. void _parseMediaRule() :
  2240. {
  2241. }
  2242. {
  2243. ( <S> )* media()
  2244. }
  2245. void _parseDeclarationBlock() :
  2246. {
  2247. }
  2248. {
  2249. ( <S> )*
  2250. ( declaration() )? ( ";" ( <S> )* ( declaration() )? )*
  2251. }
  2252. SelectorList _parseSelectors() :
  2253. { SelectorList p = null;
  2254. }
  2255. {
  2256. try {
  2257. ( <S> )* p = selectorList()
  2258. { return p; }
  2259. } catch (ThrowedParseException e) {
  2260. throw (ParseException) e.e.fillInStackTrace();
  2261. }
  2262. }
  2263. /*
  2264. * Local Variables:
  2265. * compile-command: javacc Parser.jj & javac Parser.java
  2266. * End:
  2267. */