1/*
2 * [The "BSD license"]
3 *  Copyright (c) 2010 Terence Parr
4 *  All rights reserved.
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions
8 *  are met:
9 *  1. Redistributions of source code must retain the above copyright
10 *      notice, this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright
12 *      notice, this list of conditions and the following disclaimer in the
13 *      documentation and/or other materials provided with the distribution.
14 *  3. The name of the author may not be used to endorse or promote products
15 *      derived from this software without specific prior written permission.
16 *
17 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.antlr.tool;
30
31import org.antlr.runtime.SerializedGrammar;
32
33import java.io.*;
34import java.util.Stack;
35
36/** Serialize a grammar into a highly compressed form with
37 *  only the info needed to recognize sentences.
38 *  FORMAT:
39 *
40 *  file ::= $ANTLR<version:byte><grammartype:byte><name:string>;<numRules:short><rules>
41 *  rule ::= R<rulename:string>;B<nalts:short><alts>.
42 *  alt  ::= A<elems>;
43 *  elem ::= t<tokentype:short> | r<ruleIndex:short> | -<char:uchar><char:uchar> | ~<tokentype> | w
44 */
45public class GrammarSerializerFoo {
46    protected DataOutputStream out;
47    protected String filename;
48    protected Grammar g;
49
50    protected Stack streams = new Stack();
51    protected ByteArrayOutputStream altBuf;
52    protected int numElementsInAlt = 0;
53
54    public GrammarSerializerFoo(Grammar g) {
55        this.g = g;
56    }
57
58    public void open(String filename) throws IOException {
59        this.filename = filename;
60        FileOutputStream fos = new FileOutputStream(filename);
61        BufferedOutputStream bos = new BufferedOutputStream(fos);
62        out = new DataOutputStream(bos);
63        writeString(out, SerializedGrammar.COOKIE);
64        out.writeByte(SerializedGrammar.FORMAT_VERSION);
65    }
66
67    public void close() throws IOException {
68        if ( out!=null ) out.close();
69        out = null;
70    }
71
72
73    // WRITE
74
75    public void grammar(int grammarTokenType, String name) {
76        try {
77            /*
78            switch ( grammarTokenType ) {
79                case ANTLRParser.LEXER_GRAMMAR : out.writeByte('l'); break;
80                case ANTLRParser.PARSER_GRAMMAR : out.writeByte('p'); break;
81                case ANTLRParser.TREE_GRAMMAR: out.writeByte('t'); break;
82                case ANTLRParser.COMBINED_GRAMMAR : out.writeByte('c'); break;
83            }
84            writeString(out, name);
85            */
86            out.writeShort(g.getRules().size());
87        }
88        catch (IOException ioe) {
89            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
90        }
91    }
92
93    public void rule(String name) {
94        try {
95            out.writeByte('R');
96            writeString(out, name);
97        }
98        catch (IOException ioe) {
99            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
100        }
101    }
102
103    public void endRule() {
104        try {
105            out.writeByte('.');
106        }
107        catch (IOException ioe) {
108            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
109        }
110    }
111
112    public void block(int nalts) {
113        try {
114            out.writeByte('B');
115            out.writeShort(nalts);
116        }
117        catch (IOException ioe) {
118            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
119        }
120    }
121
122    public void alt(GrammarAST alt) {
123        numElementsInAlt = 0;
124        try {
125            out.writeByte('A');
126        }
127        catch (IOException ioe) {
128            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
129        }
130        //streams.push(out);
131        //altBuf = new ByteArrayOutputStream();
132        //out = new DataOutputStream(altBuf);
133    }
134
135    public void endAlt() {
136        try {
137            //out.flush();
138            //out = (DataOutputStream)streams.pop(); // restore previous stream
139            out.writeByte(';');
140            //out.writeShort(numElementsInAlt);
141            //out.write(altBuf.toByteArray());
142        }
143        catch (IOException ioe) {
144            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
145        }
146    }
147
148    public void ruleRef(GrammarAST t) {
149        numElementsInAlt++;
150        try {
151            out.writeByte('r');
152            out.writeShort(g.getRuleIndex(t.getText()));
153        }
154        catch (IOException ioe) {
155            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
156        }
157    }
158
159    public void token(GrammarAST t) {
160        numElementsInAlt++;
161        try {
162            out.writeByte('t');
163            int ttype = g.getTokenType(t.getText());
164            out.writeShort(ttype);
165        }
166        catch (IOException ioe) {
167            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
168        }
169    }
170
171    public void charLiteral(GrammarAST t) {
172        numElementsInAlt++;
173        try {
174            if ( g.type!=Grammar.LEXER ) {
175                out.writeByte('t');
176                int ttype = g.getTokenType(t.getText());
177                out.writeShort(ttype);
178            }
179            // else lexer???
180        }
181        catch (IOException ioe) {
182            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
183        }
184    }
185
186    public void wildcard(GrammarAST t) {
187        numElementsInAlt++;
188        try {
189            out.writeByte('w');
190        }
191        catch (IOException ioe) {
192            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
193        }
194    }
195
196    public void range() { // must be char range
197        numElementsInAlt++;
198        try {
199            out.writeByte('-');
200        }
201        catch (IOException ioe) {
202            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
203        }
204    }
205
206    public void not() {
207        try {
208            out.writeByte('~');
209        }
210        catch (IOException ioe) {
211            ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, filename);
212        }
213    }
214
215    public void writeString(DataOutputStream out, String s) throws IOException {
216        out.writeBytes(s);
217        out.writeByte(';');
218    }
219}
220