Source code: com/thermidor/xml/ParserGenerator.java
1 package com.thermidor.xml;
2 /*@LEGAL@*/
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.util.Iterator;
7 import java.util.LinkedList;
8 import java.util.Properties;
9 import java.util.StringTokenizer;
10 /**
11 The parser generator generates TEMPLATE implemntation BASE classes only it
12 is not a full blown code generator.
13 @author Edward Turnock
14 */
15 public class ParserGenerator {
16 /**
17 Convert the specified token string into a lisdt of tokens
18 @param t the string to tokenize.
19 @return a list of token strings
20 */
21 private static LinkedList tokenizeToList( String t ) {
22 LinkedList retval = new LinkedList();
23 StringTokenizer tokens = new StringTokenizer( t, "," );
24
25 while ( tokens.hasMoreTokens() ) {
26 retval.add( tokens.nextToken() );
27 }
28
29 return retval;
30 }
31
32 /**
33 Display an error message an exit.
34 @param err the error message to display on std err.
35 */
36 private static void messageError( String err ) {
37 System.err.println( err );
38 System.exit( 1 );
39 }
40
41 /**
42 The main entry point to the program.
43 @param argv the commandline arguments
44 @throws Exception if anything goes wrong
45 */
46 public static void main( String[] argv ) throws Exception {
47 if ( argv.length == 0 ) {
48 String message = "ParserGenerator ../parserdefinition.properties";
49 System.out.println( message );
50 System.out.println( "exit(0)" );
51 }
52
53 ParserGenerator pg = new ParserGenerator();
54 pg.parserGeneratorName = "SAX Parser ParserGenerator";
55 pg.parserGeneratorVersion = "0.0.1";
56
57 Properties props = new Properties();
58
59 try {
60 props.load( new FileInputStream( argv[ 0 ] ) );
61
62 } catch ( IOException ioe ) {
63 System.err.println( "could not load definition file: "
64 + argv[ 0 ] );
65 System.exit( 1 );
66 }
67
68
69 String basename = props.getProperty( "basename" );
70
71 if ( basename == null ) {
72 messageError( "basename not defined" );
73 }
74
75 String packagename = props.getProperty( "packagename" );
76
77 if ( packagename == null ) {
78 messageError( "packagename not defined" );
79 }
80
81 String elements = props.getProperty( "elements" );
82
83 if ( elements == null ) {
84 messageError( "elements not defined" );
85 }
86
87 String attributes = props.getProperty( "attributes" );
88
89
90
91 pg.parserBaseName = basename;
92 pg.parserPackageName = packagename;
93 pg.attributes = tokenizeToList( attributes );
94 pg.elements = tokenizeToList( elements );
95 pg.emitBase( new PrintWriter( System.out, true ) );
96 }
97
98 /**
99 Convert the specified string into a valid java identifier.
100 @param s the string to convert
101 @return the converted string.
102 */
103 private String javaName( String s ) {
104 StringBuffer sb = new StringBuffer();
105 int len = ( s != null ) ? s.length() : 0;
106
107 if ( len > 0 ) {
108 char ch = s.charAt( 0 );
109
110 if ( ch == ':' ) {
111 sb.append( "_" );
112
113 } else {
114 sb.append( ch );
115 }
116
117 for ( int cnt = 1;cnt < len;cnt++ ) {
118 ch = s.charAt( cnt );
119
120 switch ( ch ) {
121
122 case '.': {
123 sb.append( '_' );
124 break;
125 }
126
127 case '-': {
128 sb.append( '_' );
129 break;
130 }
131
132 case ':': {
133 sb.append( '_' );
134 break;
135 }
136
137 default: {
138 sb.append( ch );
139 }
140 }
141 }
142
143 }
144
145 return sb.toString();
146 }
147
148 /**
149 The name of the parser generator
150 */
151 private String parserGeneratorName;
152 /**
153 The version of the parser generator
154 */
155 private String parserGeneratorVersion;
156 /**
157 The base name of the abstract parser to create
158 */
159 private String parserBaseName;
160 /**
161 The package name that it should have.
162 */
163 private String parserPackageName;
164 /**
165 The attributes that are declared in the DTD
166 */
167 private LinkedList attributes;
168 /**
169 The elements that are declared in the DTD.
170 */
171 private LinkedList elements;
172 /**
173 Emit the source file that corresponds to the properties that have been
174 specified in the input porpoerties file.
175 @param pw the printWriter on whihc the source will be emitted.
176 @throws IOException if an error occured trying to emit the output.
177 */
178 public void emitBase( PrintWriter pw ) throws IOException {
179 pw.println( "package " + parserPackageName + ";" );
180 pw.println( "//Generated by " +
181 parserGeneratorName + "-" +
182 parserGeneratorVersion );
183 pw.println( "import java.util.Hashtable;" );
184 pw.println( "import com.thermidor.xml.SAXParserBase;" );
185 pw.println( "public abstract class " +
186 parserBaseName + "Base extends SAXParserBase{" );
187 Iterator i = attributes.iterator();
188
189 while ( i.hasNext() ) {
190 String x = ( String ) i.next();
191 String jx = javaName( x );
192 pw.println( " public static final String ATTR_" +
193 jx + "=\"" + x + "\";" );
194 }
195
196 i = elements.iterator();
197
198 while ( i.hasNext() ) {
199 String x = ( String ) i.next();
200 String jx = javaName( x );
201 pw.println( " public static final String STR_"
202 + jx + "=\"" + x + "\";" );
203 }
204
205 int count = 0;
206 i = elements.iterator();
207
208 while ( i.hasNext() ) {
209 String x = ( String ) i.next();
210 x = javaName( x );
211 pw.println( " public static final int TOKEN_" +
212 x + "=" + count + ";" );
213 count++;
214 }
215
216 pw.print( " private static final Hashtable _tokenTable" );
217 pw.println( " =new Hashtable();" );
218 pw.println( " static" );
219 pw.println( " {" );
220
221 i = elements.iterator();
222
223 while ( i.hasNext() ) {
224 String x = ( String ) i.next();
225 x = javaName( x );
226 pw.println( " _tokenTable.put(STR_" +
227 x + ",new Integer(TOKEN_" + x + "));" );
228 }
229
230 pw.println( " }" );
231 i = elements.iterator();
232
233 while ( i.hasNext() ) {
234 String x = ( String ) i.next();
235 x = javaName( x );
236 pw.println( " protected void " +
237 x + "Start(SAXElement element){}" );
238 }
239
240 i = elements.iterator();
241
242 while ( i.hasNext() ) {
243 String x = ( String ) i.next();
244 x = javaName( x );
245 pw.println( " protected void " +
246 x + "End(SAXElement element){}" );
247 }
248
249 pw.println( " private static int select(String lname){" );
250 pw.println( " Integer result=null;" );
251 pw.println( " result=(Integer)_tokenTable.get(lname);" );
252 pw.println( " if(lname!=null){" );
253 pw.println( " return result.intValue();" );
254 pw.println( " }" );
255 pw.println( " return -1;" );
256 pw.println( " }" );
257 pw.print( " public final void handleStartElement" );
258 pw.println( "(SAXElement element){" );
259 pw.println( " int token=select(element.getLname());" );
260 pw.println( " switch(token){" );
261 i = elements.iterator();
262
263 while ( i.hasNext() ) {
264 String x = ( String ) i.next();
265 x = javaName( x );
266 pw.println( " case TOKEN_" + x + ":{" );
267 pw.println( " " + x + "Start(element); " );
268 pw.println( " break;" );
269 pw.println( " }" );
270 }
271
272 pw.println( " default:{" );
273 pw.println( " unknownElementStart(element);" );
274 pw.println( " }" );
275 pw.println( " }" );
276 pw.println( " }" );
277 pw.print( " public final void handleEndElement(" );
278 pw.println( "SAXElement element){" );
279 pw.println( " int token=select(element.getLname());" );
280 pw.println( " switch(token){" );
281 i = elements.iterator();
282
283 while ( i.hasNext() ) {
284 String x = ( String ) i.next();
285 x = javaName( x );
286 pw.println( " case TOKEN_" + x + ":{" );
287 pw.println( " " + x + "End(element); " );
288 pw.println( " break;" );
289 pw.println( " }" );
290 }
291
292 pw.println( " default:{" );
293 pw.println( " unknownElementEnd(element);" );
294 pw.println( " }" );
295 pw.println( " }" );
296 pw.println( " }" );
297 pw.print( " protected void unknownElementStart" );
298 pw.println( "(SAXElement element){" );
299 pw.println( " }" );
300 pw.print( " protected void unknownElementEnd" );
301 pw.println( "(SAXElement element){" );
302 pw.println( " }" );
303 pw.println( "}" );
304 }
305 }
306