001: package fri.patterns.interpreter.parsergenerator.builder;
002:
003: import java.io.File;
004: import fri.patterns.interpreter.parsergenerator.*;
005: import fri.patterns.interpreter.parsergenerator.syntax.Syntax;
006:
007: /**
008: This class is definitely the shortest way to construct a Parser (with Lexer) for a Syntax.
009: It uses all serialization utils in this package to quickly build a parsing environment.
010: This factory accepts a syntax where parser and lexer rules were mixed.
011: <p>
012: Example (syntax input from a file):
013: <pre>
014: File ebnfFile = new File("MySyntax.syntax");
015: Parser parser = new SerializedParser().get(ebnfFile);
016: </pre>
017: or (syntax input from a Reader, must pass a filename):
018: <pre>
019: Reader ebnfReader = new InputStreamReader(MySyntaxSemantic.class.getResourceAsStream("MySyntax.syntax"));
020: Parser parser = new SerializedParser().get(ebnfReader, "MySyntax");
021: </pre>
022:
023: @author (c) 2002, Fritz Ritzberger
024: */
025:
026: public class SerializedParser extends SerializedObject {
027: /** The suffix for serialized Parser files. */
028: public static final String PARSERFILE_SUFFIX = "Parser.ser";
029: protected boolean PRODUCTION; // setting this to false in constructor will prevent the parsing environment from being serialized
030:
031: /** Create a Parser factory that caches built Lexers. */
032: public SerializedParser() {
033: this (true);
034: }
035:
036: /** Create a Parser factory that caches built Lexers. @param production when false the Parser will not be serialized. */
037: public SerializedParser(boolean production) {
038: this .PRODUCTION = production;
039: }
040:
041: /**
042: Builds the Parser from scratch if not found its parts in filesystem, else loads all serialized parts.
043: @param syntaxInput the mixed lexer/parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
044: @return Parser, built from scratch or loaded from filesystem.
045: */
046: public Parser get(Object syntaxInput) throws Exception {
047: return get(null, syntaxInput);
048: }
049:
050: /**
051: Builds the Parser from scratch if not found its parts in filesystem, else loads all serialized parts.
052: @param syntaxInput the mixed lexer/parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
053: @param baseName basename for serialization, can be null
054: @return Parser, built from scratch or loaded from filesystem.
055: */
056: public Parser get(Object syntaxInput, String baseName)
057: throws Exception {
058: return get(null, syntaxInput, baseName);
059: }
060:
061: /**
062: Builds the Parser from scratch if not found its parts in filesystem, else loads all serialized parts.
063: @param parserType the class of ParserTables to create for the syntax (LALRParserTables.class is default).
064: @param syntaxInput the mixed lexer/parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
065: @return Parser, built from scratch or loaded from filesystem.
066: */
067: public Parser get(Class parserType, Object syntaxInput)
068: throws Exception {
069: return get(parserType, syntaxInput, null);
070: }
071:
072: /**
073: Builds the parsing environment from scratch if not found its parts in filesystem, else loads all serialized parts.
074: @param parserType the class of ParserTables to create for the syntax (LALRParserTables.class is default).
075: @param syntaxInput the mixed lexer/parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
076: @param baseName basename for serialization, can be null
077: @return Parser, built from scratch or loaded from filesystem.
078: */
079: public Parser get(Class parserType, Object syntaxInput,
080: String baseName) throws Exception {
081: fri.util.TimeStopper ts = new fri.util.TimeStopper();
082:
083: Parser parser = PRODUCTION ? (Parser) read(ensureFileName(
084: syntaxInput, baseName)) : null;
085: if (parser == null) {
086: SerializedLexer lexerFactory = newSerializedLexer();
087: lexerFactory.PRODUCTION = false; // do not store this lexer, it will be stored with parser
088: Lexer lexer = lexerFactory.buildAndStoreLexer(syntaxInput,
089: baseName, null, null); // null: forces syntax separation
090: Syntax parserSyntax = lexerFactory.getSyntaxSeparation()
091: .getParserSyntax();
092: SerializedTables tablesFactory = new SerializedTables(false); // do not store this tables, it will be stored with parser
093: ParserTables tables = tablesFactory
094: .buildAndStoreParserTables(parserType,
095: parserSyntax, syntaxInput, baseName);
096: parser = new Parser(tables);
097: parser.setLexer(lexer);
098:
099: if (PRODUCTION)
100: write(ensureFileName(syntaxInput, baseName), parser);
101: }
102:
103: System.err.println("Parser construction took "
104: + ts.getTimeMillis() + " millis");
105: return parser;
106: }
107:
108: /** To be overridden when a modified SerializedLexer is needed. */
109: protected SerializedLexer newSerializedLexer() throws Exception {
110: return new SerializedLexer(false);
111: }
112:
113: private String ensureFileName(Object syntaxInput, String baseName) {
114: if (baseName == null)
115: baseName = baseNameFromSyntax(syntaxInput);
116: return baseName + PARSERFILE_SUFFIX;
117: }
118:
119: /** Test main. Building serialized Java Parser takes 740, building from scratch takes 4000 millis. */
120: public static void main(String[] args) {
121: try {
122: File ebnfFile = new File(
123: "fri/patterns/interpreter/parsergenerator/syntax/builder/examples/SyntaxBuilder.syntax");
124: File fileToParse = new File(
125: "fri/patterns/interpreter/parsergenerator/syntax/builder/examples/SimpleSyntax.syntax");
126:
127: fri.util.TimeStopper ts = new fri.util.TimeStopper();
128: SerializedParser parserBuilder = new SerializedParser();
129: Parser parser = parserBuilder.get(null, ebnfFile,
130: "SyntaxBuilder");
131: Lexer lexer = parser.getLexer();
132: System.err.println("Parser was built in "
133: + ts.getTimeMillis() + " millis");
134: lexer.setDebug(true);
135:
136: lexer.setInput(fileToParse);
137: boolean ok = parser.parse(lexer);
138: System.err.println("Parsing result is " + ok);
139: } catch (Exception e) {
140: e.printStackTrace();
141: }
142: }
143:
144: }
|