1 8 9 package net.sourceforge.chaperon.model.grammar; 10 11 import net.sourceforge.chaperon.model.symbol.Nonterminal; 12 import net.sourceforge.chaperon.model.symbol.Symbol; 13 import net.sourceforge.chaperon.model.symbol.Terminal; 14 15 import org.xml.sax.Attributes ; 16 import org.xml.sax.Locator ; 17 import org.xml.sax.SAXException ; 18 import org.xml.sax.helpers.DefaultHandler ; 19 20 import java.util.Hashtable ; 21 import java.util.Stack ; 22 23 29 public class GrammarFactory extends DefaultHandler 30 { 31 32 public static final String NS = "http://chaperon.sourceforge.net/schema/grammar/1.0"; 33 34 35 public static final String GRAMMAR_ELEMENT = "grammar"; 36 37 38 39 41 42 public static final String PRODUCTION_ELEMENT = "production"; 43 44 45 public static final String PRECEDENCE_ATTRIBUTE = "precedence"; 46 47 48 public static final String NONTERMINALSYMBOL_ELEMENT = "nonterminal"; 49 50 51 public static final String TERMINALSYMBOL_ELEMENT = "terminal"; 52 53 54 public static final String ERRORSYMBOL_ELEMENT = "error"; 55 56 57 public static final String STARTSYMBOL_ELEMENT = "start"; 58 59 60 public static final String PRIORITY_ELEMENT = "priority"; 61 62 63 public static final String ASSOCIATIVITY_ELEMENT = "associativity"; 64 65 66 public static final String TYPE_ATTRIBUTE = "type"; 67 68 69 public static final String SYMBOL_ATTRIBUTE = "symbol"; 70 private static final int STATE_OUTER = 0; 71 private static final int STATE_GRAMMAR = 1; 72 private static final int STATE_PRODUCTION = 2; 73 private static final int STATE_START = 3; 74 private static final int STATE_NONTERMINAL = 4; 75 private static final int STATE_TERMINAL = 5; 76 private static final int STATE_ASSOCIATIVITY = 6; 77 private static final int STATE_PRIORITY = 7; 78 private static final int STATE_PRIORITYTERMINAL = 8; 79 private static final int STATE_ERROR = 9; 80 private int state = STATE_OUTER; 81 private Grammar grammar; 82 private Hashtable terminals = new Hashtable (); 83 private Hashtable nonterminals = new Hashtable (); 84 private Stack stack; 85 private Locator locator = null; 86 private int priorities = 0; 87 88 93 public Grammar getGrammar() 94 { 95 return grammar; 96 } 97 98 private String getLocation() 99 { 100 if (locator==null) 101 return "unknown"; 102 103 return locator.getSystemId()+":"+locator.getLineNumber()+":"+locator.getColumnNumber(); 104 } 105 106 109 public void setDocumentLocator(Locator locator) 110 { 111 this.locator = locator; 112 } 113 114 117 public void startDocument() 118 { 119 stack = new Stack (); 120 121 state = STATE_OUTER; 122 } 123 124 134 135 143 144 151 152 160 161 173 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) 174 throws SAXException 175 { 176 if (namespaceURI.equals(NS)) 177 { 178 if ((localName.equals(GRAMMAR_ELEMENT)) && (state==STATE_OUTER)) 179 { 180 grammar = new Grammar(); 181 grammar.setLocation(getLocation()); 182 stack.push(grammar); 183 184 state = STATE_GRAMMAR; 185 } 186 else if ((localName.equals(PRODUCTION_ELEMENT)) && (state==STATE_GRAMMAR)) 187 { 188 Production production = 189 new Production(getNonterminal(nonterminals, atts.getValue(SYMBOL_ATTRIBUTE))); 190 production.setLocation(getLocation()); 191 192 String precedencesymbol = atts.getValue(PRECEDENCE_ATTRIBUTE); 193 if ((precedencesymbol!=null) && (precedencesymbol.length()>0)) 194 production.setPrecedence(new Terminal(precedencesymbol)); 195 196 stack.push(production); 197 198 state = STATE_PRODUCTION; 199 } 200 else if ((localName.equals(NONTERMINALSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION)) 201 { 202 stack.push(getNonterminal(nonterminals, atts.getValue(SYMBOL_ATTRIBUTE))); 203 204 state = STATE_NONTERMINAL; 205 } 206 else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION)) 207 { 208 stack.push(new Terminal(atts.getValue(SYMBOL_ATTRIBUTE))); 209 210 state = STATE_TERMINAL; 211 } 212 else if ((localName.equals(ERRORSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION)) 213 { 214 stack.push(new Error ()); 215 216 state = STATE_ERROR; 217 } 218 else if ((localName.equals(STARTSYMBOL_ELEMENT)) && (state==STATE_GRAMMAR)) 219 { 220 stack.push(new Nonterminal(atts.getValue(SYMBOL_ATTRIBUTE))); 221 222 state = STATE_START; 223 } 224 else if ((localName.equals(ASSOCIATIVITY_ELEMENT)) && (state==STATE_GRAMMAR)) 225 { 226 grammar.setAssociativity(getTerminal(terminals, atts.getValue(SYMBOL_ATTRIBUTE)), 227 new Associativity(atts.getValue(TYPE_ATTRIBUTE))); 228 229 state = STATE_ASSOCIATIVITY; 230 } 231 else if ((localName.equals(PRIORITY_ELEMENT)) && (state==STATE_GRAMMAR)) 232 { 233 priorities = 0; 234 235 state = STATE_PRIORITY; 236 } 237 else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRIORITY)) 238 { 239 stack.push(getTerminal(terminals, atts.getValue(SYMBOL_ATTRIBUTE))); 240 241 priorities++; 242 243 state = STATE_PRIORITYTERMINAL; 244 } 245 else 246 throw new SAXException ("Unexpected element "+qName+" at "+getLocation()); 247 } 248 else 249 throw new SAXException ("Unexpected element "+qName+" at "+getLocation()); 250 } 251 252 264 public void endElement(String namespaceURI, String localName, String qName) 265 throws SAXException 266 { 267 if (namespaceURI.equals(NS)) 268 { 269 if ((localName.equals(GRAMMAR_ELEMENT)) && (state==STATE_GRAMMAR)) 270 { 271 grammar = (Grammar)stack.pop(); 272 273 state = STATE_OUTER; 274 } 275 else if ((localName.equals(PRODUCTION_ELEMENT)) && (state==STATE_PRODUCTION)) 276 { 277 Production production = (Production)stack.pop(); 278 Grammar grammar = (Grammar)stack.peek(); 279 280 grammar.addProduction(production); 281 282 state = STATE_GRAMMAR; 283 } 284 else if ((localName.equals(NONTERMINALSYMBOL_ELEMENT)) && (state==STATE_NONTERMINAL)) 285 { 286 Symbol ntsymbol = (Symbol)stack.pop(); 287 Production production = (Production)stack.peek(); 288 289 production.getDefinition().addSymbol(ntsymbol); 290 291 state = STATE_PRODUCTION; 292 } 293 else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_TERMINAL)) 294 { 295 Symbol tsymbol = (Symbol)stack.pop(); 296 Production production = (Production)stack.peek(); 297 298 production.getDefinition().addSymbol(tsymbol); 299 300 state = STATE_PRODUCTION; 301 } 302 else if ((localName.equals(ERRORSYMBOL_ELEMENT)) && (state==STATE_ERROR)) 303 { 304 Symbol error = (Symbol)stack.pop(); 305 Production production = (Production)stack.peek(); 306 307 production.getDefinition().addSymbol(error); 308 309 state = STATE_PRODUCTION; 310 } 311 else if ((localName.equals(STARTSYMBOL_ELEMENT)) && (state==STATE_START)) 312 { 313 Nonterminal ssymbol = (Nonterminal)stack.pop(); 314 Grammar grammar = (Grammar)stack.peek(); 315 316 grammar.setStartSymbol(ssymbol); 317 318 state = STATE_GRAMMAR; 319 } 320 else if ((localName.equals(ASSOCIATIVITY_ELEMENT)) && (state==STATE_ASSOCIATIVITY)) 321 state = STATE_GRAMMAR; 322 else if ((localName.equals(PRIORITY_ELEMENT)) && (state==STATE_PRIORITY)) 323 { 324 int i = 0; 325 while (stack.peek() instanceof Terminal) 326 { 327 grammar.setPriority((Terminal)stack.pop(), i+1); 328 i++; 329 } 330 331 state = STATE_GRAMMAR; 332 } 333 else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRIORITYTERMINAL)) 334 state = STATE_PRIORITY; 335 else 336 throw new SAXException ("Unexpected element "+qName+" at "+getLocation()); 337 } 338 else 339 throw new SAXException ("Unexpected element "+qName+" at "+getLocation()); 340 } 341 342 private Terminal getTerminal(Hashtable terminals, String name) 343 { 344 Terminal terminal = (Terminal)terminals.get(name); 345 if (terminal==null) 346 { 347 terminal = new Terminal(name); 348 terminals.put(name, terminal); 349 } 350 351 return terminal; 352 } 353 354 private Nonterminal getNonterminal(Hashtable nonterminals, String name) 355 { 356 Nonterminal nonterminal = (Nonterminal)nonterminals.get(name); 357 if (nonterminal==null) 358 { 359 nonterminal = new Nonterminal(name); 360 nonterminals.put(name, nonterminal); 361 } 362 363 return nonterminal; 364 } 365 } 366 | Popular Tags |