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