1 8 9 package net.sourceforge.chaperon.process.extended; 10 11 import net.sourceforge.chaperon.common.Decoder; 12 import net.sourceforge.chaperon.model.extended.ExtendedGrammar; 13 14 import org.apache.commons.logging.Log; 15 16 import org.xml.sax.Attributes ; 17 import org.xml.sax.ContentHandler ; 18 import org.xml.sax.Locator ; 19 import org.xml.sax.SAXException ; 20 import org.xml.sax.ext.LexicalHandler ; 21 import org.xml.sax.helpers.AttributesImpl ; 22 import org.xml.sax.helpers.LocatorImpl ; 23 24 30 public class ExtendedBacktrackingParserProcessor implements ContentHandler , LexicalHandler 31 { 32 33 public static final String NS = "http://chaperon.sourceforge.net/schema/text/1.0"; 34 public static final String TEXT = "text"; 35 36 37 public static final String NS_OUTPUT = "http://chaperon.sourceforge.net/schema/syntaxtree/2.0"; 38 public static final String OUTPUT = "output"; 39 public static final String ERROR = "error"; 40 41 42 private ContentHandler contentHandler = null; 43 private LexicalHandler lexicalHandler = null; 44 private Locator locator = null; 45 private LocatorImpl locatorImpl = null; 46 47 48 private static final int STATE_OUTER = 0; 49 private static final int STATE_INNER = 1; 50 private int state = STATE_OUTER; 51 52 53 private ExtendedParserAutomaton automaton; 54 private ExtendedGrammar grammar; 55 private boolean flatten = false; 56 private StackNode stackNode = null; 57 private Log log; 58 private CharBuffer buffer = new CharBuffer(); 59 private StackNode topmost = null; 60 61 64 public ExtendedBacktrackingParserProcessor() {} 65 66 73 public ExtendedBacktrackingParserProcessor(ExtendedParserAutomaton automaton, Log log) 74 { 75 this.automaton = automaton; 76 this.log = log; 77 } 78 79 84 public void setExtendedParserAutomaton(ExtendedParserAutomaton automaton) 85 { 86 this.automaton = automaton; 87 this.grammar = automaton.getExtendedGrammar(); 88 } 89 90 93 public void setContentHandler(ContentHandler handler) 94 { 95 this.contentHandler = handler; 96 } 97 98 101 public void setLexicalHandler(LexicalHandler handler) 102 { 103 this.lexicalHandler = handler; 104 } 105 106 111 public void setLog(Log log) 112 { 113 this.log = log; 114 } 115 116 122 public void setFlatten(boolean flatten) 123 { 124 this.flatten = flatten; 125 } 126 127 130 public void setDocumentLocator(Locator locator) 131 { 132 this.locator = locator; 133 134 if (locator!=null) 135 { 136 this.locatorImpl = new LocatorImpl (locator); 137 contentHandler.setDocumentLocator(locatorImpl); 138 } 139 } 140 141 144 public void startDocument() throws SAXException 145 { 146 locatorImpl.setLineNumber(locator.getLineNumber()); 147 locatorImpl.setColumnNumber(locator.getColumnNumber()); 148 contentHandler.startDocument(); 149 state = STATE_OUTER; 150 } 151 152 155 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) 156 throws SAXException 157 { 158 locatorImpl.setLineNumber(locator.getLineNumber()); 159 locatorImpl.setColumnNumber(locator.getColumnNumber()); 160 161 if (state==STATE_INNER) 162 throw new SAXException ("Unexpected element "+qName); 163 164 if (state==STATE_OUTER) 165 { 166 if ((namespaceURI!=null) && (namespaceURI.equals(NS))) 167 { 168 if (!localName.equals(TEXT)) 169 throw new SAXException ("Unknown element "+qName); 170 } 171 else 172 { 173 contentHandler.startElement(namespaceURI, localName, qName, atts); 174 return; 175 } 176 } 177 178 state = STATE_INNER; 179 180 buffer.clear(); 182 stackNode = new TerminalStackNode('\u0000', automaton.first, null); 183 topmost = stackNode; 184 } 185 186 189 public void characters(char[] text, int textstart, int textlength) 190 throws SAXException 191 { 192 locatorImpl.setLineNumber(locator.getLineNumber()); 193 locatorImpl.setColumnNumber(locator.getColumnNumber()); 194 195 if (state==STATE_OUTER) 196 { 197 contentHandler.characters(text, textstart, textlength); 198 199 return; 200 } 201 202 if ((log!=null) && (log.isDebugEnabled())) 203 log.debug("getting text "+Decoder.toString(new String (text, textstart, textlength))); 204 205 buffer.push(text, textstart, textlength); 206 } 207 208 211 public void endElement(String namespaceURI, String localName, String qName) 212 throws SAXException 213 { 214 locatorImpl.setLineNumber(locator.getLineNumber()); 215 locatorImpl.setColumnNumber(locator.getColumnNumber()); 216 217 if (state==STATE_OUTER) 218 contentHandler.endElement(namespaceURI, localName, qName); 219 220 if (state==STATE_INNER) 221 { 222 if ((namespaceURI!=null) && (namespaceURI.equals(NS))) 223 { 224 if (!localName.equals(TEXT)) 225 throw new SAXException ("Unknown element "+qName); 226 } 227 else 228 throw new SAXException ("Unexpected element "+qName); 229 } 230 231 while (stackNode!=null) 233 { 234 if ((log!=null) && (log.isDebugEnabled()) && (buffer.available())) 235 log.debug("process "+Decoder.toChar(buffer.peek())); 236 237 239 240 ShiftAction shiftAction = null; 241 ReduceAction[] reduceActions; 242 243 if (buffer.available()) 244 { 245 outer: 246 while (((shiftAction = stackNode.state.getShiftAction(buffer.peek()))==null) && 247 ((reduceActions = stackNode.state.getReduceActions()).length>0)) 248 { 249 reduceActions = stackNode.state.getReduceActions(); 250 251 for (int index = 0; index<=reduceActions.length; index++) 252 { 253 if (index==reduceActions.length) 254 break outer; 255 256 ReduceAction reduceAction = reduceActions[index]; 257 258 StackNode second = (reduceAction.length==2) ? stackNode : null; 259 StackNode first = (reduceAction.length==2) ? second.ancestor : null; 260 StackNode previousStackNode = (reduceAction.length==2) ? first.ancestor : stackNode; 261 262 GotoAction gotoAction = 263 (reduceAction.symbol!=null) 264 ? previousStackNode.state.getGotoAction(reduceAction.symbol) 265 : previousStackNode.state.getGotoAction(reduceAction.pattern); 266 267 if (gotoAction!=null) 268 { 269 if ((log!=null) && (log.isDebugEnabled())) 270 log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction); 271 272 stackNode = 273 new DefinitionStackNode(reduceAction, index, first, second, gotoAction.state, 274 previousStackNode); 275 276 topmost = topmost.getTopMost(stackNode); 277 278 break; 279 } 280 } 281 } 282 } 283 else 284 { 285 while ((reduceActions = stackNode.state.getReduceActions()).length>0) 286 { 287 ReduceAction reduceAction = reduceActions[0]; 288 289 StackNode second = (reduceAction.length==2) ? stackNode : null; 290 StackNode first = (reduceAction.length==2) ? second.ancestor : null; 291 StackNode previousStackNode = (reduceAction.length==2) ? first.ancestor : stackNode; 292 293 GotoAction gotoAction = 294 (reduceAction.symbol!=null) 295 ? previousStackNode.state.getGotoAction(reduceAction.symbol) 296 : previousStackNode.state.getGotoAction(reduceAction.pattern); 297 298 if ((automaton.first==previousStackNode.state) && 299 (grammar.getStartSymbol().equals(reduceAction.symbol))) 300 { 301 if ((log!=null) && (log.isDebugEnabled())) 302 log.debug("State "+automaton.indexOf(stackNode.state)+" accept"); 303 304 stackNode = 305 new DefinitionStackNode(reduceAction, 0, first, second, null, previousStackNode); 306 fireEvents(); 307 308 state = STATE_OUTER; 309 310 return; 311 } 312 else 313 { 314 if ((log!=null) && (log.isDebugEnabled())) 315 log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction); 316 317 stackNode = 318 new DefinitionStackNode(reduceAction, 0, first, second, gotoAction.state, 319 previousStackNode); 320 } 321 } 322 } 323 324 325 if (shiftAction!=null) 326 { 327 if ((log!=null) && (log.isDebugEnabled())) 328 log.debug("State "+automaton.indexOf(stackNode.state)+" "+shiftAction); 329 330 stackNode = new TerminalStackNode(buffer.read(), shiftAction.state, stackNode); 331 332 topmost = topmost.getTopMost(stackNode); 333 } 334 else 335 { 336 if ((log!=null) && (log.isDebugEnabled())) 337 if (buffer.available()) 338 log.debug("State "+automaton.indexOf(stackNode.state)+" error "+ 339 Decoder.toChar(buffer.peek())); 340 else 341 log.debug("State "+automaton.indexOf(stackNode.state)+" error EOF"); 342 343 backtrack(); 346 } 347 } 348 349 if (buffer.available()) 350 throw new IllegalArgumentException ("Character "+Decoder.toChar(buffer.peek())+ 351 " is not expected"); 352 else 353 throw new IllegalArgumentException ("Eon of file is not expected"); 354 } 355 356 private void backtrack() throws SAXException 357 { 358 while (automaton.first!=stackNode.state) 359 { 360 if ((log!=null) && (log.isDebugEnabled())) 361 log.debug("State "+automaton.indexOf(stackNode.state)+" backtracking"); 362 363 if (stackNode instanceof DefinitionStackNode) 364 { 365 DefinitionStackNode definitionStackNode = (DefinitionStackNode)stackNode; 366 stackNode = 367 (definitionStackNode.action.length==0) ? stackNode.ancestor : definitionStackNode.second; 368 369 ReduceAction[] reduceActions = stackNode.state.getReduceActions(); 370 371 if (reduceActions.length>(definitionStackNode.index+1)) 372 { 373 ReduceAction reduceAction = reduceActions[definitionStackNode.index+1]; 375 376 StackNode second = (reduceAction.length==2) ? stackNode : null; 377 StackNode first = (reduceAction.length==2) ? second.ancestor : null; 378 StackNode previousStackNode = (reduceAction.length==2) ? first.ancestor : stackNode; 379 380 GotoAction gotoAction = 381 (reduceAction.symbol!=null) 382 ? previousStackNode.state.getGotoAction(reduceAction.symbol) 383 : previousStackNode.state.getGotoAction(reduceAction.pattern); 384 385 if ((log!=null) && (log.isDebugEnabled())) 386 log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction); 387 388 stackNode = 389 new DefinitionStackNode(reduceAction, definitionStackNode.index+1, first, second, 390 gotoAction.state, previousStackNode); 391 392 return; 394 } 395 396 } 398 else 399 { 400 TerminalStackNode terminalStackNode = (TerminalStackNode)stackNode; 401 stackNode = stackNode.ancestor; 402 403 ReduceAction[] reduceActions = stackNode.state.getReduceActions(); 404 405 buffer.back(); 406 407 if (reduceActions.length>0) 408 { 409 ReduceAction reduceAction = reduceActions[0]; 411 412 StackNode second = (reduceAction.length==2) ? stackNode : null; 413 StackNode first = (reduceAction.length==2) ? second.ancestor : null; 414 StackNode previousStackNode = (reduceAction.length==2) ? first.ancestor : stackNode; 415 416 GotoAction gotoAction = 417 (reduceAction.symbol!=null) 418 ? previousStackNode.state.getGotoAction(reduceAction.symbol) 419 : previousStackNode.state.getGotoAction(reduceAction.pattern); 420 421 if ((log!=null) && (log.isDebugEnabled())) 422 log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction); 423 424 stackNode = 425 new DefinitionStackNode(reduceAction, 0, first, second, gotoAction.state, 426 previousStackNode); 427 428 return; 429 } 430 431 } 433 } 434 435 throw new SAXException ("Could not recognize text at ["+topmost.lineNumber+":"+ 436 topmost.columnNumber+"]"); 437 } 438 439 private void fireEvents() throws SAXException 440 { 441 contentHandler.startPrefixMapping("", NS_OUTPUT); 442 contentHandler.startElement(NS_OUTPUT, OUTPUT, OUTPUT, new AttributesImpl ()); 443 444 stackNode.toXML(contentHandler); 445 446 contentHandler.endElement(NS_OUTPUT, OUTPUT, OUTPUT); 447 contentHandler.endPrefixMapping(""); 448 } 449 450 453 public void ignorableWhitespace(char[] ch, int start, int length) 454 throws SAXException 455 { 456 locatorImpl.setLineNumber(locator.getLineNumber()); 457 locatorImpl.setColumnNumber(locator.getColumnNumber()); 458 459 if (state==STATE_OUTER) 460 contentHandler.ignorableWhitespace(ch, start, length); 461 } 462 463 466 public void startPrefixMapping(String prefix, String uri) 467 throws SAXException 468 { 469 locatorImpl.setLineNumber(locator.getLineNumber()); 470 locatorImpl.setColumnNumber(locator.getColumnNumber()); 471 472 contentHandler.startPrefixMapping(prefix, uri); 473 } 474 475 478 public void endPrefixMapping(String prefix) throws SAXException 479 { 480 locatorImpl.setLineNumber(locator.getLineNumber()); 481 locatorImpl.setColumnNumber(locator.getColumnNumber()); 482 483 contentHandler.endPrefixMapping(prefix); 484 } 485 486 489 public void processingInstruction(String target, String data) 490 throws SAXException 491 { 492 locatorImpl.setLineNumber(locator.getLineNumber()); 493 locatorImpl.setColumnNumber(locator.getColumnNumber()); 494 495 if (state==STATE_OUTER) 496 contentHandler.processingInstruction(target, data); 497 } 498 499 502 public void skippedEntity(String name) throws SAXException 503 { 504 locatorImpl.setLineNumber(locator.getLineNumber()); 505 locatorImpl.setColumnNumber(locator.getColumnNumber()); 506 507 if (state==STATE_OUTER) 508 contentHandler.skippedEntity(name); 509 } 510 511 514 public void endDocument() throws SAXException 515 { 516 locatorImpl.setLineNumber(locator.getLineNumber()); 517 locatorImpl.setColumnNumber(locator.getColumnNumber()); 518 519 contentHandler.endDocument(); 520 } 521 522 525 public void startDTD(String name, String publicId, String systemId) 526 throws SAXException 527 { 528 if (lexicalHandler!=null) 529 lexicalHandler.startDTD(name, publicId, systemId); 530 } 531 532 535 public void endDTD() throws SAXException 536 { 537 if (lexicalHandler!=null) 538 lexicalHandler.endDTD(); 539 } 540 541 544 public void startEntity(String name) throws SAXException 545 { 546 if (lexicalHandler!=null) 547 lexicalHandler.startEntity(name); 548 } 549 550 553 public void endEntity(String name) throws SAXException 554 { 555 if (lexicalHandler!=null) 556 lexicalHandler.endEntity(name); 557 } 558 559 562 public void startCDATA() throws SAXException 563 { 564 if (lexicalHandler!=null) 565 lexicalHandler.startCDATA(); 566 } 567 568 571 public void endCDATA() throws SAXException 572 { 573 if (lexicalHandler!=null) 574 lexicalHandler.endCDATA(); 575 } 576 577 580 public void comment(char[] ch, int start, int len) throws SAXException 581 { 582 if (lexicalHandler!=null) 583 lexicalHandler.comment(ch, start, len); 584 } 585 } 586 | Popular Tags |