001: /*
002: * $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/publishing/markups/TKMarkupParser.java,v 1.7 2001/11/26 15:14:26 sebastian Exp $
003: *
004: */
005: package com.teamkonzept.publishing.markups;
006:
007: import java.util.*;
008:
009: import com.teamkonzept.lib.*;
010:
011: public class TKMarkupParser {
012:
013: private static final String IDENTIFIERFIRSTCODES = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
014: private static final String DIGITCODES = "0123456789";
015: private static final String IDENTIFIERCODES = IDENTIFIERFIRSTCODES
016: + DIGITCODES;
017: private static final String ESCAPECODES = "<>";
018:
019: private TKMarkupItemList itemList;
020: private TKHashtable markups;
021:
022: public TKMarkup currentMarkup;
023:
024: protected TKVector diagnostics;
025:
026: public TKMarkupParser(TKVector diagnostics,
027: TKMarkupItemList itemList) {
028:
029: if (itemList == null)
030: this .itemList = new TKMarkupItemList();
031: else
032: this .itemList = itemList;
033:
034: this .markups = new TKHashtable();
035: this .diagnostics = diagnostics;
036: this .currentMarkup = null;
037: }
038:
039: public TKMarkupParser(TKVector diagnostics) {
040:
041: this (diagnostics, null);
042: }
043:
044: public void initMarkupParsing() {
045: }
046:
047: public void addDiagnostic(String diagnostic) {
048:
049: if (diagnostics == null)
050: diagnostics = new TKVector();
051: diagnostics.addElement(diagnostic);
052: }
053:
054: public TKMarkupParam createParam(String name, String value) {
055:
056: return new TKMarkupParam(name, value);
057: }
058:
059: public TKMarkup createMarkup(String name, TKHashtable params,
060: int pos) {
061:
062: return new TKMarkup(name, params, pos);
063: }
064:
065: public TKMarkup createMarkup(String name, TKHashtable params,
066: int pos, boolean backsl) {
067:
068: return new TKMarkup(name, params, pos, backsl);
069: }
070:
071: public void register(TKMarkup markup) {
072:
073: currentMarkup = markup;
074: markups.put(markup.toString(), markup);
075: }
076:
077: public void deregister(TKMarkup markup) {
078:
079: currentMarkup = null;
080: markups.remove(markup.toString());
081: }
082:
083: public void registerMarkup(String markupName) {
084: }
085:
086: public void registerParam(String paramName) {
087: }
088:
089: public Enumeration allMarkups() {
090:
091: Enumeration e = markups.elements();
092: TKVector vec = new TKVector();
093: vec.fill(e);
094:
095: return vec.elements();
096: }
097:
098: public void cleanup(TKMarkupItemList itemList, int pos) {
099: }
100:
101: public void cleanupCloseLevel() {
102: }
103:
104: public boolean closeLevel(TKMarkupItemList itemList) {
105: return false;
106: }
107:
108: public static boolean quotingRequired(String text) {
109:
110: boolean isId = true;
111: boolean isInt = true;
112: boolean isFloat = true;
113:
114: if (text == null)
115: return false;
116:
117: int pos = 0;
118: while (pos < text.length()) {
119:
120: char chr = text.charAt(pos++);
121:
122: if ((pos == 0) && (IDENTIFIERFIRSTCODES.indexOf(chr) == -1))
123: isId = false;
124: else if ((pos != 0) && (IDENTIFIERCODES.indexOf(chr) == -1))
125: isId = false;
126:
127: if (chr == '.') {
128: if (!isInt)
129: isFloat = false;
130: else
131: isInt = false;
132: } else if (DIGITCODES.indexOf(chr) == -1) {
133: isInt = false;
134: isFloat = false;
135: }
136:
137: if (!isId && !isInt && !isFloat)
138: return true;
139: }
140:
141: return false;
142: }
143:
144: public static String doEscapes(String text) {
145:
146: if (text == null)
147: return null;
148:
149: StringBuffer buf = new StringBuffer();
150:
151: int pos = 0;
152: while (pos < text.length()) {
153:
154: char chr = text.charAt(pos++);
155:
156: if (chr == '\\') {
157:
158: if (pos + 1 < text.length())
159: buf.append(text.charAt(pos++));
160: else
161: buf.append(chr);
162:
163: } else
164: buf.append(chr);
165: }
166:
167: return buf.toString();
168: }
169:
170: public static String par2tmpl(String text) {
171:
172: if (text == null)
173: return null;
174:
175: StringBuffer buf = new StringBuffer();
176:
177: int pos = 0;
178: while (pos < text.length()) {
179:
180: char chr = text.charAt(pos++);
181:
182: if ((ESCAPECODES.indexOf(chr) != -1) || (chr == '\\')
183: || (chr == ';') || (chr == '='))
184: buf.append('\\');
185:
186: buf.append(chr);
187: }
188:
189: return buf.toString();
190: }
191:
192: public static String par2quotes(String text) {
193:
194: if (text == null)
195: return null;
196:
197: StringBuffer buf = new StringBuffer();
198: buf.append('"');
199:
200: int pos = 0;
201: while (pos < text.length()) {
202:
203: char chr = text.charAt(pos++);
204:
205: if ((chr == '\\') || (chr == '"'))
206: buf.append('\\');
207:
208: buf.append(chr);
209: }
210:
211: buf.append('"');
212: return buf.toString();
213: }
214:
215: public int parseText(String text, int pos, StringBuffer str) {
216:
217: while (pos < text.length()) {
218:
219: char chr = text.charAt(pos);
220:
221: if ((chr == '\\') && (pos + 1 < text.length())) {
222:
223: if (str == null)
224: pos++;
225:
226: else {
227:
228: char escapedChar = text.charAt(++pos);
229:
230: if ((ESCAPECODES.indexOf(escapedChar) != -1)
231: || (escapedChar == chr))
232: str.append(chr);
233:
234: str.append(escapedChar);
235:
236: }
237: }
238:
239: else if (chr == '<')
240: break;
241:
242: else if (str != null) {
243:
244: if (chr == '\\')
245: str.append(chr).append(chr);
246: else
247: str.append(chr);
248: }
249:
250: pos++;
251: }
252:
253: return pos;
254: }
255:
256: public int parsePattern(String text, int pos, StringBuffer str,
257: String pattern) {
258:
259: int i = 0;
260:
261: while ((pos + i < text.length()) && (i < pattern.length())) {
262:
263: char chr = text.charAt(pos + i);
264:
265: if (chr != pattern.charAt(i++))
266: return pos;
267: else if (str != null)
268: str.append(chr);
269: }
270:
271: if (i == pattern.length())
272: return pos + i;
273: else
274: return pos;
275: }
276:
277: public int parsePatternIgnoreCase(String text, int pos,
278: StringBuffer str, String pattern) {
279:
280: int i = 0;
281:
282: while ((pos + i < text.length()) && (i < pattern.length())) {
283:
284: char chr = Character.toUpperCase(text.charAt(pos + i));
285:
286: if (chr != Character.toUpperCase(pattern.charAt(i++)))
287: return pos;
288: else if (str != null)
289: str.append(chr);
290: }
291:
292: if (i == pattern.length())
293: return pos + i;
294: else
295: return pos;
296: }
297:
298: public int parseWhitespace(String text, int pos, StringBuffer space) {
299:
300: while (pos < text.length()) {
301:
302: char chr = text.charAt(pos);
303:
304: if (Character.isWhitespace(chr)) {
305:
306: if (space != null)
307: space.append(chr);
308:
309: } else
310: break;
311:
312: pos++;
313: }
314:
315: return pos;
316: }
317:
318: public int parseIdentifier(String text, int pos,
319: StringBuffer identifier) {
320:
321: while (pos < text.length()) {
322:
323: char chr = text.charAt(pos);
324:
325: if (((identifier.length() == 0) && (IDENTIFIERFIRSTCODES
326: .indexOf(chr) != -1))
327: || (IDENTIFIERCODES.indexOf(chr) != -1)) {
328:
329: if (identifier != null)
330: identifier.append(chr);
331:
332: } else
333: break;
334:
335: pos++;
336: }
337:
338: return pos;
339: }
340:
341: public int parseStringValue(String text, int pos, StringBuffer value)
342: throws TKMarkupParserException {
343:
344: int oldPos = pos;
345: pos = parsePattern(text, pos, null, "\"");
346: if (pos <= oldPos)
347: return oldPos;
348:
349: while (pos < text.length()) {
350:
351: char chr = text.charAt(pos);
352:
353: if (chr == '"')
354: break;
355:
356: else if ((chr == '\\') && (pos + 1 < text.length())) {
357:
358: if (value == null)
359: pos++;
360: else
361: value.append(text.charAt(++pos));
362:
363: } else if (value != null)
364: value.append(chr);
365:
366: pos++;
367: }
368:
369: return forcePattern(text, pos, null, "\"");
370: }
371:
372: public int parseValue(String text, int pos, StringBuffer value)
373: throws TKMarkupParserException {
374:
375: int oldPos = pos;
376: pos = parseStringValue(text, pos, value);
377: if (pos > oldPos)
378: return pos;
379:
380: boolean isId = true;
381: boolean isInt = true;
382: boolean isFloat = true;
383:
384: while (pos < text.length()) {
385:
386: char chr = text.charAt(pos);
387:
388: if ((pos == 0) && (IDENTIFIERFIRSTCODES.indexOf(chr) == -1))
389: isId = false;
390: else if ((pos != 0) && (IDENTIFIERCODES.indexOf(chr) == -1))
391: isId = false;
392:
393: if (chr == '.') {
394: if (!isInt)
395: isFloat = false;
396: else
397: isInt = false;
398: } else if (DIGITCODES.indexOf(chr) == -1) {
399: isInt = false;
400: isFloat = false;
401: }
402:
403: if (!isId && !isInt && !isFloat)
404: break;
405: if (value != null)
406: value.append(chr);
407:
408: pos++;
409: }
410:
411: return pos;
412: }
413:
414: public int forceText(String text, int pos, TKMarkupItemList itemList)
415: throws TKMarkupParserException {
416:
417: StringBuffer str = itemList != null ? new StringBuffer() : null;
418: int oldPos = pos;
419:
420: pos = parseText(text, pos, str);
421: if (pos == oldPos)
422: throw new TKMarkupParserException("Fehler: Text erwartet",
423: pos);
424:
425: if (itemList != null)
426: itemList.addElement(new String(str));
427:
428: return pos;
429: }
430:
431: public int forcePattern(String text, int pos,
432: TKMarkupItemList itemList, String pattern)
433: throws TKMarkupParserException {
434:
435: StringBuffer str = itemList != null ? new StringBuffer() : null;
436: int oldPos = pos;
437:
438: pos = parsePattern(text, pos, str, pattern);
439: if (pattern.length() != (pos - oldPos))
440: throw new TKMarkupParserException("Syntax: '" + pattern
441: + "' erwartet", pos);
442:
443: if (itemList != null)
444: itemList.addElement(new String(str));
445:
446: return pos;
447: }
448:
449: public int forceWhitespace(String text, int pos,
450: TKMarkupItemList itemList) throws TKMarkupParserException {
451:
452: StringBuffer space = itemList != null ? new StringBuffer()
453: : null;
454: int oldPos = pos;
455:
456: pos = parseWhitespace(text, pos, space);
457: if (pos == oldPos)
458: throw new TKMarkupParserException(
459: "Syntax: Leerraum erwartet", pos);
460:
461: if (itemList != null)
462: itemList.addElement(new String(space));
463:
464: return pos;
465: }
466:
467: public int forceValue(String text, int pos, StringBuffer value)
468: throws TKMarkupParserException {
469:
470: int oldPos = pos;
471:
472: pos = parseValue(text, pos, value);
473: if (pos == oldPos)
474: throw new TKMarkupParserException("Syntax: Wert erwartet",
475: pos);
476:
477: return pos;
478: }
479:
480: public int forceIdentifier(String text, int pos,
481: StringBuffer identifier) throws TKMarkupParserException {
482:
483: int oldPos = pos;
484:
485: pos = parseIdentifier(text, pos, identifier);
486: if (pos == oldPos)
487: throw new TKMarkupParserException(
488: "Syntax: Bezeichner erwartet", pos);
489:
490: return pos;
491: }
492:
493: public int forceIdentifier(String text, int pos,
494: TKMarkupItemList itemList) throws TKMarkupParserException {
495:
496: StringBuffer identifier = itemList != null ? new StringBuffer()
497: : null;
498:
499: pos = forceIdentifier(text, pos, identifier);
500:
501: if (itemList != null)
502: itemList.addElement(new String(identifier));
503:
504: return pos;
505: }
506:
507: public int forceParam(String text, int pos, TKHashtable params)
508: throws TKMarkupParserException {
509:
510: StringBuffer name = new StringBuffer();
511: String valueStr = null;
512:
513: pos = forceIdentifier(text, pos, name);
514: pos = parseWhitespace(text, pos, null);
515:
516: String nameStr = new String(name).toUpperCase();
517: registerParam(nameStr);
518:
519: if ((pos < text.length()) && (text.charAt(pos) == '=')) {
520:
521: StringBuffer value = new StringBuffer();
522:
523: pos = parseWhitespace(text, ++pos, null);
524: pos = forceValue(text, pos, value);
525:
526: valueStr = new String(value);
527: }
528:
529: TKMarkupParam old = (TKMarkupParam) params.get(name);
530: if (old != null)
531: throw new TKMarkupParserException("Syntax: Parameter "
532: + nameStr + " mehrfach", pos);
533:
534: TKMarkupParam param = createParam(nameStr, valueStr);
535: params.put(nameStr, param);
536:
537: return pos;
538: }
539:
540: public int forceMarkup(String text, int pos,
541: TKMarkupItemList itemList) throws TKMarkupParserException {
542:
543: if (pos >= text.length())
544: return pos;
545:
546: initMarkupParsing();
547:
548: StringBuffer name = new StringBuffer();
549: int startPos = pos;
550:
551: pos = parseAliens(text, pos);
552: if (pos > startPos)
553: return pos;
554:
555: try {
556: pos = forceIdentifier(text, pos, name);
557: } catch (TKMarkupParserException ex) {
558: ex.throwAgain(pos);
559: }
560:
561: String markupName = new String(name).toUpperCase();
562: TKHashtable params = new TKHashtable();
563: registerMarkup(markupName);
564: boolean backsl = false;
565: try {
566: pos = parseWhitespace(text, pos, null);
567:
568: while (pos < text.length()) {
569:
570: if (text.charAt(pos) == '>')
571: break;
572:
573: if (pos + 1 < text.length()) {
574: if (text.charAt(pos + 1) == '>'
575: && text.charAt(pos) == '/') {
576: backsl = true;
577: break;
578: }
579: }
580: int oldPos = pos;
581: pos = parseAlienTrailer(text, pos);
582: if (pos > oldPos)
583: break;
584:
585: pos = forceParam(text, pos, params);
586: pos = parseWhitespace(text, pos, null);
587: }
588:
589: if (backsl)
590: pos = forcePattern(text, pos, null, "/>");
591: else
592: pos = forcePattern(text, pos, null, ">");
593:
594: } catch (TKMarkupParserException ex) {
595: ex.throwAgain(pos);
596: } catch (Exception ex) {
597:
598: TKMarkupParserException.throwAgain(ex, "Fehler in "
599: + markupName + ": ", pos);
600: }
601:
602: TKMarkup markup = createMarkup(markupName, params, startPos,
603: backsl);
604:
605: register(markup);
606: pos = tieMarkup(text, pos, markup, itemList);
607:
608: return pos;
609: }
610:
611: public int parseAliens(String text, int pos)
612: throws TKMarkupParserException {
613:
614: return pos;
615: }
616:
617: public int parseAlienTrailer(String text, int pos)
618: throws TKMarkupParserException {
619:
620: return pos;
621: }
622:
623: public String compoundName() {
624: return null;
625: }
626:
627: public int parse(String text, int pos, TKMarkupItemList itemList) {
628:
629: TKMarkup storeMarkup = currentMarkup;
630: currentMarkup = null;
631:
632: while ((pos < text.length()) && !closeLevel(itemList)) {
633:
634: try {
635: char chr = text.charAt(pos);
636:
637: if (chr == '<')
638: pos = forceMarkup(text, pos + 1, itemList);
639: else
640: pos = forceText(text, pos, itemList);
641:
642: } catch (TKMarkupParserException ex) {
643:
644: diagnostics = ex.handle(diagnostics);
645: pos = ex.pos + 1;
646: }
647: }
648:
649: currentMarkup = storeMarkup;
650:
651: return pos;
652: }
653:
654: public void parse(String text) {
655:
656: int pos = 0;
657: while ((text != null) && (pos < text.length())) {
658:
659: pos = parse(text, pos, itemList);
660: cleanup(itemList, pos);
661: }
662: }
663:
664: public int tieMarkup(String text, int pos, TKMarkup markup,
665: TKMarkupItemList itemList) {
666:
667: itemList.addElement(markup);
668:
669: return pos;
670: }
671:
672: public TKVector dump() {
673:
674: TKVector dump = new TKVector();
675: if (itemList != null)
676: itemList.dump(dump, 0);
677: return dump;
678: }
679:
680: public String normalize() {
681:
682: return itemList == null ? "" : itemList.toString();
683: }
684:
685: public String expand() {
686:
687: return itemList == null ? "" : itemList.expand();
688: }
689:
690: public String convert2Tmpl() {
691:
692: return itemList == null ? "" : itemList.convert2Tmpl();
693: }
694:
695: public String convert2Xml() {
696:
697: return itemList == null ? "" : itemList.convert2Xml();
698: }
699: //{{DECLARE_CONTROLS
700: //}}
701: }
|