001: /*
002: * ValidationElement.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.ant;
035:
036: import java.io.File;
037: import java.io.FileNotFoundException;
038: import java.io.FileReader;
039:
040: import org.apache.tools.ant.BuildException;
041:
042: import net.percederberg.grammatica.Grammar;
043: import net.percederberg.grammatica.GrammarException;
044: import net.percederberg.grammatica.TreePrinter;
045: import net.percederberg.grammatica.parser.Analyzer;
046: import net.percederberg.grammatica.parser.Node;
047: import net.percederberg.grammatica.parser.ParseException;
048: import net.percederberg.grammatica.parser.Parser;
049: import net.percederberg.grammatica.parser.ParserCreationException;
050: import net.percederberg.grammatica.parser.ParserLogException;
051: import net.percederberg.grammatica.parser.Token;
052: import net.percederberg.grammatica.parser.Tokenizer;
053:
054: /**
055: * A grammar validation element. This element validates or tests the
056: * grammar in various ways.
057: *
058: * @author Per Cederberg, <per at percederberg dot net>
059: * @version 1.4
060: * @since 1.4
061: */
062: public class ValidationElement implements ProcessingElement {
063:
064: /**
065: * The validation type.
066: */
067: private String type = null;
068:
069: /**
070: * The input test file.
071: */
072: private File file = null;
073:
074: /**
075: * The quiet output flag.
076: */
077: private boolean quiet = false;
078:
079: /**
080: * Creates a new validation element.
081: */
082: public ValidationElement() {
083: }
084:
085: /**
086: * Sets the validation type. The type must be one of "debug",
087: * "tokenize", "parse", or "profile".
088: *
089: * @param type the validation type
090: */
091: public void setType(String type) {
092: this .type = type;
093: }
094:
095: /**
096: * Sets the input test file. The test file is not needed for the
097: * debug validation type.
098: *
099: * @param file the input test file
100: */
101: public void setInputfile(File file) {
102: this .file = file;
103: }
104:
105: /**
106: * Sets the quiet output flag.
107: *
108: * @param quiet the quiet output flag
109: */
110: public void setQuiet(boolean quiet) {
111: this .quiet = quiet;
112: }
113:
114: /**
115: * Validates all attributes in the element.
116: *
117: * @throws BuildException if some attribute was missing or had an
118: * invalid value
119: */
120: public void validate() throws BuildException {
121: if (type == null) {
122: throw new BuildException(
123: "missing 'type' attribute in <validate>");
124: }
125: if (!type.equals("debug") && !type.equals("tokenize")
126: && !type.equals("parse") && !type.equals("profile")) {
127:
128: throw new BuildException(
129: "value of 'type' attribute in <validate> must be one "
130: + "of 'debug', 'tokenize', 'parse', or 'profile'");
131: }
132: if (file == null && !type.equals("debug")) {
133: throw new BuildException(
134: "missing 'inputfile' attribute in <validate>");
135: }
136: }
137:
138: /**
139: * Proceses the specified grammar.
140: *
141: * @param grammar the grammar to process
142: *
143: * @throws BuildException if the grammar couldn't be processed
144: * correctly
145: */
146: public void process(Grammar grammar) throws BuildException {
147: if (type.equals("debug")) {
148: debug(grammar);
149: } else if (type.equals("tokenize")) {
150: tokenize(grammar);
151: } else if (type.equals("parse")) {
152: parse(grammar);
153: } else if (type.equals("profile")) {
154: profile(grammar);
155: } else {
156: throw new BuildException("unknown <validation> type: "
157: + type);
158: }
159: }
160:
161: /**
162: * Debugs a grammar by printing the internal representation.
163: *
164: * @param grammar the grammar to use
165: *
166: * @throws BuildException if a parser couldn't be created
167: */
168: private void debug(Grammar grammar) throws BuildException {
169: Tokenizer tokenizer = null;
170: Parser parser = null;
171:
172: // Create tokenizer and parser
173: try {
174: tokenizer = grammar.createTokenizer(null);
175: parser = grammar.createParser(tokenizer);
176: } catch (GrammarException e) {
177: throw new BuildException("in grammar "
178: + grammar.getFileName() + ": " + e.getMessage());
179: }
180:
181: // Print tokenizer and parser
182: if (!quiet) {
183: System.out.println("Contents of " + grammar.getFileName()
184: + ":");
185: System.out.println();
186: System.out.println("Token Declarations:");
187: System.out.println("-------------------");
188: System.out.print(tokenizer);
189: System.out.println("Production Declarations:");
190: System.out.println("------------------------");
191: System.out.print(parser);
192: }
193: }
194:
195: /**
196: * Tokenizes the input file with the token patterns from the
197: * grammar.
198: *
199: * @param grammar the grammar to use
200: *
201: * @throws BuildException if the input file couldn't be tokenized
202: * correctly
203: */
204: private void tokenize(Grammar grammar) throws BuildException {
205: Tokenizer tokenizer;
206: Token token;
207:
208: try {
209: tokenizer = grammar.createTokenizer(new FileReader(file));
210: if (!quiet) {
211: System.out.println("Tokens from " + file + ":");
212: }
213: while ((token = tokenizer.next()) != null) {
214: if (!quiet) {
215: System.out.println(token);
216: }
217: }
218: } catch (FileNotFoundException e) {
219: throw new BuildException(e.getMessage());
220: } catch (GrammarException e) {
221: throw new BuildException("in grammar "
222: + grammar.getFileName() + ": " + e.getMessage());
223: } catch (ParseException e) {
224: throw new BuildException("in file " + file + ": "
225: + e.getMessage());
226: }
227: }
228:
229: /**
230: * Parses the input file with the grammar.
231: *
232: * @param grammar the grammar to use
233: *
234: * @throws BuildException if the input file couldn't be parsed
235: * correctly
236: */
237: private void parse(Grammar grammar) throws BuildException {
238: Tokenizer tokenizer;
239: Analyzer analyzer;
240: Parser parser;
241:
242: try {
243: tokenizer = grammar.createTokenizer(new FileReader(file));
244: if (quiet) {
245: analyzer = null;
246: } else {
247: analyzer = new TreePrinter(System.out);
248: }
249: parser = grammar.createParser(tokenizer, analyzer);
250: if (!quiet) {
251: System.out.println("Parse tree from " + file + ":");
252: }
253: parser.parse();
254: } catch (FileNotFoundException e) {
255: throw new BuildException(e.getMessage());
256: } catch (GrammarException e) {
257: throw new BuildException("in grammar "
258: + grammar.getFileName() + ": " + e.getMessage());
259: } catch (ParserCreationException e) {
260: throw new BuildException("in grammar "
261: + grammar.getFileName() + ": " + e.getMessage());
262: } catch (ParserLogException e) {
263: throw new BuildException("in file " + file + ": "
264: + e.getMessage());
265: }
266: }
267:
268: /**
269: * Parses the input file with the grammar and prints profiling
270: * information.
271: *
272: * @param grammar the grammar to use
273: *
274: * @throws BuildException if the input file couldn't be profiled
275: * correctly
276: */
277: private void profile(Grammar grammar) throws BuildException {
278: Tokenizer tokenizer;
279: Parser parser;
280: Node node;
281: long time;
282: int counter;
283:
284: // Profile tokenizer
285: try {
286: tokenizer = grammar.createTokenizer(new FileReader(file));
287: System.out.println("Tokenizing " + file);
288: time = System.currentTimeMillis();
289: counter = 0;
290: while (tokenizer.next() != null) {
291: counter++;
292: }
293: time = System.currentTimeMillis() - time;
294: System.out
295: .println(" Time elapsed: " + time + " millisec");
296: System.out.println(" Tokens found: " + counter);
297: System.out.println(" Average speed: " + (counter / time)
298: + " tokens/millisec");
299: } catch (FileNotFoundException e) {
300: throw new BuildException(e.getMessage());
301: } catch (GrammarException e) {
302: throw new BuildException("in grammar "
303: + grammar.getFileName() + ": " + e.getMessage());
304: } catch (ParseException e) {
305: throw new BuildException("in file " + file + ": "
306: + e.getMessage());
307: }
308:
309: // Profile parser
310: try {
311: tokenizer = grammar.createTokenizer(new FileReader(file));
312: parser = grammar.createParser(tokenizer);
313: System.out.println("Parsing " + file);
314: time = System.currentTimeMillis();
315: node = parser.parse();
316: time = System.currentTimeMillis() - time;
317: counter = 1 + node.getDescendantCount();
318: System.out
319: .println(" Time elapsed: " + time + " millisec");
320: System.out.println(" Nodes found: " + counter);
321: System.out.println(" Average speed: " + (counter / time)
322: + " nodes/millisec");
323: } catch (FileNotFoundException e) {
324: throw new BuildException(e.getMessage());
325: } catch (GrammarException e) {
326: throw new BuildException("in grammar "
327: + grammar.getFileName() + ": " + e.getMessage());
328: } catch (ParserCreationException e) {
329: throw new BuildException("in grammar "
330: + grammar.getFileName() + ": " + e.getMessage());
331: } catch (ParserLogException e) {
332: throw new BuildException("in file " + file + ": "
333: + e.getMessage());
334: }
335: }
336: }
|