KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fri > patterns > interpreter > parsergenerator > builder > SerializedLexer


1 package fri.patterns.interpreter.parsergenerator.builder;
2
3 import java.util.List JavaDoc;
4 import fri.util.TimeStopper;
5 import fri.patterns.interpreter.parsergenerator.Lexer;
6 import fri.patterns.interpreter.parsergenerator.syntax.*;
7 import fri.patterns.interpreter.parsergenerator.syntax.builder.SyntaxSeparation;
8 import fri.patterns.interpreter.parsergenerator.lexer.*;
9
10 /**
11     Buffering Lexers. SerializedLexer will build the Lexer from scratch
12     only the first time. Every following call will load the serialized Lexer
13     from filesystem.
14     <p>
15     The time to build a lexer from scratch is equal to deserializing it
16     in most cases. So a standalone lexer can be built without this class.
17     When needed for a Parser, use the SerializedParser factory!
18     <p>
19     This factory will separate the passed syntax into parser and lexer syntax if
20     token and ignored symbol Lists are null. So take care to use "token" and "ignored"
21     rules within syntax to achieve the desired result!
22     <p>
23     Example (syntax input from a file):
24     <pre>
25     File ebnfFile = ...;
26     Lexer lexer = new SerializedLexer().get(ebnfFile);
27     </pre>
28     or (syntax input from a Reader, must pass a filename):
29     <pre>
30     Reader ebnfReader = ...;
31     Lexer lexer = new SerializedLexer().get(ebnfReader, "MyLexer.ser");
32     </pre>
33     
34     @author (c) 2002, Fritz Ritzberger
35 */

36
37 public class SerializedLexer extends SerializedObject
38 {
39     private SyntaxSeparation separation;
40     protected boolean PRODUCTION; // setting this to false in constructor will prevent the Lexer from being serialized
41

42     /** Create a Lexer factory that caches built Lexers. */
43     public SerializedLexer() {
44         this(true);
45     }
46     
47     /** Create a Lexer factory that caches built Lexers. @param production when false the Lexer will not be serialized. */
48     public SerializedLexer(boolean production) {
49         this.PRODUCTION = production;
50     }
51
52     /**
53         Builds the Lexer from scratch if not found in filesystem, else loads the serialized Lexer.
54         @param syntaxInput the Lexer syntax as File, InputStream, List of Lists, String [][] or Syntax.
55         @return deserialized Lexer, or one built from scratch that gets written to filesystem.
56     */

57     public Lexer get(Object JavaDoc syntaxInput)
58         throws Exception JavaDoc
59     {
60         return get(syntaxInput, null);
61     }
62
63     /**
64         Builds the Lexer from scratch if not found in filesystem, else loads the serialized Lexer.
65         @param syntaxInput the Lexer syntax as File, InputStream, List of Lists, String [][] or Syntax.
66         @param baseName name of serialization file, can be null when syntaxInput is a File
67         @return deserialized Lexer, or one built from scratch that gets written to filesystem.
68     */

69     public Lexer get(Object JavaDoc syntaxInput, String JavaDoc baseName)
70         throws Exception JavaDoc
71     {
72         return get(syntaxInput, baseName, null, null);
73     }
74     
75     /**
76         Builds the Lexer from scratch if not found in filesystem, else loads the serialized Lexer.
77         @param syntaxInput the Lexer syntax as File, InputStream, List of Lists, String [][] or Syntax.
78         @param baseName name of serialization file, can be null when syntaxInput is a File
79         @param tokenSymbols the token symbols when used by a prebuilt Parser
80         @param ignoredSymbols the ignored symbols when used by a prebuilt Parser
81         @return deserialized Lexer, or one built from scratch that gets written to filesystem.
82     */

83     public Lexer get(Object JavaDoc syntaxInput, String JavaDoc baseName, List JavaDoc tokenSymbols, List JavaDoc ignoredSymbols)
84         throws Exception JavaDoc
85     {
86         Lexer lexer = readLexer(syntaxInput, baseName);
87         if (lexer == null)
88             lexer = buildAndStoreLexer(syntaxInput, baseName, tokenSymbols, ignoredSymbols);
89         return lexer;
90     }
91
92     private String JavaDoc ensureFileName(Object JavaDoc syntaxInput, String JavaDoc baseName) {
93         if (baseName == null)
94             baseName = baseNameFromSyntax(syntaxInput);
95         return baseName+"Lexer.ser";
96     }
97
98     /**
99      * Tries to read the lexer from a serialized file. One of the two arguments must be non-null.
100      * @param syntaxInput the lexer syntax input to retrieve a default name when it is a File
101      * @param baseName if baseName is "Xml", the file "XmlLexer.ser" will be read, can be null
102      */

103     public Lexer readLexer(Object JavaDoc syntaxInput, String JavaDoc baseName) {
104         if (PRODUCTION)
105             return (Lexer) read(ensureFileName(syntaxInput, baseName));
106         return null;
107     }
108
109     /**
110      * Builds a lexer from passed syntax and stores it to a File (when PRODUCTION is true, this is default).
111      * @param syntaxInput the lexer syntax input
112      * @param baseName a file basename, if "Xml", the file "XmlLexer.ser" will be written
113      */

114     public Lexer buildAndStoreLexer(Object JavaDoc syntaxInput, String JavaDoc baseName, List JavaDoc tokenSymbols, List JavaDoc ignoredSymbols)
115         throws Exception JavaDoc
116     {
117         Syntax syntax = toSyntax(syntaxInput);
118         
119         if (tokenSymbols == null || ignoredSymbols == null) {
120             this.separation = newSyntaxSeparation(syntax);
121             syntax = separation.getLexerSyntax();
122             
123             if (tokenSymbols == null)
124                 tokenSymbols = separation.getTokenSymbols();
125             if (ignoredSymbols == null)
126                 ignoredSymbols = separation.getIgnoredSymbols();
127         }
128         // else: assume that syntaxInput is a prebuilt lexer Syntax and a list of ignored tokens
129

130         TimeStopper ts = new TimeStopper();
131         LexerBuilder builder = newLexerBuilder(syntax, ignoredSymbols);
132         Lexer lexer = builder.getLexer();
133         lexer.setTerminals(tokenSymbols);
134         System.err.println("Lexer scratch construction took "+ts.getTimeMillis()+" millis");
135         
136         if (PRODUCTION)
137             write(ensureFileName(syntaxInput, baseName), lexer);
138
139         return lexer;
140     }
141     
142     /** To be overridden when a modified SyntaxSeparation is needed. */
143     protected SyntaxSeparation newSyntaxSeparation(Syntax syntax)
144         throws SyntaxException
145     {
146         return new SyntaxSeparation(syntax);
147     }
148     
149     /** To be overridden when a modified LexerBuilder is needed. */
150     protected LexerBuilder newLexerBuilder(Syntax syntax, List JavaDoc ignoredSymbols)
151         throws LexerException, SyntaxException
152     {
153         return new LexerBuilder(syntax, ignoredSymbols);
154     }
155     
156     /**
157         If the lexer was built from scratch, the SyntaxSeparation object returned
158         will not be null and can be used to retrieve the parser syntax, else
159         null is returned, as the separation is not available in serialized Lexer.
160     */

161     public SyntaxSeparation getSyntaxSeparation() {
162         return separation;
163     }
164
165
166
167     /** Test main. Building serialized Lexer takes 330, building from scratch takes 130 millis. */
168     public static void main(String JavaDoc [] args) {
169         try {
170             TimeStopper ts = new TimeStopper();
171             Lexer lexer = new SerializedLexer().get(StandardLexerRules.lexerSyntax, "SyntaxBuilder");
172             System.err.println("Lexer was built in "+ts.getTimeMillis()+" millis");
173         }
174         catch (Exception JavaDoc e) {
175             e.printStackTrace();
176         }
177     }
178
179 }
180
Popular Tags