1 /* 2 * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.*; 25 import java.util.*; 26 27 /* 28 assignment : key = value; 29 key : string 30 value : string | array | dict 31 nValue : , value 32 array : ( value nValue ) 33 nAssignment: , assignment|value 34 dict : { assignment* } 35 string : "*" or anything but a ,(){}= 36 37 special characters: ,(){}= 38 */ 39 40 public class PParser { 41 protected static final int OPEN_PAIR = 1; 42 protected static final int CLOSE_PAIR = 2; 43 protected static final int OPEN_ARRAY = 3; 44 protected static final int CLOSE_ARRAY = 4; 45 protected static final int MORE = 5; 46 protected static final int EQUAL = 6; 47 protected static final int STRING = 7; 48 protected static final int WS = 8; 49 50 protected Reader reader; 51 protected boolean bufferedToken; 52 protected StringBuffer stringBuffer = new StringBuffer(); 53 protected int lastChar; 54 protected int lastToken; 55 protected int lineNumber; 56 protected int column; 57 58 public PParser() { 59 } 60 61 public Hashtable parse(Reader r) throws IOException { 62 this.reader = r; 63 bufferedToken = false; 64 lineNumber = 0; 65 column = 0; 66 if (getToken() != OPEN_PAIR) { 67 error("No initial open"); 68 } 69 return parsePair(); 70 } 71 72 protected Object parseValue(int lookAhead) throws IOException { 73 int token; 74 75 if (lookAhead == -1) { 76 token = getToken(); 77 } 78 else { 79 token = lookAhead; 80 } 81 switch (token) { 82 case STRING: 83 return stringBuffer.toString(); 84 case OPEN_ARRAY: 85 return parseArray(); 86 case OPEN_PAIR: 87 return parsePair(); 88 default: 89 error("Expecting value"); 90 } 91 return null; 92 } 93 94 protected Object parseArray() throws IOException { 95 Vector array = new Vector(); 96 int token; 97 98 while ((token = getToken()) != CLOSE_ARRAY) { 99 if (token == MORE) { 100 token = getToken(); 101 } 102 if (token != CLOSE_ARRAY) { 103 array.addElement(parseValue(token)); 104 } 105 } 106 return array; 107 } 108 109 protected Hashtable parsePair() throws IOException { 110 Hashtable ht = new Hashtable(11); 111 int token; 112 113 while ((token = getToken()) != CLOSE_PAIR) { 114 if (token != STRING) { 115 error("Pair expecting string got"); 116 } 117 String key = stringBuffer.toString(); 118 119 if (getToken() != EQUAL) { 120 error("Expecting = "); 121 } 122 123 Object value = parseValue(-1); 124 125 ht.put(key, value); 126 } 127 return ht; 128 } 129 130 protected void ungetToken() { 131 if (bufferedToken) { 132 error("Can not buffer more than one token"); 133 } 134 bufferedToken = true; 135 } 136 137 protected int getToken() throws IOException { 138 int token = getToken(false, false); 139 140 return token; 141 } 142 143 protected int getToken(boolean wantsWS, boolean inString) 144 throws IOException { 145 if (bufferedToken) { 146 bufferedToken = false; 147 if (lastToken != WS || wantsWS) { 148 return lastToken; 149 } 150 } 151 while ((lastChar = reader.read()) != -1) { 152 // If a line starts with '#', skip the line. 153 if (column == 0 && lastChar == '#') { 154 while ((lastChar = reader.read()) != -1 155 && lastChar != '\n') { 156 } 157 if (lastChar == -1) { 158 break; 159 } 160 } 161 162 column++; 163 switch(lastChar) { 164 case '\n': 165 lineNumber++; 166 column = 0; 167 case ' ': 168 case '\r': 169 case '\t': 170 if (wantsWS) { 171 lastToken = WS; 172 return WS; 173 } 174 break; 175 case ',': 176 lastToken = MORE; 177 return MORE; 178 case '(': 179 lastToken = OPEN_ARRAY; 180 return OPEN_ARRAY; 181 case ')': 182 lastToken = CLOSE_ARRAY; 183 return CLOSE_ARRAY; 184 case '{': 185 lastToken = OPEN_PAIR; 186 return OPEN_PAIR; 187 case '}': 188 lastToken = CLOSE_PAIR; 189 return CLOSE_PAIR; 190 case '=': 191 lastToken = EQUAL; 192 return EQUAL; 193 case '"': 194 lastToken = STRING; 195 if (!inString) { 196 stringBuffer.setLength(0); 197 while (true) { 198 getToken(true, true); 199 if (lastChar == '"') { 200 lastToken = STRING; 201 return STRING; 202 } 203 stringBuffer.append((char)lastChar); 204 } 205 } 206 return STRING; 207 default: 208 lastToken = STRING; 209 if (!inString) { 210 stringBuffer.setLength(0); 211 stringBuffer.append((char)lastChar); 212 while (getToken(true, true) == STRING) { 213 if (lastChar == '"') { 214 error("Unexpected quote"); 215 } 216 stringBuffer.append((char)lastChar); 217 } 218 ungetToken(); 219 } 220 return STRING; 221 } 222 } 223 return -1; 224 } 225 226 protected void error(String errorString) { 227 throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column); 228 } 229 230 public static void dump(Object o) { 231 if (o instanceof String) { 232 System.out.print(o); 233 } 234 else if(o instanceof Vector) { 235 Enumeration e = ((Vector)o).elements(); 236 237 dump(" ("); 238 while (e.hasMoreElements()) { 239 dump(e.nextElement()); 240 dump(" -- "); 241 } 242 dump(" )"); 243 } 244 else { 245 Hashtable ht = (Hashtable)o; 246 Enumeration e = ht.keys(); 247 248 dump(" {"); 249 while (e.hasMoreElements()) { 250 Object key = e.nextElement(); 251 252 dump(key); 253 dump(" = "); 254 dump(ht.get(key)); 255 dump(";"); 256 } 257 dump(" }"); 258 } 259 } 260 261 public static void main(String[] args) { 262 if (args.length == 0) { 263 System.out.println("need filename"); 264 } 265 else { 266 try { 267 FileReader fr = new FileReader(args[0]); 268 PParser parser = new PParser(); 269 Hashtable ht = parser.parse(fr); 270 271 dump(ht); 272 System.out.println(); 273 } 274 catch (IOException ioe) { 275 System.out.println("Couldn't parse: " + ioe); 276 } 277 } 278 } 279 }