001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.xpointer.parser;
018:
019: import java.util.HashMap;
020:
021: import org.apache.cocoon.components.xpointer.ElementPathPart;
022: import org.apache.cocoon.components.xpointer.ShorthandPart;
023: import org.apache.cocoon.components.xpointer.UnsupportedPart;
024: import org.apache.cocoon.components.xpointer.XPointer;
025: import org.apache.cocoon.components.xpointer.XPointerPart;
026: import org.apache.cocoon.components.xpointer.XmlnsPart;
027:
028: public class XPointerFrameworkParser implements
029: XPointerFrameworkParserConstants {
030: private XPointer xpointer = new XPointer();
031: private HashMap namespaces = new HashMap();
032:
033: public static void main(String[] args) throws Exception {
034: System.out.println("will parse this: " + args[0]);
035: XPointerFrameworkParser xfp = new XPointerFrameworkParser(
036: new java.io.StringReader(args[0]));
037: xfp.pointer();
038: }
039:
040: public static XPointer parse(String xpointer) throws ParseException {
041: XPointerFrameworkParser xfp = new XPointerFrameworkParser(
042: new java.io.StringReader(xpointer));
043: try {
044: xfp.pointer();
045: } catch (TokenMgrError e) {
046: // Rethrow TokenMgrErrors as ParseExceptions, because errors aren't caught by Cocoon,
047: // and mistyping in a xpointer isn't such a grave error
048: throw new ParseException(e.getMessage());
049: }
050: return xfp.getXPointer();
051: }
052:
053: public XPointer getXPointer() {
054: return xpointer;
055: }
056:
057: private String unescape(String data) throws ParseException {
058: StringBuffer result = new StringBuffer(data.length());
059: boolean inCircumflex = false;
060: for (int i = 0; i < data.length(); i++) {
061: char c = data.charAt(i);
062: if (inCircumflex) {
063: switch (c) {
064: case '^':
065: case '(':
066: case ')':
067: result.append(c);
068: inCircumflex = false;
069: break;
070: default:
071: throw new ParseException(
072: "Incorrect use of circumflex character at position "
073: + i + " in the string " + data);
074: }
075: } else if (c == '^') {
076: inCircumflex = true;
077: } else {
078: result.append(c);
079: }
080: }
081: return result.toString();
082: }
083:
084: final public void pointer() throws ParseException {
085: if (jj_2_1(2)) {
086: schemeBased();
087: } else {
088: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
089: case NCName:
090: shortHand();
091: break;
092: default:
093: jj_la1[0] = jj_gen;
094: jj_consume_token(-1);
095: throw new ParseException();
096: }
097: }
098: }
099:
100: final public void shortHand() throws ParseException {
101: Token x;
102: x = jj_consume_token(NCName);
103: xpointer.addPart(new ShorthandPart(x.image));
104: }
105:
106: final public void schemeBased() throws ParseException {
107: pointerPart();
108: label_1: while (true) {
109: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
110: case NCName:
111: case WS:
112: case QName:
113: break;
114: default:
115: jj_la1[1] = jj_gen;
116: break label_1;
117: }
118: label_2: while (true) {
119: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
120: case WS:
121: break;
122: default:
123: jj_la1[2] = jj_gen;
124: break label_2;
125: }
126: jj_consume_token(WS);
127: }
128: pointerPart();
129: }
130: }
131:
132: final public void pointerPart() throws ParseException {
133: Token x;
134: String schemeName;
135: String schemeData;
136: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
137: case NCName:
138: x = jj_consume_token(NCName);
139: break;
140: case QName:
141: x = jj_consume_token(QName);
142: break;
143: default:
144: jj_la1[3] = jj_gen;
145: jj_consume_token(-1);
146: throw new ParseException();
147: }
148: jj_consume_token(LBRACE);
149: // when going inside the scheme data, swith to a different lexical state
150: token_source.switchTo(IN_SCHEME);
151:
152: // store the scheme name
153: schemeName = x.image;
154: schemeData = schemeData();
155: jj_consume_token(RBRACE);
156: // when going outside the scheme data, swith back to the default lexical state
157: token_source.switchTo(DEFAULT);
158:
159: // parse schemeName in prefix and localName
160: String schemeNamespace = null, schemeLocalName = null;
161: int colonPos = schemeName.indexOf(':');
162: if (colonPos != -1) {
163: String schemePrefix = schemeName.substring(0, colonPos);
164: schemeNamespace = (String) namespaces.get(schemePrefix);
165: schemeLocalName = schemeName.substring(colonPos + 1);
166: } else {
167: schemeLocalName = schemeName;
168: }
169:
170: // add the pointer part
171: if (schemeNamespace == null && schemeLocalName.equals("xmlns")) {
172: int eqPos = schemeData.indexOf("=");
173: if (eqPos == -1) {
174: if (true)
175: throw new ParseException(
176: "xmlns scheme data should contain an equals sign");
177: }
178:
179: // Note: the trimming below is not entirely correct, since space is only allowed left
180: // and right of the equal sign, but not at the beginning and end of the schemeData
181: String prefix = schemeData.substring(0, eqPos).trim();
182: String namespace = schemeData.substring(eqPos + 1,
183: schemeData.length()).trim();
184: xpointer.addPart(new XmlnsPart(prefix, namespace));
185: namespaces.put(prefix, namespace);
186: } else if (schemeNamespace == null
187: && schemeLocalName.equals("xpointer")) {
188: xpointer.addPart(new XPointerPart(schemeData));
189: } else if ("http://apache.org/cocoon/xpointer"
190: .equals(schemeNamespace)
191: && schemeLocalName.equals("elementpath")) {
192: xpointer.addPart(new ElementPathPart(schemeData));
193: } else {
194: xpointer.addPart(new UnsupportedPart(schemeName));
195: }
196: }
197:
198: final public String schemeData() throws ParseException {
199: String temp;
200: StringBuffer schemeData = new StringBuffer();
201: label_3: while (true) {
202: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
203: case LBRACE:
204: case CIRC_LBRACE:
205: case CIRC_RBRACE:
206: case DOUBLE_CIRC:
207: case NormalChar:
208: break;
209: default:
210: jj_la1[4] = jj_gen;
211: break label_3;
212: }
213: temp = escapedData();
214: schemeData.append(temp);
215: }
216: {
217: if (true)
218: return unescape(schemeData.toString());
219: }
220: throw new Error("Missing return statement in function");
221: }
222:
223: final public String escapedData() throws ParseException {
224: Token x;
225: String temp;
226: StringBuffer data = new StringBuffer();
227: switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
228: case NormalChar:
229: x = jj_consume_token(NormalChar);
230: data.append(x.image);
231: break;
232: case CIRC_LBRACE:
233: x = jj_consume_token(CIRC_LBRACE);
234: data.append(x.image);
235: break;
236: case CIRC_RBRACE:
237: x = jj_consume_token(CIRC_RBRACE);
238: data.append(x.image);
239: break;
240: case DOUBLE_CIRC:
241: x = jj_consume_token(DOUBLE_CIRC);
242: data.append(x.image);
243: break;
244: case LBRACE:
245: x = jj_consume_token(LBRACE);
246: data.append(x.image);
247: temp = schemeData();
248: data.append(temp);
249: x = jj_consume_token(RBRACE);
250: data.append(x.image);
251: break;
252: default:
253: jj_la1[5] = jj_gen;
254: jj_consume_token(-1);
255: throw new ParseException();
256: }
257: {
258: if (true)
259: return data.toString();
260: }
261: throw new Error("Missing return statement in function");
262: }
263:
264: final private boolean jj_2_1(int xla) {
265: jj_la = xla;
266: jj_lastpos = jj_scanpos = token;
267: boolean retval = !jj_3_1();
268: jj_save(0, xla);
269: return retval;
270: }
271:
272: final private boolean jj_3R_6() {
273: if (jj_scan_token(NCName))
274: return true;
275: if (jj_la == 0 && jj_scanpos == jj_lastpos)
276: return false;
277: return false;
278: }
279:
280: final private boolean jj_3R_4() {
281: if (jj_3R_5())
282: return true;
283: if (jj_la == 0 && jj_scanpos == jj_lastpos)
284: return false;
285: return false;
286: }
287:
288: final private boolean jj_3R_5() {
289: Token xsp;
290: xsp = jj_scanpos;
291: if (jj_3R_6()) {
292: jj_scanpos = xsp;
293: if (jj_3R_7())
294: return true;
295: if (jj_la == 0 && jj_scanpos == jj_lastpos)
296: return false;
297: } else if (jj_la == 0 && jj_scanpos == jj_lastpos)
298: return false;
299: if (jj_scan_token(LBRACE))
300: return true;
301: if (jj_la == 0 && jj_scanpos == jj_lastpos)
302: return false;
303: return false;
304: }
305:
306: final private boolean jj_3R_7() {
307: if (jj_scan_token(QName))
308: return true;
309: if (jj_la == 0 && jj_scanpos == jj_lastpos)
310: return false;
311: return false;
312: }
313:
314: final private boolean jj_3_1() {
315: if (jj_3R_4())
316: return true;
317: if (jj_la == 0 && jj_scanpos == jj_lastpos)
318: return false;
319: return false;
320: }
321:
322: public XPointerFrameworkParserTokenManager token_source;
323: SimpleCharStream jj_input_stream;
324: public Token token, jj_nt;
325: private int jj_ntk;
326: private Token jj_scanpos, jj_lastpos;
327: private int jj_la;
328: public boolean lookingAhead = false;
329: private int jj_gen;
330: final private int[] jj_la1 = new int[6];
331: static private int[] jj_la1_0;
332: static {
333: jj_la1_0();
334: }
335:
336: private static void jj_la1_0() {
337: jj_la1_0 = new int[] { 0x80, 0x380, 0x100, 0x280, 0xf400,
338: 0xf400, };
339: }
340:
341: final private JJCalls[] jj_2_rtns = new JJCalls[1];
342: private boolean jj_rescan = false;
343: private int jj_gc = 0;
344:
345: public XPointerFrameworkParser(java.io.InputStream stream) {
346: jj_input_stream = new SimpleCharStream(stream, 1, 1);
347: token_source = new XPointerFrameworkParserTokenManager(
348: jj_input_stream);
349: token = new Token();
350: jj_ntk = -1;
351: jj_gen = 0;
352: for (int i = 0; i < 6; i++)
353: jj_la1[i] = -1;
354: for (int i = 0; i < jj_2_rtns.length; i++)
355: jj_2_rtns[i] = new JJCalls();
356: }
357:
358: public void reInit(java.io.InputStream stream) {
359: jj_input_stream.reInit(stream, 1, 1);
360: token_source.reInit(jj_input_stream);
361: token = new Token();
362: jj_ntk = -1;
363: jj_gen = 0;
364: for (int i = 0; i < 6; i++)
365: jj_la1[i] = -1;
366: for (int i = 0; i < jj_2_rtns.length; i++)
367: jj_2_rtns[i] = new JJCalls();
368: }
369:
370: public XPointerFrameworkParser(java.io.Reader stream) {
371: jj_input_stream = new SimpleCharStream(stream, 1, 1);
372: token_source = new XPointerFrameworkParserTokenManager(
373: jj_input_stream);
374: token = new Token();
375: jj_ntk = -1;
376: jj_gen = 0;
377: for (int i = 0; i < 6; i++)
378: jj_la1[i] = -1;
379: for (int i = 0; i < jj_2_rtns.length; i++)
380: jj_2_rtns[i] = new JJCalls();
381: }
382:
383: public void reInit(java.io.Reader stream) {
384: jj_input_stream.reInit(stream, 1, 1);
385: token_source.reInit(jj_input_stream);
386: token = new Token();
387: jj_ntk = -1;
388: jj_gen = 0;
389: for (int i = 0; i < 6; i++)
390: jj_la1[i] = -1;
391: for (int i = 0; i < jj_2_rtns.length; i++)
392: jj_2_rtns[i] = new JJCalls();
393: }
394:
395: public XPointerFrameworkParser(
396: XPointerFrameworkParserTokenManager tm) {
397: token_source = tm;
398: token = new Token();
399: jj_ntk = -1;
400: jj_gen = 0;
401: for (int i = 0; i < 6; i++)
402: jj_la1[i] = -1;
403: for (int i = 0; i < jj_2_rtns.length; i++)
404: jj_2_rtns[i] = new JJCalls();
405: }
406:
407: public void reInit(XPointerFrameworkParserTokenManager tm) {
408: token_source = tm;
409: token = new Token();
410: jj_ntk = -1;
411: jj_gen = 0;
412: for (int i = 0; i < 6; i++)
413: jj_la1[i] = -1;
414: for (int i = 0; i < jj_2_rtns.length; i++)
415: jj_2_rtns[i] = new JJCalls();
416: }
417:
418: final private Token jj_consume_token(int kind)
419: throws ParseException {
420: Token oldToken;
421: if ((oldToken = token).next != null)
422: token = token.next;
423: else
424: token = token.next = token_source.getNextToken();
425: jj_ntk = -1;
426: if (token.kind == kind) {
427: jj_gen++;
428: if (++jj_gc > 100) {
429: jj_gc = 0;
430: for (int i = 0; i < jj_2_rtns.length; i++) {
431: JJCalls c = jj_2_rtns[i];
432: while (c != null) {
433: if (c.gen < jj_gen)
434: c.first = null;
435: c = c.next;
436: }
437: }
438: }
439: return token;
440: }
441: token = oldToken;
442: jj_kind = kind;
443: throw generateParseException();
444: }
445:
446: final private boolean jj_scan_token(int kind) {
447: if (jj_scanpos == jj_lastpos) {
448: jj_la--;
449: if (jj_scanpos.next == null) {
450: jj_lastpos = jj_scanpos = jj_scanpos.next = token_source
451: .getNextToken();
452: } else {
453: jj_lastpos = jj_scanpos = jj_scanpos.next;
454: }
455: } else {
456: jj_scanpos = jj_scanpos.next;
457: }
458: if (jj_rescan) {
459: int i = 0;
460: Token tok = token;
461: while (tok != null && tok != jj_scanpos) {
462: i++;
463: tok = tok.next;
464: }
465: if (tok != null)
466: jj_add_error_token(kind, i);
467: }
468: return (jj_scanpos.kind != kind);
469: }
470:
471: final public Token getNextToken() {
472: if (token.next != null)
473: token = token.next;
474: else
475: token = token.next = token_source.getNextToken();
476: jj_ntk = -1;
477: jj_gen++;
478: return token;
479: }
480:
481: final public Token getToken(int index) {
482: Token t = lookingAhead ? jj_scanpos : token;
483: for (int i = 0; i < index; i++) {
484: if (t.next != null)
485: t = t.next;
486: else
487: t = t.next = token_source.getNextToken();
488: }
489: return t;
490: }
491:
492: final private int jj_ntk() {
493: if ((jj_nt = token.next) == null)
494: return (jj_ntk = (token.next = token_source.getNextToken()).kind);
495: else
496: return (jj_ntk = jj_nt.kind);
497: }
498:
499: private java.util.Vector jj_expentries = new java.util.Vector();
500: private int[] jj_expentry;
501: private int jj_kind = -1;
502: private int[] jj_lasttokens = new int[100];
503: private int jj_endpos;
504:
505: private void jj_add_error_token(int kind, int pos) {
506: if (pos >= 100)
507: return;
508: if (pos == jj_endpos + 1) {
509: jj_lasttokens[jj_endpos++] = kind;
510: } else if (jj_endpos != 0) {
511: jj_expentry = new int[jj_endpos];
512: for (int i = 0; i < jj_endpos; i++) {
513: jj_expentry[i] = jj_lasttokens[i];
514: }
515: boolean exists = false;
516: for (java.util.Enumeration enumeration = jj_expentries
517: .elements(); enumeration.hasMoreElements();) {
518: int[] oldentry = (int[]) (enumeration.nextElement());
519: if (oldentry.length == jj_expentry.length) {
520: exists = true;
521: for (int i = 0; i < jj_expentry.length; i++) {
522: if (oldentry[i] != jj_expentry[i]) {
523: exists = false;
524: break;
525: }
526: }
527: if (exists)
528: break;
529: }
530: }
531: if (!exists)
532: jj_expentries.addElement(jj_expentry);
533: if (pos != 0)
534: jj_lasttokens[(jj_endpos = pos) - 1] = kind;
535: }
536: }
537:
538: public ParseException generateParseException() {
539: jj_expentries.removeAllElements();
540: boolean[] la1tokens = new boolean[16];
541: for (int i = 0; i < 16; i++) {
542: la1tokens[i] = false;
543: }
544: if (jj_kind >= 0) {
545: la1tokens[jj_kind] = true;
546: jj_kind = -1;
547: }
548: for (int i = 0; i < 6; i++) {
549: if (jj_la1[i] == jj_gen) {
550: for (int j = 0; j < 32; j++) {
551: if ((jj_la1_0[i] & (1 << j)) != 0) {
552: la1tokens[j] = true;
553: }
554: }
555: }
556: }
557: for (int i = 0; i < 16; i++) {
558: if (la1tokens[i]) {
559: jj_expentry = new int[1];
560: jj_expentry[0] = i;
561: jj_expentries.addElement(jj_expentry);
562: }
563: }
564: jj_endpos = 0;
565: jj_rescan_token();
566: jj_add_error_token(0, 0);
567: int[][] exptokseq = new int[jj_expentries.size()][];
568: for (int i = 0; i < jj_expentries.size(); i++) {
569: exptokseq[i] = (int[]) jj_expentries.elementAt(i);
570: }
571: return new ParseException(token, exptokseq, tokenImage);
572: }
573:
574: final public void enable_tracing() {
575: }
576:
577: final public void disable_tracing() {
578: }
579:
580: final private void jj_rescan_token() {
581: jj_rescan = true;
582: for (int i = 0; i < 1; i++) {
583: JJCalls p = jj_2_rtns[i];
584: do {
585: if (p.gen > jj_gen) {
586: jj_la = p.arg;
587: jj_lastpos = jj_scanpos = p.first;
588: switch (i) {
589: case 0:
590: jj_3_1();
591: break;
592: }
593: }
594: p = p.next;
595: } while (p != null);
596: }
597: jj_rescan = false;
598: }
599:
600: final private void jj_save(int index, int xla) {
601: JJCalls p = jj_2_rtns[index];
602: while (p.gen > jj_gen) {
603: if (p.next == null) {
604: p = p.next = new JJCalls();
605: break;
606: }
607: p = p.next;
608: }
609: p.gen = jj_gen + xla - jj_la;
610: p.first = token;
611: p.arg = xla;
612: }
613:
614: static final class JJCalls {
615: int gen;
616: Token first;
617: int arg;
618: JJCalls next;
619: }
620:
621: }
|