1 2 package com.sun.java_cup.internal; 3 4 import java.util.Enumeration ; 5 import java.io.*; 6 7 66 67 public class Main { 68 69 70 71 72 74 private Main() { } 75 76 77 78 79 80 protected static boolean print_progress = true; 81 82 protected static boolean opt_dump_states = false; 83 84 protected static boolean opt_dump_tables = false; 85 86 protected static boolean opt_dump_grammar = false; 87 88 protected static boolean opt_show_timing = false; 89 90 protected static boolean opt_do_debug = false; 91 93 protected static boolean opt_compact_red = false; 94 96 protected static boolean include_non_terms = false; 97 98 protected static boolean no_summary = false; 99 100 protected static int expect_conflicts = 0; 101 102 103 104 protected static boolean lr_values = true; 105 106 107 protected static boolean sym_interface = false; 108 109 111 protected static boolean suppress_scanner = false; 112 113 114 115 116 117 protected static long start_time = 0; 118 119 protected static long prelim_end = 0; 120 121 protected static long parse_end = 0; 122 123 protected static long check_end = 0; 124 125 protected static long dump_end = 0; 126 127 protected static long build_end = 0; 128 129 protected static long nullability_end = 0; 130 131 protected static long first_end = 0; 132 133 protected static long machine_end = 0; 134 135 protected static long table_end = 0; 136 137 protected static long reduce_check_end = 0; 138 139 protected static long emit_end = 0; 140 141 protected static long final_time = 0; 142 143 144 145 146 147 148 149 152 public static void main(String argv[]) 153 throws internal_error, java.io.IOException , java.lang.Exception 154 { 155 boolean did_output = false; 156 157 start_time = System.currentTimeMillis(); 158 159 160 parse_args(argv); 161 162 164 emit.set_lr_values(lr_values); 165 166 if (print_progress) System.err.println("Opening files..."); 167 168 input_file = new BufferedInputStream(System.in); 169 170 prelim_end = System.currentTimeMillis(); 171 172 173 if (print_progress) 174 System.err.println("Parsing specification from standard input..."); 175 parse_grammar_spec(); 176 177 parse_end = System.currentTimeMillis(); 178 179 180 if (lexer.error_count == 0) 181 { 182 183 if (print_progress) System.err.println("Checking specification..."); 184 check_unused(); 185 186 check_end = System.currentTimeMillis(); 187 188 189 if (print_progress) System.err.println("Building parse tables..."); 190 build_parser(); 191 192 build_end = System.currentTimeMillis(); 193 194 195 if (lexer.error_count != 0) { 196 opt_dump_tables = false; 198 } else { if (print_progress) System.err.println("Writing parser..."); 200 open_files(); 201 emit_parser(); 202 did_output = true; 203 } 204 } 205 206 emit_end = System.currentTimeMillis(); 207 208 209 if (opt_dump_grammar) dump_grammar(); 210 if (opt_dump_states) dump_machine(); 211 if (opt_dump_tables) dump_tables(); 212 213 dump_end = System.currentTimeMillis(); 214 215 216 if (print_progress) System.err.println("Closing files..."); 217 close_files(); 218 219 220 if (!no_summary) emit_summary(did_output); 221 222 224 if (lexer.error_count != 0) 225 System.exit(100); 226 } 227 228 229 230 234 protected static void usage(String message) 235 { 236 System.err.println(); 237 System.err.println(message); 238 System.err.println(); 239 System.err.println( 240 "Usage: " + version.program_name + " [options]\n" + 241 " and expects a specification file on standard input.\n" + 242 " Legal options include:\n" + 243 " -package name specify package generated classes go in [default none]\n" + 244 " -parser name specify parser class name [default \"parser\"]\n" + 245 " -symbols name specify name for symbol constant class [default \"sym\"]\n"+ 246 " -interface put symbols in an interface, rather than a class\n" + 247 " -nonterms put non terminals in symbol constant class\n" + 248 " -expect # number of conflicts expected/allowed [default 0]\n" + 249 " -compact_red compact tables by defaulting to most frequent reduce\n" + 250 " -nowarn don't warn about useless productions, etc.\n" + 251 " -nosummary don't print the usual summary of parse states, etc.\n" + 252 " -nopositions don't propagate the left and right token position values\n" + 253 " -noscanner don't refer to com.sun.java_cup.internal.runtime.Scanner\n" + 254 " -progress print messages to indicate progress of the system\n" + 255 " -time print time usage summary\n" + 256 " -dump_grammar produce a human readable dump of the symbols and grammar\n"+ 257 " -dump_states produce a dump of parse state machine\n"+ 258 " -dump_tables produce a dump of the parse tables\n"+ 259 " -dump produce a dump of all of the above\n"+ 260 " -version print the version information for CUP and exit\n" 261 ); 262 System.exit(1); 263 } 264 265 266 267 271 protected static void parse_args(String argv[]) 272 { 273 int len = argv.length; 274 int i; 275 276 277 for (i=0; i<len; i++) 278 { 279 280 if (argv[i].equals("-package")) 281 { 282 283 if (++i >= len || argv[i].startsWith("-") || 284 argv[i].endsWith(".cup")) 285 usage("-package must have a name argument"); 286 287 288 emit.package_name = argv[i]; 289 } 290 else if (argv[i].equals("-parser")) 291 { 292 293 if (++i >= len || argv[i].startsWith("-") || 294 argv[i].endsWith(".cup")) 295 usage("-parser must have a name argument"); 296 297 298 emit.parser_class_name = argv[i]; 299 } 300 else if (argv[i].equals("-symbols")) 301 { 302 303 if (++i >= len || argv[i].startsWith("-") || 304 argv[i].endsWith(".cup")) 305 usage("-symbols must have a name argument"); 306 307 308 emit.symbol_const_class_name = argv[i]; 309 } 310 else if (argv[i].equals("-nonterms")) 311 { 312 include_non_terms = true; 313 } 314 else if (argv[i].equals("-expect")) 315 { 316 317 if (++i >= len || argv[i].startsWith("-") || 318 argv[i].endsWith(".cup")) 319 usage("-expect must have a name argument"); 320 321 322 try { 323 expect_conflicts = Integer.parseInt(argv[i]); 324 } catch (NumberFormatException e) { 325 usage("-expect must be followed by a decimal integer"); 326 } 327 } 328 else if (argv[i].equals("-compact_red")) opt_compact_red = true; 329 else if (argv[i].equals("-nosummary")) no_summary = true; 330 else if (argv[i].equals("-nowarn")) emit.nowarn = true; 331 else if (argv[i].equals("-dump_states")) opt_dump_states = true; 332 else if (argv[i].equals("-dump_tables")) opt_dump_tables = true; 333 else if (argv[i].equals("-progress")) print_progress = true; 334 else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true; 335 else if (argv[i].equals("-dump")) 336 opt_dump_states = opt_dump_tables = opt_dump_grammar = true; 337 else if (argv[i].equals("-time")) opt_show_timing = true; 338 else if (argv[i].equals("-debug")) opt_do_debug = true; 339 340 else if (argv[i].equals("-nopositions")) lr_values = false; 341 342 else if (argv[i].equals("-interface")) sym_interface = true; 343 344 else if (argv[i].equals("-noscanner")) suppress_scanner = true; 345 346 else if (argv[i].equals("-version")) { 347 System.out.println(version.title_str); 348 System.exit(1); 349 } 350 else 351 { 352 usage("Unrecognized option \"" + argv[i] + "\""); 353 } 354 } 355 } 356 357 358 359 360 361 362 363 364 protected static BufferedInputStream input_file; 365 366 367 protected static PrintWriter parser_class_file; 368 369 370 protected static PrintWriter symbol_class_file; 371 372 373 374 375 protected static void open_files() 376 { 377 File fil; 378 String out_name; 379 380 381 382 383 out_name = emit.parser_class_name + ".java"; 384 fil = new File(out_name); 385 try { 386 parser_class_file = new PrintWriter( 387 new BufferedOutputStream(new FileOutputStream(fil), 4096)); 388 } catch(Exception e) { 389 System.err.println("Can't open \"" + out_name + "\" for output"); 390 System.exit(3); 391 } 392 393 394 out_name = emit.symbol_const_class_name + ".java"; 395 fil = new File(out_name); 396 try { 397 symbol_class_file = new PrintWriter( 398 new BufferedOutputStream(new FileOutputStream(fil), 4096)); 399 } catch(Exception e) { 400 System.err.println("Can't open \"" + out_name + "\" for output"); 401 System.exit(4); 402 } 403 } 404 405 406 407 408 protected static void close_files() throws java.io.IOException 409 { 410 if (input_file != null) input_file.close(); 411 if (parser_class_file != null) parser_class_file.close(); 412 if (symbol_class_file != null) symbol_class_file.close(); 413 } 414 415 416 417 423 protected static void parse_grammar_spec() throws java.lang.Exception 424 { 425 parser parser_obj; 426 427 428 parser_obj = new parser(); 429 try { 430 if (opt_do_debug) 431 parser_obj.debug_parse(); 432 else 433 parser_obj.parse(); 434 } catch (Exception e) 435 { 436 438 lexer.emit_error("Internal error: Unexpected exception"); 439 throw e; 440 } 441 } 442 443 444 445 448 protected static void check_unused() 449 { 450 terminal term; 451 non_terminal nt; 452 453 454 for (Enumeration t = terminal.all(); t.hasMoreElements(); ) 455 { 456 term = (terminal)t.nextElement(); 457 458 459 if (term == terminal.EOF) continue; 460 461 462 if (term == terminal.error) continue; 463 464 465 if (term.use_count() == 0) 466 { 467 468 emit.unused_term++; 469 if (!emit.nowarn) 470 { 471 System.err.println("Warning: Terminal \"" + term.name() + 472 "\" was declared but never used"); 473 lexer.warning_count++; 474 } 475 } 476 } 477 478 479 for (Enumeration n = non_terminal.all(); n.hasMoreElements(); ) 480 { 481 nt = (non_terminal)n.nextElement(); 482 483 484 if (nt.use_count() == 0) 485 { 486 487 emit.unused_term++; 488 if (!emit.nowarn) 489 { 490 System.err.println("Warning: Non terminal \"" + nt.name() + 491 "\" was declared but never used"); 492 lexer.warning_count++; 493 } 494 } 495 } 496 497 } 498 499 500 501 502 503 504 protected static lalr_state start_state; 505 506 507 protected static parse_action_table action_table; 508 509 510 protected static parse_reduce_table reduce_table; 511 512 513 514 523 protected static void build_parser() throws internal_error 524 { 525 526 if (opt_do_debug || print_progress) 527 System.err.println(" Computing non-terminal nullability..."); 528 non_terminal.compute_nullability(); 529 530 nullability_end = System.currentTimeMillis(); 531 532 533 if (opt_do_debug || print_progress) 534 System.err.println(" Computing first sets..."); 535 non_terminal.compute_first_sets(); 536 537 first_end = System.currentTimeMillis(); 538 539 540 if (opt_do_debug || print_progress) 541 System.err.println(" Building state machine..."); 542 start_state = lalr_state.build_machine(emit.start_production); 543 544 machine_end = System.currentTimeMillis(); 545 546 547 if (opt_do_debug || print_progress) 548 System.err.println(" Filling in tables..."); 549 action_table = new parse_action_table(); 550 reduce_table = new parse_reduce_table(); 551 for (Enumeration st = lalr_state.all(); st.hasMoreElements(); ) 552 { 553 lalr_state lst = (lalr_state)st.nextElement(); 554 lst.build_table_entries( 555 action_table, reduce_table); 556 } 557 558 table_end = System.currentTimeMillis(); 559 560 561 if (opt_do_debug || print_progress) 562 System.err.println(" Checking for non-reduced productions..."); 563 action_table.check_reductions(); 564 565 reduce_check_end = System.currentTimeMillis(); 566 567 568 if (emit.num_conflicts > expect_conflicts) 569 { 570 System.err.println("*** More conflicts encountered than expected " + 571 "-- parser generation aborted"); 572 lexer.error_count++; } 575 } 576 577 578 579 580 protected static void emit_parser() throws internal_error 581 { 582 emit.symbols(symbol_class_file, include_non_terms, sym_interface); 583 emit.parser(parser_class_file, action_table, reduce_table, 584 start_state.index(), emit.start_production, opt_compact_red, 585 suppress_scanner); 586 } 587 588 589 590 593 protected static String plural(int val) 594 { 595 if (val == 1) 596 return ""; 597 else 598 return "s"; 599 } 600 601 602 603 609 protected static void emit_summary(boolean output_produced) 610 { 611 final_time = System.currentTimeMillis(); 612 613 if (no_summary) return; 614 615 System.err.println("------- " + version.title_str + 616 " Parser Generation Summary -------"); 617 618 619 System.err.println(" " + lexer.error_count + " error" + 620 plural(lexer.error_count) + " and " + lexer.warning_count + 621 " warning" + plural(lexer.warning_count)); 622 623 624 System.err.print(" " + terminal.number() + " terminal" + 625 plural(terminal.number()) + ", "); 626 System.err.print(non_terminal.number() + " non-terminal" + 627 plural(non_terminal.number()) + ", and "); 628 System.err.println(production.number() + " production" + 629 plural(production.number()) + " declared, "); 630 System.err.println(" producing " + lalr_state.number() + 631 " unique parse states."); 632 633 634 System.err.println(" " + emit.unused_term + " terminal" + 635 plural(emit.unused_term) + " declared but not used."); 636 System.err.println(" " + emit.unused_non_term + " non-terminal" + 637 plural(emit.unused_term) + " declared but not used."); 638 639 640 System.err.println(" " + emit.not_reduced + " production" + 641 plural(emit.not_reduced) + " never reduced."); 642 643 644 System.err.println(" " + emit.num_conflicts + " conflict" + 645 plural(emit.num_conflicts) + " detected" + 646 " (" + expect_conflicts + " expected)."); 647 648 649 if (output_produced) 650 System.err.println(" Code written to \"" + emit.parser_class_name + 651 ".java\", and \"" + emit.symbol_const_class_name + ".java\"."); 652 else 653 System.err.println(" No code produced."); 654 655 if (opt_show_timing) show_times(); 656 657 System.err.println( 658 "---------------------------------------------------- (" + 659 version.version_str + ")"); 660 } 661 662 663 664 665 protected static void show_times() 666 { 667 long total_time = final_time - start_time; 668 669 System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . "); 670 System.err.println(" Timing Summary"); 671 System.err.println(" Total time " 672 + timestr(final_time-start_time, total_time)); 673 System.err.println(" Startup " 674 + timestr(prelim_end-start_time, total_time)); 675 System.err.println(" Parse " 676 + timestr(parse_end-prelim_end, total_time) ); 677 if (check_end != 0) 678 System.err.println(" Checking " 679 + timestr(check_end-parse_end, total_time)); 680 if (check_end != 0 && build_end != 0) 681 System.err.println(" Parser Build " 682 + timestr(build_end-check_end, total_time)); 683 if (nullability_end != 0 && check_end != 0) 684 System.err.println(" Nullability " 685 + timestr(nullability_end-check_end, total_time)); 686 if (first_end != 0 && nullability_end != 0) 687 System.err.println(" First sets " 688 + timestr(first_end-nullability_end, total_time)); 689 if (machine_end != 0 && first_end != 0) 690 System.err.println(" State build " 691 + timestr(machine_end-first_end, total_time)); 692 if (table_end != 0 && machine_end != 0) 693 System.err.println(" Table build " 694 + timestr(table_end-machine_end, total_time)); 695 if (reduce_check_end != 0 && table_end != 0) 696 System.err.println(" Checking " 697 + timestr(reduce_check_end-table_end, total_time)); 698 if (emit_end != 0 && build_end != 0) 699 System.err.println(" Code Output " 700 + timestr(emit_end-build_end, total_time)); 701 if (emit.symbols_time != 0) 702 System.err.println(" Symbols " 703 + timestr(emit.symbols_time, total_time)); 704 if (emit.parser_time != 0) 705 System.err.println(" Parser class " 706 + timestr(emit.parser_time, total_time)); 707 if (emit.action_code_time != 0) 708 System.err.println(" Actions " 709 + timestr(emit.action_code_time, total_time)); 710 if (emit.production_table_time != 0) 711 System.err.println(" Prod table " 712 + timestr(emit.production_table_time, total_time)); 713 if (emit.action_table_time != 0) 714 System.err.println(" Action tab " 715 + timestr(emit.action_table_time, total_time)); 716 if (emit.goto_table_time != 0) 717 System.err.println(" Reduce tab " 718 + timestr(emit.goto_table_time, total_time)); 719 720 System.err.println(" Dump Output " 721 + timestr(dump_end-emit_end, total_time)); 722 } 723 724 725 726 733 protected static String timestr(long time_val, long total_time) 734 { 735 boolean neg; 736 long ms = 0; 737 long sec = 0; 738 long percent10; 739 String pad; 740 741 742 neg = time_val < 0; 743 if (neg) time_val = -time_val; 744 745 746 ms = time_val % 1000; 747 sec = time_val / 1000; 748 749 750 if (sec < 10) 751 pad = " "; 752 else if (sec < 100) 753 pad = " "; 754 else if (sec < 1000) 755 pad = " "; 756 else 757 pad = ""; 758 759 760 percent10 = (time_val*1000)/total_time; 761 762 763 return (neg ? "-" : "") + pad + sec + "." + 764 ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" + 765 " (" + percent10/10 + "." + percent10%10 + "%)"; 766 } 767 768 769 770 771 public static void dump_grammar() throws internal_error 772 { 773 System.err.println("===== Terminals ====="); 774 for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++) 775 { 776 System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" "); 777 if ((cnt+1) % 5 == 0) System.err.println(); 778 } 779 System.err.println(); 780 System.err.println(); 781 782 System.err.println("===== Non terminals ====="); 783 for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++) 784 { 785 System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" "); 786 if ((cnt+1) % 5 == 0) System.err.println(); 787 } 788 System.err.println(); 789 System.err.println(); 790 791 792 System.err.println("===== Productions ====="); 793 for (int pidx=0; pidx < production.number(); pidx++) 794 { 795 production prod = production.find(pidx); 796 System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= "); 797 for (int i=0; i<prod.rhs_length(); i++) 798 if (prod.rhs(i).is_action()) 799 System.err.print("{action} "); 800 else 801 System.err.print( 802 ((symbol_part)prod.rhs(i)).the_symbol().name() + " "); 803 System.err.println(); 804 } 805 System.err.println(); 806 } 807 808 809 810 813 public static void dump_machine() 814 { 815 lalr_state ordered[] = new lalr_state[lalr_state.number()]; 816 817 818 for (Enumeration s = lalr_state.all(); s.hasMoreElements(); ) 819 { 820 lalr_state st = (lalr_state)s.nextElement(); 821 ordered[st.index()] = st; 822 } 823 824 System.err.println("===== Viable Prefix Recognizer ====="); 825 for (int i = 0; i<lalr_state.number(); i++) 826 { 827 if (ordered[i] == start_state) System.err.print("START "); 828 System.err.println(ordered[i]); 829 System.err.println("-------------------"); 830 } 831 } 832 833 834 835 836 public static void dump_tables() 837 { 838 System.err.println(action_table); 839 System.err.println(reduce_table); 840 } 841 842 843 844 } 845 846 | Popular Tags |