KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > percederberg > grammatica > parser > ProductionPatternAlternative


1 /*
2  * ProductionPatternAlternative.java
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2.1
7  * of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307, USA.
18  *
19  * Copyright (c) 2003-2005 Per Cederberg. All rights reserved.
20  */

21
22 package net.percederberg.grammatica.parser;
23
24 import java.util.ArrayList JavaDoc;
25
26 /**
27  * A production pattern alternative. This class represents a list of
28  * production pattern elements. In order to provide productions that
29  * cannot be represented with the element occurance counters, multiple
30  * alternatives must be created and added to the same production
31  * pattern. A production pattern alternative is always contained
32  * within a production pattern.
33  *
34  * @author Per Cederberg, <per at percederberg dot net>
35  * @version 1.0
36  */

37 public class ProductionPatternAlternative {
38
39     /**
40      * The production pattern.
41      */

42     private ProductionPattern pattern;
43
44     /**
45      * The element list.
46      */

47     private ArrayList JavaDoc elements = new ArrayList JavaDoc();
48
49     /**
50      * The look-ahead set associated with this alternative.
51      */

52     private LookAheadSet lookAhead = null;
53
54     /**
55      * Creates a new production pattern alternative.
56      */

57     public ProductionPatternAlternative() {
58     }
59
60     /**
61      * Checks if this alternative is recursive on the left-hand side.
62      * This method checks all the possible left side elements and
63      * returns true if the pattern itself is among them.
64      *
65      * @return true if the alternative is left side recursive, or
66      * false otherwise
67      */

68     public boolean isLeftRecursive() {
69         ProductionPatternElement elem;
70
71         for (int i = 0; i < elements.size(); i++) {
72             elem = (ProductionPatternElement) elements.get(i);
73             if (elem.getId() == pattern.getId()) {
74                 return true;
75             } else if (elem.getMinCount() > 0) {
76                 break;
77             }
78         }
79         return false;
80     }
81
82     /**
83      * Checks if this alternative is recursive on the right-hand side.
84      * This method checks all the possible right side elements and
85      * returns true if the pattern itself is among them.
86      *
87      * @return true if the alternative is right side recursive, or
88      * false otherwise
89      */

90     public boolean isRightRecursive() {
91         ProductionPatternElement elem;
92
93         for (int i = elements.size() - 1; i >= 0; i--) {
94             elem = (ProductionPatternElement) elements.get(i);
95             if (elem.getId() == pattern.getId()) {
96                 return true;
97             } else if (elem.getMinCount() > 0) {
98                 break;
99             }
100         }
101         return false;
102     }
103
104     /**
105      * Checks if this alternative would match an empty stream of
106      * tokens. This check is equivalent of getMinElementCount()
107      * returning zero (0).
108      *
109      * @return true if the rule can match an empty token stream, or
110      * false otherwise
111      */

112     public boolean isMatchingEmpty() {
113         return getMinElementCount() == 0;
114     }
115
116     /**
117      * Returns the production pattern containing this alternative.
118      *
119      * @return the production pattern for this alternative
120      */

121     public ProductionPattern getPattern() {
122         return pattern;
123     }
124
125     /**
126      * Changes the production pattern containing this alternative.
127      * This method should only be called by the production pattern
128      * class.
129      *
130      * @param pattern the new production pattern
131      */

132     void setPattern(ProductionPattern pattern) {
133         this.pattern = pattern;
134     }
135
136     /**
137      * Returns the number of elements in this alternative.
138      *
139      * @return the number of elements in this alternative
140      */

141     public int getElementCount() {
142         return elements.size();
143     }
144
145     /**
146      * Returns the minimum number of elements needed to satisfy this
147      * alternative. The value returned is the sum of all the elements
148      * minimum count.
149      *
150      * @return the minimum number of elements
151      */

152     public int getMinElementCount() {
153         ProductionPatternElement elem;
154         int min = 0;
155
156         for (int i = 0; i < elements.size(); i++) {
157             elem = (ProductionPatternElement) elements.get(i);
158             min += elem.getMinCount();
159         }
160         return min;
161     }
162
163     /**
164      * Returns the maximum number of elements needed to satisfy this
165      * alternative. The value returned is the sum of all the elements
166      * maximum count.
167      *
168      * @return the maximum number of elements
169      */

170     public int getMaxElementCount() {
171         ProductionPatternElement elem;
172         int max = 0;
173
174         for (int i = 0; i < elements.size(); i++) {
175             elem = (ProductionPatternElement) elements.get(i);
176             if (elem.getMaxCount() >= Integer.MAX_VALUE) {
177                 return Integer.MAX_VALUE;
178             } else {
179                 max += elem.getMaxCount();
180             }
181         }
182         return max;
183     }
184
185     /**
186      * Returns an element in this alternative.
187      *
188      * @param pos the element position, 0 <= pos < count
189      *
190      * @return the element found
191      */

192     public ProductionPatternElement getElement(int pos) {
193         return (ProductionPatternElement) elements.get(pos);
194     }
195
196     /**
197      * Adds a token to this alternative. The token is appended to the
198      * end of the element list. The multiplicity values specified
199      * define if the token is optional or required, and if it can be
200      * repeated.
201      *
202      * @param id the token (pattern) id
203      * @param min the minimum number of occurancies
204      * @param max the maximum number of occurancies, or
205      * -1 for infinite
206      */

207     public void addToken(int id, int min, int max) {
208         addElement(new ProductionPatternElement(true, id, min, max));
209     }
210
211     /**
212      * Adds a production to this alternative. The production is
213      * appended to the end of the element list. The multiplicity
214      * values specified define if the production is optional or
215      * required, and if it can be repeated.
216      *
217      * @param id the production (pattern) id
218      * @param min the minimum number of occurancies
219      * @param max the maximum number of occurancies, or
220      * -1 for infinite
221      */

222     public void addProduction(int id, int min, int max) {
223         addElement(new ProductionPatternElement(false, id, min, max));
224     }
225
226     /**
227      * Adds a production pattern element to this alternative. The
228      * element is appended to the end of the element list.
229      *
230      * @param elem the production pattern element
231      */

232     public void addElement(ProductionPatternElement elem) {
233         elements.add(elem);
234     }
235
236     /**
237      * Adds a production pattern element to this alternative. The
238      * multiplicity values in the element will be overridden with the
239      * specified values. The element is appended to the end of the
240      * element list.
241      *
242      * @param elem the production pattern element
243      * @param min the minimum number of occurancies
244      * @param max the maximum number of occurancies, or
245      * -1 for infinite
246      */

247     public void addElement(ProductionPatternElement elem,
248                            int min,
249                            int max) {
250
251         if (elem.isToken()) {
252             addToken(elem.getId(), min, max);
253         } else {
254             addProduction(elem.getId(), min, max);
255         }
256     }
257
258     /**
259      * Checks if this object is equal to another. This method only
260      * returns true for another production pattern alternative with
261      * identical elements in the same order.
262      *
263      * @param obj the object to compare with
264      *
265      * @return true if the object is identical to this one, or
266      * false otherwise
267      */

268     public boolean equals(Object JavaDoc obj) {
269         ProductionPatternAlternative alt;
270
271         if (obj instanceof ProductionPatternAlternative) {
272             alt = (ProductionPatternAlternative) obj;
273             return elements.equals(alt.elements);
274         } else {
275             return false;
276         }
277     }
278
279     /**
280      * Returns a string representation of this object.
281      *
282      * @return a token string representation
283      */

284     public String JavaDoc toString() {
285         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
286
287         for (int i = 0; i < elements.size(); i++) {
288             if (i > 0) {
289                 buffer.append(" ");
290             }
291             buffer.append(elements.get(i));
292         }
293         return buffer.toString();
294     }
295
296     /**
297      * Returns the look-ahead set associated with this alternative.
298      *
299      * @return the look-ahead set associated with this alternative
300      */

301     LookAheadSet getLookAhead() {
302         return lookAhead;
303     }
304
305     /**
306      * Sets the look-ahead set for this alternative.
307      *
308      * @param lookAhead the new look-ahead set
309      */

310     void setLookAhead(LookAheadSet lookAhead) {
311         this.lookAhead = lookAhead;
312     }
313 }
314
Popular Tags