KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > chaperon > process > PatternProcessor


1 /*
2  * Copyright (C) Chaperon. All rights reserved.
3  * -------------------------------------------------------------------------
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE file.
7  */

8
9 package net.sourceforge.chaperon.process;
10
11 import net.sourceforge.chaperon.common.IntegerList;
12
13 /**
14  * Processor for pattern, which try for matching against a pattern.
15  *
16  * @author <a HREF="mailto:stephan@apache.org">Stephan Michels</a>
17  * @version CVS $Id: PatternProcessor.java,v 1.9 2003/12/09 19:55:53 benedikta Exp $
18  */

19 public class PatternProcessor
20 {
21   private PatternAutomaton automaton;
22   private IntegerList states = new IntegerList();
23   private IntegerList statekeys = new IntegerList();
24   private IntegerList newstates = new IntegerList();
25   private IntegerList newstatekeys = new IntegerList();
26
27   // for storing the traversed states
28
private IntegerList historystates = new IntegerList();
29   private IntegerList dependencies = new IntegerList();
30
31   // for storing the group, which were found
32
private String JavaDoc[] groups = new String JavaDoc[10];
33   private int[] groupstarts = new int[10];
34   private int[] groupends = new int[10];
35   private int groupcount = 0;
36
37   /**
38    * Create a new pattern processor.
39    */

40   public PatternProcessor() {}
41
42   /**
43    * Create a new pattern processor.
44    *
45    * @param automaton Automaton, which the processor should use.
46    */

47   public PatternProcessor(PatternAutomaton automaton)
48   {
49     setPatternAutomaton(automaton);
50   }
51
52   /**
53    * Set the pattern automaton.
54    *
55    * @param automaton Automaton, which the processor should use.
56    */

57   public void setPatternAutomaton(PatternAutomaton automaton)
58   {
59     if (automaton==null)
60       throw new NullPointerException JavaDoc();
61
62     this.automaton = automaton;
63     if (groupstarts.length<=(automaton.getGroupCount()))
64     {
65       groups = new String JavaDoc[automaton.getGroupCount()+1];
66       groupstarts = new int[automaton.getGroupCount()+1];
67       groupends = new int[automaton.getGroupCount()+1];
68     }
69   }
70
71   /**
72    * Search a postion, where the processor is successful.
73    *
74    * @param text Text.
75    *
76    * @return Next first position where the parser is successfull otherwise -1.
77    */

78   public boolean search(char[] text)
79   {
80     return search(text, 0);
81   }
82
83   /**
84    * Search a postion, where the processor is successful.
85    *
86    * @param text Text.
87    * @param start Start position within the text.
88    *
89    * @return Next first position where the parser is successfull otherwise -1.
90    */

91   public boolean search(char[] text, int start)
92   {
93     for (int position = start; position<=text.length; position++)
94       if (match(text, position))
95         return true;
96
97     return false;
98   }
99
100   private boolean verbose = false;
101
102   public void setVerbose(boolean verbose)
103   {
104     this.verbose = verbose;
105   }
106
107   /**
108    * Matches for pattern.
109    *
110    * @param text Text.
111    *
112    * @return True, if the processor matches successfully.
113    */

114   public boolean match(char[] text)
115   {
116     return match(text, 0);
117   }
118
119   /**
120    * Matches for pattern at specified position within the text.
121    *
122    * @param text Text
123    * @param start Position within the text.
124    *
125    * @return True, if the processor matches successfully.
126    */

127   public boolean match(char[] text, int start)
128   {
129     if (automaton==null)
130       throw new NullPointerException JavaDoc("PatternAutomaton is null");
131
132     if (automaton.getStateCount()<=0)
133       return false;
134
135     for (int i = 0; i<=automaton.getGroupCount(); i++)
136     {
137       groupstarts[i] = start;
138       groupends[i] = start;
139       groups[i] = null;
140     }
141
142     int position = start;
143     int state;
144     int key;
145     boolean found = false;
146     int foundkey = 0;
147     int foundPosition = start;
148
149     states.clear();
150     states.push(automaton.getFirstState());
151
152     newstates.clear();
153
154     statekeys.clear();
155     statekeys.push(0);
156
157     historystates.clear();
158     historystates.push(automaton.getFirstState());
159
160     dependencies.clear();
161     dependencies.push(0);
162
163     while ((!states.isEmpty()) && (position<=text.length))
164     {
165       state = states.pop();
166       key = statekeys.pop();
167
168       if (automaton.isFinalState(state))
169       {
170         found = true;
171         foundkey = key;
172         foundPosition = position;
173       }
174       else
175       {
176         switch (automaton.getType(state))
177         {
178           case PatternAutomaton.TYPE_NOMATCH:
179             pushState(states, statekeys, state, key);
180             break;
181           case PatternAutomaton.TYPE_MATCH:
182             if ((position<text.length) && (automaton.getIntervalBegin(state)<=text[position]) &&
183                 (automaton.getIntervalEnd(state)>=text[position]))
184               pushState(newstates, newstatekeys, state, key);
185
186             break;
187           case PatternAutomaton.TYPE_EXMATCH:
188             if ((position<text.length) &&
189                 ((automaton.getIntervalBegin(state)>text[position]) ||
190                 (automaton.getIntervalEnd(state)<text[position])))
191               pushState(states, statekeys, state, key);
192
193             break;
194           case PatternAutomaton.TYPE_MATCHANY:
195             pushState(newstates, newstatekeys, state, key);
196             break;
197           case PatternAutomaton.TYPE_BOL:
198             if (position==0)
199               pushState(states, statekeys, state, key);
200             else if ((position==1) &&
201                      (((text[position-1]=='\n') && (text[position]!='\r')) ||
202                      (text[position-1]=='\r')))
203               pushState(states, statekeys, state, key);
204             else if ((text[position-1]=='\r') ||
205                      ((text[position-1]=='\n') && (text[position]!='\r')))
206               pushState(states, statekeys, state, key);
207
208             break;
209           case PatternAutomaton.TYPE_EOL:
210             if (position>=text.length)
211               pushState(states, statekeys, state, key);
212             else if (((position+1)==text.length) &&
213                      ((text[position]=='\r') || (text[position]=='\n')))
214               pushState(states, statekeys, state, key);
215             else if ((text[position]=='\r') || (text[position]=='\n'))
216               pushState(states, statekeys, state, key);
217
218             break;
219           case PatternAutomaton.TYPE_GROUPSTART:
220             pushState(states, statekeys, state, key);
221             break;
222           case PatternAutomaton.TYPE_GROUPEND:
223             pushState(states, statekeys, state, key);
224             break;
225         }
226       }
227
228       if (states.isEmpty())
229       {
230         IntegerList temp = newstates;
231         newstates = states;
232         states = temp;
233
234         temp = newstatekeys;
235         newstatekeys = statekeys;
236         statekeys = temp;
237
238         position++; // next character
239
}
240     }
241
242     position = foundPosition;
243     key = foundkey;
244     while (key!=0)
245     {
246       key = dependencies.get(key);
247       state = historystates.get(key);
248
249       switch (automaton.getType(state))
250       {
251         case PatternAutomaton.TYPE_NOMATCH:
252           break;
253         case PatternAutomaton.TYPE_MATCH:
254           position--;
255           break;
256         case PatternAutomaton.TYPE_EXMATCH:
257           break;
258         case PatternAutomaton.TYPE_MATCHANY:
259           position--;
260           break;
261         case PatternAutomaton.TYPE_BOL:
262           break;
263         case PatternAutomaton.TYPE_EOL:
264           break;
265         case PatternAutomaton.TYPE_GROUPSTART:
266           if (groups[automaton.getGroupIndex(state)]==null)
267           {
268             groupstarts[automaton.getGroupIndex(state)] = position;
269             groups[automaton.getGroupIndex(state)] =
270               new String JavaDoc(text, position, groupends[automaton.getGroupIndex(state)]-position);
271           }
272
273           break;
274         case PatternAutomaton.TYPE_GROUPEND:
275           if (groups[automaton.getGroupIndex(state)]==null)
276             groupends[automaton.getGroupIndex(state)] = position;
277
278           break;
279       }
280     }
281
282     groupcount = automaton.getGroupCount();
283     for (int i = groupcount-1; (i>=0) && (groups[i]==null); i--)
284       groupcount--;
285
286     return found;
287   }
288
289   /**
290    * Push a state into the history.
291    *
292    * @param states The traversed states.
293    * @param keys Keys of the traversed paths.
294    * @param state Current state.
295    * @param key Current key.
296    */

297   private void pushState(IntegerList states, IntegerList keys, int state, int key)
298   {
299     states.push(automaton.getTransitions(state));
300     historystates.push(automaton.getTransitions(state));
301     for (int i = automaton.getTransitions(state).length; i>0; i--)
302     {
303       keys.push(dependencies.getCount());
304       dependencies.push(key);
305     }
306   }
307
308   /**
309    * Return the text, which in last match was found.
310    *
311    * @return Text.
312    */

313   public String JavaDoc getGroup()
314   {
315     return groups[0];
316   }
317
318   /**
319    * Return the text of the specifed group, which in last match was found.
320    *
321    * @param group Index of group;
322    *
323    * @return Text
324    */

325   public String JavaDoc getGroup(int group)
326   {
327     return groups[group];
328   }
329
330   /**
331    * Return count of groups.
332    *
333    * @return Count of groups.
334    */

335   public int getGroupCount()
336   {
337     return groupcount;
338   }
339
340   /**
341    * Return the start position of the last match.
342    *
343    * @return Start position.
344    */

345   public int getGroupStart()
346   {
347     return groupstarts[0];
348   }
349
350   /**
351    * Return the start position of a group from the last match.
352    *
353    * @param group Index of group.
354    *
355    * @return Start position.
356    */

357   public int getGroupStart(int group)
358   {
359     return groupstarts[group];
360   }
361
362   /**
363    * Return the end position of the last match.
364    *
365    * @return End position.
366    */

367   public int getGroupEnd()
368   {
369     return groupends[0];
370   }
371
372   /**
373    * Return the end position of a group from the last match.
374    *
375    * @param group Index of group.
376    *
377    * @return End position.
378    */

379   public int getGroupEnd(int group)
380   {
381     return groupends[group];
382   }
383 }
384
Popular Tags