001: /*
002: * JavaParserGenerator.java
003: *
004: * This work is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published
006: * by the Free Software Foundation; either version 2 of the License,
007: * or (at your option) any later version.
008: *
009: * This work is distributed in the hope that it will be useful, but
010: * WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017: * USA
018: *
019: * As a special exception, the copyright holders of this library give
020: * you permission to link this library with independent modules to
021: * produce an executable, regardless of the license terms of these
022: * independent modules, and to copy and distribute the resulting
023: * executable under terms of your choice, provided that you also meet,
024: * for each linked independent module, the terms and conditions of the
025: * license of that module. An independent module is a module which is
026: * not derived from or based on this library. If you modify this
027: * library, you may extend this exception to your version of the
028: * library, but you are not obligated to do so. If you do not wish to
029: * do so, delete this exception statement from your version.
030: *
031: * Copyright (c) 2003 Per Cederberg. All rights reserved.
032: */
033:
034: package net.percederberg.grammatica.output;
035:
036: import java.io.IOException;
037:
038: import net.percederberg.grammatica.Grammar;
039: import net.percederberg.grammatica.code.CodeStyle;
040: import net.percederberg.grammatica.code.java.JavaFile;
041: import net.percederberg.grammatica.code.java.JavaPackage;
042: import net.percederberg.grammatica.parser.ProductionPattern;
043: import net.percederberg.grammatica.parser.TokenPattern;
044:
045: /**
046: * A Java parser generator. This class generates the source code files
047: * needed for a Java parser.
048: *
049: * @author Per Cederberg, <per at percederberg dot net>
050: * @version 1.0
051: */
052: public class JavaParserGenerator extends ParserGenerator {
053:
054: /**
055: * The fully qualified Java package name.
056: */
057: private String basePackage = null;
058:
059: /**
060: * The Java class name prefix.
061: */
062: private String baseName = null;
063:
064: /**
065: * The public class and interface access flag.
066: */
067: private boolean publicAccess = false;
068:
069: /**
070: * The Java class comment.
071: */
072: private String classComment = null;
073:
074: /**
075: * Creates a new Java parser generator.
076: *
077: * @param grammar the grammar to use
078: */
079: public JavaParserGenerator(Grammar grammar) {
080: super (grammar);
081: initialize();
082: }
083:
084: /**
085: * Initializes various instance variables.
086: */
087: private void initialize() {
088: StringBuffer buffer;
089: String str;
090:
091: // Set base name
092: str = getGrammar().getFileName();
093: if (str.indexOf('/') >= 0) {
094: str = str.substring(str.lastIndexOf('/') + 1);
095: }
096: if (str.indexOf('\\') >= 0) {
097: str = str.substring(str.lastIndexOf('\\') + 1);
098: }
099: if (str.indexOf('.') > 0) {
100: str = str.substring(0, str.indexOf('.'));
101: }
102: if (Character.isLowerCase(str.charAt(0))) {
103: str = Character.toUpperCase(str.charAt(0))
104: + str.substring(1);
105: }
106: baseName = str;
107:
108: // Create class comment
109: buffer = new StringBuffer();
110: str = getGrammar().getDeclaration(Grammar.AUTHOR_DECLARATION);
111: if (str != null) {
112: buffer.append("@author ");
113: buffer.append(str);
114: }
115: str = getGrammar().getDeclaration(Grammar.VERSION_DECLARATION);
116: if (str != null) {
117: if (buffer.length() > 0) {
118: buffer.append("\n");
119: }
120: buffer.append("@version ");
121: buffer.append(str);
122: }
123: classComment = buffer.toString();
124: }
125:
126: /**
127: * Returns the Java package where the classes will be created.
128: *
129: * @return the fully qualified Java package name
130: */
131: public String getBasePackage() {
132: return basePackage;
133: }
134:
135: /**
136: * Sets the Java package name where the classes will be created.
137: *
138: * @param pkg the fully qualified package name
139: */
140: public void setBasePackage(String pkg) {
141: this .basePackage = pkg;
142: }
143:
144: /**
145: * Returns the Java class name prefix.
146: *
147: * @return the Java class name prefix
148: */
149: public String getBaseName() {
150: return baseName;
151: }
152:
153: /**
154: * Sets the Java class name prefix.
155: *
156: * @param name the Java class name prefix
157: */
158: public void setBaseName(String name) {
159: this .baseName = name;
160: }
161:
162: /**
163: * Returns the public access flag.
164: *
165: * @return true if the classes should have public access, or
166: * false otherwise
167: */
168: public boolean getPublicAccess() {
169: return publicAccess;
170: }
171:
172: /**
173: * Sets the public access flag.
174: *
175: * @param flag the new public access flag value
176: */
177: public void setPublicAccess(boolean flag) {
178: publicAccess = flag;
179: }
180:
181: /**
182: * Returns the Java code style to use.
183: *
184: * @return the Java code style to use
185: */
186: public CodeStyle getCodeStyle() {
187: return CodeStyle.JAVA;
188: }
189:
190: /**
191: * Returns the Java class comment.
192: *
193: * @return the Java class comment
194: */
195: public String getClassComment() {
196: return classComment;
197: }
198:
199: /**
200: * Writes the Java source code files.
201: *
202: * @throws IOException if the files couldn't be written correctly
203: */
204: public void write() throws IOException {
205: Grammar grammar = getGrammar();
206: JavaConstantsFile constants = new JavaConstantsFile(this );
207: JavaTokenizerFile tokenizer = new JavaTokenizerFile(this );
208: JavaParserFile parser = new JavaParserFile(this , tokenizer);
209: JavaAnalyzerFile analyzer = new JavaAnalyzerFile(this );
210: TokenPattern token;
211: ProductionPattern production;
212: int i;
213:
214: // Create token declarations
215: for (i = 0; i < grammar.getTokenPatternCount(); i++) {
216: token = grammar.getTokenPattern(i);
217: constants.addToken(token);
218: tokenizer.addToken(token, constants);
219: analyzer.addToken(token, constants);
220: }
221:
222: // Create production constants
223: for (i = 0; i < grammar.getProductionPatternCount(); i++) {
224: production = grammar.getProductionPattern(i);
225: constants.addProduction(production);
226: parser.addProductionConstant(production);
227: analyzer.addProduction(production, constants);
228: }
229:
230: // Create production definitions
231: for (i = 0; i < grammar.getProductionPatternCount(); i++) {
232: production = grammar.getProductionPattern(i);
233: parser.addProduction(production, constants);
234: }
235:
236: // Write source code files
237: constants.writeCode();
238: tokenizer.writeCode();
239: parser.writeCode();
240: analyzer.writeCode();
241: }
242:
243: /**
244: * Creates a Java file in the correct base directory. The package
245: * will be set if applicable.
246: *
247: * @return a new Java file
248: */
249: public JavaFile createJavaFile() {
250: if (basePackage == null) {
251: return new JavaFile(getBaseDir());
252: } else {
253: return new JavaFile(getBaseDir(), new JavaPackage(
254: getBasePackage()));
255: }
256: }
257: }
|