001/* 002 * Copyright 2006 - 2013 003 * Stefan Balev <stefan.balev@graphstream-project.org> 004 * Julien Baudry <julien.baudry@graphstream-project.org> 005 * Antoine Dutot <antoine.dutot@graphstream-project.org> 006 * Yoann Pigné <yoann.pigne@graphstream-project.org> 007 * Guilhelm Savin <guilhelm.savin@graphstream-project.org> 008 * 009 * This file is part of GraphStream <http://graphstream-project.org>. 010 * 011 * GraphStream is a library whose purpose is to handle static or dynamic 012 * graph, create them from scratch, file or any source and display them. 013 * 014 * This program is free software distributed under the terms of two licenses, the 015 * CeCILL-C license that fits European law, and the GNU Lesser General Public 016 * License. You can use, modify and/ or redistribute the software under the terms 017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following 018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by 019 * the Free Software Foundation, either version 3 of the License, or (at your 020 * option) any later version. 021 * 022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 024 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 025 * 026 * You should have received a copy of the GNU Lesser General Public License 027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 028 * 029 * The fact that you are presently reading this means that you have had 030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. 031 */ 032package org.graphstream.stream.file.dot; 033 034import java.io.InputStream; 035import java.io.IOException; 036import java.io.Reader; 037 038import java.util.HashMap; 039import java.util.HashSet; 040import java.util.LinkedList; 041 042import org.graphstream.stream.SourceBase.ElementType; 043import org.graphstream.stream.file.FileSourceDOT; 044import org.graphstream.graph.implementations.AbstractElement.AttributeChangeEvent; 045 046import org.graphstream.util.parser.ParseException; 047import org.graphstream.util.parser.Parser; 048import org.graphstream.util.parser.SimpleCharStream; 049import org.graphstream.util.parser.Token; 050import org.graphstream.util.parser.TokenMgrError; 051 052/** 053 * This class defines a DOT parser. 054 * 055 * It respects the specifications of the DOT language that can be found <a 056 * href="http://www.graphviz.org/doc/info/lang.html">here</a>. 057 * 058 * Subgraph produces no error but has no effect on the graph. 059 */ 060@SuppressWarnings("unused") 061public class DOTParser implements Parser, DOTParserConstants { 062 /** 063 * The DOT source associated with this parser. 064 */ 065 private FileSourceDOT dot; 066 067 /** 068 * Id of the parser used in events. 069 */ 070 private String sourceId; 071 072 /** 073 * Flag telling if the graph is directed. 074 */ 075 private boolean directed; 076 077 /** 078 * Flag telling if the graph is 'strict'. 079 */ 080 private boolean strict; 081 082 /** 083 * Global attributes of nodes. 084 */ 085 private HashMap<String, Object> globalNodesAttributes; 086 087 /** 088 * Global attributes of edges. 089 */ 090 private HashMap<String, Object> globalEdgesAttributes; 091 092 /** 093 * IDs of added nodes. 094 */ 095 private HashSet<String> nodeAdded; 096 097 /** 098 * Create a new parser associated with a DOT source from an input stream. 099 */ 100 public DOTParser(FileSourceDOT dot, InputStream stream) { 101 this(stream); 102 init(dot); 103 } 104 105 /** 106 * Create a new parser associated with a DOT source from a reader. 107 */ 108 public DOTParser(FileSourceDOT dot, Reader stream) { 109 this(stream); 110 init(dot); 111 } 112 113 /** 114 * Closes the parser, closing the opened stream. 115 */ 116 public void close() throws IOException { 117 jj_input_stream.close(); 118 } 119 120 private void init(FileSourceDOT dot) { 121 this.dot = dot; 122 this.sourceId = String.format("<DOT stream %x>", System.nanoTime()); 123 124 globalNodesAttributes = new HashMap<String, Object>(); 125 globalEdgesAttributes = new HashMap<String, Object>(); 126 127 nodeAdded = new HashSet<String>(); 128 } 129 130 private void addNode(String nodeId, String[] port, 131 HashMap<String, Object> attr) { 132 if (nodeAdded.contains(nodeId)) { 133 if (attr != null) { 134 for (String key : attr.keySet()) 135 dot.sendAttributeChangedEvent(sourceId, nodeId, 136 ElementType.NODE, key, AttributeChangeEvent.ADD, 137 null, attr.get(key)); 138 } 139 } else { 140 dot.sendNodeAdded(sourceId, nodeId); 141 nodeAdded.add(nodeId); 142 143 if (attr == null) { 144 for (String key : globalNodesAttributes.keySet()) 145 dot.sendAttributeChangedEvent(sourceId, nodeId, 146 ElementType.NODE, key, AttributeChangeEvent.ADD, 147 null, globalNodesAttributes.get(key)); 148 } else { 149 for (String key : globalNodesAttributes.keySet()) { 150 if (!attr.containsKey(key)) 151 dot.sendAttributeChangedEvent(sourceId, nodeId, 152 ElementType.NODE, key, 153 AttributeChangeEvent.ADD, null, 154 globalNodesAttributes.get(key)); 155 } 156 157 for (String key : attr.keySet()) 158 dot.sendAttributeChangedEvent(sourceId, nodeId, 159 ElementType.NODE, key, AttributeChangeEvent.ADD, 160 null, attr.get(key)); 161 } 162 } 163 } 164 165 private void addEdges(LinkedList<String> edges, HashMap<String, Object> attr) { 166 HashMap<String, Integer> hash = new HashMap<String, Integer>(); 167 String[] ids = new String[(edges.size() - 1) / 2]; 168 boolean[] directed = new boolean[(edges.size() - 1) / 2]; 169 int count = 0; 170 171 for (int i = 0; i < edges.size() - 1; i += 2) { 172 String from = edges.get(i); 173 String to = edges.get(i + 2); 174 175 if (!nodeAdded.contains(from)) 176 addNode(from, null, null); 177 if (!nodeAdded.contains(to)) 178 addNode(to, null, null); 179 180 String edgeId = String.format("(%s;%s)", from, to); 181 String rev = String.format("(%s;%s)", to, from); 182 183 if (hash.containsKey(rev)) { 184 directed[hash.get(rev)] = false; 185 } else { 186 hash.put(edgeId, count); 187 ids[count] = edgeId; 188 directed[count] = edges.get(i + 1).equals("->"); 189 190 count++; 191 } 192 } 193 194 hash.clear(); 195 196 if (count == 1 && attr != null && attr.containsKey("id")) { 197 ids[0] = attr.get("id").toString(); 198 attr.remove("id"); 199 } 200 201 for (int i = 0; i < count; i++) { 202 dot.sendEdgeAdded(sourceId, ids[i], edges.get(i * 2), edges 203 .get((i + 1) * 2), directed[i]); 204 205 if (attr == null) { 206 for (String key : globalEdgesAttributes.keySet()) 207 dot.sendAttributeChangedEvent(sourceId, ids[i], 208 ElementType.EDGE, key, AttributeChangeEvent.ADD, 209 null, globalEdgesAttributes.get(key)); 210 } else { 211 for (String key : globalEdgesAttributes.keySet()) { 212 if (!attr.containsKey(key)) 213 dot.sendAttributeChangedEvent(sourceId, ids[i], 214 ElementType.EDGE, key, 215 AttributeChangeEvent.ADD, null, 216 globalEdgesAttributes.get(key)); 217 } 218 219 for (String key : attr.keySet()) 220 dot.sendAttributeChangedEvent(sourceId, ids[i], 221 ElementType.EDGE, key, AttributeChangeEvent.ADD, 222 null, attr.get(key)); 223 } 224 } 225 } 226 227 private void setGlobalAttributes(String who, HashMap<String, Object> attr) { 228 if (who.equalsIgnoreCase("graph")) { 229 for (String key : attr.keySet()) 230 dot.sendAttributeChangedEvent(sourceId, sourceId, 231 ElementType.GRAPH, key, AttributeChangeEvent.ADD, null, 232 attr.get(key)); 233 } else if (who.equalsIgnoreCase("node")) 234 globalNodesAttributes.putAll(attr); 235 else if (who.equalsIgnoreCase("edge")) 236 globalEdgesAttributes.putAll(attr); 237 } 238 239 final public void all() throws ParseException { 240 graph(); 241 label_1: while (true) { 242 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 243 case GRAPH: 244 case SUBGRAPH: 245 case NODE: 246 case EDGE: 247 case REAL: 248 case STRING: 249 case WORD: 250 ; 251 break; 252 default: 253 jj_la1[0] = jj_gen; 254 break label_1; 255 } 256 statement(); 257 } 258 jj_consume_token(RBRACE); 259 } 260 261 final public boolean next() throws ParseException { 262 boolean hasMore = false; 263 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 264 case GRAPH: 265 case SUBGRAPH: 266 case NODE: 267 case EDGE: 268 case REAL: 269 case STRING: 270 case WORD: 271 statement(); 272 hasMore = true; 273 break; 274 case RBRACE: 275 jj_consume_token(RBRACE); 276 break; 277 case 0: 278 jj_consume_token(0); 279 break; 280 default: 281 jj_la1[1] = jj_gen; 282 jj_consume_token(-1); 283 throw new ParseException(); 284 } 285 286 return hasMore; 287 } 288 289 final public void open() throws ParseException { 290 graph(); 291 } 292 293 final private void graph() throws ParseException { 294 directed = false; 295 strict = false; 296 297 globalNodesAttributes.clear(); 298 globalEdgesAttributes.clear(); 299 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 300 case STRICT: 301 jj_consume_token(STRICT); 302 strict = true; 303 break; 304 default: 305 jj_la1[2] = jj_gen; 306 ; 307 } 308 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 309 case GRAPH: 310 jj_consume_token(GRAPH); 311 break; 312 case DIGRAPH: 313 jj_consume_token(DIGRAPH); 314 directed = true; 315 break; 316 default: 317 jj_la1[3] = jj_gen; 318 jj_consume_token(-1); 319 throw new ParseException(); 320 } 321 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 322 case REAL: 323 case STRING: 324 case WORD: 325 this.sourceId = id(); 326 break; 327 default: 328 jj_la1[4] = jj_gen; 329 ; 330 } 331 jj_consume_token(LBRACE); 332 } 333 334 final private void subgraph() throws ParseException { 335 jj_consume_token(SUBGRAPH); 336 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 337 case REAL: 338 case STRING: 339 case WORD: 340 id(); 341 break; 342 default: 343 jj_la1[5] = jj_gen; 344 ; 345 } 346 jj_consume_token(LBRACE); 347 label_2: while (true) { 348 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 349 case GRAPH: 350 case SUBGRAPH: 351 case NODE: 352 case EDGE: 353 case REAL: 354 case STRING: 355 case WORD: 356 ; 357 break; 358 default: 359 jj_la1[6] = jj_gen; 360 break label_2; 361 } 362 statement(); 363 } 364 jj_consume_token(RBRACE); 365 } 366 367 final private String id() throws ParseException { 368 Token t; 369 String id; 370 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 371 case STRING: 372 t = jj_consume_token(STRING); 373 id = t.image.substring(1, t.image.length() - 1); 374 break; 375 case REAL: 376 t = jj_consume_token(REAL); 377 id = t.image; 378 break; 379 case WORD: 380 t = jj_consume_token(WORD); 381 id = t.image; 382 break; 383 default: 384 jj_la1[7] = jj_gen; 385 jj_consume_token(-1); 386 throw new ParseException(); 387 } 388 389 return id; 390 } 391 392 final private void statement() throws ParseException { 393 if (jj_2_1(3)) { 394 edgeStatement(); 395 } else { 396 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 397 case REAL: 398 case STRING: 399 case WORD: 400 nodeStatement(); 401 break; 402 case GRAPH: 403 case NODE: 404 case EDGE: 405 attributeStatement(); 406 break; 407 case SUBGRAPH: 408 subgraph(); 409 break; 410 default: 411 jj_la1[8] = jj_gen; 412 jj_consume_token(-1); 413 throw new ParseException(); 414 } 415 } 416 jj_consume_token(27); 417 } 418 419 final private void nodeStatement() throws ParseException { 420 String nodeId; 421 String[] port; 422 HashMap<String, Object> attr = null; 423 424 port = null; 425 nodeId = id(); 426 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 427 case COLON: 428 port = port(); 429 break; 430 default: 431 jj_la1[9] = jj_gen; 432 ; 433 } 434 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 435 case LSQBR: 436 attr = attributesList(); 437 break; 438 default: 439 jj_la1[10] = jj_gen; 440 ; 441 } 442 addNode(nodeId, port, attr); 443 } 444 445 final private String compassPoint() throws ParseException { 446 Token pt = null; 447 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 448 case 28: 449 pt = jj_consume_token(28); 450 break; 451 case 29: 452 pt = jj_consume_token(29); 453 break; 454 case 30: 455 pt = jj_consume_token(30); 456 break; 457 case 31: 458 pt = jj_consume_token(31); 459 break; 460 case 32: 461 pt = jj_consume_token(32); 462 break; 463 case 33: 464 pt = jj_consume_token(33); 465 break; 466 case 34: 467 pt = jj_consume_token(34); 468 break; 469 case 35: 470 pt = jj_consume_token(35); 471 break; 472 case 36: 473 pt = jj_consume_token(36); 474 break; 475 case 37: 476 pt = jj_consume_token(37); 477 break; 478 default: 479 jj_la1[11] = jj_gen; 480 jj_consume_token(-1); 481 throw new ParseException(); 482 } 483 484 return pt.image; 485 } 486 487 final private String[] port() throws ParseException { 488 String[] p = { null, null }; 489 jj_consume_token(COLON); 490 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 491 case REAL: 492 case STRING: 493 case WORD: 494 p[0] = id(); 495 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 496 case COLON: 497 jj_consume_token(COLON); 498 p[1] = compassPoint(); 499 break; 500 default: 501 jj_la1[12] = jj_gen; 502 ; 503 } 504 break; 505 case 28: 506 case 29: 507 case 30: 508 case 31: 509 case 32: 510 case 33: 511 case 34: 512 case 35: 513 case 36: 514 case 37: 515 p[1] = compassPoint(); 516 break; 517 default: 518 jj_la1[13] = jj_gen; 519 jj_consume_token(-1); 520 throw new ParseException(); 521 } 522 523 return p; 524 } 525 526 final private void edgeStatement() throws ParseException { 527 String id; 528 LinkedList<String> edges = new LinkedList<String>(); 529 HashMap<String, Object> attr = null; 530 id = id(); 531 edges.add(id); 532 edgeRHS(edges); 533 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 534 case LSQBR: 535 attr = attributesList(); 536 break; 537 default: 538 jj_la1[14] = jj_gen; 539 ; 540 } 541 addEdges(edges, attr); 542 } 543 544 final private void edgeRHS(LinkedList<String> edges) throws ParseException { 545 Token t; 546 String i; 547 t = jj_consume_token(EDGE_OP); 548 edges.add(t.image); 549 i = id(); 550 edges.add(i); 551 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 552 case EDGE_OP: 553 edgeRHS(edges); 554 break; 555 default: 556 jj_la1[15] = jj_gen; 557 ; 558 } 559 } 560 561 final private void attributeStatement() throws ParseException { 562 Token t; 563 HashMap<String, Object> attr; 564 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 565 case GRAPH: 566 t = jj_consume_token(GRAPH); 567 break; 568 case NODE: 569 t = jj_consume_token(NODE); 570 break; 571 case EDGE: 572 t = jj_consume_token(EDGE); 573 break; 574 default: 575 jj_la1[16] = jj_gen; 576 jj_consume_token(-1); 577 throw new ParseException(); 578 } 579 attr = attributesList(); 580 setGlobalAttributes(t.image, attr); 581 } 582 583 final private HashMap<String, Object> attributesList() 584 throws ParseException { 585 HashMap<String, Object> attributes = new HashMap<String, Object>(); 586 label_3: while (true) { 587 jj_consume_token(LSQBR); 588 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 589 case REAL: 590 case STRING: 591 case WORD: 592 attributeList(attributes); 593 label_4: while (true) { 594 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 595 case COMMA: 596 ; 597 break; 598 default: 599 jj_la1[17] = jj_gen; 600 break label_4; 601 } 602 jj_consume_token(COMMA); 603 attributeList(attributes); 604 } 605 break; 606 default: 607 jj_la1[18] = jj_gen; 608 ; 609 } 610 jj_consume_token(RSQBR); 611 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 612 case LSQBR: 613 ; 614 break; 615 default: 616 jj_la1[19] = jj_gen; 617 break label_3; 618 } 619 } 620 621 return attributes; 622 } 623 624 final private void attributeList(HashMap<String, Object> attributes) 625 throws ParseException { 626 String key; 627 Object val; 628 629 Token t; 630 key = id(); 631 val = Boolean.TRUE; 632 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 633 case EQUALS: 634 jj_consume_token(EQUALS); 635 if (jj_2_2(2)) { 636 t = jj_consume_token(REAL); 637 val = Double.parseDouble(t.image); 638 } else { 639 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { 640 case REAL: 641 case STRING: 642 case WORD: 643 val = id(); 644 break; 645 default: 646 jj_la1[20] = jj_gen; 647 jj_consume_token(-1); 648 throw new ParseException(); 649 } 650 } 651 break; 652 default: 653 jj_la1[21] = jj_gen; 654 ; 655 } 656 attributes.put(key, val); 657 } 658 659 private boolean jj_2_1(int xla) { 660 jj_la = xla; 661 jj_lastpos = jj_scanpos = token; 662 try { 663 return !jj_3_1(); 664 } catch (LookaheadSuccess ls) { 665 return true; 666 } finally { 667 jj_save(0, xla); 668 } 669 } 670 671 private boolean jj_2_2(int xla) { 672 jj_la = xla; 673 jj_lastpos = jj_scanpos = token; 674 try { 675 return !jj_3_2(); 676 } catch (LookaheadSuccess ls) { 677 return true; 678 } finally { 679 jj_save(1, xla); 680 } 681 } 682 683 private boolean jj_3R_6() { 684 Token xsp; 685 xsp = jj_scanpos; 686 if (jj_3R_8()) { 687 jj_scanpos = xsp; 688 if (jj_3R_9()) { 689 jj_scanpos = xsp; 690 if (jj_3R_10()) 691 return true; 692 } 693 } 694 return false; 695 } 696 697 private boolean jj_3_2() { 698 if (jj_scan_token(REAL)) 699 return true; 700 return false; 701 } 702 703 private boolean jj_3R_8() { 704 if (jj_scan_token(STRING)) 705 return true; 706 return false; 707 } 708 709 private boolean jj_3R_10() { 710 if (jj_scan_token(WORD)) 711 return true; 712 return false; 713 } 714 715 private boolean jj_3R_7() { 716 if (jj_scan_token(EDGE_OP)) 717 return true; 718 if (jj_3R_6()) 719 return true; 720 return false; 721 } 722 723 private boolean jj_3R_9() { 724 if (jj_scan_token(REAL)) 725 return true; 726 return false; 727 } 728 729 private boolean jj_3R_5() { 730 if (jj_3R_6()) 731 return true; 732 if (jj_3R_7()) 733 return true; 734 return false; 735 } 736 737 private boolean jj_3_1() { 738 if (jj_3R_5()) 739 return true; 740 return false; 741 } 742 743 /** Generated Token Manager. */ 744 public DOTParserTokenManager token_source; 745 SimpleCharStream jj_input_stream; 746 /** Current token. */ 747 public Token token; 748 /** Next token. */ 749 public Token jj_nt; 750 private int jj_ntk; 751 private Token jj_scanpos, jj_lastpos; 752 private int jj_la; 753 private int jj_gen; 754 final private int[] jj_la1 = new int[22]; 755 static private int[] jj_la1_0; 756 static private int[] jj_la1_1; 757 static { 758 jj_la1_init_0(); 759 jj_la1_init_1(); 760 } 761 762 private static void jj_la1_init_0() { 763 jj_la1_0 = new int[] { 0x73a0000, 0x73a2001, 0x400000, 0x60000, 764 0x7000000, 0x7000000, 0x73a0000, 0x7000000, 0x73a0000, 0x4000, 765 0x400, 0xf0000000, 0x4000, 0xf7000000, 0x400, 0x800000, 766 0x320000, 0x8000, 0x7000000, 0x400, 0x7000000, 0x10000, }; 767 } 768 769 private static void jj_la1_init_1() { 770 jj_la1_1 = new int[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 771 0x0, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 772 0x0, }; 773 } 774 775 final private JJCalls[] jj_2_rtns = new JJCalls[2]; 776 private boolean jj_rescan = false; 777 private int jj_gc = 0; 778 779 /** Constructor with InputStream. */ 780 public DOTParser(java.io.InputStream stream) { 781 this(stream, null); 782 } 783 784 /** Constructor with InputStream and supplied encoding */ 785 public DOTParser(java.io.InputStream stream, String encoding) { 786 try { 787 jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); 788 } catch (java.io.UnsupportedEncodingException e) { 789 throw new RuntimeException(e); 790 } 791 token_source = new DOTParserTokenManager(jj_input_stream); 792 token = new Token(); 793 jj_ntk = -1; 794 jj_gen = 0; 795 for (int i = 0; i < 22; i++) 796 jj_la1[i] = -1; 797 for (int i = 0; i < jj_2_rtns.length; i++) 798 jj_2_rtns[i] = new JJCalls(); 799 } 800 801 /** Reinitialise. */ 802 public void ReInit(java.io.InputStream stream) { 803 ReInit(stream, null); 804 } 805 806 /** Reinitialise. */ 807 public void ReInit(java.io.InputStream stream, String encoding) { 808 try { 809 jj_input_stream.ReInit(stream, encoding, 1, 1); 810 } catch (java.io.UnsupportedEncodingException e) { 811 throw new RuntimeException(e); 812 } 813 token_source.ReInit(jj_input_stream); 814 token = new Token(); 815 jj_ntk = -1; 816 jj_gen = 0; 817 for (int i = 0; i < 22; i++) 818 jj_la1[i] = -1; 819 for (int i = 0; i < jj_2_rtns.length; i++) 820 jj_2_rtns[i] = new JJCalls(); 821 } 822 823 /** Constructor. */ 824 public DOTParser(java.io.Reader stream) { 825 jj_input_stream = new SimpleCharStream(stream, 1, 1); 826 token_source = new DOTParserTokenManager(jj_input_stream); 827 token = new Token(); 828 jj_ntk = -1; 829 jj_gen = 0; 830 for (int i = 0; i < 22; i++) 831 jj_la1[i] = -1; 832 for (int i = 0; i < jj_2_rtns.length; i++) 833 jj_2_rtns[i] = new JJCalls(); 834 } 835 836 /** Reinitialise. */ 837 public void ReInit(java.io.Reader stream) { 838 jj_input_stream.ReInit(stream, 1, 1); 839 token_source.ReInit(jj_input_stream); 840 token = new Token(); 841 jj_ntk = -1; 842 jj_gen = 0; 843 for (int i = 0; i < 22; i++) 844 jj_la1[i] = -1; 845 for (int i = 0; i < jj_2_rtns.length; i++) 846 jj_2_rtns[i] = new JJCalls(); 847 } 848 849 /** Constructor with generated Token Manager. */ 850 public DOTParser(DOTParserTokenManager tm) { 851 token_source = tm; 852 token = new Token(); 853 jj_ntk = -1; 854 jj_gen = 0; 855 for (int i = 0; i < 22; i++) 856 jj_la1[i] = -1; 857 for (int i = 0; i < jj_2_rtns.length; i++) 858 jj_2_rtns[i] = new JJCalls(); 859 } 860 861 /** Reinitialise. */ 862 public void ReInit(DOTParserTokenManager tm) { 863 token_source = tm; 864 token = new Token(); 865 jj_ntk = -1; 866 jj_gen = 0; 867 for (int i = 0; i < 22; i++) 868 jj_la1[i] = -1; 869 for (int i = 0; i < jj_2_rtns.length; i++) 870 jj_2_rtns[i] = new JJCalls(); 871 } 872 873 private Token jj_consume_token(int kind) throws ParseException { 874 Token oldToken; 875 if ((oldToken = token).next != null) 876 token = token.next; 877 else 878 token = token.next = token_source.getNextToken(); 879 jj_ntk = -1; 880 if (token.kind == kind) { 881 jj_gen++; 882 if (++jj_gc > 100) { 883 jj_gc = 0; 884 for (int i = 0; i < jj_2_rtns.length; i++) { 885 JJCalls c = jj_2_rtns[i]; 886 while (c != null) { 887 if (c.gen < jj_gen) 888 c.first = null; 889 c = c.next; 890 } 891 } 892 } 893 return token; 894 } 895 token = oldToken; 896 jj_kind = kind; 897 throw generateParseException(); 898 } 899 900 @SuppressWarnings("serial") 901 static private final class LookaheadSuccess extends java.lang.Error { 902 } 903 904 final private LookaheadSuccess jj_ls = new LookaheadSuccess(); 905 906 private boolean jj_scan_token(int kind) { 907 if (jj_scanpos == jj_lastpos) { 908 jj_la--; 909 if (jj_scanpos.next == null) { 910 jj_lastpos = jj_scanpos = jj_scanpos.next = token_source 911 .getNextToken(); 912 } else { 913 jj_lastpos = jj_scanpos = jj_scanpos.next; 914 } 915 } else { 916 jj_scanpos = jj_scanpos.next; 917 } 918 if (jj_rescan) { 919 int i = 0; 920 Token tok = token; 921 while (tok != null && tok != jj_scanpos) { 922 i++; 923 tok = tok.next; 924 } 925 if (tok != null) 926 jj_add_error_token(kind, i); 927 } 928 if (jj_scanpos.kind != kind) 929 return true; 930 if (jj_la == 0 && jj_scanpos == jj_lastpos) 931 throw jj_ls; 932 return false; 933 } 934 935 /** Get the next Token. */ 936 final public Token getNextToken() { 937 if (token.next != null) 938 token = token.next; 939 else 940 token = token.next = token_source.getNextToken(); 941 jj_ntk = -1; 942 jj_gen++; 943 return token; 944 } 945 946 /** Get the specific Token. */ 947 final public Token getToken(int index) { 948 Token t = token; 949 for (int i = 0; i < index; i++) { 950 if (t.next != null) 951 t = t.next; 952 else 953 t = t.next = token_source.getNextToken(); 954 } 955 return t; 956 } 957 958 private int jj_ntk() { 959 if ((jj_nt = token.next) == null) 960 return (jj_ntk = (token.next = token_source.getNextToken()).kind); 961 else 962 return (jj_ntk = jj_nt.kind); 963 } 964 965 private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>(); 966 private int[] jj_expentry; 967 private int jj_kind = -1; 968 private int[] jj_lasttokens = new int[100]; 969 private int jj_endpos; 970 971 private void jj_add_error_token(int kind, int pos) { 972 if (pos >= 100) 973 return; 974 if (pos == jj_endpos + 1) { 975 jj_lasttokens[jj_endpos++] = kind; 976 } else if (jj_endpos != 0) { 977 jj_expentry = new int[jj_endpos]; 978 for (int i = 0; i < jj_endpos; i++) { 979 jj_expentry[i] = jj_lasttokens[i]; 980 } 981 jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries 982 .iterator(); it.hasNext();) { 983 int[] oldentry = (int[]) (it.next()); 984 if (oldentry.length == jj_expentry.length) { 985 for (int i = 0; i < jj_expentry.length; i++) { 986 if (oldentry[i] != jj_expentry[i]) { 987 continue jj_entries_loop; 988 } 989 } 990 jj_expentries.add(jj_expentry); 991 break jj_entries_loop; 992 } 993 } 994 if (pos != 0) 995 jj_lasttokens[(jj_endpos = pos) - 1] = kind; 996 } 997 } 998 999 /** Generate ParseException. */ 1000 public ParseException generateParseException() { 1001 jj_expentries.clear(); 1002 boolean[] la1tokens = new boolean[38]; 1003 if (jj_kind >= 0) { 1004 la1tokens[jj_kind] = true; 1005 jj_kind = -1; 1006 } 1007 for (int i = 0; i < 22; i++) { 1008 if (jj_la1[i] == jj_gen) { 1009 for (int j = 0; j < 32; j++) { 1010 if ((jj_la1_0[i] & (1 << j)) != 0) { 1011 la1tokens[j] = true; 1012 } 1013 if ((jj_la1_1[i] & (1 << j)) != 0) { 1014 la1tokens[32 + j] = true; 1015 } 1016 } 1017 } 1018 } 1019 for (int i = 0; i < 38; i++) { 1020 if (la1tokens[i]) { 1021 jj_expentry = new int[1]; 1022 jj_expentry[0] = i; 1023 jj_expentries.add(jj_expentry); 1024 } 1025 } 1026 jj_endpos = 0; 1027 jj_rescan_token(); 1028 jj_add_error_token(0, 0); 1029 int[][] exptokseq = new int[jj_expentries.size()][]; 1030 for (int i = 0; i < jj_expentries.size(); i++) { 1031 exptokseq[i] = jj_expentries.get(i); 1032 } 1033 return new ParseException(token, exptokseq, tokenImage); 1034 } 1035 1036 /** Enable tracing. */ 1037 final public void enable_tracing() { 1038 } 1039 1040 /** Disable tracing. */ 1041 final public void disable_tracing() { 1042 } 1043 1044 private void jj_rescan_token() { 1045 jj_rescan = true; 1046 for (int i = 0; i < 2; i++) { 1047 try { 1048 JJCalls p = jj_2_rtns[i]; 1049 do { 1050 if (p.gen > jj_gen) { 1051 jj_la = p.arg; 1052 jj_lastpos = jj_scanpos = p.first; 1053 switch (i) { 1054 case 0: 1055 jj_3_1(); 1056 break; 1057 case 1: 1058 jj_3_2(); 1059 break; 1060 } 1061 } 1062 p = p.next; 1063 } while (p != null); 1064 } catch (LookaheadSuccess ls) { 1065 } 1066 } 1067 jj_rescan = false; 1068 } 1069 1070 private void jj_save(int index, int xla) { 1071 JJCalls p = jj_2_rtns[index]; 1072 while (p.gen > jj_gen) { 1073 if (p.next == null) { 1074 p = p.next = new JJCalls(); 1075 break; 1076 } 1077 p = p.next; 1078 } 1079 p.gen = jj_gen + xla - jj_la; 1080 p.first = token; 1081 p.arg = xla; 1082 } 1083 1084 static final class JJCalls { 1085 int gen; 1086 Token first; 1087 int arg; 1088 JJCalls next; 1089 } 1090 1091}