KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fri > patterns > interpreter > parsergenerator > syntax > builder > SyntaxBuilder


1 package fri.patterns.interpreter.parsergenerator.syntax.builder;
2
3 import java.util.*;
4 import java.io.IOException JavaDoc;
5 import fri.patterns.interpreter.parsergenerator.*;
6 import fri.patterns.interpreter.parsergenerator.lexer.*;
7 import fri.patterns.interpreter.parsergenerator.syntax.*;
8 import fri.patterns.interpreter.parsergenerator.parsertables.LALRParserTables;
9 import fri.patterns.interpreter.parsergenerator.parsertables.ParserBuildException;
10
11 /**
12     Connects SyntaxSeparation and LexerBuilder.
13     SyntaxBuilder builds a <i>Syntax</i> object from a text input which can be
14     File, InputStream, Reader, String, StringBuffer. Mind that you DO NOT need
15     a SyntaxBuilder to create a Syntax from a String [][] or a List of rule Lists!
16     <p>
17     Following symbols can be used within the syntax specification text (spaces are ignored):
18     <pre>
19         a ::= b? ; // a derives to one or none b
20         a ::= b* ; // a derives to any number of b including zero
21         a ::= b+ ; // a derives to any number of b excluding zero
22         a ::= (b c)* d ; // grouping of b and c by parenthesis
23         a ::= b | c | ; // a derives to b or c or nothing
24         start ::= "BEGIN" ; // a fixed terminal string
25         letter ::= 'a' .. 'z' ; // character set a-z
26         newline ::= '\r' | '\n' | '\r' '\n' ; // newlines of all wellknown platforms
27         positive ::= digit - '0' ; // digit but not zero
28         id ::= `identifier` ; // using the pre-built lexer rules for <i>identifier</i> (lexer ruleref)
29         source ::= char - comment ; // source is all characters, but without comments
30     </pre>
31     This EBNF-like language is case-sensitive and differs from EBNF only at these symbols:
32     . { } &lt; &gt; [ ]. Archetype was the notation used by the w3c.
33     
34     @author (c) 2002, Fritz Ritzberger
35 */

36
37 public class SyntaxBuilder
38 {
39     private Syntax syntax;
40     private Syntax lexerSyntax, parserSyntax;
41     private Lexer lexer;
42     private List tokenSymbols, ignoredSymbols;
43     private List initialNonterminals;
44     
45     /**
46         Parse a syntax specification text and process it to a <i>Syntax</i> object.
47         The syntax, a Lexer, a parserSyntax and a token-symbol list will be retrieveable after construction.
48         @param syntaxInput text to parse and build a syntax from, File, InputStream, Reader, String, StringBuffer.
49             If InputStream is used, no Reader will be wrapped around (raw byte input).
50     */

51     public SyntaxBuilder(Object JavaDoc syntaxInput)
52         throws SyntaxException, LexerException, ParserBuildException, IOException JavaDoc
53     {
54         // build the hardcoded default BNF lexer
55

56         SyntaxSeparation.DEBUG = false; // avoid output of syntax control messages
57
SyntaxSeparation separation = new SyntaxSeparation(new Syntax(StandardLexerRules.lexerSyntax));
58         SyntaxSeparation.DEBUG = true;
59         
60         LexerBuilder builder = new LexerBuilder(separation.getLexerSyntax(), separation.getIgnoredSymbols());
61         Lexer lexer = builder.getLexer();
62         lexer.setInput(syntaxInput);
63         
64         // build the (hardcoded) BNF parser
65

66         //ParserTables parserTables = new LALRParserTables(new Syntax(SyntaxUtil.ruleArrayToList(SyntaxBuilderSemantic.syntax)));
67
// COMMENT OUT FOLLOWING LINE AND COMMENT IN PREVIOUS LINE TO BUILD NEW SyntaxBuilderParserTables AFTER HAVING CHANGED SYNTAX!
68
ParserTables parserTables = new SyntaxBuilderParserTables();
69         
70         // start the BNF parser with syntax input
71
Parser parser = new Parser(parserTables);
72         initialNonterminals = new ArrayList(64);
73         boolean ok = parser.parse(lexer, new SyntaxBuilderSemantic(initialNonterminals));
74         if (ok == false)
75             throw new SyntaxException("Failed building Syntax from "+syntaxInput);
76         
77         List result = (List) parser.getResult(); // must be a List, according to applied semantic
78
List rules = new ArrayList(); // can not predict size
79
ArtificialRule.resolveArtificialRules(result, rules);
80         this.syntax = new Syntax(rules);
81         //System.err.println("Built result syntax:\n"+this.syntax);
82
}
83
84     private void ensureSeparation()
85         throws SyntaxException
86     {
87         if (tokenSymbols == null) {
88             SyntaxSeparation separation = new SyntaxSeparation(syntax);
89             this.tokenSymbols = separation.getTokenSymbols();
90             this.ignoredSymbols = separation.getIgnoredSymbols();
91             this.parserSyntax = separation.getParserSyntax();
92             this.lexerSyntax = separation.getLexerSyntax();
93         }
94     }
95
96
97     /** Returns a Lexer for the built syntax. */
98     public Lexer getLexer()
99         throws LexerException, SyntaxException
100     {
101         if (lexer == null) {
102             ensureSeparation();
103             LexerBuilder builder = new LexerBuilder(lexerSyntax, ignoredSymbols);
104             this.lexer = builder.getLexer();
105         }
106         return this.lexer;
107     }
108
109     /** Returns only the ready-made parser syntax (to feed the parser tables). */
110     public Syntax getParserSyntax()
111         throws SyntaxException
112     {
113         ensureSeparation();
114         return this.parserSyntax;
115     }
116
117 // /** Returns the list of lexer token symbols for <i>setTerminals()</i> call if the Lexer is used standalone (without Parser). */
118
// public List getTokenSymbols()
119
// throws SyntaxException
120
// {
121
// ensureSeparation();
122
// return this.tokenSymbols;
123
// }
124

125     /** Returns the whole syntax (both parser and lexer syntax). */
126     public Syntax getSyntax() {
127         return syntax;
128     }
129
130     /**
131      * Returns the list of initial nonterminals (before parenthesis and quantifiers get resolved).
132      * This is for internal use in SourceGenerator.
133      */

134     public List getInitialNonterminals() {
135         return initialNonterminals;
136     }
137
138     /**
139         Resolves all singular rules (only one symbol on right side, only one occurence).
140         This must be called directly after construction to have an effect.
141     */

142     public Syntax resolveSingulars() {
143         getSyntax().resolveSingulars();
144         return getSyntax();
145     }
146
147
148
149     /** Creates SyntaxBuilderParserTables.java (in this directory) from the rules defined in SyntaxBuilderSemantic. */
150     public static void main(String JavaDoc [] args) {
151         try {
152             new LALRParserTables(new Syntax(SyntaxBuilderSemantic.syntax)).toSourceFile(
153                     "fri.patterns.interpreter.parsergenerator.syntax.builder.SyntaxBuilderParserTables");
154         }
155         catch (Exception JavaDoc e) {
156             e.printStackTrace();
157         }
158     }
159     
160 }
161
Popular Tags