KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > parsec > Scanners


1 /*****************************************************************************
2  * Copyright (C) Zephyr Business Solutions Corp. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  *****************************************************************************/

8 /*
9  * Created on Dec 17, 2004
10  *
11  * Author Ben Yu
12  */

13 package jfun.parsec;
14
15 import jfun.parsec.pattern.CharPredicate;
16 import jfun.parsec.pattern.CharPredicates;
17 import jfun.parsec.pattern.Pattern;
18 import jfun.parsec.pattern.Patterns;
19
20
21 /**
22  * Scanners class provides basic character level parsers
23  * and the combinators that only work on scanners.
24  * <p>
25  * All scanners return null. "_" is used as type parameter to indicate this.
26  * <p>
27  * @author Ben Yu
28  *
29  * Dec 17, 2004
30  */

31 public final class Scanners {
32
33   /**
34    * Scans greedily for 0 or more characters
35    * that satisfies the given CharPredicate.
36    * @param cp the predicate object.
37    * @return the Parser object.
38    */

39   public static Parser<_> many(CharPredicate cp){return many("many", cp);}
40   /**
41    * Scans greedily for 1 or more characters
42    * that satisfies the given CharPredicate.
43    * @param cp the predicate object.
44    * @return the Parser object.
45    */

46   public static Parser<_> many1(CharPredicate cp){return many1("many1", cp);}
47   /**
48    * Scans greedily for 0 or more occurrences of the given pattern.
49    * @param pp the pattern object.
50    * @return the Parser object.
51    */

52   public static Parser<_> many(Pattern pp){return many("many", pp);}
53   /**
54    * Scans greedily for 1 or more occurrences of the given pattern.
55    * @param pp the pattern object.
56    * @return the Parser object.
57    */

58   public static Parser<_> many1(Pattern pp){return many1("many1", pp);}
59   /**
60    * Scans greedily for 0 or more characters
61    * that satisfies the given CharPredicate.
62    * @param name the name of the Parser object.
63    * @param cp the predicate object.
64    * @return the Parser object.
65    */

66   public static Parser<_> many(final String JavaDoc name, final CharPredicate cp){
67     return isPattern(name, Patterns.many(cp), "many");
68   }
69   /**
70    * Scans greedily for 1 or more characters
71    * that satisfies the given CharPredicate.
72    * @param name the name of the Parser object.
73    * @param cp the predicate object.
74    * @return the Parser object.
75    */

76   public static Parser<_> many1(final String JavaDoc name, final CharPredicate cp){
77     return isPattern(name, Patterns.many1(cp), "many1");
78   }
79   /**
80    * Scans greedily for 0 or more occurrences of the given pattern.
81    * @param name the name of the Parser object.
82    * @param pp the pattern object.
83    * @return the Parser object.
84    */

85   public static Parser<_> many(final String JavaDoc name, final Pattern pp){
86     return isPattern(name, pp.many(), "many");
87   }
88   /**
89    * Scans greedily for 1 or more occurrences of the given pattern.
90    * @param name the name of the Parser object.
91    * @param pp the pattern object.
92    * @return the Parser object.
93    */

94   public static Parser<_> many1(final String JavaDoc name, final Pattern pp){
95     return isPattern(name, pp.many1(), "many1");
96   }
97
98   /**
99    * matches the input against the specified string.
100    * @param str the string to match
101    * @return the scanner.
102    */

103   public static Parser<_> isString(final String JavaDoc str){
104     return isString(str, str);
105   }
106   /**
107    * matches the input against the specified string.
108    * @param str the string to match
109    * @param err the error message if fails.
110    * @return the scanner.
111    */

112   public static Parser<_> isString(final String JavaDoc str, final String JavaDoc err){
113     return isString("=="+str, str, err);
114   }
115   /**
116    * matches the input against the specified string.
117    * @param name the scanner name.
118    * @param str the string to match
119    * @param err the error message if fails.
120    * @return the scanner.
121    */

122   public static Parser<_> isString(final String JavaDoc name, final String JavaDoc str, final String JavaDoc err){
123     return isPattern(name, Patterns.isString(str), err);
124   }
125   /**
126    * Scans greedily for 1 or more whitespace characters.
127    * @return the Parser object.
128    */

129   public static Parser<_> isWhitespaces(){
130     return isWhitespaces("isWhitespaces");
131   }
132   /**
133    * Scans greedily for 1 or more whitespace characters.
134    * @param name the Parser object name.
135    * @return the Parser object.
136    */

137   public static Parser<_> isWhitespaces(final String JavaDoc name){
138     return isWhitespaces(name, "whitespaces");
139   }
140   /**
141    * Scans greedily for 1 or more whitespace characters.
142    * @param name the Parser object name.
143    * @param err the expected message when fails.
144    * @return the Parser object.
145    */

146   public static Parser<_> isWhitespaces(final String JavaDoc name, final String JavaDoc err){
147     return isPattern(name, Patterns.many1(CharPredicates.isWhitespace()), err);
148   }
149   /**
150    * Scans the input for an occurrence of a string pattern.
151    * @param pp the pattern object.
152    * @param err the expected message when fails.
153    * @return the Parser object.
154    */

155   public static Parser<_> isPattern(final Pattern pp, final String JavaDoc err){
156     return isPattern("isPattern", pp, err);
157   }
158   /**
159    * Scans the input for an occurrence of a string pattern.
160    * @param name the Parser object name.
161    * @param pp the pattern object.
162    * @param err the expected message when fails.
163    * @return the Parser object.
164    */

165   public static Parser<_> isPattern(final String JavaDoc name, final Pattern pp, final String JavaDoc err){
166     return new Parser<_>(name){
167       boolean apply(final ParseContext ctxt){
168         final int at = ctxt.getAt();
169         final CharSequence JavaDoc src = ctxt.getSource();
170         final int mlen = pp.match(src, src.length(), at);
171         if(mlen < 0){
172           return setErrorExpecting(err, ctxt);
173         }
174         ctxt.next(mlen);
175         return nothing(ctxt);
176       }
177     };
178   }
179
180   //case insensitive
181
/**
182    * matches the input against the specified string case insensitively.
183    * @param str the string to match
184    * @param err the error message if fails.
185    * @return the scanner.
186    */

187   public static Parser<_> isStringCI(final String JavaDoc str, final String JavaDoc err){
188     return isStringCI("is " + str, str, err);
189   }
190   /**
191    * matches the input against the specified string case insensitively.
192    * @param name the scanner name.
193    * @param str the string to match
194    * @param err the error message if fails.
195    * @return the scanner.
196    */

197   public static Parser<_> isStringCI(final String JavaDoc name, final String JavaDoc str, final String JavaDoc err){
198     return isPattern(name, Patterns.isStringCI(str), err);
199   }
200   /**
201    * matches the input against the specified string case insensitively.
202    * @param str the string to match
203    * @return the scanner.
204    */

205   public static Parser<_> isStringCI(final String JavaDoc str){
206     return isStringCI(str, str);
207   }
208   /**
209    * matches any character in the input.
210    * Different from one(), it fails on EOF. Also it consumes the current character in the input.
211    * @return the scanner.
212    */

213   public static Parser<_> anyChar(){
214     return anyChar("any character");
215   }
216   /**
217    * matches any character in the input.
218    * Different from one(), it fails on EOF. Also it consumes the current character in the input.
219    * @param err the error message if fails.
220    * @return the scanner.
221    */

222   public static Parser<_> anyChar(final String JavaDoc err){
223     return anyChar("anyChar", err);
224   }
225   /**
226    * matches any character in the input.
227    * Different from one(), it fails on EOF. Also it consumes the current character in the input.
228    * @param name the scanner name.
229    * @param err the error message if fails.
230    * @return the scanner.
231    */

232   public static Parser<_> anyChar(final String JavaDoc name, final String JavaDoc err){
233     return new Parser<_>(name){
234       boolean apply(final ParseContext ctxt){
235         if(ctxt.isEof()){
236           return setErrorExpecting(err, ctxt);
237         }
238         ctxt.next();
239         return nothing(ctxt);
240       }
241     };
242   }
243
244   /**
245    * succeed and consume the current character if it satisfies the given CharPredicate.
246    * @param cp the predicate.
247    * @return the scanner.
248    */

249   public static Parser<_> isChar(final CharPredicate cp){
250     return isChar("isChar", cp);
251   }
252   /**
253    * succeed and consume the current character if it satisfies the given CharPredicate.
254    * @param name the scanner name.
255    * @param cp the predicate.
256    * @return the scanner.
257    */

258   public static Parser<_> isChar(final String JavaDoc name, final CharPredicate cp){
259     return isChar(name, cp, "" + cp);
260   }
261   /**
262    * succeed and consume the current character if it satisfies the given CharPredicate.
263    * @param cp the predicate.
264    * @param err the error message.
265    * @return the scanner.
266    */

267   public static Parser<_> isChar(final CharPredicate cp, final String JavaDoc err){
268     return isChar("isChar", cp, err);
269   }
270   /**
271    * succeed and consume the current character if it satisfies the given CharPredicate.
272    * @param name the scanner name.
273    * @param cp the predicate.
274    * @param err the error message.
275    * @return the scanner.
276    */

277   public static Parser<_> isChar(final String JavaDoc name, final CharPredicate cp, final String JavaDoc err){
278     return new Parser<_>(name){
279       boolean apply(final ParseContext ctxt){
280         if(ctxt.isEof()){
281           return setErrorExpecting(err, ctxt);
282         }
283         final char c = ctxt.peekChar();
284         if(cp.isChar(c)){
285           ctxt.next();
286           return nothing(ctxt);
287         }
288         else{
289           return setErrorExpecting(err, ctxt);
290         }
291       }
292     };
293   }
294
295   /**
296    * succeed and consume the current character if it is equal to ch.
297    * @param ch the expected character.
298    * @param err the error message.
299    * @return the scanner.
300    */

301   public static Parser<_> isChar(final char ch, final String JavaDoc err){
302     return isChar("=="+ch, ch, err);
303   }
304   /**
305    * succeed and consume the current character if it is equal to ch.
306    * @param name the scanner name.
307    * @param ch the expected character.
308    * @param err the error message.
309    * @return the scanner.
310    */

311   public static Parser<_> isChar(final String JavaDoc name, final char ch, final String JavaDoc err){
312     return isChar(name, CharPredicates.isChar(ch), err);
313   }
314   /**
315    * succeed and consume the current character if it is equal to ch.
316    * @param ch the expected character.
317    * @return the scanner.
318    */

319   public static Parser<_> isChar(final char ch){
320     return isChar("=="+ch, ch);
321   }
322   /**
323    * succeed and consume the current character if it is equal to ch.
324    * @param name the scanner name.
325    * @param ch the expected character.
326    * @return the scanner.
327    */

328   public static Parser<_> isChar(final String JavaDoc name, final char ch){
329     return isChar(name, ch, CharEncoder.encode(ch));
330   }
331   /**
332    * succeed and consume the current character if it is equal to ch.
333    * @param ch the expected character.
334    * @param err the error message.
335    * @return the scanner.
336    */

337   public static Parser<_> notChar(final char ch, final String JavaDoc err){
338     return notChar("!="+ch, ch, err);
339   }
340   /**
341    * succeed and consume the current character if it is not equal to ch.
342    * @param name the scanner name.
343    * @param ch the expected character.
344    * @param err the error message.
345    * @return the scanner.
346    */

347   public static Parser<_> notChar(final String JavaDoc name, final char ch, final String JavaDoc err){
348     return isChar(name, CharPredicates.notChar(ch), err);
349   }
350   /**
351    * succeed and consume the current character if it is not equal to ch.
352    * @param ch the expected character.
353    * @return the scanner.
354    */

355   public static Parser<_> notChar(final char ch){
356     return notChar("!="+ch, ch);
357   }
358   /**
359    * succeed and consume the current character if it is not equal to ch.
360    * @param name the scanner name.
361    * @param ch the expected character.
362    * @return the scanner.
363    */

364   public static Parser<_> notChar(final String JavaDoc name, final char ch){
365     return notChar(name, ch, "^"+CharEncoder.encode(ch));
366   }
367
368   private static char[] copy(final char[] chars){
369     return (char[])chars.clone();
370   }
371   private static StringBuffer JavaDoc toString(final StringBuffer JavaDoc buf, final char[] chars){
372     buf.append('[');
373     if(chars.length >0){
374       buf.append(CharEncoder.encode(chars[0]));
375       for(int i=1; i<chars.length; i++){
376         buf.append(',').append(CharEncoder.encode(chars[i]));
377       }
378     }
379     buf.append(']');
380     return buf;
381   }
382   private static Parser<_> _among(final String JavaDoc name, final char[] chars, final String JavaDoc err){
383     return isChar(name, CharPredicates.among(chars), err);
384   }
385   private static Parser<_> _notAmong(final String JavaDoc name, final char[] chars, final String JavaDoc err){
386     return isChar(name, CharPredicates.notAmong(chars), err);
387   }
388   /**
389    * succeed and consume the current character if it equals to one of the given characters.
390    *
391    * @param name the scanner name.
392    * @param chars the characters.
393    * @param err the error message when the character is not among the given values.
394    * @return the scanner.
395    */

396   public static Parser<_> among(final String JavaDoc name, final char[] chars, final String JavaDoc err){
397     if(chars.length==0)return Parsers.zero();
398     if(chars.length==1)return isChar(name, chars[0], err);
399     return _among(name, copy(chars), err);
400   }
401   /**
402    * succeed and consume the current character if it equals to one of the given characters.
403    *
404    * @param name the scanner name.
405    * @param chars the characters.
406    * @return the scanner.
407    */

408   public static Parser<_> among(final String JavaDoc name, final char[] chars){
409     final StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
410     toString(buf, chars);
411     return among(name, chars, buf.toString());
412   }
413   /**
414    * succeed and consume the current character if it equals to one of the given characters.
415    *
416    * @param chars the characters.
417    * @param err the error message when the character is not among the given values.
418    * @return the scanner.
419    */

420   public static Parser<_> among(final char[] chars, final String JavaDoc err){
421     return among("among", chars, err);
422   }
423   /**
424    * succeed and consume the current character if it equals to one of the given characters.
425    *
426    * @param chars the characters.
427    * @return the scanner.
428    */

429   public static Parser<_> among(final char[] chars){
430     return among("among", chars);
431   }
432   /**
433    * succeed and consume the current character if it is not equal to any of the given characters.
434    *
435    * @param name the scanner name.
436    * @param chars the characters.
437    * @param err the error message when the character is among the given values.
438    * @return the scanner.
439    */

440   public static Parser<_> notAmong(final String JavaDoc name, final char[] chars, final String JavaDoc err){
441     if(chars.length==0)return anyChar();
442     if(chars.length==1)return notChar(name, chars[0], err);
443     return _notAmong(name, copy(chars), err);
444   }
445   /**
446    * succeed and consume the current character if it is not equal to any of the given characters.
447    *
448    * @param name the scanner name.
449    * @param chars the characters.
450    * @return the scanner.
451    */

452   public static Parser<_> notAmong(final String JavaDoc name, final char[] chars){
453     final StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
454     buf.append("^");
455     toString(buf, chars);
456     return notAmong(name, chars, buf.toString());
457   }
458   /**
459    * succeed and consume the current character if it is not equal to any of the given characters.
460    *
461    * @param chars the characters.
462    * @param err the error message when the character is not among the given values.
463    * @return the scanner.
464    */

465   public static Parser<_> notAmong(final char[] chars, final String JavaDoc err){
466     return among("notAmong", chars, err);
467   }
468   /**
469    * succeed and consume the current character if it is not equal to any of the given characters.
470    *
471    * @param chars the characters.
472    * @return the scanner.
473    */

474   public static Parser<_> notAmong(final char[] chars){
475     return notAmong("notAmong", chars);
476   }
477
478   /**
479    * if the current input starts with the given string, succeed and consumes all the characters until the end of line '\n character.
480    * It does not consume the end of line character.
481    * @param start the start string.
482    * @return the scanner.
483    */

484   public static Parser<_> isLineComment(final String JavaDoc start){
485     return isLineComment("isLineComment", start);
486   }
487   /**
488    * if the current input starts with the given string, succeed and consumes all the characters until the end of line '\n character.
489    * It does not consume the end of line character.
490    * @param name the scanner name.
491    * @param start the start string.
492    * @return the scanner.
493    */

494   public static Parser<_> isLineComment(final String JavaDoc name, final String JavaDoc start){
495     return isPattern(name, Patterns.isLineComment(start), start);
496   }
497   /**
498    * scanner for c++/java style line comment.
499    * @return the scanner.
500    */

501   public static Parser<_> javaLineComment(){
502     return isLineComment("//");
503   }
504   /**
505    * scanner for T-SQL style line comment.
506    * @return the scanner.
507    */

508   public static Parser<_> sqlLineComment(){
509     return isLineComment("--");
510   }
511   /**
512    * scanner for c++/java style block comment.
513    * @return the scanner.
514    */

515   public static Parser<_> javaBlockComment(){
516     //return isBlockComment("/*", "*/");
517
return Parsers.seq(isString("/*"),
518         /*many(p_javaBlockCommented())*/
519         p_javaBlockCommented(), isString("*/"));
520     //isNestableBlockComment("/*", "*/");
521
}
522   /**
523    * scanner for haskell style block comment. ({- -})
524    * @return the scanner.
525    */

526   public static Parser<_> haskellBlockComment(){
527     return
528     //isBlockCommentWith("{-", "-}");
529
Parsers.seq(isString("{-"), p_haskellBlockCommented(), isString("-}"));
530   }
531   /**
532    * scanner for haskell style line comment. (--)
533    * @return the scanner.
534    */

535   public static Parser<_> haskellLineComment(){
536     return isLineComment("--");
537   }
538   /**
539    * scanner for non-nested block comment.
540    * @param start the start string of a block comment.
541    * @param end the end string of a block comment.
542    * @return the scanner.
543    */

544   public static Parser<_> isBlockComment(final String JavaDoc start, final String JavaDoc end){
545     return isBlockComment("isBlockComment", start, end);
546   }
547   /**
548    * scanner for non-nested block comment.
549    * @param name the scanner name.
550    * @param start the start string of a block comment.
551    * @param end the end string of a block comment.
552    * @return the scanner.
553    */

554   public static Parser<_> isBlockComment(
555       final String JavaDoc name, final String JavaDoc start, final String JavaDoc end){
556     final Pattern opening = Patterns.isString(start).seq(Patterns.notString(end).many());
557     return isPattern(opening, start).seq(name, isString(end));
558   }
559   /**
560    * Scans a non-nestable block comment.
561    * @param open the opening string.
562    * @param close the closing string.
563    * @param commented the commented pattern.
564    * @return the Scanner for the block comment.
565    */

566   public static Parser<_> isBlockComment(final String JavaDoc open, final String JavaDoc close,
567       final Pattern commented){
568     final Pattern opening = Patterns.isString(open)
569     .seq(Patterns.isString(close).not().seq(commented).many());
570     return isPattern(opening, open).seq(isString(close));
571   }
572   /**
573    * Scans a non-nestable block comment.
574    * @param open the opening pattern.
575    * @param close the closing pattern.
576    * @param commented the commented pattern.
577    * @return the Scanner for the block comment.
578    */

579   public static Parser<_> isBlockComment(final Parser<_> open,
580       final Parser<_> close, final Parser<?> commented){
581     return isBlockComment("isBlockComment", open, close, commented);
582   }
583   /**
584    * Scans a non-nestable block comment.
585    * @param name the name of the block comment scanner.
586    * @param open the opening pattern.
587    * @param close the closing pattern.
588    * @param commented the commented pattern.
589    * @return the Scanner for the block comment.
590    */

591   public static Parser<_> isBlockComment(final String JavaDoc name,
592       final Parser<_> open, final Parser<_> close, final Parser<?> commented){
593     return Parsers.seq(name, open, close.not().seq(commented).many(), close);
594   }
595   /**
596    * Scans a nestable block comment.
597    * Nested comments and any other characters can be in the comment body.
598    * @param open the opening pattern.
599    * @param close the closing pattern.
600    * @return the block comment scanner.
601    */

602   public static Parser<_> isNestableBlockComment(final String JavaDoc open, final String JavaDoc close){
603     return isNestableBlockComment(open, close, anyChar());
604   }
605   /**
606    * Scans a nestable block comment.
607    * Nested comments and some commented pattern can be in the comment body.
608    * @param open the opening string.
609    * @param close the closing string.
610    * @param commented the commented pattern except for nested comments.
611    * @return the block comment scanner.
612    */

613   public static Parser<_> isNestableBlockComment(final String JavaDoc open, final String JavaDoc close,
614       final Parser<?> commented){
615     return isNestableBlockComment(isString(open), isString(close), commented);
616   }
617   /**
618    * Scans a nestable block comment.
619    * Nested comments and some commented pattern can be in the comment body.
620    * @param open the opening pattern.
621    * @param close the closing pattern.
622    * @param commented the commented pattern except for nested comments.
623    * @return the block comment scanner.
624    */

625   public static Parser<_> isNestableBlockComment(
626       final Parser<?> open, final Parser<?> close,
627       final Parser<?> commented){
628     return isNestableBlockComment("isNestableBlockComment",
629         open, close, commented);
630   }
631   /**
632    * Scans a nestable block comment.
633    * Nested comments and some commented pattern can be in the comment body.
634    * @param name the name of the block comment scanner.
635    * @param open the opening pattern.
636    * @param close the closing pattern.
637    * @param commented the commented pattern except for nested comments.
638    * @return the block comment scanner.
639    */

640   public static Parser<_> isNestableBlockComment(
641       final String JavaDoc name, final Parser<?> open, final Parser<?> close,
642       final Parser<?> commented){
643     return new Parser<_>(name){
644       boolean apply(final ParseContext ctxt){
645         if(!open.parse(ctxt)) return false;
646         for(int level=1; level>0;){
647           final int at = ctxt.getAt();
648           if(close.parse(ctxt)){
649             if(at == ctxt.getAt())
650               throw new IllegalParserStateException("closing comment scanner not consuming input.");
651             level--;
652             continue;
653           }
654           if(at != ctxt.getAt()) return false;
655           if(open.parse(ctxt)){
656             if(at == ctxt.getAt())
657               throw new IllegalParserStateException("opening comment scanner not consuming input.");
658             level++;
659             continue;
660           }
661           if(at != ctxt.getAt()) return false;
662           if(commented.parse(ctxt)){
663             if(at == ctxt.getAt())
664               throw new IllegalParserStateException("commented scanner not consuming input.");
665             continue;
666           }
667           return false;
668         }
669         return nothing(ctxt);
670       }
671     };
672   }
673   /**
674    * a scanner with a pattern for sql server string literal.
675    * a sql server string literal is a string quoted by single quote,
676    * a single quote character is escaped by 2 single quotes.
677    * @return the scanner.
678    */

679   public static Parser<_> isSqlString(){
680     return isSqlString("isSqlString");
681   }
682   /**
683    * a scanner with a pattern for sql server string literal.
684    * a sql server string literal is a string quoted by single quote,
685    * a single quote character is escaped by 2 single quotes.
686    * @param name the name of the scanner.
687    * @return the scanner.
688    */

689   public static Parser<_> isSqlString(final String JavaDoc name){
690     /*
691     final Pattern open = Patterns.isChar('\'').seq(
692         Patterns.or(Patterns.notChar('\''), Patterns.isString("''"))
693         .many()
694     );
695     return isPattern(open, "'").seq(name, isChar('\''));
696     */

697     final Parser<_> q = isChar('\'');
698     final Parser<_> qs = isPattern(
699         Patterns.regex("(('')|[^'])*"), "quoted string");
700     return Parsers.between(name, q, q, qs);
701   }
702   /**
703    * a scanner with a pattern for double quoted string literal.
704    * backslash '\' is used as escape character.
705    * @param name the name of the scanner.
706    * @return the scanner.
707    */

708   public static Parser<_> isQuotedString(final String JavaDoc name){
709     /*
710     final Pattern q = Patterns.isChar('"');
711     final Pattern open = q.seq(quoted().many());
712     return isPattern(open, "\"").seq(name, isPattern(q, "\""));
713     */

714     final Parser<_> q = Scanners.isChar('"');
715     final Parser<_> qc = isPattern(
716        quoted_str ,"quoted string");
717     return Parsers.between(name, q, q, qc);
718   }
719   private static final Pattern quoted_str =
720     Patterns.regex("((\\\\.)|[^\"\\\\])*");
721   /**
722    * a scanner with a pattern for double quoted string literal.
723    * backslash '\' is used as escape character.
724    * @return the scanner.
725    */

726   public static Parser<_> isQuotedString(){
727     return isQuotedString("isQuotedString");
728   }
729   /*
730   private static Pattern quoted(){
731     return Patterns.or(
732             Patterns.isEscaped(),
733             Patterns.notChar('"')
734         );
735   }*/

736   private static final Pattern quoted_char =
737     Patterns.regex("(\\\\.)|[^'\\\\]");
738   /**
739    * scanner for a c/c++/java style character literal. such as 'a' or '\\'.
740    * @param name the name of the scanner.
741    * @return the scanner.
742    */

743   public static Parser<_> isQuotedChar(final String JavaDoc name){
744     //final Scanner q = isChar('\'');
745
/*
746     final Pattern q = Patterns.isChar('\'');
747     final Pattern qc = Patterns.or(
748         Patterns.isString("\\'"),
749         Patterns.notChar('\'')
750     );
751     return isPattern(q.seq(qc), "'").seq(name, isPattern(q, "'"));
752     */

753     final Parser<_> q = Scanners.isChar('\'');
754     final Parser<_> qc = isPattern(
755        quoted_char ,"quoted char");
756     return Parsers.between(name, q, q, qc);
757   }
758   /**
759    * scanner for a c/c++/java style character literal. such as 'a' or '\\'.
760    * @return the scanner.
761    */

762   public static Parser<_> isQuotedChar(){
763     return isQuotedChar("isQuotedChar");
764   }
765   /**
766    * scans a quoted string that is opened by c1 and closed by c2.
767    * @param c1 the opening character.
768    * @param c2 the closing character.
769    * @return the scanner.
770    */

771   public static Parser<_> quoted(final char c1, final char c2){
772     return quoted("quoted", c1, c2);
773   }
774   /**
775    * scans a quoted string that is opened by c1 and closed by c2.
776    * @param name the scanner name.
777    * @param c1 the opening character.
778    * @param c2 the closing character.
779    * @return the scanner.
780    */

781   public static Parser<_> quoted(final String JavaDoc name, final char c1, final char c2){
782     return isPattern(name, Patterns.isChar(c1)
783             .seq(Patterns.many(CharPredicates.notChar(c2))),
784             ""+c1).seq(isChar(c2));
785   }
786   /**
787    * scans a quoted string that is opened by c1 and closed by c2.
788    * @param open the opening character.
789    * @param close the closing character.
790    * @return the scanner.
791    */

792   public static Parser<_> quoted(final Parser<_> open, final Parser<_> close, final Parser<?> s){
793     return quoted("quoted", open, close, s);
794   }
795   /**
796    * scans a quoted string that is opened by pattern represented by Scanner open and closed by pattern represented by Scanner close.
797    * @param name the scanner name.
798    * @param open the scanner for the opening pattern.
799    * @param close the scanner for the closing pattern.
800    * @return the scanner.
801    */

802   public static Parser<_> quoted(
803       final String JavaDoc name, final Parser<_> open, final Parser<_> close, final Parser<?> s){
804     return Parsers.seq(name, open, s.many(), close);
805   }
806   /**
807    * the c++/java style delimiter of tokens.
808    * whitespace, line comment, block comment.
809    * @return the scanner.
810    */

811   public static Parser<_> javaDelimiter(){
812     return javaDelimiter("javaDelimiter");
813   }
814   /**
815    * the c++/java style delimiter of tokens.
816    * whitespace, line comment, block comment.
817    * @param name the scanner name.
818    * @return the scanner.
819    */

820   public static Parser<_> javaDelimiter(final String JavaDoc name){
821     return Parsers.sum(
822         isWhitespaces(), javaLineComment(), javaBlockComment()).many(name);
823   }
824   /**
825    * the haskell style delimiter of tokens.
826    * whitespace, line comment, block comment.
827    * @return the scanner.
828    */

829   public static Parser<_> haskellDelimiter(){
830     return haskellDelimiter("haskellDelimiter");
831   }
832   /**
833    * the haskell style delimiter of tokens.
834    * whitespace, line comment, block comment.
835    * @param name the scanner name.
836    * @return the scanner.
837    */

838   public static Parser<_> haskellDelimiter(final String JavaDoc name){
839     return Parsers.sum(
840         isWhitespaces(), haskellBlockComment(), haskellLineComment()).many(name);
841   }
842   /**
843    * the T-SQL style delimiter of tokens.
844    * whitespace and line comment.
845    * @return the scanner.
846    */

847   public static Parser<_> sqlDelimiter(){
848     return sqlDelimiter("sqlDelimiter");
849   }
850   /**
851    * the T-SQL style delimiter of tokens.
852    * whitespace and line comment.
853    * @param name the scanner name.
854    * @return the scanner.
855    */

856   public static Parser<_> sqlDelimiter(final String JavaDoc name){
857     return Parsers.sum(isWhitespaces(), sqlLineComment(), javaBlockComment())
858       .many(name);
859   }
860   /**
861    * Any delimiter with whitespace, non-nested block comment and line comment.
862    * @param name the scanner name.
863    * @param lcomment line comment starting string.
864    * @param openc block comment opening string.
865    * @param closec block comment closing string.
866    * @return the scanner.
867    */

868   public static Parser<_> stdDelimiter(final String JavaDoc name,
869       final String JavaDoc lcomment, final String JavaDoc openc, final String JavaDoc closec){
870     return Parsers.sum(isWhitespaces(), isLineComment(lcomment), isBlockComment(openc, closec))
871       .many(name);
872   }
873   /**
874    * Any delimiter with whitespace, non-nested block comment and line comment.
875    * @param lcomment line comment starting string.
876    * @param openc block comment opening string.
877    * @param closec block comment closing string.
878    * @return the scanner.
879    */

880   public static Parser<_> stdDelimiter(final String JavaDoc lcomment, final String JavaDoc openc, final String JavaDoc closec){
881     return stdDelimiter("stdDelimiter", lcomment, openc, closec);
882   }
883
884   /**
885    * If a string is not followed by a alphanumeric character, it is well-delimited.
886    * delimited() make sure the pattern represented by scanner s is delimited.
887    * @param s the scanner for the to-be-delimited pattern.
888    * @param err the error message if it is not delimited.
889    * @return the new scanner.
890    */

891   public static <R> Parser<R> delimited(final Parser<R> s, final String JavaDoc err){
892     return delimited("delimited", s, err);
893   }
894   /**
895    * If a string is not followed by a alphanumeric character, it is well-delimited.
896    * delimited() make sure the pattern represented by scanner s is delimited.
897    * @param name the new scanner name.
898    * @param s the scanner for the to-be-delimited pattern.
899    * @param err the error message if it is not delimited.
900    * @return the new scanner.
901    */

902   public static <R> Parser<R> delimited(final String JavaDoc name, final Parser<R> s, final String JavaDoc err){
903     return s.followedBy(name, isChar(CharPredicates.isAlphaNumeric(), err).not());
904   }
905   /**
906    * If a string is not followed by a alphanumeric character, it is well-delimited.
907    * delimited() make sure the pattern represented by scanner s is delimited.
908    * @param s the scanner for the to-be-delimited pattern.
909    * @return the new scanner.
910    */

911   public static <R> Parser<R> delimited(final Parser<R> s){
912     return delimited("delimited", s);
913   }
914   /**
915    * If a string is not followed by a alphanumeric character, it is well-delimited.
916    * delimited() make sure the pattern represented by scanner s is delimited.
917    * @param name the new scanner name.
918    * @param s the scanner for the to-be-delimited pattern.
919    * @return the new scanner.
920    */

921   public static <R> Parser<R> delimited(final String JavaDoc name, final Parser<R> s){
922     return delimited(name, s, "delimiter");
923   }
924   /**
925    * After character level parser p succeeds,
926    * subsequently feed the recognized characters to the Parser scanner
927    * for a nested scanning.
928    * @param p the first parser object to identify the characters.
929    * @param scanner the second parser object to scan the characters again.
930    * @param module the module name.
931    * @return the new Parser object.
932    */

933   public static Parser<_> scanChars(final Parser<?> p, final Parser<_> scanner,
934       final String JavaDoc module){
935     return scanChars("scanChars", p, scanner, module);
936   }
937   /**
938    * After character level parser p succeeds,
939    * subsequently feed the recognized characters to the Parser scanner
940    * for a nested scanning.
941    * @param name the name of the new Parser object.
942    * @param p the first parser object to identify the characters.
943    * @param scanner the second parser object to scan the characters again.
944    * @param module the module name.
945    * @return the new Parser object.
946    */

947   public static Parser<_> scanChars(final String JavaDoc name,
948       final Parser<?> p, final Parser<_> scanner, final String JavaDoc module){
949     return new Parser<_>(name){
950       boolean apply(final ParseContext ctxt){
951         final int from = ctxt.getAt();
952         if(!p.parse(ctxt)) return false;
953         final ScannerState s0 =
954           new ScannerState(ctxt.getSource(), from,
955               module, ctxt.getPositionMap(), ctxt.getAt()-from,
956               ctxt.getReturn(), ctxt.getUserState());
957         return ParserInternals.cont(ctxt, s0, scanner);
958       }
959     };
960   }
961   /**
962    * Matches a character if the input has at least 1 character;
963    * and if the input has at least 2 characters,
964    * the first 2 characters are not c1 and c2.
965    * @return the Pattern object.
966    */

967   private static Pattern notChar2(final char c1, final char c2){
968     return new Pattern(){
969       public int match(final CharSequence JavaDoc src, final int len, final int from){
970         if(from >= len-1) return Pattern.MISMATCH;
971         if(src.charAt(from) == c1 && src.charAt(from+1) == c2) return Pattern.MISMATCH;
972         return 1;
973       }
974     };
975   }
976   
977   private static Parser<_> p_javaBlockCommented(){
978     return isPattern(notChar2('*', '/').many(), "commented block");
979   }
980   /*
981   private static final Parser<_> p_javaBlockCommented =
982     isPattern(Patterns.regex("([^*]|(\\*[^/]))*"), "block content");
983   private static final Parser<_> p_haskellBlockCommented =
984     isPattern(Patterns.regex("([^-]|(\\*[^}]))*"), "block content");
985   */

986   private static Parser<_> p_haskellBlockCommented(){
987     return isPattern(notChar2('-', '}').many(), "commented block");
988   }
989   private static boolean setErrorExpecting(final String JavaDoc msg, final ParseContext ctxt){
990     return ParserInternals.setErrorExpecting(msg, ctxt);
991   }
992   private static boolean nothing(ParseContext ctxt){
993     ctxt.setReturn(null);
994     return true;
995   }
996   /**
997    * Greedily runs Parser s repeatedly,
998    * and ignores the pattern recognized by Parser delim before and after each s.
999    * Parser s has to be a lexer object that returns a Tok object.
1000   * The result Tok objects are collected and returned in a Tok[] array.
1001   * @param delim the delimiter Parser object.
1002   * @param s the Parser object.
1003   * @return the new Parser object.
1004   */

1005  @Deprecated JavaDoc
1006  public static Parser<Tok[]> lexeme(final Parser<?> delim, final Parser<Tok> s){
1007    return Lexers.lexeme(delim, s);
1008  }
1009  /**
1010   * Greedily runs Parser s repeatedly,
1011   * and ignores the pattern recognized by Parser delim before and after each s.
1012   * Parser s has to be a lexer object that returns a Tok object.
1013   * The result Tok objects are collected and returned in a Tok[] array.
1014   * @param name the name of the new Parser object.
1015   * @param delim the delimiter Parser object.
1016   * @param s the Parser object.
1017   * @return the new Parser object.
1018   */

1019  @Deprecated JavaDoc
1020  public static Parser<Tok[]> lexeme(final String JavaDoc name,
1021      final Parser<?> delim, final Parser<Tok> s){
1022    return Lexers.lexeme(name, delim, s);
1023  }
1024  /**
1025   * Transform the recognized character range of scanner s to a token object
1026   * with a Tokenizer.
1027   * If the Tokenizer.toToken() returns null, scan fails.
1028   * @param s the scanner to transform.
1029   * @param tn the Tokenizer object.
1030   * @return the new Scanner.
1031   */

1032  @Deprecated JavaDoc
1033  public static Parser<Tok> lexer(final Parser<?> s, final Tokenizer tn){
1034    return Lexers.lexer(s,tn);
1035  }
1036  /**
1037   * Transform the recognized character range of scanner s to a token object
1038   * with a Tokenizer.
1039   * If the Tokenizer.toToken() returns null, scan fails.
1040   * @param s the scanner to transform.
1041   * @param tn the Tokenizer object.
1042   * @param err the error message when the tokenizer returns null.
1043   * @return the new Scanner.
1044   */

1045  @Deprecated JavaDoc
1046  public static Parser<Tok> lexer(final Parser<?> s, final Tokenizer tn, final String JavaDoc err){
1047    return Lexers.lexer(s, tn, err);
1048  }
1049  /**
1050   * Transform the recognized character range of scanner s to a token object
1051   * with a Tokenizer.
1052   * If the Tokenizer.toToken() returns null, scan fails.
1053   * @param name the name of the new Scanner.
1054   * @param tn the Tokenizer object.
1055   * @param s the scanner to transform.
1056   * @return the new Scanner.
1057   */

1058  @Deprecated JavaDoc
1059  public static Parser<Tok> lexer(final String JavaDoc name, final Parser<?> s, final Tokenizer tn){
1060    return Lexers.lexer(name, s, tn);
1061  }
1062  /**
1063   * Transform the recognized character range of scanner s to a token object
1064   * with a Tokenizer.
1065   * If the Tokenizer.toToken() returns null, scan fails.
1066   * @param name the name of the new Scanner.
1067   * @param s the scanner to transform.
1068   * @param tn the Tokenizer object.
1069   * @param err the error message when the tokenizer returns null.
1070   * @return the new Scanner.
1071   */

1072  @Deprecated JavaDoc
1073  public static Parser<Tok> lexer(final String JavaDoc name, final Parser<?> s, final Tokenizer tn,
1074      final String JavaDoc err){
1075    return Lexers.lexer(name, s, tn, err);
1076  }
1077  
1078}
1079
Popular Tags