source: other-projects/rsyntax-textarea/devel-packages/jflex-1.4.3/src/JFlex/Macros.java@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 6.6 KB
Line 
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * JFlex 1.4.3 *
3 * Copyright (C) 1998-2009 Gerwin Klein <[email protected]> *
4 * All rights reserved. *
5 * *
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. *
9 * *
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. *
14 * *
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 *
18 * *
19 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20
21package JFlex;
22
23import java.util.*;
24
25
26/**
27 * Symbol table and expander for macros.
28 *
29 * Maps macros to their (expanded) definitions, detects cycles and
30 * unused macros.
31 *
32 * @author Gerwin Klein
33 * @version JFlex 1.4.3, $Revision: 433 $, $Date: 2009-01-31 19:52:34 +1100 (Sat, 31 Jan 2009) $
34 */
35final public class Macros {
36
37 /** Maps names of macros to their definition */
38 private Hashtable macros;
39
40 /** Maps names of macros to their "used" flag */
41 private Hashtable used;
42
43
44 /**
45 * Creates a new macro expander.
46 */
47 public Macros() {
48 macros = new Hashtable();
49 used = new Hashtable();
50 }
51
52
53 /**
54 * Stores a new macro and its definition.
55 *
56 * @param name the name of the new macro
57 * @param definition the definition of the new macro
58 *
59 * @return <code>true</code>, iff the macro name has not been
60 * stored before.
61 */
62 public boolean insert(String name, RegExp definition) {
63
64 if (Options.DEBUG)
65 Out.debug("inserting macro "+name+" with definition :"+Out.NL+definition); //$NON-NLS-1$ //$NON-NLS-2$
66
67 used.put(name, Boolean.FALSE);
68 return macros.put(name,definition) == null;
69 }
70
71
72 /**
73 * Marks a makro as used.
74 *
75 * @return <code>true</code>, iff the macro name has been
76 * stored before.
77 */
78 public boolean markUsed(String name) {
79 return used.put(name, Boolean.TRUE) != null;
80 }
81
82
83 /**
84 * Tests if a macro has been used.
85 *
86 * @return <code>true</code>, iff the macro has been used in
87 * a regular expression.
88 */
89 public boolean isUsed(String name) {
90 return ((Boolean)used.get(name)).booleanValue();
91 }
92
93
94 /**
95 * Returns all unused macros.
96 *
97 * @return the enumeration of macro names that have not been used.
98 */
99 public Enumeration unused() {
100
101 Vector unUsed = new Vector();
102
103 Enumeration names = used.keys();
104 while ( names.hasMoreElements() ) {
105 String name = (String) names.nextElement();
106 Boolean isUsed = (Boolean) used.get( name );
107 if ( !isUsed.booleanValue() ) unUsed.addElement(name);
108 }
109
110 return unUsed.elements();
111 }
112
113
114 /**
115 * Fetches the definition of the macro with the specified name,
116 * <p>
117 * The definition will either be the same as stored (expand() not
118 * called), or an equivalent one, that doesn't contain any macro
119 * usages (expand() called before).
120 *
121 * @param name the name of the macro
122 *
123 * @return the definition of the macro, <code>null</code> if
124 * no macro with the specified name has been stored.
125 *
126 * @see JFlex.Macros#expand
127 */
128 public RegExp getDefinition(String name) {
129 return (RegExp) macros.get(name);
130 }
131
132
133 /**
134 * Expands all stored macros, so that getDefinition always returns
135 * a defintion that doesn't contain any macro usages.
136 *
137 * @throws MacroException if there is a cycle in the macro usage graph.
138 */
139 public void expand() throws MacroException {
140
141 Enumeration names;
142
143 names = macros.keys();
144
145 while ( names.hasMoreElements() ) {
146 String name = (String) names.nextElement();
147 if ( isUsed(name) )
148 macros.put(name, expandMacro(name, getDefinition(name)));
149 // this put doesn't get a new key, so only a new value
150 // is set for the key "name" (without changing the enumeration
151 // "names"!)
152 }
153 }
154
155
156 /**
157 * Expands the specified macro by replacing each macro usage
158 * with the stored definition.
159 *
160 * @param name the name of the macro to expand (for detecting cycles)
161 * @param definition the definition of the macro to expand
162 *
163 * @return the expanded definition of the macro.
164 *
165 * @throws MacroException when an error (such as a cyclic definition)
166 * occurs during expansion
167 */
168 private RegExp expandMacro(String name, RegExp definition) throws MacroException {
169
170 // Out.print("checking macro "+name);
171 // Out.print("definition is "+definition);
172
173 switch ( definition.type ) {
174 case sym.BAR:
175 case sym.CONCAT:
176 RegExp2 binary = (RegExp2) definition;
177 binary.r1 = expandMacro(name, binary.r1);
178 binary.r2 = expandMacro(name, binary.r2);
179 return definition;
180
181 case sym.STAR:
182 case sym.PLUS:
183 case sym.QUESTION:
184 case sym.BANG:
185 case sym.TILDE:
186 RegExp1 unary = (RegExp1) definition;
187 unary.content = expandMacro(name, (RegExp) unary.content);
188 return definition;
189
190 case sym.MACROUSE:
191 String usename = (String) ((RegExp1) definition).content;
192
193 if ( name.equals(usename) )
194 throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_CYCLE, name));
195
196 RegExp usedef = getDefinition(usename);
197
198 if ( usedef == null )
199 throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_DEF_MISSING, usename, name));
200
201 markUsed(usename);
202
203 return expandMacro(name, usedef);
204
205 case sym.STRING:
206 case sym.STRING_I:
207 case sym.CHAR:
208 case sym.CHAR_I:
209 case sym.CCLASS:
210 case sym.CCLASSNOT:
211 return definition;
212
213 default:
214 throw new MacroException("unknown expression type "+definition.type+" in macro expansion"); //$NON-NLS-1$ //$NON-NLS-2$
215 }
216 }
217}
Note: See TracBrowser for help on using the repository browser.