support for CAPTCHAs
[mir.git] / source / mir / util / SimpleParser.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License, 
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
23  * (or with modified versions of the above that use the same license as the above), 
24  * and distribute linked combinations including the two.  You must obey the 
25  * GNU General Public License in all respects for all of the code used other than 
26  * the above mentioned libraries.  If you modify this file, you may extend this 
27  * exception to your version of the file, but you are not obligated to do so.  
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mir.util;
32
33 import multex.Failure;
34 import org.apache.oro.text.regex.*;
35
36 /**
37  * Simple parser. Can be used to parse a <code>String</code> based using
38  * regular epxression.
39  */
40 public class SimpleParser {
41   private int position;
42
43   private Perl5Compiler compiler = new Perl5Compiler();
44   private Perl5Matcher matcher = new Perl5Matcher();
45   private PatternMatcherInput input;
46
47
48   /**
49    * Initialize a new <code>SimpleParser</code>, with <code>someData</code>
50    * as the text to parse.
51    *
52    * @param someData the text to parse
53    */
54
55   public SimpleParser(String someData) {
56     position = 0;
57     input = new PatternMatcherInput(someData);
58   }
59
60   /**
61    * Parses a regular expression. Uses suppled <code>aMessage</code> parameter
62    * in case of an error.
63    *
64    * @param aRegularExpression  the expression to find at the cursor position
65    * @param aMessage the error message to apply if the regular expression couldn't be found
66    *
67    * @return the text that matched the regular expression
68    *
69    * @throws mir.util.SimpleParser.UnExpectedTokenExc
70    *     if the token wasn't found. <code>aMessage</code> will be used in the
71    *     exception's message 
72    */
73   public String parse(Pattern aRegularExpression, String aMessage) throws UnExpectedTokenExc {
74     input.setCurrentOffset(position);
75     if ( matcher.contains(input, aRegularExpression) && input.getMatchBeginOffset() == position) {
76         position = input.getMatchEndOffset();
77
78         return input.match();
79     }
80     else {
81       throw new UnExpectedTokenExc(aMessage + " at position " +
82               position + " in '" + input.toString() + "'");
83     }
84   }
85
86   /**
87    * Attempts to match the data right after the parsing position to
88    * a regular expression
89    *
90    * @throws UnExpectedTokenExc if no match could be found for the given regular
91    * expression.
92    */
93   public String parse(Pattern aRegularExpression) throws UnExpectedTokenExc {
94     return parse( aRegularExpression, "No match found for '" + aRegularExpression.getPattern() + "'");
95   }
96
97   /**
98    * Attempts to skip data at the parsing position matching the supplied regular expression.
99    * If no match is found, the method will simply return 
100    *
101    * @param aRegularExpression the expression to find and skip at the parsing position.
102    */
103
104   public void skip(Pattern aRegularExpression) {
105       input.setCurrentOffset(position);
106     
107       if (matcher.contains(input, aRegularExpression) &&
108           input.getMatchBeginOffset() == position) {
109           position = input.getMatchEndOffset();
110       }
111   }
112
113   /**
114    * Returns <code>true</code> if the data at the parsing position matches the given
115    * regular expression.
116    */
117   public boolean parses(String anExpression) throws MalformedRegularExpressionExc {
118     try {
119       return parses(compiler.compile(anExpression));
120     }
121     catch (MalformedPatternException e) {
122         throw new MalformedRegularExpressionExc(e);
123     }
124   }
125
126   /**
127    * Tests whether the data at the parsing position matches a given
128    * regular expression.
129    *
130    * @param aRegularExpression the pattern to look for
131    * @return returns <code>true</code> if the regular expression is found at the
132    *    parsing position
133    */
134   public boolean parses(Pattern aRegularExpression) {
135      input.setCurrentOffset(position);
136
137      return matcher.contains(input, aRegularExpression) && input.getMatchBeginOffset() == position;
138   }
139
140   /**
141    * Attempts to match the data right after the parsing position to
142    * a regular expression
143    *
144    * @throws SimpleParserExc if no match could be found for the given regular
145    * expression.
146    */
147   public String parse(String anExpression) throws MalformedRegularExpressionExc, UnExpectedTokenExc {
148     try {
149       return parse(compiler.compile(anExpression));
150     }
151     catch (MalformedPatternException e) {
152         throw new MalformedRegularExpressionExc(e);
153     }
154   }
155
156
157   /**
158    * Parses text at the current parsing position matching the given <code>anExpression</code>.
159    * Will apply the supplied message to an exception if no match could be found.
160    */
161   public String parse(String anExpression, String aMessage) throws MalformedRegularExpressionExc, UnExpectedTokenExc {
162     try {
163       return parse(compiler.compile(anExpression), aMessage);
164     }
165     catch (MalformedPatternException e) {
166         throw new MalformedRegularExpressionExc(e);
167     }
168   }
169
170   /**
171    * Skips (i.e. discards) text matching the supplied regular expression
172    */
173
174   public void skip(String anExpression) throws MalformedRegularExpressionExc {
175     try {
176       skip(compiler.compile(anExpression));
177     }
178     catch (MalformedPatternException e) {
179         throw new MalformedRegularExpressionExc(e);
180     }
181   }
182
183   /**
184    * returns <code>true</code> if the parser is at the end of the data
185    */
186   public boolean isAtEnd() {
187     return position >=input.getEndOffset();
188   }
189
190   /**
191    * Returns the "remaining" data: the data after the current position
192    */
193   public String remainingData() {
194     return input.toString().substring(input.getEndOffset());
195   }
196
197   /**
198    * Unchecked exception thrown from <code>SimpleParser</code>
199    */
200
201   public static class SimpleParserFailure extends Failure {
202     public SimpleParserFailure(Throwable aThrowable) {
203       super(aThrowable.getMessage(), aThrowable);
204     }
205
206     public SimpleParserFailure(String aMessage, Throwable aThrowable) {
207       super(aMessage, aThrowable);
208     }
209   }
210
211   /**
212    * Checked exception thrown from <code>SimpleParser</code>
213    */
214   public static class SimpleParserExc extends Exception {
215     protected SimpleParserExc(String aMessage, Throwable aCause) {
216       super(aMessage, aCause);
217     }
218
219     public SimpleParserExc(Throwable aCause) {
220       super(aCause);
221     }
222
223     public SimpleParserExc(String aMessage) {
224       super(aMessage);
225     }
226   }
227
228   public static class MalformedRegularExpressionExc extends SimpleParserExc {
229     public MalformedRegularExpressionExc(String aMessage, Throwable aCause) {
230       super(aMessage, aCause);
231     }
232
233     public MalformedRegularExpressionExc(Throwable aCause) {
234       super(aCause);
235     }
236   }
237
238   public static class UnExpectedTokenExc extends SimpleParserExc {
239     public UnExpectedTokenExc(String aMessage) {
240       super(aMessage);
241     }
242   }
243
244 }