1 /* 2 [The "BSD license"] 3 Copyright (c) 2005-2009 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 29 package org.antlr.runtime; 30 31 import java.io.IOException; 32 import java.io.FileInputStream; 33 import java.io.BufferedInputStream; 34 import java.io.DataInputStream; 35 import java.util.List; 36 import java.util.ArrayList; 37 38 public class SerializedGrammar { 39 public static final String COOKIE = "$ANTLR"; 40 public static final int FORMAT_VERSION = 1; 41 //public static org.antlr.tool.Grammar gr; // TESTING ONLY; remove later 42 43 public String name; 44 public char type; // in {l, p, t, c} 45 public List rules; 46 47 class Rule { 48 String name; 49 Block block; 50 public Rule(String name, Block block) { 51 this.name = name; 52 this.block = block; 53 } 54 public String toString() { 55 return name+":"+block; 56 } 57 } 58 59 class Block { 60 List[] alts; 61 public Block(List[] alts) { 62 this.alts = alts; 63 } 64 public String toString() { 65 StringBuffer buf = new StringBuffer(); 66 buf.append("("); 67 for (int i = 0; i < alts.length; i++) { 68 List alt = alts[i]; 69 if ( i>0 ) buf.append("|"); 70 buf.append(alt.toString()); 71 } 72 buf.append(")"); 73 return buf.toString(); 74 } 75 } 76 77 class TokenRef { 78 int ttype; 79 public TokenRef(int ttype) { this.ttype = ttype; } 80 public String toString() { return String.valueOf(ttype); } 81 } 82 83 class RuleRef { 84 int ruleIndex; 85 public RuleRef(int ruleIndex) { this.ruleIndex = ruleIndex; } 86 public String toString() { return String.valueOf(ruleIndex); } 87 } 88 89 public SerializedGrammar(String filename) throws IOException { 90 System.out.println("loading "+filename); 91 FileInputStream fis = new FileInputStream(filename); 92 BufferedInputStream bos = new BufferedInputStream(fis); 93 DataInputStream in = new DataInputStream(bos); 94 readFile(in); 95 in.close(); 96 } 97 98 protected void readFile(DataInputStream in) throws IOException { 99 String cookie = readString(in); // get $ANTLR 100 if ( !cookie.equals(COOKIE) ) throw new IOException("not a serialized grammar file"); 101 int version = in.readByte(); 102 char grammarType = (char)in.readByte(); 103 this.type = grammarType; 104 String grammarName = readString(in); 105 this.name = grammarName; 106 System.out.println(grammarType+" grammar "+grammarName); 107 int numRules = in.readShort(); 108 System.out.println("num rules = "+numRules); 109 rules = readRules(in, numRules); 110 } 111 112 protected List readRules(DataInputStream in, int numRules) throws IOException { 113 List rules = new ArrayList(); 114 for (int i=0; i<numRules; i++) { 115 Rule r = readRule(in); 116 rules.add(r); 117 } 118 return rules; 119 } 120 121 protected Rule readRule(DataInputStream in) throws IOException { 122 byte R = in.readByte(); 123 if ( R!='R' ) throw new IOException("missing R on start of rule"); 124 String name = readString(in); 125 System.out.println("rule: "+name); 126 byte B = in.readByte(); 127 Block b = readBlock(in); 128 byte period = in.readByte(); 129 if ( period!='.' ) throw new IOException("missing . on end of rule"); 130 return new Rule(name, b); 131 } 132 133 protected Block readBlock(DataInputStream in) throws IOException { 134 int nalts = in.readShort(); 135 List[] alts = new List[nalts]; 136 //System.out.println("enter block n="+nalts); 137 for (int i=0; i<nalts; i++) { 138 List alt = readAlt(in); 139 alts[i] = alt; 140 } 141 //System.out.println("exit block"); 142 return new Block(alts); 143 } 144 145 protected List readAlt(DataInputStream in) throws IOException { 146 List alt = new ArrayList(); 147 byte A = in.readByte(); 148 if ( A!='A' ) throw new IOException("missing A on start of alt"); 149 byte cmd = in.readByte(); 150 while ( cmd!=';' ) { 151 switch (cmd) { 152 case 't' : 153 int ttype = in.readShort(); 154 alt.add(new TokenRef(ttype)); 155 //System.out.println("read token "+gr.getTokenDisplayName(ttype)); 156 break; 157 case 'r' : 158 int ruleIndex = in.readShort(); 159 alt.add(new RuleRef(ruleIndex)); 160 //System.out.println("read rule "+gr.getRuleName(ruleIndex)); 161 break; 162 case '.' : // wildcard 163 break; 164 case '-' : // range 165 int from = in.readChar(); 166 int to = in.readChar(); 167 break; 168 case '~' : // not 169 int notThisTokenType = in.readShort(); 170 break; 171 case 'B' : // nested block 172 Block b = readBlock(in); 173 alt.add(b); 174 break; 175 } 176 cmd = in.readByte(); 177 } 178 //System.out.println("exit alt"); 179 return alt; 180 } 181 182 protected String readString(DataInputStream in) throws IOException { 183 byte c = in.readByte(); 184 StringBuffer buf = new StringBuffer(); 185 while ( c!=';' ) { 186 buf.append((char)c); 187 c = in.readByte(); 188 } 189 return buf.toString(); 190 } 191 192 public String toString() { 193 StringBuffer buf = new StringBuffer(); 194 buf.append(type+" grammar "+name); 195 buf.append(rules); 196 return buf.toString(); 197 } 198 } 199