1 /* 2 * Copyright (c) 2008, 2013, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.oracle.javafx.jmx.json.impl; 27 28 import com.oracle.javafx.jmx.json.JSONException; 29 import java.io.IOException; 30 import java.util.HashMap; 31 import java.util.Stack; 32 33 34 /** 35 * JSON syntax. Collection of symbols linked with grammar processor. Grammar 36 * tree trversal generate events fed into JSONParserHandler instance. 37 */ 38 enum JSONSymbol { 39 40 X, O, O1, O3, OV, A, A1, A2, V, VA, 41 CURLYOPEN, CURLYCLOSE, COLON, COMMA, SQUAREOPEN, SQUARECLOSE, KEYWORD, STRING, NUMBER, EOS, 42 X_, O_, O1_, O3_, OV_, A_, A1_, A2_, V_, VA_; 43 44 static final boolean DEBUG = false; 45 46 static { 47 final JSONSymbol[] epsilon = new JSONSymbol[0]; 48 X.transition(CURLYOPEN, new JSONSymbol[]{O}); 49 X.transition(SQUAREOPEN, new JSONSymbol[]{A}); 50 O.transition(CURLYOPEN, new JSONSymbol[]{CURLYOPEN, O1, CURLYCLOSE}); 51 O1.transition(CURLYCLOSE, epsilon); 52 O1.transition(STRING, new JSONSymbol[]{OV, O3}); 53 O3.transition(CURLYCLOSE, epsilon); 54 O3.transition(COMMA, new JSONSymbol[]{COMMA, OV, O3}); 55 OV.transition(STRING, new JSONSymbol[]{STRING, COLON, V}); 56 A.transition(SQUAREOPEN, new JSONSymbol[]{SQUAREOPEN, A1, SQUARECLOSE}); 57 A1.transition(CURLYOPEN, new JSONSymbol[]{VA, A2}); 58 A1.transition(SQUAREOPEN, new JSONSymbol[]{VA, A2}); 59 A1.transition(SQUARECLOSE, epsilon); 60 A1.transition(KEYWORD, new JSONSymbol[]{VA, A2}); 61 A1.transition(STRING, new JSONSymbol[]{VA, A2}); 62 A1.transition(NUMBER, new JSONSymbol[]{VA, A2}); 63 A2.transition(COMMA, new JSONSymbol[]{COMMA, VA, A2}); 64 A2.transition(SQUARECLOSE, epsilon); 65 VA.transition(CURLYOPEN, new JSONSymbol[]{V}); 66 VA.transition(SQUAREOPEN, new JSONSymbol[]{V}); 67 VA.transition(STRING, new JSONSymbol[]{V}); 68 VA.transition(NUMBER, new JSONSymbol[]{V}); 69 VA.transition(KEYWORD, new JSONSymbol[]{V}); 70 V.transition(CURLYOPEN, new JSONSymbol[]{O}); 71 V.transition(SQUAREOPEN, new JSONSymbol[]{A}); 72 V.transition(KEYWORD, new JSONSymbol[]{KEYWORD}); 73 V.transition(STRING, new JSONSymbol[]{STRING}); 74 V.transition(NUMBER, new JSONSymbol[]{NUMBER}); 75 X.marker(X_); 76 O.marker(O_); 77 O1.marker(O1_); 78 O3.marker(O3_); 79 OV.marker(OV_); 80 A.marker(A_); 81 A1.marker(A1_); 82 A2.marker(A2_); 83 VA.marker(VA_); 84 V.marker(V_); 85 } 86 87 boolean isTerminal = true; 88 boolean isMarker = false; 89 HashMap<JSONSymbol, JSONSymbol[]> transitions; 90 JSONSymbol markerSymbol; 91 92 private void transition(JSONSymbol s, JSONSymbol[] sequence) { 93 if (isTerminal) { 94 isTerminal = false; 95 transitions = new HashMap<JSONSymbol, JSONSymbol[]>(); 96 } 97 transitions.put(s, sequence); 98 } 99 100 private void marker(JSONSymbol s) { 101 this.markerSymbol = s; 102 s.isMarker = true; 103 } 104 105 private static Stack<JSONSymbol> stack; 106 private static JSONSymbol terminal; 107 private static JSONSymbol current; 108 private static JSONScanner scanner; 109 private static String value; 110 111 static void init(JSONScanner js) throws JSONException, IOException { 112 scanner = js; 113 stack = new Stack<JSONSymbol>(); 114 115 stack.push(X); 116 terminal = scanner.nextSymbol(); 117 } 118 119 static JSONSymbol next() throws JSONException, IOException { 120 current = stack.pop(); 121 if (DEBUG) { 122 Object[] args = {current}; 123 System.out.println(JSONMessages.localize(args, "parser_current")); 124 } 125 126 if (current.isMarker) { 127 if (current == X_) { 128 // reached bottom of processing stack 129 return current; 130 } 131 } else if (current.isTerminal) { 132 if (current != terminal) { 133 Object[] args = {current, terminal}; 134 throw new JSONException(JSONMessages.localize(args, "expected_but_found"), scanner.line(), scanner.column()); 135 } 136 value = scanner.getValue(); 137 if (DEBUG) { 138 Object[] args = {current, value}; 139 System.out.println(JSONMessages.localize(args, "parser_type")); 140 } 141 terminal = scanner.nextSymbol(); 142 if (DEBUG) { 143 Object[] args = {terminal, scanner.line(), scanner.column()}; 144 System.out.println(JSONMessages.localize(args, "parser_next_terminal")); 145 } 146 } else { 147 JSONSymbol[] target = current.transitions.get(terminal); 148 if (target == null) { 149 Object[] args = {terminal, current}; 150 throw new JSONException(JSONMessages.localize(args, "unexpected_terminal"), scanner.line(), scanner.column()); 151 } 152 153 if (DEBUG) { 154 Object[] args = {current.markerSymbol}; 155 System.out.print(JSONMessages.localize(args, "parser_target") + ", "); 156 } 157 stack.push(current.markerSymbol); 158 159 for (int i = target.length; --i >= 0;) { 160 final JSONSymbol s = target[i]; 161 162 if (DEBUG) { 163 System.out.print(s.toString() + (i > 0 ? ", " : "\n")); 164 } 165 166 stack.push(s); 167 } 168 } 169 return current; 170 } 171 172 static String getValue() { 173 return value; 174 } 175 }