1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3
* Copyright (C) 1998-2001 Gerwin Klein <lsf@jflex.de> *
4
* All rights reserved. *
6
* This program is free software; you can redistribute it and/or modify *
7
* it under the terms of the GNU General Public License. See the file *
8
* COPYRIGHT for more information. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License along *
16
* with this program; if not, write to the Free Software Foundation, Inc., *
17
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
26
* Performs simple semantic analysis on regular expressions.
28
* (used for checking if trailing contexts are legal)
30
* @author Gerwin Klein
31
* @version JFlex 1.3.5, $Revision: 1.15 $, $Date: 2001/10/08 10:08:05 $
33
public final class SemCheck {
35
// stored globally since they are used as constants in all checks
36
private static Macros macros;
37
private static char maxChar;
41
* Performs semantic analysis for all expressions.
43
* Currently: illegal lookahead check only
44
* [fixme: more checks possible]
46
* @param rs the reg exps to be checked
47
* @param m the macro table (in expanded form)
48
* @param max max character of the used charset (for negation)
49
* @param f the spec file containing the rules [fixme]
51
public static void check(RegExps rs, Macros m, char max, File f) {
55
boolean errors = false;
56
int num = rs.getNum();
57
for (int i = 0; i < num; i++) {
58
RegExp r = rs.getRegExp(i);
59
RegExp l = rs.getLookAhead(i);
61
if (!checkLookAhead(r,l)) {
63
Out.error(f, ErrorMessages.LOOKAHEAD_ERROR, rs.getLine(i), -1);
67
if (errors) throw new GeneratorException();
72
* Checks for illegal lookahead expressions.
74
* Lookahead in JFlex only works when the first expression has fixed
75
* length or when the intersection of the last set of the first expression
76
* and the first set of the second expression is empty.
78
* @param r1 first regexp
79
* @param r2 second regexp (the lookahead)
81
* @return true iff JFlex can generate code for the lookahead expression
83
private static boolean checkLookAhead(RegExp r1, RegExp r2) {
84
return r2 == null || length(r1) > 0 || !(last(r1).and(first(r2)).containsElements());
89
* Returns length if expression has fixed length, -1 otherwise.
91
private static int length(RegExp re) {
98
int l1 = length(r.r1);
99
if (l1 < 0) return -1;
100
int l2 = length(r.r2);
110
int l1 = length(r.r1);
111
if (l1 < 0) return -1;
112
int l2 = length(r.r2);
113
if (l2 < 0) return -1;
128
String content = (String) ((RegExp1) re).content;
129
return content.length();
133
return length(macros.getDefinition((String) ((RegExp1) re).content));
136
throw new Error("Unkown expression type "+re.type+" in "+re);
141
* Returns true iff the matched language contains epsilon
143
private static boolean containsEpsilon(RegExp re) {
150
return containsEpsilon(r.r1) || containsEpsilon(r.r2);
154
if (containsEpsilon(r.r1))
155
return containsEpsilon(r.r2);
164
return containsEpsilon( (RegExp) ((RegExp1)re).content );
172
return ((String) ((RegExp1) re).content).length() <= 0;
175
return containsEpsilon(macros.getDefinition((String) ((RegExp1) re).content));
178
throw new Error("Unkown expression type "+re.type+" in "+re);
183
* Returns the first set of an expression.
185
* (the first-character-projection of the language)
187
private static IntCharSet first(RegExp re) {
194
return first(r.r1).add(first(r.r2));
198
if ( containsEpsilon(r.r1) )
199
return first(r.r1).add(first(r.r2));
206
return first((RegExp) ((RegExp1)re).content);
209
return new IntCharSet((Vector) ((RegExp1) re).content);
212
IntCharSet all = new IntCharSet(new Intervall( (char) 0,maxChar));
213
IntCharSet set = new IntCharSet((Vector) ((RegExp1) re).content);
218
return new IntCharSet(((Character) ((RegExp1) re).content).charValue());
221
String content = (String) ((RegExp1) re).content;
222
if (content.length() > 0)
223
return new IntCharSet(content.charAt(0));
225
return new IntCharSet();
228
return first(macros.getDefinition((String) ((RegExp1) re).content));
231
throw new Error("Unkown expression type "+re.type+" in "+re);
236
* Returns the last set of the expression
238
* (the last-charater-projection of the language)
240
private static IntCharSet last(RegExp re) {
248
return last(r.r1).add(last(r.r2));
252
if ( containsEpsilon(r.r2) )
253
return last(r.r1).add(last(r.r2));
260
return last((RegExp) ((RegExp1)re).content);
263
return new IntCharSet((Vector) ((RegExp1) re).content);
266
IntCharSet all = new IntCharSet(new Intervall( (char) 0,maxChar));
267
IntCharSet set = new IntCharSet((Vector) ((RegExp1) re).content);
272
return new IntCharSet(((Character) ((RegExp1) re).content).charValue());
275
String content = (String) ((RegExp1) re).content;
276
if (content.length() > 0)
277
return new IntCharSet(content.charAt(content.length()-1));
279
return new IntCharSet();
282
return last(macros.getDefinition((String) ((RegExp1) re).content));
285
throw new Error("Unkown expression type "+re.type+" in "+re);