KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > percederberg > grammatica > output > VisualBasicParserFile


1 /*
2  * VisualBasicParserFile.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) 2004 Adrian Moore. All rights reserved.
20  * Copyright (c) 2004-2005 Per Cederberg. All rights reserved.
21  */

22
23 package net.percederberg.grammatica.output;
24
25 import java.io.IOException JavaDoc;
26 import java.util.HashMap JavaDoc;
27
28 import net.percederberg.grammatica.code.visualbasic.VisualBasicClass;
29 import net.percederberg.grammatica.code.visualbasic.VisualBasicComment;
30 import net.percederberg.grammatica.code.visualbasic.VisualBasicConstructor;
31 import net.percederberg.grammatica.code.visualbasic.VisualBasicEnumeration;
32 import net.percederberg.grammatica.code.visualbasic.VisualBasicFile;
33 import net.percederberg.grammatica.code.visualbasic.VisualBasicImports;
34 import net.percederberg.grammatica.code.visualbasic.VisualBasicMethod;
35 import net.percederberg.grammatica.code.visualbasic.VisualBasicNamespace;
36 import net.percederberg.grammatica.parser.ProductionPattern;
37 import net.percederberg.grammatica.parser.ProductionPatternAlternative;
38 import net.percederberg.grammatica.parser.ProductionPatternElement;
39
40 /**
41  * The Visual Basic parser file generator. This class encapsulates all
42  * the Visual Basic (.NET) code necessary for creating a parser.
43  *
44  * @author Adrian Moore, <adrianrob at hotmail dot com>
45  * @author Per Cederberg, <per at percederberg dot net>
46  * @version 1.5
47  * @since 1.5
48  */

49 class VisualBasicParserFile {
50
51     /**
52      * The type comment.
53      */

54     private static final String JavaDoc TYPE_COMMENT =
55         "<remarks>A token stream parser.</remarks>";
56
57     /**
58      * The production enumeration comment.
59      */

60     private static final String JavaDoc ENUM_COMMENT =
61         "<summary>An enumeration with the generated production node\n" +
62         "identity constants.</summary>";
63
64     /**
65      * The first constructor comment.
66      */

67     private static final String JavaDoc CONSTRUCTOR1_COMMENT =
68         "<summary>Creates a new parser.</summary>\n\n" +
69         "<param name='input'>the input stream to read from</param>\n\n" +
70         "<exception cref='ParserCreationException'>if the parser\n" +
71         "couldn't be initialized correctly</exception>";
72
73     /**
74      * The second constructor comment.
75      */

76     private static final String JavaDoc CONSTRUCTOR2_COMMENT =
77         "<summary>Creates a new parser.</summary>\n\n" +
78         "<param name='input'>the input stream to read from</param>\n\n" +
79         "<param name='analyzer'>the analyzer to parse with</param>\n\n" +
80         "<exception cref='ParserCreationException'>if the parser\n" +
81         "couldn't be initialized correctly</exception>";
82
83     /**
84      * The init method comment.
85      */

86     private static final String JavaDoc INIT_METHOD_COMMENT =
87         "<summary>Initializes the parser by creating all the production\n" +
88         "patterns.</summary>\n\n" +
89         "<exception cref='ParserCreationException'>if the parser\n" +
90         "couldn't be initialized correctly</exception>";
91
92     /**
93      * The parser generator.
94      */

95     private VisualBasicParserGenerator gen;
96
97     /**
98      * The tokenizer file generator.
99      */

100     private VisualBasicTokenizerFile tokenizer;
101
102     /**
103      * The file to write.
104      */

105     private VisualBasicFile file;
106
107     /**
108      * The class to write.
109      */

110     private VisualBasicClass cls;
111
112     /**
113      * The syntetic contants enumeration.
114      */

115     private VisualBasicEnumeration enm;
116
117     /**
118      * The class initializer method.
119      */

120     private VisualBasicMethod initMethod;
121
122     /**
123      * A map with the production constants in this class. This map
124      * is indexed with the pattern id and contains the production
125      * constant name.
126      */

127     private HashMap JavaDoc constantNames = new HashMap JavaDoc();
128
129     /**
130      * The first available constant id number.
131      */

132     private int constantId = 1;
133
134     /**
135      * Creates a new parser file.
136      *
137      * @param gen the parser generator to use
138      * @param tokenizer the tokenizer file generator
139      */

140     public VisualBasicParserFile(VisualBasicParserGenerator gen,
141                                  VisualBasicTokenizerFile tokenizer) {
142
143         String JavaDoc name = gen.getBaseName() + "Parser";
144         int modifiers;
145
146         this.gen = gen;
147         this.tokenizer = tokenizer;
148         this.file = new VisualBasicFile(gen.getBaseDir(), name);
149         if (gen.getPublicAccess()) {
150             modifiers = VisualBasicClass.PUBLIC;
151         } else {
152             modifiers = VisualBasicClass.FRIEND;
153         }
154         this.cls = new VisualBasicClass(modifiers,
155                                         name,
156                                         "RecursiveDescentParser");
157         this.enm = new VisualBasicEnumeration(VisualBasicEnumeration.PRIVATE,
158                                               "SynteticPatterns");
159         this.initMethod = new VisualBasicMethod(VisualBasicMethod.PRIVATE,
160                                                 "CreatePatterns",
161                                                 "",
162                                                 "");
163         initializeCode();
164     }
165
166     /**
167      * Initializes the source code objects.
168      */

169     private void initializeCode() {
170         VisualBasicConstructor constr;
171         VisualBasicNamespace n;
172         String JavaDoc str;
173
174         // Add using
175
file.addImports(new VisualBasicImports("System.IO"));
176         file.addImports(new VisualBasicImports("PerCederberg.Grammatica.Runtime"));
177
178         // Add namespace
179
if (gen.getNamespace() == null) {
180             file.addClass(cls);
181         } else {
182             n = new VisualBasicNamespace(gen.getNamespace());
183             n.addClass(cls);
184             file.addNamespace(n);
185         }
186
187         // Add file comment
188
str = file.toString() + "\n\n" + gen.getFileComment();
189         file.addComment(new VisualBasicComment(VisualBasicComment.SINGLELINE,
190                                                str));
191
192         // Add type comment
193
cls.addComment(new VisualBasicComment(TYPE_COMMENT));
194
195         // Add enumeration
196
cls.addEnumeration(enm);
197         enm.addComment(new VisualBasicComment(ENUM_COMMENT));
198
199         // Add constructor
200
constr = new VisualBasicConstructor("ByVal input As TextReader");
201         cls.addConstructor(constr);
202         constr.addComment(new VisualBasicComment(CONSTRUCTOR1_COMMENT));
203         constr.addCode("MyBase.New(" + tokenizer.getConstructorCall("input") +
204                        ")");
205         constr.addCode("CreatePatterns()");
206
207         // Add constructor
208
constr = new VisualBasicConstructor("ByVal input As TextReader, " +
209                                             "ByVal analyzer As Analyzer");
210         cls.addConstructor(constr);
211         constr.addComment(new VisualBasicComment(CONSTRUCTOR2_COMMENT));
212         constr.addCode("MyBase.New(" + tokenizer.getConstructorCall("input") +
213                        ", analyzer)");
214         constr.addCode("CreatePatterns()");
215
216         // Add init method
217
cls.addMethod(initMethod);
218         initMethod.addComment(new VisualBasicComment(INIT_METHOD_COMMENT));
219         initMethod.addCode("Dim pattern As ProductionPattern");
220         initMethod.addCode("Dim alt As ProductionPatternAlternative");
221     }
222
223     /**
224      * Adds a production constant definition to this file.
225      *
226      * @param pattern the production pattern
227      */

228     public void addProductionConstant(ProductionPattern pattern) {
229         String JavaDoc constant;
230
231         if (pattern.isSynthetic()) {
232             constant = "SUBPRODUCTION_" + constantId;
233             enm.addConstant(constant, String.valueOf(constantId + 3000));
234             constantNames.put(new Integer JavaDoc(pattern.getId()), constant);
235             constantId++;
236         }
237     }
238
239     /**
240      * Adds a production pattern definition to this file.
241      *
242      * @param pattern the production pattern
243      * @param constants the constants file generator
244      */

245     public void addProduction(ProductionPattern pattern,
246                               VisualBasicConstantsFile constants) {
247         StringBuffer JavaDoc code;
248         String JavaDoc str;
249
250         // Create new pattern
251
code = new StringBuffer JavaDoc();
252         code.append("pattern = New ProductionPattern(CInt(");
253         code.append(getConstant(constants, pattern.getId()));
254         code.append("), \"");
255         if (pattern.isSynthetic()) {
256             str = (String JavaDoc) constantNames.get(new Integer JavaDoc(pattern.getId()));
257             code.append(gen.getCodeStyle().getMixedCase(str, true));
258         } else {
259             code.append(pattern.getName());
260         }
261         code.append("\")");
262         initMethod.addCode("");
263         initMethod.addCode(code.toString());
264
265         // Set syntetic flag
266
if (pattern.isSynthetic()) {
267             initMethod.addCode("pattern.Synthetic = True");
268         }
269
270         // Create pattern rules
271
for (int i = 0; i < pattern.getAlternativeCount(); i++) {
272             addProductionAlternative(pattern.getAlternative(i),
273                                      constants);
274         }
275
276         // Add pattern to parser
277
initMethod.addCode("AddPattern(pattern)");
278     }
279
280     /**
281      * Adds a production pattern alternative definition to the init
282      * method.
283      *
284      * @param alt the production pattern alternative
285      * @param constants the constants file generator
286      */

287     private void addProductionAlternative(ProductionPatternAlternative alt,
288                                           VisualBasicConstantsFile constants) {
289
290         ProductionPatternElement elem;
291         StringBuffer JavaDoc code;
292
293         initMethod.addCode("alt = New ProductionPatternAlternative()");
294         for (int i = 0; i < alt.getElementCount(); i++) {
295             elem = alt.getElement(i);
296             code = new StringBuffer JavaDoc();
297             code.append("alt.");
298             if (elem.isToken()) {
299                 code.append("AddToken(");
300             } else {
301                 code.append("AddProduction(");
302             }
303             code.append("CInt(");
304             code.append(getConstant(constants, elem.getId()));
305             code.append("), ");
306             code.append(elem.getMinCount());
307             code.append(", ");
308             if (elem.getMaxCount() == Integer.MAX_VALUE) {
309                 code.append("-1");
310             } else {
311                 code.append(elem.getMaxCount());
312             }
313             code.append(")");
314             initMethod.addCode(code.toString());
315         }
316         initMethod.addCode("pattern.AddAlternative(alt)");
317     }
318
319     /**
320      * Returns the constant name for a specified pattern or token id.
321      *
322      * @param constants the constants file
323      * @param id the pattern id
324      *
325      * @return the constant name to use
326      */

327     private String JavaDoc getConstant(VisualBasicConstantsFile constants, int id) {
328         Integer JavaDoc value = new Integer JavaDoc(id);
329
330         if (constantNames.containsKey(value)) {
331             return "SynteticPatterns." + constantNames.get(value);
332         } else {
333             return constants.getConstant(id);
334         }
335     }
336
337     /**
338      * Writes the file source code.
339      *
340      * @throws IOException if the output file couldn't be created
341      * correctly
342      */

343     public void writeCode() throws IOException JavaDoc {
344         file.writeCode(gen.getCodeStyle());
345     }
346 }
347
Popular Tags