| | +/************************************************************** |
| | + JLex: A Lexical Analyzer Generator for Java(TM) |
| | + Written by Elliot Berk <ejberk@cs.princeton.edu>. Copyright 1996. |
| | + Maintained by C. Scott Ananian <cananian@alumni.princeton.edu>. |
| | + See below for copyright notice, license, and disclaimer. |
| | + New releases from http://www.cs.princeton.edu/~appel/modern/java/JLex/ |
| | + |
| | + Version 1.2.6, 2/7/03, [C. Scott Ananian] |
| | + Renamed 'assert' function 'ASSERT' to accomodate Java 1.4's new keyword. |
| | + Fixed a bug which certain forms of comment in the JLex directives section |
| | + (which are not allowed) to be incorrectly parsed as macro definitions. |
| | + Version 1.2.5, 7/25/99-5/16/00, [C. Scott Ananian] |
| | + Stomped on one more 8-bit character bug. Should work now (really!). |
| | + Added unicode support, including unicode escape sequences. |
| | + Rewrote internal JavaLexBitSet class as SparseBitSet for efficient |
| | + unicoding. |
| | + Added an NFA character class simplification pass for unicode efficiency. |
| | + Changed byte- and stream-oriented I/O routines to use characters and |
| | + java.io.Reader and java.io.Writer instead --- which means we read in |
| | + unicode specifications correctly and write out a proper unicode java |
| | + source file. As a happy side-effect, the output java file is written |
| | + with your platform's preferred newline character(s). |
| | + Rewrote CInput to fix bugs with line-counting in the specification file |
| | + and "unusual behaviour" when the last line of the specification wasn't |
| | + terminated with a newline. Thanks to Matt Hanna <mhanna@cs.caltech.edu> |
| | + for pointing out the bug. |
| | + Fixed a bug that would cause JLex not to terminate given certain input |
| | + specifications. Thanks to Mark Greenstreet <mrg@cs.ubc.ca> and |
| | + Frank B. Brokken <frank@suffix.icce.rug.nl> for reporting this. |
| | + CUP parser integration improved according to suggestions made by |
| | + David MacMahon <davidm@smartsc.com>. The %cup directive now tells |
| | + JLex to generate a parser conforming to the java_cup.runtime.Scanner |
| | + interface; see manual for more details. |
| | + Fixed bug with null string literals ("") in regexps. Reported by |
| | + Charles Fischer <fischer@cs.wisc.edu>. |
| | + Rewrote start-of-line and end-of-line handling, closing active bug #5. |
| | + Also fixed line-counting code, closing active bug #12. All |
| | + new-line handling is now platform-independent. |
| | + Used unpackFromString more extensively to allow larger cmap, etc, |
| | + tables. This helps unicode support work reliably. It's also |
| | + prettier now if you happen to read the source to the generated |
| | + lexer. |
| | + Generated lexer now accepts unicode LS (U+2028) and PS (U+2029) as |
| | + line separators for strict unicode compliance; see |
| | + http://www.unicode.org/unicode/reports/tr18/ |
| | + Fixed bug with character constants in action strings. Reported by |
| | + Andrew Appel against 1.2.5b3. |
| | + Fixed bug with illegal \^C-style escape sequences. Reported by |
| | + Toshiya Iwai <iwai@isdnet.co.jp> against 1.2.5b4. |
| | + Fixed "newline in quoted string" error when unpaired single- or |
| | + double-quotes were present in comments in the action phrase. |
| | + Reported by Stephen Ostermiller <1010JLex@ostermiller.com> |
| | + against 1.2.5b4. Reported by Eric Esposito <eric.esposito@unh.edu> |
| | + against 1.2.4 and 1.2.5b2. |
| | + Fixed "newline in quoted string" error when /* or // appeared |
| | + in quoted strings in the action phrase. Reported by |
| | + David Eichmann <david-eichmann@uiowa.edu> against 1.2.5b5. |
| | + Fixed 'illegal constant' errors in case statements caused by |
| | + Sun's JDK 1.3 more closely adhering to the Java Language |
| | + Specification. Reported by a number of people, but |
| | + Harold Grovesteen <hgrovesteen@home.com> was the first to direct me to |
| | + a Sun bug report (4119776) which quoted the relevant section of the |
| | + JLS (15.27) to convince me that the JLex construction actually was |
| | + illegal. Reported against 1.2.5b6, but this bit of code has been |
| | + present since the very first version of JLex (1.1.1). |
| | + |
| | + Version 1.2.4, 7/24/99, [C. Scott Ananian] |
| | + Correct the parsing of '-' in character classes, closing active |
| | + bug #1. Behaviour follows egrep: leading and trailing dashes in |
| | + a character class lose their special meaning, so [-+] and [+-] do |
| | + what you would expect them to. |
| | + New %ignorecase directive for generating case-insensitive lexers by |
| | + expanding matched character classes in a unicode-friendly way. |
| | + Handle unmatched braces in quoted strings or comments within |
| | + action code blocks. |
| | + Fixed input lexer to allow whitespace in character classes, closing |
| | + active bug #9. Whitespace in quotes had been previously fixed. |
| | + Made Yylex.YYEOF and %yyeof work like the manual says they should. |
| | + |
| | + Version 1.2.3, 6/26/97, [Raimondas Lencevicius] |
| | + Fixed the yy_nxt[][] assignment that has generated huge code |
| | + exceeding 64K method size limit. Now the assignment |
| | + is handled by unpacking a string encoding of integer array. |
| | + To achieve that, added |
| | + "private int [][] unpackFromString(int size1, int size2, String st)" |
| | + function and coded the yy_nxt[][] values into a string |
| | + by printing integers into a string and representing |
| | + integer sequences as "value:length" pairs. |
| | + Improvement: generated .java file reduced 2 times, .class file |
| | + reduced 6 times for sample grammar. No 64K errors. |
| | + Possible negatives: Some editors and OSs may not be able to handle |
| | + the huge one-line generated string. String unpacking may be slower |
| | + than direct array initialization. |
| | + |
| | + Version 1.2.2, 10/24/97, [Martin Dirichs] |
| | + Notes: |
| | + Changed yy_instream to yy_reader of type BufferedReader. This reflects |
| | + the improvements in the JDK 1.1 concerning InputStreams. As a |
| | + consequence, changed yy_buffer from byte[] to char[]. |
| | + The lexer can now be initialized with either an InputStream |
| | + or a Reader. A third, private constructor is called by the other |
| | + two to execute user specified constructor code. |
| | + |
| | + Version 1.2.1, 9/15/97 [A. Appel] |
| | + Fixed bugs 6 (character codes > 127) and 10 (deprecated String constructor). |
| | + |
| | + Version 1.2, 5/5/97, [Elliot Berk] |
| | + Notes: |
| | + Simply changed the name from JavaLex to JLex. No other changes. |
| | + |
| | + Version 1.1.5, 2/25/97, [Elliot Berk] |
| | + Notes: |
| | + Simple optimization to the creation of the source files. |
| | + Added a BufferedOutputStream in the creation of the DataOutputStream |
| | + field m_outstream of the class CLexGen. This helps performance by |
| | + doing some buffering, and was suggested by Max Hailperin, |
| | + Associate Professor of Computer Science, Gustavus Adolphus College. |
| | + |
| | + Version 1.1.4, 12/12/96, [Elliot Berk] |
| | + Notes: |
| | + Added %public directive to make generated class public. |
| | + |
| | + Version 1.1.3, 12/11/96, [Elliot Berk] |
| | + Notes: |
| | + Converted assertion failure on invalid character class |
| | + when a dash '-' is not preceded with a start-of-range character. |
| | + Converted this into parse error E_DASH. |
| | + |
| | + Version 1.1.2, October 30, 1996 [Elliot Berk] |
| | + Fixed BitSet bugs by installing a BitSet class of my own, |
| | + called JavaLexBitSet. Fixed support for '\r', non-UNIX |
| | + sequences. Added try/catch block around lexer generation |
| | + in main routine to moderate error information presented |
| | + to user. Fixed macro expansion, so that macros following |
| | + quotes are expanded correctly in regular expressions. |
| | + Fixed dynamic reallocation of accept action buffers. |
| | + |
| | + Version 1.1.1, September 3, 1996 [Andrew Appel] |
| | + Made the class "Main" instead of "JavaLex", |
| | + improved the installation instructions to reflect this. |
| | + |
| | + Version 1.1, August 15, 1996 [Andrew Appel] |
| | + Made yychar, yyline, yytext global to the lexer so that |
| | + auxiliary functions can access them. |
| | + **************************************************************/ |
| | + |
| | +/*************************************************************** |
| | + JLEX COPYRIGHT NOTICE, LICENSE, AND DISCLAIMER |
| | + Copyright 1996-2000 by Elliot Joel Berk and C. Scott Ananian |
| | + |
| | + Permission to use, copy, modify, and distribute this software and its |
| | + documentation for any purpose and without fee is hereby granted, |
| | + provided that the above copyright notice appear in all copies and that |
| | + both the copyright notice and this permission notice and warranty |
| | + disclaimer appear in supporting documentation, and that the name of |
| | + the authors or their employers not be used in advertising or publicity |
| | + pertaining to distribution of the software without specific, written |
| | + prior permission. |
| | + |
| | + The authors and their employers disclaim all warranties with regard to |
| | + this software, including all implied warranties of merchantability and |
| | + fitness. In no event shall the authors or their employers be liable |
| | + for any special, indirect or consequential damages or any damages |
| | + whatsoever resulting from loss of use, data or profits, whether in an |
| | + action of contract, negligence or other tortious action, arising out |
| | + of or in connection with the use or performance of this software. |
| | + **************************************************************/ |
| | + |
| | +/*************************************************************** |
| | + Package Declaration |
| | + **************************************************************/ |
| | +package JLex; |
| | + |
| | +/*************************************************************** |
| | + Imported Packages |
| | + **************************************************************/ |
| | +import java.lang.System; |
| | +import java.lang.Integer; |
| | +import java.lang.Character; |
| | + |
| | +import java.util.Enumeration; |
| | +import java.util.Stack; |
| | +import java.util.Hashtable; |
| | +import java.util.Vector; |
| | + |
| | +/****************************** |
| | + Questions: |
| | + 2) How should I use the Java package system |
| | + to make my tool more modularized and |
| | + coherent? |
| | + |
| | + Unimplemented: |
| | + !) Fix BitSet issues -- expand only when necessary. |
| | + 2) Repeated accept rules. |
| | + 6) Clean up the CAlloc class and use buffered |
| | + allocation. |
| | + 9) Add to spec about extending character set. |
| | + 11) m_verbose -- what should be done with it? |
| | + 12) turn lexical analyzer into a coherent |
| | + Java package |
| | + 13) turn lexical analyzer generator into a |
| | + coherent Java package |
| | + 16) pretty up generated code |
| | + 17) make it possible to have white space in |
| | + regular expressions |
| | + 18) clean up all of the class files the lexer |
| | + generator produces when it is compiled, |
| | + and reduce this number in some way. |
| | + 24) character format to and from file: writeup |
| | + and implementation |
| | + 25) Debug by testing all arcane regular expression cases. |
| | + 26) Look for and fix all UNDONE comments below. |
| | + 27) Fix package system. |
| | + 28) Clean up unnecessary classes. |
| | + *****************************/ |
| | + |
| | +/*************************************************************** |
| | + Class: CSpec |
| | + **************************************************************/ |
| | +class CSpec |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + |
| | + /* Lexical States. */ |
| | + Hashtable m_states; /* Hashtable taking state indices (Integer) |
| | + to state name (String). */ |
| | + |
| | + /* Regular Expression Macros. */ |
| | + Hashtable m_macros; /* Hashtable taking macro name (String) |
| | + to corresponding char buffer that |
| | + holds macro definition. */ |
| | + |
| | + /* NFA Machine. */ |
| | + CNfa m_nfa_start; /* Start state of NFA machine. */ |
| | + Vector m_nfa_states; /* Vector of states, with index |
| | + corresponding to label. */ |
| | + |
| | + Vector m_state_rules[]; /* An array of Vectors of Integers. |
| | + The ith Vector represents the lexical state |
| | + with index i. The contents of the ith |
| | + Vector are the indices of the NFA start |
| | + states that can be matched while in |
| | + the ith lexical state. */ |
| | + |
| | + |
| | + int m_state_dtrans[]; |
| | + |
| | + /* DFA Machine. */ |
| | + Vector m_dfa_states; /* Vector of states, with index |
| | + corresponding to label. */ |
| | + Hashtable m_dfa_sets; /* Hashtable taking set of NFA states |
| | + to corresponding DFA state, |
| | + if the latter exists. */ |
| | + |
| | + /* Accept States and Corresponding Anchors. */ |
| | + Vector m_accept_vector; |
| | + int m_anchor_array[]; |
| | + |
| | + /* Transition Table. */ |
| | + Vector m_dtrans_vector; |
| | + int m_dtrans_ncols; |
| | + int m_row_map[]; |
| | + int m_col_map[]; |
| | + |
| | + /* Special pseudo-characters for beginning-of-line and end-of-file. */ |
| | + static final int NUM_PSEUDO=2; |
| | + int BOL; // beginning-of-line |
| | + int EOF; // end-of-line |
| | + |
| | + /** NFA character class minimization map. */ |
| | + int m_ccls_map[]; |
| | + |
| | + /* Regular expression token variables. */ |
| | + int m_current_token; |
| | + char m_lexeme; |
| | + boolean m_in_quote; |
| | + boolean m_in_ccl; |
| | + |
| | + /* Verbose execution flag. */ |
| | + boolean m_verbose; |
| | + |
| | + /* JLex directives flags. */ |
| | + boolean m_integer_type; |
| | + boolean m_intwrap_type; |
| | + boolean m_yyeof; |
| | + boolean m_count_chars; |
| | + boolean m_count_lines; |
| | + boolean m_cup_compatible; |
| | + boolean m_unix; |
| | + boolean m_public; |
| | + boolean m_ignorecase; |
| | + |
| | + char m_init_code[]; |
| | + int m_init_read; |
| | + |
| | + char m_init_throw_code[]; |
| | + int m_init_throw_read; |
| | + |
| | + char m_class_code[]; |
| | + int m_class_read; |
| | + |
| | + char m_eof_code[]; |
| | + int m_eof_read; |
| | + |
| | + char m_eof_value_code[]; |
| | + int m_eof_value_read; |
| | + |
| | + char m_eof_throw_code[]; |
| | + int m_eof_throw_read; |
| | + |
| | + char m_yylex_throw_code[]; |
| | + int m_yylex_throw_read; |
| | + |
| | + /* Class, function, type names. */ |
| | + char m_class_name[] = { |
| | + 'Y', 'y', 'l', |
| | + 'e', 'x' |
| | + }; |
| | + char m_implements_name[] = {}; |
| | + char m_function_name[] = { |
| | + 'y', 'y', 'l', |
| | + 'e', 'x' |
| | + }; |
| | + char m_type_name[] = { |
| | + 'Y', 'y', 't', |
| | + 'o', 'k', 'e', |
| | + 'n' |
| | + }; |
| | + |
| | + /* Lexical Generator. */ |
| | + private CLexGen m_lexGen; |
| | + |
| | + /*************************************************************** |
| | + Constants |
| | + ***********************************************************/ |
| | + static final int NONE = 0; |
| | + static final int START = 1; |
| | + static final int END = 2; |
| | + |
| | + /*************************************************************** |
| | + Function: CSpec |
| | + Description: Constructor. |
| | + **************************************************************/ |
| | + CSpec |
| | + ( |
| | + CLexGen lexGen |
| | + ) |
| | + { |
| | + m_lexGen = lexGen; |
| | + |
| | + /* Initialize regular expression token variables. */ |
| | + m_current_token = m_lexGen.EOS; |
| | + m_lexeme = '\0'; |
| | + m_in_quote = false; |
| | + m_in_ccl = false; |
| | + |
| | + /* Initialize hashtable for lexer states. */ |
| | + m_states = new Hashtable(); |
| | + m_states.put(new String("YYINITIAL"),new Integer(m_states.size())); |
| | + |
| | + /* Initialize hashtable for lexical macros. */ |
| | + m_macros = new Hashtable(); |
| | + |
| | + /* Initialize variables for lexer options. */ |
| | + m_integer_type = false; |
| | + m_intwrap_type = false; |
| | + m_count_lines = false; |
| | + m_count_chars = false; |
| | + m_cup_compatible = false; |
| | + m_unix = true; |
| | + m_public = false; |
| | + m_yyeof = false; |
| | + m_ignorecase = false; |
| | + |
| | + /* Initialize variables for JLex runtime options. */ |
| | + m_verbose = true; |
| | + |
| | + m_nfa_start = null; |
| | + m_nfa_states = new Vector(); |
| | + |
| | + m_dfa_states = new Vector(); |
| | + m_dfa_sets = new Hashtable(); |
| | + |
| | + m_dtrans_vector = new Vector(); |
| | + m_dtrans_ncols = CUtility.MAX_SEVEN_BIT + 1; |
| | + m_row_map = null; |
| | + m_col_map = null; |
| | + |
| | + m_accept_vector = null; |
| | + m_anchor_array = null; |
| | + |
| | + m_init_code = null; |
| | + m_init_read = 0; |
| | + |
| | + m_init_throw_code = null; |
| | + m_init_throw_read = 0; |
| | + |
| | + m_yylex_throw_code = null; |
| | + m_yylex_throw_read = 0; |
| | + |
| | + m_class_code = null; |
| | + m_class_read = 0; |
| | + |
| | + m_eof_code = null; |
| | + m_eof_read = 0; |
| | + |
| | + m_eof_value_code = null; |
| | + m_eof_value_read = 0; |
| | + |
| | + m_eof_throw_code = null; |
| | + m_eof_throw_read = 0; |
| | + |
| | + m_state_dtrans = null; |
| | + |
| | + m_state_rules = null; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CEmit |
| | + **************************************************************/ |
| | +class CEmit |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + private CSpec m_spec; |
| | + private java.io.PrintWriter m_outstream; |
| | + |
| | + /*************************************************************** |
| | + Constants: Anchor Types |
| | + **************************************************************/ |
| | + private final int START = 1; |
| | + private final int END = 2; |
| | + private final int NONE = 4; |
| | + |
| | + /*************************************************************** |
| | + Constants |
| | + **************************************************************/ |
| | + private final boolean EDBG = true; |
| | + private final boolean NOT_EDBG = false; |
| | + |
| | + /*************************************************************** |
| | + Function: CEmit |
| | + Description: Constructor. |
| | + **************************************************************/ |
| | + CEmit |
| | + ( |
| | + ) |
| | + { |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: reset |
| | + Description: Clears member variables. |
| | + **************************************************************/ |
| | + private void reset |
| | + ( |
| | + ) |
| | + { |
| | + m_spec = null; |
| | + m_outstream = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: set |
| | + Description: Initializes member variables. |
| | + **************************************************************/ |
| | + private void set |
| | + ( |
| | + CSpec spec, |
| | + java.io.PrintWriter outstream |
| | + ) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != spec); |
| | + CUtility.ASSERT(null != outstream); |
| | + } |
| | + |
| | + m_spec = spec; |
| | + m_outstream = outstream; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_imports |
| | + Description: Emits import packages at top of |
| | + generated source file. |
| | + **************************************************************/ |
| | + /*void emit_imports |
| | + ( |
| | + CSpec spec, |
| | + OutputStream outstream |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + set(spec,outstream); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + }*/ |
| | + |
| | + /*m_outstream.println("import java.lang.String;"); |
| | + m_outstream.println("import java.lang.System;"); |
| | + m_outstream.println("import java.io.BufferedReader;"); |
| | + m_outstream.println("import java.io.InputStream;");*/ |
| | + /* |
| | + reset(); |
| | + }*/ |
| | + |
| | + /*************************************************************** |
| | + Function: print_details |
| | + Description: Debugging output. |
| | + **************************************************************/ |
| | + private void print_details |
| | + ( |
| | + ) |
| | + { |
| | + int i; |
| | + int j; |
| | + int next; |
| | + int state; |
| | + CDTrans dtrans; |
| | + CAccept accept; |
| | + boolean tr; |
| | + |
| | + System.out.println("---------------------- Transition Table " |
| | + + "----------------------"); |
| | + |
| | + for (i = 0; i < m_spec.m_row_map.length; ++i) |
| | + { |
| | + System.out.print("State " + i); |
| | + |
| | + accept = (CAccept) m_spec.m_accept_vector.elementAt(i); |
| | + if (null == accept) |
| | + { |
| | + System.out.println(" [nonaccepting]"); |
| | + } |
| | + else |
| | + { |
| | + System.out.println(" [accepting, line " |
| | + + accept.m_line_number |
| | + + " <" |
| | + + (new java.lang.String(accept.m_action,0, |
| | + accept.m_action_read)) |
| | + + ">]"); |
| | + } |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(m_spec.m_row_map[i]); |
| | + |
| | + tr = false; |
| | + state = dtrans.m_dtrans[m_spec.m_col_map[0]]; |
| | + if (CDTrans.F != state) |
| | + { |
| | + tr = true; |
| | + System.out.print("\tgoto " + state + " on [" + ((char) 0)); |
| | + } |
| | + for (j = 1; j < m_spec.m_dtrans_ncols; ++j) |
| | + { |
| | + next = dtrans.m_dtrans[m_spec.m_col_map[j]]; |
| | + if (state == next) |
| | + { |
| | + if (CDTrans.F != state) |
| | + { |
| | + System.out.print((char) j); |
| | + } |
| | + } |
| | + else |
| | + { |
| | + state = next; |
| | + if (tr) |
| | + { |
| | + System.out.println("]"); |
| | + tr = false; |
| | + } |
| | + if (CDTrans.F != state) |
| | + { |
| | + tr = true; |
| | + System.out.print("\tgoto " + state + " on [" + ((char) j)); |
| | + } |
| | + } |
| | + } |
| | + if (tr) |
| | + { |
| | + System.out.println("]"); |
| | + } |
| | + } |
| | + |
| | + System.out.println("---------------------- Transition Table " |
| | + + "----------------------"); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit |
| | + Description: High-level access function to module. |
| | + **************************************************************/ |
| | + void emit |
| | + ( |
| | + CSpec spec, |
| | + java.io.PrintWriter outstream |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + set(spec,outstream); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + if (CUtility.OLD_DEBUG) { |
| | + print_details(); |
| | + } |
| | + |
| | + emit_header(); |
| | + emit_construct(); |
| | + emit_helpers(); |
| | + emit_driver(); |
| | + emit_footer(); |
| | + |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_construct |
| | + Description: Emits constructor, member variables, |
| | + and constants. |
| | + **************************************************************/ |
| | + private void emit_construct |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + /* Constants */ |
| | + m_outstream.println("\tprivate final int YY_BUFFER_SIZE = 512;"); |
| | + |
| | + m_outstream.println("\tprivate final int YY_F = -1;"); |
| | + m_outstream.println("\tprivate final int YY_NO_STATE = -1;"); |
| | + |
| | + m_outstream.println("\tprivate final int YY_NOT_ACCEPT = 0;"); |
| | + m_outstream.println("\tprivate final int YY_START = 1;"); |
| | + m_outstream.println("\tprivate final int YY_END = 2;"); |
| | + m_outstream.println("\tprivate final int YY_NO_ANCHOR = 4;"); |
| | + |
| | + // internal |
| | + m_outstream.println("\tprivate final int YY_BOL = "+m_spec.BOL+";"); |
| | + m_outstream.println("\tprivate final int YY_EOF = "+m_spec.EOF+";"); |
| | + // external |
| | + if (m_spec.m_integer_type || true == m_spec.m_yyeof) |
| | + m_outstream.println("\tpublic final int YYEOF = -1;"); |
| | + |
| | + /* User specified class code. */ |
| | + if (null != m_spec.m_class_code) |
| | + { |
| | + m_outstream.print(new String(m_spec.m_class_code,0, |
| | + m_spec.m_class_read)); |
| | + } |
| | + |
| | + /* Member Variables */ |
| | + m_outstream.println("\tprivate java.io.BufferedReader yy_reader;"); |
| | + m_outstream.println("\tprivate int yy_buffer_index;"); |
| | + m_outstream.println("\tprivate int yy_buffer_read;"); |
| | + m_outstream.println("\tprivate int yy_buffer_start;"); |
| | + m_outstream.println("\tprivate int yy_buffer_end;"); |
| | + m_outstream.println("\tprivate char yy_buffer[];"); |
| | + if (m_spec.m_count_chars) |
| | + { |
| | + m_outstream.println("\tprivate int yychar;"); |
| | + } |
| | + if (m_spec.m_count_lines) |
| | + { |
| | + m_outstream.println("\tprivate int yyline;"); |
| | + } |
| | + m_outstream.println("\tprivate boolean yy_at_bol;"); |
| | + m_outstream.println("\tprivate int yy_lexical_state;"); |
| | + /*if (m_spec.m_count_lines || true == m_spec.m_count_chars) |
| | + { |
| | + m_outstream.println("\tprivate int yy_buffer_prev_start;"); |
| | + }*/ |
| | + m_outstream.println(); |
| | + |
| | + |
| | + /* Function: first constructor (Reader) */ |
| | + m_outstream.print("\t"); |
| | + if (true == m_spec.m_public) { |
| | + m_outstream.print("public "); |
| | + } |
| | + m_outstream.print(new String(m_spec.m_class_name)); |
| | + m_outstream.print(" (java.io.Reader reader)"); |
| | + |
| | + if (null != m_spec.m_init_throw_code) |
| | + { |
| | + m_outstream.println(); |
| | + m_outstream.print("\t\tthrows "); |
| | + m_outstream.print(new String(m_spec.m_init_throw_code,0, |
| | + m_spec.m_init_throw_read)); |
| | + m_outstream.println(); |
| | + m_outstream.println("\t\t{"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + m_outstream.println("\t\tthis ();"); |
| | + m_outstream.println("\t\tif (null == reader) {"); |
| | + m_outstream.println("\t\t\tthrow (new Error(\"Error: Bad input " |
| | + + "stream initializer.\"));"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t\tyy_reader = new java.io.BufferedReader(reader);"); |
| | + m_outstream.println("\t}"); |
| | + m_outstream.println(); |
| | + |
| | + |
| | + /* Function: second constructor (InputStream) */ |
| | + m_outstream.print("\t"); |
| | + if (true == m_spec.m_public) { |
| | + m_outstream.print("public "); |
| | + } |
| | + m_outstream.print(new String(m_spec.m_class_name)); |
| | + m_outstream.print(" (java.io.InputStream instream)"); |
| | + |
| | + if (null != m_spec.m_init_throw_code) |
| | + { |
| | + m_outstream.println(); |
| | + m_outstream.print("\t\tthrows "); |
| | + m_outstream.println(new String(m_spec.m_init_throw_code,0, |
| | + m_spec.m_init_throw_read)); |
| | + m_outstream.println("\t\t{"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + m_outstream.println("\t\tthis ();"); |
| | + m_outstream.println("\t\tif (null == instream) {"); |
| | + m_outstream.println("\t\t\tthrow (new Error(\"Error: Bad input " |
| | + + "stream initializer.\"));"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t\tyy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream));"); |
| | + m_outstream.println("\t}"); |
| | + m_outstream.println(); |
| | + |
| | + |
| | + /* Function: third, private constructor - only for internal use */ |
| | + m_outstream.print("\tprivate "); |
| | + m_outstream.print(new String(m_spec.m_class_name)); |
| | + m_outstream.print(" ()"); |
| | + |
| | + if (null != m_spec.m_init_throw_code) |
| | + { |
| | + m_outstream.println(); |
| | + m_outstream.print("\t\tthrows "); |
| | + m_outstream.println(new String(m_spec.m_init_throw_code,0, |
| | + m_spec.m_init_throw_read)); |
| | + m_outstream.println("\t\t{"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + m_outstream.println("\t\tyy_buffer = new char[YY_BUFFER_SIZE];"); |
| | + m_outstream.println("\t\tyy_buffer_read = 0;"); |
| | + m_outstream.println("\t\tyy_buffer_index = 0;"); |
| | + m_outstream.println("\t\tyy_buffer_start = 0;"); |
| | + m_outstream.println("\t\tyy_buffer_end = 0;"); |
| | + if (m_spec.m_count_chars) |
| | + { |
| | + m_outstream.println("\t\tyychar = 0;"); |
| | + } |
| | + if (m_spec.m_count_lines) |
| | + { |
| | + m_outstream.println("\t\tyyline = 0;"); |
| | + } |
| | + m_outstream.println("\t\tyy_at_bol = true;"); |
| | + m_outstream.println("\t\tyy_lexical_state = YYINITIAL;"); |
| | + /*if (m_spec.m_count_lines || true == m_spec.m_count_chars) |
| | + { |
| | + m_outstream.println("\t\tyy_buffer_prev_start = 0;"); |
| | + }*/ |
| | + |
| | + /* User specified constructor code. */ |
| | + if (null != m_spec.m_init_code) |
| | + { |
| | + m_outstream.print(new String(m_spec.m_init_code,0, |
| | + m_spec.m_init_read)); |
| | + } |
| | + |
| | + m_outstream.println("\t}"); |
| | + m_outstream.println(); |
| | + |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_states |
| | + Description: Emits constants that serve as lexical states, |
| | + including YYINITIAL. |
| | + **************************************************************/ |
| | + private void emit_states |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + Enumeration states; |
| | + String state; |
| | + int index; |
| | + |
| | + states = m_spec.m_states.keys(); |
| | + /*index = 0;*/ |
| | + while (states.hasMoreElements()) |
| | + { |
| | + state = (String) states.nextElement(); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != state); |
| | + } |
| | + |
| | + m_outstream.println("\tprivate final int " |
| | + + state |
| | + + " = " |
| | + + (m_spec.m_states.get(state)).toString() |
| | + + ";"); |
| | + /*++index;*/ |
| | + } |
| | + |
| | + m_outstream.println("\tprivate final int yy_state_dtrans[] = {"); |
| | + for (index = 0; index < m_spec.m_state_dtrans.length; ++index) |
| | + { |
| | + m_outstream.print("\t\t" + m_spec.m_state_dtrans[index]); |
| | + if (index < m_spec.m_state_dtrans.length - 1) |
| | + { |
| | + m_outstream.println(","); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(); |
| | + } |
| | + } |
| | + m_outstream.println("\t};"); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_helpers |
| | + Description: Emits helper functions, particularly |
| | + error handling and input buffering. |
| | + **************************************************************/ |
| | + private void emit_helpers |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + /* Function: yy_do_eof */ |
| | + m_outstream.println("\tprivate boolean yy_eof_done = false;"); |
| | + if (null != m_spec.m_eof_code) |
| | + { |
| | + m_outstream.print("\tprivate void yy_do_eof ()"); |
| | + |
| | + if (null != m_spec.m_eof_throw_code) |
| | + { |
| | + m_outstream.println(); |
| | + m_outstream.print("\t\tthrows "); |
| | + m_outstream.println(new String(m_spec.m_eof_throw_code,0, |
| | + m_spec.m_eof_throw_read)); |
| | + m_outstream.println("\t\t{"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + m_outstream.println("\t\tif (false == yy_eof_done) {"); |
| | + m_outstream.print(new String(m_spec.m_eof_code,0, |
| | + m_spec.m_eof_read)); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t\tyy_eof_done = true;"); |
| | + m_outstream.println("\t}"); |
| | + } |
| | + |
| | + emit_states(); |
| | + |
| | + /* Function: yybegin */ |
| | + m_outstream.println("\tprivate void yybegin (int state) {"); |
| | + m_outstream.println("\t\tyy_lexical_state = state;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_initial_dtrans */ |
| | + /*m_outstream.println("\tprivate int yy_initial_dtrans (int state) {"); |
| | + m_outstream.println("\t\treturn yy_state_dtrans[state];"); |
| | + m_outstream.println("\t}");*/ |
| | + |
| | + /* Function: yy_advance */ |
| | + m_outstream.println("\tprivate int yy_advance ()"); |
| | + m_outstream.println("\t\tthrows java.io.IOException {"); |
| | + /*m_outstream.println("\t\t{");*/ |
| | + m_outstream.println("\t\tint next_read;"); |
| | + m_outstream.println("\t\tint i;"); |
| | + m_outstream.println("\t\tint j;"); |
| | + m_outstream.println(); |
| | + |
| | + m_outstream.println("\t\tif (yy_buffer_index < yy_buffer_read) {"); |
| | + m_outstream.println("\t\t\treturn yy_buffer[yy_buffer_index++];"); |
| | + /*m_outstream.println("\t\t\t++yy_buffer_index;");*/ |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println(); |
| | + |
| | + m_outstream.println("\t\tif (0 != yy_buffer_start) {"); |
| | + m_outstream.println("\t\t\ti = yy_buffer_start;"); |
| | + m_outstream.println("\t\t\tj = 0;"); |
| | + m_outstream.println("\t\t\twhile (i < yy_buffer_read) {"); |
| | + m_outstream.println("\t\t\t\tyy_buffer[j] = yy_buffer[i];"); |
| | + m_outstream.println("\t\t\t\t++i;"); |
| | + m_outstream.println("\t\t\t\t++j;"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t\tyy_buffer_end = yy_buffer_end - yy_buffer_start;"); |
| | + m_outstream.println("\t\t\tyy_buffer_start = 0;"); |
| | + m_outstream.println("\t\t\tyy_buffer_read = j;"); |
| | + m_outstream.println("\t\t\tyy_buffer_index = j;"); |
| | + m_outstream.println("\t\t\tnext_read = yy_reader.read(yy_buffer,"); |
| | + m_outstream.println("\t\t\t\t\tyy_buffer_read,"); |
| | + m_outstream.println("\t\t\t\t\tyy_buffer.length - yy_buffer_read);"); |
| | + m_outstream.println("\t\t\tif (-1 == next_read) {"); |
| | + m_outstream.println("\t\t\t\treturn YY_EOF;"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t\tyy_buffer_read = yy_buffer_read + next_read;"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println(); |
| | + |
| | + m_outstream.println("\t\twhile (yy_buffer_index >= yy_buffer_read) {"); |
| | + m_outstream.println("\t\t\tif (yy_buffer_index >= yy_buffer.length) {"); |
| | + m_outstream.println("\t\t\t\tyy_buffer = yy_double(yy_buffer);"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t\tnext_read = yy_reader.read(yy_buffer,"); |
| | + m_outstream.println("\t\t\t\t\tyy_buffer_read,"); |
| | + m_outstream.println("\t\t\t\t\tyy_buffer.length - yy_buffer_read);"); |
| | + m_outstream.println("\t\t\tif (-1 == next_read) {"); |
| | + m_outstream.println("\t\t\t\treturn YY_EOF;"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t\tyy_buffer_read = yy_buffer_read + next_read;"); |
| | + m_outstream.println("\t\t}"); |
| | + |
| | + m_outstream.println("\t\treturn yy_buffer[yy_buffer_index++];"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_move_end */ |
| | + m_outstream.println("\tprivate void yy_move_end () {"); |
| | + m_outstream.println("\t\tif (yy_buffer_end > yy_buffer_start &&"); |
| | + m_outstream.println("\t\t '\\n' == yy_buffer[yy_buffer_end-1])"); |
| | + m_outstream.println("\t\t\tyy_buffer_end--;"); |
| | + m_outstream.println("\t\tif (yy_buffer_end > yy_buffer_start &&"); |
| | + m_outstream.println("\t\t '\\r' == yy_buffer[yy_buffer_end-1])"); |
| | + m_outstream.println("\t\t\tyy_buffer_end--;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_mark_start */ |
| | + m_outstream.println("\tprivate boolean yy_last_was_cr=false;"); |
| | + m_outstream.println("\tprivate void yy_mark_start () {"); |
| | + if (m_spec.m_count_lines || true == m_spec.m_count_chars) |
| | + { |
| | + if (m_spec.m_count_lines) |
| | + { |
| | + m_outstream.println("\t\tint i;"); |
| | + m_outstream.println("\t\tfor (i = yy_buffer_start; " |
| | + + "i < yy_buffer_index; ++i) {"); |
| | + m_outstream.println("\t\t\tif ('\\n' == yy_buffer[i] && !yy_last_was_cr) {"); |
| | + m_outstream.println("\t\t\t\t++yyline;"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t\tif ('\\r' == yy_buffer[i]) {"); |
| | + m_outstream.println("\t\t\t\t++yyline;"); |
| | + m_outstream.println("\t\t\t\tyy_last_was_cr=true;"); |
| | + m_outstream.println("\t\t\t} else yy_last_was_cr=false;"); |
| | + m_outstream.println("\t\t}"); |
| | + } |
| | + if (m_spec.m_count_chars) |
| | + { |
| | + m_outstream.println("\t\tyychar = yychar"); |
| | + m_outstream.println("\t\t\t+ yy_buffer_index - yy_buffer_start;"); |
| | + } |
| | + } |
| | + m_outstream.println("\t\tyy_buffer_start = yy_buffer_index;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_mark_end */ |
| | + m_outstream.println("\tprivate void yy_mark_end () {"); |
| | + m_outstream.println("\t\tyy_buffer_end = yy_buffer_index;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_to_mark */ |
| | + m_outstream.println("\tprivate void yy_to_mark () {"); |
| | + m_outstream.println("\t\tyy_buffer_index = yy_buffer_end;"); |
| | + m_outstream.println("\t\tyy_at_bol = "+ |
| | + "(yy_buffer_end > yy_buffer_start) &&"); |
| | + m_outstream.println("\t\t "+ |
| | + "('\\r' == yy_buffer[yy_buffer_end-1] ||"); |
| | + m_outstream.println("\t\t "+ |
| | + " '\\n' == yy_buffer[yy_buffer_end-1] ||"); |
| | + m_outstream.println("\t\t "+ /* unicode LS */ |
| | + " 2028/*LS*/ == yy_buffer[yy_buffer_end-1] ||"); |
| | + m_outstream.println("\t\t "+ /* unicode PS */ |
| | + " 2029/*PS*/ == yy_buffer[yy_buffer_end-1]);"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yytext */ |
| | + m_outstream.println("\tprivate java.lang.String yytext () {"); |
| | + m_outstream.println("\t\treturn (new java.lang.String(yy_buffer,"); |
| | + m_outstream.println("\t\t\tyy_buffer_start,"); |
| | + m_outstream.println("\t\t\tyy_buffer_end - yy_buffer_start));"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yylength */ |
| | + m_outstream.println("\tprivate int yylength () {"); |
| | + m_outstream.println("\t\treturn yy_buffer_end - yy_buffer_start;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_double */ |
| | + m_outstream.println("\tprivate char[] yy_double (char buf[]) {"); |
| | + m_outstream.println("\t\tint i;"); |
| | + m_outstream.println("\t\tchar newbuf[];"); |
| | + m_outstream.println("\t\tnewbuf = new char[2*buf.length];"); |
| | + m_outstream.println("\t\tfor (i = 0; i < buf.length; ++i) {"); |
| | + m_outstream.println("\t\t\tnewbuf[i] = buf[i];"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t\treturn newbuf;"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_error */ |
| | + m_outstream.println("\tprivate final int YY_E_INTERNAL = 0;"); |
| | + m_outstream.println("\tprivate final int YY_E_MATCH = 1;"); |
| | + m_outstream.println("\tprivate java.lang.String yy_error_string[] = {"); |
| | + m_outstream.println("\t\t\"Error: Internal error.\\n\","); |
| | + m_outstream.println("\t\t\"Error: Unmatched input.\\n\""); |
| | + m_outstream.println("\t};"); |
| | + m_outstream.println("\tprivate void yy_error (int code,boolean fatal) {"); |
| | + m_outstream.println("\t\tjava.lang.System.out.print(yy_error_string[code]);"); |
| | + m_outstream.println("\t\tjava.lang.System.out.flush();"); |
| | + m_outstream.println("\t\tif (fatal) {"); |
| | + m_outstream.println("\t\t\tthrow new Error(\"Fatal Error.\\n\");"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /* Function: yy_next */ |
| | + /*m_outstream.println("\tprivate int yy_next (int current,char lookahead) {"); |
| | + m_outstream.println("\t\treturn yy_nxt[yy_rmap[current]][yy_cmap[lookahead]];"); |
| | + m_outstream.println("\t}");*/ |
| | + |
| | + /* Function: yy_accept */ |
| | + /*m_outstream.println("\tprivate int yy_accept (int current) {"); |
| | + m_outstream.println("\t\treturn yy_acpt[current];"); |
| | + m_outstream.println("\t}");*/ |
| | + |
| | + |
| | + // Function: private int [][] unpackFromString(int size1, int size2, String st) |
| | + // Added 6/24/98 Raimondas Lencevicius |
| | + // May be made more efficient by replacing String operations |
| | + // Assumes correctly formed input String. Performs no error checking |
| | + m_outstream.println("\tprivate int[][] unpackFromString"+ |
| | + "(int size1, int size2, String st) {"); |
| | + m_outstream.println("\t\tint colonIndex = -1;"); |
| | + m_outstream.println("\t\tString lengthString;"); |
| | + m_outstream.println("\t\tint sequenceLength = 0;"); |
| | + m_outstream.println("\t\tint sequenceInteger = 0;"); |
| | + m_outstream.println(); |
| | + m_outstream.println("\t\tint commaIndex;"); |
| | + m_outstream.println("\t\tString workString;"); |
| | + m_outstream.println(); |
| | + m_outstream.println("\t\tint res[][] = new int[size1][size2];"); |
| | + m_outstream.println("\t\tfor (int i= 0; i < size1; i++) {"); |
| | + m_outstream.println("\t\t\tfor (int j= 0; j < size2; j++) {"); |
| | + m_outstream.println("\t\t\t\tif (sequenceLength != 0) {"); |
| | + m_outstream.println("\t\t\t\t\tres[i][j] = sequenceInteger;"); |
| | + m_outstream.println("\t\t\t\t\tsequenceLength--;"); |
| | + m_outstream.println("\t\t\t\t\tcontinue;"); |
| | + m_outstream.println("\t\t\t\t}"); |
| | + m_outstream.println("\t\t\t\tcommaIndex = st.indexOf(',');"); |
| | + m_outstream.println("\t\t\t\tworkString = (commaIndex==-1) ? st :"); |
| | + m_outstream.println("\t\t\t\t\tst.substring(0, commaIndex);"); |
| | + m_outstream.println("\t\t\t\tst = st.substring(commaIndex+1);"); |
| | + m_outstream.println("\t\t\t\tcolonIndex = workString.indexOf(':');"); |
| | + m_outstream.println("\t\t\t\tif (colonIndex == -1) {"); |
| | + m_outstream.println("\t\t\t\t\tres[i][j]=Integer.parseInt(workString);"); |
| | + m_outstream.println("\t\t\t\t\tcontinue;"); |
| | + m_outstream.println("\t\t\t\t}"); |
| | + m_outstream.println("\t\t\t\tlengthString ="); |
| | + m_outstream.println("\t\t\t\t\tworkString.substring(colonIndex+1);"); |
| | + m_outstream.println("\t\t\t\tsequenceLength="+ |
| | + "Integer.parseInt(lengthString);"); |
| | + m_outstream.println("\t\t\t\tworkString="+ |
| | + "workString.substring(0,colonIndex);"); |
| | + m_outstream.println("\t\t\t\tsequenceInteger="+ |
| | + "Integer.parseInt(workString);"); |
| | + m_outstream.println("\t\t\t\tres[i][j] = sequenceInteger;"); |
| | + m_outstream.println("\t\t\t\tsequenceLength--;"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t\treturn res;"); |
| | + m_outstream.println("\t}"); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_header |
| | + Description: Emits class header. |
| | + **************************************************************/ |
| | + private void emit_header |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + m_outstream.println(); |
| | + m_outstream.println(); |
| | + if (true == m_spec.m_public) { |
| | + m_outstream.print("public "); |
| | + } |
| | + m_outstream.print("class "); |
| | + m_outstream.print(new String(m_spec.m_class_name,0, |
| | + m_spec.m_class_name.length)); |
| | + if (m_spec.m_implements_name.length > 0) { |
| | + m_outstream.print(" implements "); |
| | + m_outstream.print(new String(m_spec.m_implements_name,0, |
| | + m_spec.m_implements_name.length)); |
| | + } |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_table |
| | + Description: Emits transition table. |
| | + **************************************************************/ |
| | + private void emit_table |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int i; |
| | + int elem; |
| | + int size; |
| | + CDTrans dtrans; |
| | + boolean is_start; |
| | + boolean is_end; |
| | + CAccept accept; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + m_outstream.println("\tprivate int yy_acpt[] = {"); |
| | + size = m_spec.m_accept_vector.size(); |
| | + for (elem = 0; elem < size; ++elem) |
| | + { |
| | + accept = (CAccept) m_spec.m_accept_vector.elementAt(elem); |
| | + |
| | + m_outstream.print("\t\t/* "+elem+" */ "); |
| | + if (null != accept) |
| | + { |
| | + is_start = (0 != (m_spec.m_anchor_array[elem] & CSpec.START)); |
| | + is_end = (0 != (m_spec.m_anchor_array[elem] & CSpec.END)); |
| | + |
| | + if (is_start && true == is_end) |
| | + { |
| | + m_outstream.print("YY_START | YY_END"); |
| | + } |
| | + else if (is_start) |
| | + { |
| | + m_outstream.print("YY_START"); |
| | + } |
| | + else if (is_end) |
| | + { |
| | + m_outstream.print("YY_END"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.print("YY_NO_ANCHOR"); |
| | + } |
| | + } |
| | + else |
| | + { |
| | + m_outstream.print("YY_NOT_ACCEPT"); |
| | + } |
| | + |
| | + if (elem < size - 1) |
| | + { |
| | + m_outstream.print(","); |
| | + } |
| | + |
| | + m_outstream.println(); |
| | + } |
| | + m_outstream.println("\t};"); |
| | + |
| | + // CSA: modified yy_cmap to use string packing 9-Aug-1999 |
| | + int[] yy_cmap = new int[m_spec.m_ccls_map.length]; |
| | + for (i = 0; i < m_spec.m_ccls_map.length; ++i) |
| | + yy_cmap[i] = m_spec.m_col_map[m_spec.m_ccls_map[i]]; |
| | + m_outstream.print("\tprivate int yy_cmap[] = unpackFromString("); |
| | + emit_table_as_string(new int[][] { yy_cmap }); |
| | + m_outstream.println(")[0];"); |
| | + m_outstream.println(); |
| | + |
| | + // CSA: modified yy_rmap to use string packing 9-Aug-1999 |
| | + m_outstream.print("\tprivate int yy_rmap[] = unpackFromString("); |
| | + emit_table_as_string(new int[][] { m_spec.m_row_map }); |
| | + m_outstream.println(")[0];"); |
| | + m_outstream.println(); |
| | + |
| | + // 6/24/98 Raimondas Lencevicius |
| | + // modified to use |
| | + // int[][] unpackFromString(int size1, int size2, String st) |
| | + size = m_spec.m_dtrans_vector.size(); |
| | + int[][] yy_nxt = new int[size][]; |
| | + for (elem=0; elem<size; elem++) { |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(elem); |
| | + CUtility.ASSERT(dtrans.m_dtrans.length==m_spec.m_dtrans_ncols); |
| | + yy_nxt[elem] = dtrans.m_dtrans; |
| | + } |
| | + m_outstream.print |
| | + ("\tprivate int yy_nxt[][] = unpackFromString("); |
| | + emit_table_as_string(yy_nxt); |
| | + m_outstream.println(");"); |
| | + m_outstream.println(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_driver |
| | + Description: Output an integer table as a string. Written by |
| | + Raimondas Lencevicius 6/24/98; reorganized by CSA 9-Aug-1999. |
| | + From his original comments: |
| | + yy_nxt[][] values are coded into a string |
| | + by printing integers and representing |
| | + integer sequences as "value:length" pairs. |
| | + **************************************************************/ |
| | + private void emit_table_as_string(int[][] ia) { |
| | + int sequenceLength = 0; // RL - length of the number sequence |
| | + boolean sequenceStarted = false; // RL - has number sequence started? |
| | + int previousInt = -20; // RL - Bogus -20 state. |
| | + |
| | + // RL - Output matrix size |
| | + m_outstream.print(ia.length); |
| | + m_outstream.print(","); |
| | + m_outstream.print(ia.length>0?ia[0].length:0); |
| | + m_outstream.println(","); |
| | + |
| | + StringBuffer outstr = new StringBuffer(); |
| | + |
| | + // RL - Output matrix |
| | + for (int elem = 0; elem < ia.length; ++elem) |
| | + { |
| | + for (int i = 0; i < ia[elem].length; ++i) |
| | + { |
| | + int writeInt = ia[elem][i]; |
| | + if (writeInt == previousInt) // RL - sequence? |
| | + { |
| | + if (sequenceStarted) |
| | + { |
| | + sequenceLength++; |
| | + } |
| | + else |
| | + { |
| | + outstr.append(writeInt); |
| | + outstr.append(":"); |
| | + sequenceLength = 2; |
| | + sequenceStarted = true; |
| | + } |
| | + } |
| | + else // RL - no sequence or end sequence |
| | + { |
| | + if (sequenceStarted) |
| | + { |
| | + outstr.append(sequenceLength); |
| | + outstr.append(","); |
| | + sequenceLength = 0; |
| | + sequenceStarted = false; |
| | + } |
| | + else |
| | + { |
| | + if (previousInt != -20) |
| | + { |
| | + outstr.append(previousInt); |
| | + outstr.append(","); |
| | + } |
| | + } |
| | + } |
| | + previousInt = writeInt; |
| | + // CSA: output in 75 character chunks. |
| | + if (outstr.length() > 75) { |
| | + String s = outstr.toString(); |
| | + m_outstream.println("\""+s.substring(0,75)+"\" +"); |
| | + outstr = new StringBuffer(s.substring(75)); |
| | + } |
| | + } |
| | + } |
| | + if (sequenceStarted) |
| | + { |
| | + outstr.append(sequenceLength); |
| | + } |
| | + else |
| | + { |
| | + outstr.append(previousInt); |
| | + } |
| | + // CSA: output in 75 character chunks. |
| | + if (outstr.length() > 75) { |
| | + String s = outstr.toString(); |
| | + m_outstream.println("\""+s.substring(0,75)+"\" +"); |
| | + outstr = new StringBuffer(s.substring(75)); |
| | + } |
| | + m_outstream.print("\""+outstr+"\""); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_driver |
| | + Description: |
| | + **************************************************************/ |
| | + private void emit_driver |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + emit_table(); |
| | + |
| | + if (m_spec.m_integer_type) |
| | + { |
| | + m_outstream.print("\tpublic int "); |
| | + m_outstream.print(new String(m_spec.m_function_name)); |
| | + m_outstream.println(" ()"); |
| | + } |
| | + else if (m_spec.m_intwrap_type) |
| | + { |
| | + m_outstream.print("\tpublic java.lang.Integer "); |
| | + m_outstream.print(new String(m_spec.m_function_name)); |
| | + m_outstream.println(" ()"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.print("\tpublic "); |
| | + m_outstream.print(new String(m_spec.m_type_name)); |
| | + m_outstream.print(" "); |
| | + m_outstream.print(new String(m_spec.m_function_name)); |
| | + m_outstream.println(" ()"); |
| | + } |
| | + |
| | + /*m_outstream.println("\t\tthrows java.io.IOException {");*/ |
| | + m_outstream.print("\t\tthrows java.io.IOException"); |
| | + if (null != m_spec.m_yylex_throw_code) |
| | + { |
| | + m_outstream.print(", "); |
| | + m_outstream.print(new String(m_spec.m_yylex_throw_code,0, |
| | + m_spec.m_yylex_throw_read)); |
| | + m_outstream.println(); |
| | + m_outstream.println("\t\t{"); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println(" {"); |
| | + } |
| | + |
| | + m_outstream.println("\t\tint yy_lookahead;"); |
| | + m_outstream.println("\t\tint yy_anchor = YY_NO_ANCHOR;"); |
| | + /*m_outstream.println("\t\tint yy_state " |
| | + + "= yy_initial_dtrans(yy_lexical_state);");*/ |
| | + m_outstream.println("\t\tint yy_state " |
| | + + "= yy_state_dtrans[yy_lexical_state];"); |
| | + m_outstream.println("\t\tint yy_next_state = YY_NO_STATE;"); |
| | + /*m_outstream.println("\t\tint yy_prev_stave = YY_NO_STATE;");*/ |
| | + m_outstream.println("\t\tint yy_last_accept_state = YY_NO_STATE;"); |
| | + m_outstream.println("\t\tboolean yy_initial = true;"); |
| | + m_outstream.println("\t\tint yy_this_accept;"); |
| | + m_outstream.println(); |
| | + |
| | + m_outstream.println("\t\tyy_mark_start();"); |
| | + /*m_outstream.println("\t\tyy_this_accept = yy_accept(yy_state);");*/ |
| | + m_outstream.println("\t\tyy_this_accept = yy_acpt[yy_state];"); |
| | + m_outstream.println("\t\tif (YY_NOT_ACCEPT != yy_this_accept) {"); |
| | + m_outstream.println("\t\t\tyy_last_accept_state = yy_state;"); |
| | + m_outstream.println("\t\t\tyy_mark_end();"); |
| | + m_outstream.println("\t\t}"); |
| | + |
| | + if (NOT_EDBG) |
| | + { |
| | + m_outstream.println("\t\tjava.lang.System.out.println(\"Begin\");"); |
| | + } |
| | + |
| | + m_outstream.println("\t\twhile (true) {"); |
| | + |
| | + m_outstream.println("\t\t\tif (yy_initial && yy_at_bol) "+ |
| | + "yy_lookahead = YY_BOL;"); |
| | + m_outstream.println("\t\t\telse yy_lookahead = yy_advance();"); |
| | + m_outstream.println("\t\t\tyy_next_state = YY_F;"); |
| | + /*m_outstream.println("\t\t\t\tyy_next_state = " |
| | + + "yy_next(yy_state,yy_lookahead);");*/ |
| | + m_outstream.println("\t\t\tyy_next_state = " |
| | + + "yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]];"); |
| | + |
| | + if (NOT_EDBG) |
| | + { |
| | + m_outstream.println("java.lang.System.out.println(\"Current state: \"" |
| | + + " + yy_state"); |
| | + m_outstream.println("+ \"\tCurrent input: \""); |
| | + m_outstream.println(" + ((char) yy_lookahead));"); |
| | + } |
| | + if (NOT_EDBG) |
| | + { |
| | + m_outstream.println("\t\t\tjava.lang.System.out.println(\"State = \"" |
| | + + "+ yy_state);"); |
| | + m_outstream.println("\t\t\tjava.lang.System.out.println(\"Accepting status = \"" |
| | + + "+ yy_this_accept);"); |
| | + m_outstream.println("\t\t\tjava.lang.System.out.println(\"Last accepting state = \"" |
| | + + "+ yy_last_accept_state);"); |
| | + m_outstream.println("\t\t\tjava.lang.System.out.println(\"Next state = \"" |
| | + + "+ yy_next_state);"); |
| | + m_outstream.println("\t\t\tjava.lang.System.out.println(\"Lookahead input = \"" |
| | + + "+ ((char) yy_lookahead));"); |
| | + } |
| | + |
| | + // handle bare EOF. |
| | + m_outstream.println("\t\t\tif (YY_EOF == yy_lookahead " |
| | + + "&& true == yy_initial) {"); |
| | + if (null != m_spec.m_eof_code) |
| | + { |
| | + m_outstream.println("\t\t\t\tyy_do_eof();"); |
| | + } |
| | + if (true == m_spec.m_integer_type) |
| | + { |
| | + m_outstream.println("\t\t\t\treturn YYEOF;"); |
| | + } |
| | + else if (null != m_spec.m_eof_value_code) |
| | + { |
| | + m_outstream.print(new String(m_spec.m_eof_value_code,0, |
| | + m_spec.m_eof_value_read)); |
| | + } |
| | + else |
| | + { |
| | + m_outstream.println("\t\t\t\treturn null;"); |
| | + } |
| | + m_outstream.println("\t\t\t}"); |
| | + |
| | + m_outstream.println("\t\t\tif (YY_F != yy_next_state) {"); |
| | + m_outstream.println("\t\t\t\tyy_state = yy_next_state;"); |
| | + m_outstream.println("\t\t\t\tyy_initial = false;"); |
| | + /*m_outstream.println("\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/ |
| | + m_outstream.println("\t\t\t\tyy_this_accept = yy_acpt[yy_state];"); |
| | + m_outstream.println("\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {"); |
| | + m_outstream.println("\t\t\t\t\tyy_last_accept_state = yy_state;"); |
| | + m_outstream.println("\t\t\t\t\tyy_mark_end();"); |
| | + m_outstream.println("\t\t\t\t}"); |
| | + /*m_outstream.println("\t\t\t\tyy_prev_state = yy_state;");*/ |
| | + /*m_outstream.println("\t\t\t\tyy_state = yy_next_state;");*/ |
| | + m_outstream.println("\t\t\t}"); |
| | + |
| | + m_outstream.println("\t\t\telse {"); |
| | + |
| | + m_outstream.println("\t\t\t\tif (YY_NO_STATE == yy_last_accept_state) {"); |
| | + |
| | + |
| | + /*m_outstream.println("\t\t\t\t\tyy_error(YY_E_MATCH,false);"); |
| | + m_outstream.println("\t\t\t\t\tyy_initial = true;"); |
| | + m_outstream.println("\t\t\t\t\tyy_state " |
| | + + "= yy_state_dtrans[yy_lexical_state];"); |
| | + m_outstream.println("\t\t\t\t\tyy_next_state = YY_NO_STATE;");*/ |
| | + /*m_outstream.println("\t\t\t\t\tyy_prev_state = YY_NO_STATE;");*/ |
| | + /*m_outstream.println("\t\t\t\t\tyy_last_accept_state = YY_NO_STATE;"); |
| | + m_outstream.println("\t\t\t\t\tyy_mark_start();");*/ |
| | + /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/ |
| | + /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_acpt[yy_state];"); |
| | + m_outstream.println("\t\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {"); |
| | + m_outstream.println("\t\t\t\t\t\tyy_last_accept_state = yy_state;"); |
| | + m_outstream.println("\t\t\t\t\t}");*/ |
| | + |
| | + m_outstream.println("\t\t\t\t\tthrow (new Error(\"Lexical Error: Unmatched Input.\"));"); |
| | + m_outstream.println("\t\t\t\t}"); |
| | + |
| | + m_outstream.println("\t\t\t\telse {"); |
| | + |
| | + m_outstream.println("\t\t\t\t\tyy_anchor = yy_acpt[yy_last_accept_state];"); |
| | + /*m_outstream.println("\t\t\t\t\tyy_anchor " |
| | + + "= yy_accept(yy_last_accept_state);");*/ |
| | + m_outstream.println("\t\t\t\t\tif (0 != (YY_END & yy_anchor)) {"); |
| | + m_outstream.println("\t\t\t\t\t\tyy_move_end();"); |
| | + m_outstream.println("\t\t\t\t\t}"); |
| | + m_outstream.println("\t\t\t\t\tyy_to_mark();"); |
| | + |
| | + m_outstream.println("\t\t\t\t\tswitch (yy_last_accept_state) {"); |
| | + |
| | + emit_actions("\t\t\t\t\t"); |
| | + |
| | + m_outstream.println("\t\t\t\t\tdefault:"); |
| | + m_outstream.println("\t\t\t\t\t\tyy_error(YY_E_INTERNAL,false);"); |
| | + /*m_outstream.println("\t\t\t\t\t\treturn null;");*/ |
| | + m_outstream.println("\t\t\t\t\tcase -1:"); |
| | + m_outstream.println("\t\t\t\t\t}"); |
| | + |
| | + m_outstream.println("\t\t\t\t\tyy_initial = true;"); |
| | + m_outstream.println("\t\t\t\t\tyy_state " |
| | + + "= yy_state_dtrans[yy_lexical_state];"); |
| | + m_outstream.println("\t\t\t\t\tyy_next_state = YY_NO_STATE;"); |
| | + /*m_outstream.println("\t\t\t\t\tyy_prev_state = YY_NO_STATE;");*/ |
| | + m_outstream.println("\t\t\t\t\tyy_last_accept_state = YY_NO_STATE;"); |
| | + |
| | + m_outstream.println("\t\t\t\t\tyy_mark_start();"); |
| | + |
| | + /*m_outstream.println("\t\t\t\t\tyy_this_accept = yy_accept(yy_state);");*/ |
| | + m_outstream.println("\t\t\t\t\tyy_this_accept = yy_acpt[yy_state];"); |
| | + m_outstream.println("\t\t\t\t\tif (YY_NOT_ACCEPT != yy_this_accept) {"); |
| | + m_outstream.println("\t\t\t\t\t\tyy_last_accept_state = yy_state;"); |
| | + m_outstream.println("\t\t\t\t\t\tyy_mark_end();"); |
| | + m_outstream.println("\t\t\t\t\t}"); |
| | + |
| | + m_outstream.println("\t\t\t\t}"); |
| | + m_outstream.println("\t\t\t}"); |
| | + m_outstream.println("\t\t}"); |
| | + m_outstream.println("\t}"); |
| | + |
| | + /*m_outstream.println("\t\t\t\t"); |
| | + m_outstream.println("\t\t\t"); |
| | + m_outstream.println("\t\t\t"); |
| | + m_outstream.println("\t\t\t"); |
| | + m_outstream.println("\t\t\t"); |
| | + m_outstream.println("\t\t}");*/ |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_actions |
| | + Description: |
| | + **************************************************************/ |
| | + private void emit_actions |
| | + ( |
| | + String tabs |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int elem; |
| | + int size; |
| | + int bogus_index; |
| | + CAccept accept; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_spec.m_accept_vector.size() |
| | + == m_spec.m_anchor_array.length); |
| | + } |
| | + |
| | + bogus_index = -2; |
| | + size = m_spec.m_accept_vector.size(); |
| | + for (elem = 0; elem < size; ++elem) |
| | + { |
| | + accept = (CAccept) m_spec.m_accept_vector.elementAt(elem); |
| | + if (null != accept) |
| | + { |
| | + m_outstream.println(tabs + "case " + elem |
| | + + ":"); |
| | + m_outstream.print(tabs + "\t"); |
| | + m_outstream.print(new String(accept.m_action,0, |
| | + accept.m_action_read)); |
| | + m_outstream.println(); |
| | + m_outstream.println(tabs + "case " + bogus_index + ":"); |
| | + m_outstream.println(tabs + "\tbreak;"); |
| | + --bogus_index; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: emit_footer |
| | + Description: |
| | + **************************************************************/ |
| | + private void emit_footer |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + } |
| | + |
| | + m_outstream.println("}"); |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CBunch |
| | + **************************************************************/ |
| | +class CBunch |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + Vector m_nfa_set; /* Vector of CNfa states in dfa state. */ |
| | + SparseBitSet m_nfa_bit; /* BitSet representation of CNfa labels. */ |
| | + CAccept m_accept; /* Accepting actions, or null if nonaccepting state. */ |
| | + int m_anchor; /* Anchors on regular expression. */ |
| | + int m_accept_index; /* CNfa index corresponding to accepting actions. */ |
| | + |
| | + /*************************************************************** |
| | + Function: CBunch |
| | + Description: Constructor. |
| | + **************************************************************/ |
| | + CBunch |
| | + ( |
| | + ) |
| | + { |
| | + m_nfa_set = null; |
| | + m_nfa_bit = null; |
| | + m_accept = null; |
| | + m_anchor = CSpec.NONE; |
| | + m_accept_index = -1; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CMakeNfa |
| | + **************************************************************/ |
| | +class CMakeNfa |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + private CSpec m_spec; |
| | + private CLexGen m_lexGen; |
| | + private CInput m_input; |
| | + |
| | + /*************************************************************** |
| | + Function: CMakeNfa |
| | + Description: Constructor. |
| | + **************************************************************/ |
| | + CMakeNfa |
| | + ( |
| | + ) |
| | + { |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: reset |
| | + Description: Resets CMakeNfa member variables. |
| | + **************************************************************/ |
| | + private void reset |
| | + ( |
| | + ) |
| | + { |
| | + m_input = null; |
| | + m_lexGen = null; |
| | + m_spec = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: set |
| | + Description: Sets CMakeNfa member variables. |
| | + **************************************************************/ |
| | + private void set |
| | + ( |
| | + CLexGen lexGen, |
| | + CSpec spec, |
| | + CInput input |
| | + ) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != input); |
| | + CUtility.ASSERT(null != lexGen); |
| | + CUtility.ASSERT(null != spec); |
| | + } |
| | + |
| | + m_input = input; |
| | + m_lexGen = lexGen; |
| | + m_spec = spec; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: allocate_BOL_EOF |
| | + Description: Expands character class to include special BOL and |
| | + EOF characters. Puts numeric index of these characters in |
| | + input CSpec. |
| | + **************************************************************/ |
| | + void allocate_BOL_EOF |
| | + ( |
| | + CSpec spec |
| | + ) |
| | + { |
| | + CUtility.ASSERT(CSpec.NUM_PSEUDO==2); |
| | + spec.BOL = spec.m_dtrans_ncols++; |
| | + spec.EOF = spec.m_dtrans_ncols++; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: thompson |
| | + Description: High level access function to module. |
| | + Deposits result in input CSpec. |
| | + **************************************************************/ |
| | + void thompson |
| | + ( |
| | + CLexGen lexGen, |
| | + CSpec spec, |
| | + CInput input |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int i; |
| | + CNfa elem; |
| | + int size; |
| | + |
| | + /* Set member variables. */ |
| | + reset(); |
| | + set(lexGen,spec,input); |
| | + |
| | + size = m_spec.m_states.size(); |
| | + m_spec.m_state_rules = new Vector[size]; |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + m_spec.m_state_rules[i] = new Vector(); |
| | + } |
| | + |
| | + /* Initialize current token variable |
| | + and create nfa. */ |
| | + /*m_spec.m_current_token = m_lexGen.EOS; |
| | + m_lexGen.advance();*/ |
| | + |
| | + m_spec.m_nfa_start = machine(); |
| | + |
| | + /* Set labels in created nfa machine. */ |
| | + size = m_spec.m_nfa_states.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + elem = (CNfa) m_spec.m_nfa_states.elementAt(i); |
| | + elem.m_label = i; |
| | + } |
| | + |
| | + /* Debugging output. */ |
| | + if (CUtility.DO_DEBUG) |
| | + { |
| | + m_lexGen.print_nfa(); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("NFA comprised of " |
| | + + (m_spec.m_nfa_states.size() + 1) |
| | + + " states."); |
| | + } |
| | + |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: discardCNfa |
| | + Description: |
| | + **************************************************************/ |
| | + private void discardCNfa |
| | + ( |
| | + CNfa nfa |
| | + ) |
| | + { |
| | + m_spec.m_nfa_states.removeElement(nfa); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: processStates |
| | + Description: |
| | + **************************************************************/ |
| | + private void processStates |
| | + ( |
| | + SparseBitSet states, |
| | + CNfa current |
| | + ) |
| | + { |
| | + int size; |
| | + int i; |
| | + |
| | + size = m_spec.m_states.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + if (states.get(i)) |
| | + { |
| | + m_spec.m_state_rules[i].addElement(current); |
| | + } |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: machine |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private CNfa machine |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfa start; |
| | + CNfa p; |
| | + SparseBitSet states; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("machine",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + start = CAlloc.newCNfa(m_spec); |
| | + p = start; |
| | + |
| | + states = m_lexGen.getStates(); |
| | + |
| | + /* Begin: Added for states. */ |
| | + m_spec.m_current_token = m_lexGen.EOS; |
| | + m_lexGen.advance(); |
| | + /* End: Added for states. */ |
| | + |
| | + if (m_lexGen.END_OF_INPUT != m_spec.m_current_token) // CSA fix. |
| | + { |
| | + p.m_next = rule(); |
| | + |
| | + processStates(states,p.m_next); |
| | + } |
| | + |
| | + while (m_lexGen.END_OF_INPUT != m_spec.m_current_token) |
| | + { |
| | + /* Make state changes HERE. */ |
| | + states = m_lexGen.getStates(); |
| | + |
| | + /* Begin: Added for states. */ |
| | + m_lexGen.advance(); |
| | + if (m_lexGen.END_OF_INPUT == m_spec.m_current_token) |
| | + { |
| | + break; |
| | + } |
| | + /* End: Added for states. */ |
| | + |
| | + p.m_next2 = CAlloc.newCNfa(m_spec); |
| | + p = p.m_next2; |
| | + p.m_next = rule(); |
| | + |
| | + processStates(states,p.m_next); |
| | + } |
| | + |
| | + // CSA: add pseudo-rules for BOL and EOF |
| | + SparseBitSet all_states = new SparseBitSet(); |
| | + for (int i = 0; i < m_spec.m_states.size(); ++i) |
| | + all_states.set(i); |
| | + p.m_next2 = CAlloc.newCNfa(m_spec); |
| | + p = p.m_next2; |
| | + p.m_next = CAlloc.newCNfa(m_spec); |
| | + p.m_next.m_edge = CNfa.CCL; |
| | + p.m_next.m_next = CAlloc.newCNfa(m_spec); |
| | + p.m_next.m_set = new CSet(); |
| | + p.m_next.m_set.add(m_spec.BOL); |
| | + p.m_next.m_set.add(m_spec.EOF); |
| | + p.m_next.m_next.m_accept = // do-nothing accept rule |
| | + new CAccept(new char[0], 0, m_input.m_line_number+1); |
| | + processStates(all_states,p.m_next); |
| | + // CSA: done. |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("machine",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + return start; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: rule |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private CNfa rule |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfaPair pair; |
| | + CNfa p; |
| | + CNfa start = null; |
| | + CNfa end = null; |
| | + int anchor = CSpec.NONE; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("rule",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + pair = CAlloc.newCNfaPair(); |
| | + |
| | + if (m_lexGen.AT_BOL == m_spec.m_current_token) |
| | + { |
| | + anchor = anchor | CSpec.START; |
| | + m_lexGen.advance(); |
| | + expr(pair); |
| | + |
| | + // CSA: fixed beginning-of-line operator. 8-aug-1999 |
| | + start = CAlloc.newCNfa(m_spec); |
| | + start.m_edge = m_spec.BOL; |
| | + start.m_next = pair.m_start; |
| | + end = pair.m_end; |
| | + } |
| | + else |
| | + { |
| | + expr(pair); |
| | + start = pair.m_start; |
| | + end = pair.m_end; |
| | + } |
| | + |
| | + if (m_lexGen.AT_EOL == m_spec.m_current_token) |
| | + { |
| | + m_lexGen.advance(); |
| | + // CSA: fixed end-of-line operator. 8-aug-1999 |
| | + CNfaPair nlpair = CAlloc.newNLPair(m_spec); |
| | + end.m_next = CAlloc.newCNfa(m_spec); |
| | + end.m_next.m_next = nlpair.m_start; |
| | + end.m_next.m_next2 = CAlloc.newCNfa(m_spec); |
| | + end.m_next.m_next2.m_edge = m_spec.EOF; |
| | + end.m_next.m_next2.m_next = nlpair.m_end; |
| | + end = nlpair.m_end; |
| | + anchor = anchor | CSpec.END; |
| | + } |
| | + |
| | + /* Check for null rules. Charles Fischer found this bug. [CSA] */ |
| | + if (end==null) |
| | + CError.parse_error(CError.E_ZERO, m_input.m_line_number); |
| | + |
| | + /* Handle end of regular expression. See page 103. */ |
| | + end.m_accept = m_lexGen.packAccept(); |
| | + end.m_anchor = anchor; |
| | + |
| | + /* Begin: Removed for states. */ |
| | + /*m_lexGen.advance();*/ |
| | + /* End: Removed for states. */ |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("rule",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + return start; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: expr |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private void expr |
| | + ( |
| | + CNfaPair pair |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfaPair e2_pair; |
| | + CNfa p; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("expr",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != pair); |
| | + } |
| | + |
| | + e2_pair = CAlloc.newCNfaPair(); |
| | + |
| | + cat_expr(pair); |
| | + |
| | + while (m_lexGen.OR == m_spec.m_current_token) |
| | + { |
| | + m_lexGen.advance(); |
| | + cat_expr(e2_pair); |
| | + |
| | + p = CAlloc.newCNfa(m_spec); |
| | + p.m_next2 = e2_pair.m_start; |
| | + p.m_next = pair.m_start; |
| | + pair.m_start = p; |
| | + |
| | + p = CAlloc.newCNfa(m_spec); |
| | + pair.m_end.m_next = p; |
| | + e2_pair.m_end.m_next = p; |
| | + pair.m_end = p; |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("expr",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: cat_expr |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private void cat_expr |
| | + ( |
| | + CNfaPair pair |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfaPair e2_pair; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("cat_expr",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != pair); |
| | + } |
| | + |
| | + e2_pair = CAlloc.newCNfaPair(); |
| | + |
| | + if (first_in_cat(m_spec.m_current_token)) |
| | + { |
| | + factor(pair); |
| | + } |
| | + |
| | + while (first_in_cat(m_spec.m_current_token)) |
| | + { |
| | + factor(e2_pair); |
| | + |
| | + /* Destroy */ |
| | + pair.m_end.mimic(e2_pair.m_start); |
| | + discardCNfa(e2_pair.m_start); |
| | + |
| | + pair.m_end = e2_pair.m_end; |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("cat_expr",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: first_in_cat |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private boolean first_in_cat |
| | + ( |
| | + int token |
| | + ) |
| | + { |
| | + switch (token) |
| | + { |
| | + case CLexGen.CLOSE_PAREN: |
| | + case CLexGen.AT_EOL: |
| | + case CLexGen.OR: |
| | + case CLexGen.EOS: |
| | + return false; |
| | + |
| | + case CLexGen.CLOSURE: |
| | + case CLexGen.PLUS_CLOSE: |
| | + case CLexGen.OPTIONAL: |
| | + CError.parse_error(CError.E_CLOSE,m_input.m_line_number); |
| | + return false; |
| | + |
| | + case CLexGen.CCL_END: |
| | + CError.parse_error(CError.E_BRACKET,m_input.m_line_number); |
| | + return false; |
| | + |
| | + case CLexGen.AT_BOL: |
| | + CError.parse_error(CError.E_BOL,m_input.m_line_number); |
| | + return false; |
| | + |
| | + default: |
| | + break; |
| | + } |
| | + |
| | + return true; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: factor |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private void factor |
| | + ( |
| | + CNfaPair pair |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfa start = null; |
| | + CNfa end = null; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("factor",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + term(pair); |
| | + |
| | + if (m_lexGen.CLOSURE == m_spec.m_current_token |
| | + || m_lexGen.PLUS_CLOSE == m_spec.m_current_token |
| | + || m_lexGen.OPTIONAL == m_spec.m_current_token) |
| | + { |
| | + start = CAlloc.newCNfa(m_spec); |
| | + end = CAlloc.newCNfa(m_spec); |
| | + |
| | + start.m_next = pair.m_start; |
| | + pair.m_end.m_next = end; |
| | + |
| | + if (m_lexGen.CLOSURE == m_spec.m_current_token |
| | + || m_lexGen.OPTIONAL == m_spec.m_current_token) |
| | + { |
| | + start.m_next2 = end; |
| | + } |
| | + |
| | + if (m_lexGen.CLOSURE == m_spec.m_current_token |
| | + || m_lexGen.PLUS_CLOSE == m_spec.m_current_token) |
| | + { |
| | + pair.m_end.m_next2 = pair.m_start; |
| | + } |
| | + |
| | + pair.m_start = start; |
| | + pair.m_end = end; |
| | + m_lexGen.advance(); |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("factor",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: term |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private void term |
| | + ( |
| | + CNfaPair pair |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CNfa start; |
| | + boolean isAlphaL; |
| | + int c; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("term",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + if (m_lexGen.OPEN_PAREN == m_spec.m_current_token) |
| | + { |
| | + m_lexGen.advance(); |
| | + expr(pair); |
| | + |
| | + if (m_lexGen.CLOSE_PAREN == m_spec.m_current_token) |
| | + { |
| | + m_lexGen.advance(); |
| | + } |
| | + else |
| | + { |
| | + CError.parse_error(CError.E_SYNTAX,m_input.m_line_number); |
| | + } |
| | + } |
| | + else |
| | + { |
| | + start = CAlloc.newCNfa(m_spec); |
| | + pair.m_start = start; |
| | + |
| | + start.m_next = CAlloc.newCNfa(m_spec); |
| | + pair.m_end = start.m_next; |
| | + |
| | + if (m_lexGen.L == m_spec.m_current_token && |
| | + Character.isLetter(m_spec.m_lexeme)) |
| | + { |
| | + isAlphaL = true; |
| | + } |
| | + else |
| | + { |
| | + isAlphaL = false; |
| | + } |
| | + if (false == (m_lexGen.ANY == m_spec.m_current_token |
| | + || m_lexGen.CCL_START == m_spec.m_current_token |
| | + || (m_spec.m_ignorecase && isAlphaL))) |
| | + { |
| | + start.m_edge = m_spec.m_lexeme; |
| | + m_lexGen.advance(); |
| | + } |
| | + else |
| | + { |
| | + start.m_edge = CNfa.CCL; |
| | + |
| | + start.m_set = new CSet(); |
| | + |
| | + /* Match case-insensitive letters using character class. */ |
| | + if (m_spec.m_ignorecase && isAlphaL) |
| | + { |
| | + start.m_set.addncase(m_spec.m_lexeme); |
| | + } |
| | + /* Match dot (.) using character class. */ |
| | + else if (m_lexGen.ANY == m_spec.m_current_token) |
| | + { |
| | + start.m_set.add('\n'); |
| | + start.m_set.add('\r'); |
| | + // CSA: exclude BOL and EOF from character classes |
| | + start.m_set.add(m_spec.BOL); |
| | + start.m_set.add(m_spec.EOF); |
| | + start.m_set.complement(); |
| | + } |
| | + else |
| | + { |
| | + m_lexGen.advance(); |
| | + if (m_lexGen.AT_BOL == m_spec.m_current_token) |
| | + { |
| | + m_lexGen.advance(); |
| | + |
| | + // CSA: exclude BOL and EOF from character classes |
| | + start.m_set.add(m_spec.BOL); |
| | + start.m_set.add(m_spec.EOF); |
| | + start.m_set.complement(); |
| | + } |
| | + if (false == (m_lexGen.CCL_END == m_spec.m_current_token)) |
| | + { |
| | + dodash(start.m_set); |
| | + } |
| | + /*else |
| | + { |
| | + for (c = 0; c <= ' '; ++c) |
| | + { |
| | + start.m_set.add((byte) c); |
| | + } |
| | + }*/ |
| | + } |
| | + m_lexGen.advance(); |
| | + } |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("term",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: dodash |
| | + Description: Recursive descent regular expression parser. |
| | + **************************************************************/ |
| | + private void dodash |
| | + ( |
| | + CSet set |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int first = -1; |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.enter("dodash",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + |
| | + while (m_lexGen.EOS != m_spec.m_current_token |
| | + && m_lexGen.CCL_END != m_spec.m_current_token) |
| | + { |
| | + // DASH loses its special meaning if it is first in class. |
| | + if (m_lexGen.DASH == m_spec.m_current_token && -1 != first) |
| | + { |
| | + m_lexGen.advance(); |
| | + // DASH loses its special meaning if it is last in class. |
| | + if (m_spec.m_current_token == m_lexGen.CCL_END) |
| | + { |
| | + // 'first' already in set. |
| | + set.add('-'); |
| | + break; |
| | + } |
| | + for ( ; first <= m_spec.m_lexeme; ++first) |
| | + { |
| | + if (m_spec.m_ignorecase) |
| | + set.addncase((char)first); |
| | + else |
| | + set.add(first); |
| | + } |
| | + } |
| | + else |
| | + { |
| | + first = m_spec.m_lexeme; |
| | + if (m_spec.m_ignorecase) |
| | + set.addncase(m_spec.m_lexeme); |
| | + else |
| | + set.add(m_spec.m_lexeme); |
| | + } |
| | + |
| | + m_lexGen.advance(); |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + CUtility.leave("dodash",m_spec.m_lexeme,m_spec.m_current_token); |
| | + } |
| | + } |
| | +} |
| | + |
| | +/** |
| | + * Extract character classes from NFA and simplify. |
| | + * @author C. Scott Ananian 25-Jul-1999 |
| | + */ |
| | +class CSimplifyNfa |
| | +{ |
| | + private int[] ccls; // character class mapping. |
| | + private int original_charset_size; // original charset size |
| | + private int mapped_charset_size; // reduced charset size |
| | + |
| | + void simplify(CSpec m_spec) { |
| | + computeClasses(m_spec); // initialize fields. |
| | + |
| | + // now rewrite the NFA using our character class mapping. |
| | + for (Enumeration e=m_spec.m_nfa_states.elements(); e.hasMoreElements(); ) { |
| | + CNfa nfa = (CNfa) e.nextElement(); |
| | + if (nfa.m_edge==CNfa.EMPTY || nfa.m_edge==CNfa.EPSILON) |
| | + continue; // no change. |
| | + if (nfa.m_edge==CNfa.CCL) { |
| | + CSet ncset = new CSet(); |
| | + ncset.map(nfa.m_set, ccls); // map it. |
| | + nfa.m_set = ncset; |
| | + } else { // single character |
| | + nfa.m_edge = ccls[nfa.m_edge]; // map it. |
| | + } |
| | + } |
| | + |
| | + // now update m_spec with the mapping. |
| | + m_spec.m_ccls_map = ccls; |
| | + m_spec.m_dtrans_ncols = mapped_charset_size; |
| | + } |
| | + /** Compute minimum set of character classes needed to disambiguate |
| | + * edges. We optimistically assume that every character belongs to |
| | + * a single character class, and then incrementally split classes |
| | + * as we see edges that require discrimination between characters in |
| | + * the class. [CSA, 25-Jul-1999] */ |
| | + private void computeClasses(CSpec m_spec) { |
| | + this.original_charset_size = m_spec.m_dtrans_ncols; |
| | + this.ccls = new int[original_charset_size]; // initially all zero. |
| | + |
| | + int nextcls = 1; |
| | + SparseBitSet clsA = new SparseBitSet(), clsB = new SparseBitSet(); |
| | + Hashtable h = new Hashtable(); |
| | + |
| | + System.out.print("Working on character classes."); |
| | + for (Enumeration e=m_spec.m_nfa_states.elements(); e.hasMoreElements(); ) { |
| | + CNfa nfa = (CNfa) e.nextElement(); |
| | + if (nfa.m_edge==CNfa.EMPTY || nfa.m_edge==CNfa.EPSILON) |
| | + continue; // no discriminatory information. |
| | + clsA.clearAll(); clsB.clearAll(); |
| | + for (int i=0; i<ccls.length; i++) |
| | + if (nfa.m_edge==i || // edge labeled with a character |
| | + nfa.m_edge==CNfa.CCL && nfa.m_set.contains(i)) // set of characters |
| | + clsA.set(ccls[i]); |
| | + else |
| | + clsB.set(ccls[i]); |
| | + // now figure out which character classes we need to split. |
| | + clsA.and(clsB); // split the classes which show up on both sides of edge |
| | + System.out.print(clsA.size()==0?".":":"); |
| | + if (clsA.size()==0) continue; // nothing to do. |
| | + // and split them. |
| | + h.clear(); // h will map old to new class name |
| | + for (int i=0; i<ccls.length; i++) |
| | + if (clsA.get(ccls[i])) // a split class |
| | + if (nfa.m_edge==i || |
| | + nfa.m_edge==CNfa.CCL && nfa.m_set.contains(i)) { // on A side |
| | + Integer split = new Integer(ccls[i]); |
| | + if (!h.containsKey(split)) |
| | + h.put(split, new Integer(nextcls++)); // make new class |
| | + ccls[i] = ((Integer)h.get(split)).intValue(); |
| | + } |
| | + } |
| | + System.out.println(); |
| | + System.out.println("NFA has "+nextcls+" distinct character classes."); |
| | + |
| | + this.mapped_charset_size = nextcls; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CMinimize |
| | + **************************************************************/ |
| | +class CMinimize |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + CSpec m_spec; |
| | + Vector m_group; |
| | + int m_ingroup[]; |
| | + |
| | + /*************************************************************** |
| | + Function: CMinimize |
| | + Description: Constructor. |
| | + **************************************************************/ |
| | + CMinimize |
| | + ( |
| | + ) |
| | + { |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: reset |
| | + Description: Resets member variables. |
| | + **************************************************************/ |
| | + private void reset |
| | + ( |
| | + ) |
| | + { |
| | + m_spec = null; |
| | + m_group = null; |
| | + m_ingroup = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: set |
| | + Description: Sets member variables. |
| | + **************************************************************/ |
| | + private void set |
| | + ( |
| | + CSpec spec |
| | + ) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != spec); |
| | + } |
| | + |
| | + m_spec = spec; |
| | + m_group = null; |
| | + m_ingroup = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: min_dfa |
| | + Description: High-level access function to module. |
| | + **************************************************************/ |
| | + void min_dfa |
| | + ( |
| | + CSpec spec |
| | + ) |
| | + { |
| | + set(spec); |
| | + |
| | + /* Remove redundant states. */ |
| | + minimize(); |
| | + |
| | + /* Column and row compression. |
| | + Save accept states in auxilary vector. */ |
| | + reduce(); |
| | + |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: col_copy |
| | + Description: Copies source column into destination column. |
| | + **************************************************************/ |
| | + private void col_copy |
| | + ( |
| | + int dest, |
| | + int src |
| | + ) |
| | + { |
| | + int n; |
| | + int i; |
| | + CDTrans dtrans; |
| | + |
| | + n = m_spec.m_dtrans_vector.size(); |
| | + for (i = 0; i < n; ++i) |
| | + { |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + dtrans.m_dtrans[dest] = dtrans.m_dtrans[src]; |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: trunc_col |
| | + Description: Truncates each column to the 'correct' length. |
| | + **************************************************************/ |
| | + private void trunc_col |
| | + ( |
| | + ) |
| | + { |
| | + int n; |
| | + int i; |
| | + CDTrans dtrans; |
| | + |
| | + n = m_spec.m_dtrans_vector.size(); |
| | + for (i = 0; i < n; ++i) |
| | + { |
| | + int[] ndtrans = new int[m_spec.m_dtrans_ncols]; |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + System.arraycopy(dtrans.m_dtrans, 0, ndtrans, 0, ndtrans.length); |
| | + dtrans.m_dtrans = ndtrans; |
| | + } |
| | + } |
| | + /*************************************************************** |
| | + Function: row_copy |
| | + Description: Copies source row into destination row. |
| | + **************************************************************/ |
| | + private void row_copy |
| | + ( |
| | + int dest, |
| | + int src |
| | + ) |
| | + { |
| | + CDTrans dtrans; |
| | + |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(src); |
| | + m_spec.m_dtrans_vector.setElementAt(dtrans,dest); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: col_equiv |
| | + Description: |
| | + **************************************************************/ |
| | + private boolean col_equiv |
| | + ( |
| | + int col1, |
| | + int col2 |
| | + ) |
| | + { |
| | + int n; |
| | + int i; |
| | + CDTrans dtrans; |
| | + |
| | + n = m_spec.m_dtrans_vector.size(); |
| | + for (i = 0; i < n; ++i) |
| | + { |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + if (dtrans.m_dtrans[col1] != dtrans.m_dtrans[col2]) |
| | + { |
| | + return false; |
| | + } |
| | + } |
| | + |
| | + return true; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: row_equiv |
| | + Description: |
| | + **************************************************************/ |
| | + private boolean row_equiv |
| | + ( |
| | + int row1, |
| | + int row2 |
| | + ) |
| | + { |
| | + int i; |
| | + CDTrans dtrans1; |
| | + CDTrans dtrans2; |
| | + |
| | + dtrans1 = (CDTrans) m_spec.m_dtrans_vector.elementAt(row1); |
| | + dtrans2 = (CDTrans) m_spec.m_dtrans_vector.elementAt(row2); |
| | + |
| | + for (i = 0; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + if (dtrans1.m_dtrans[i] != dtrans2.m_dtrans[i]) |
| | + { |
| | + return false; |
| | + } |
| | + } |
| | + |
| | + return true; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: reduce |
| | + Description: |
| | + **************************************************************/ |
| | + private void reduce |
| | + ( |
| | + ) |
| | + { |
| | + int i; |
| | + int j; |
| | + int k; |
| | + int nrows; |
| | + int reduced_ncols; |
| | + int reduced_nrows; |
| | + SparseBitSet set; |
| | + CDTrans dtrans; |
| | + int size; |
| | + |
| | + set = new SparseBitSet(); |
| | + |
| | + /* Save accept nodes and anchor entries. */ |
| | + size = m_spec.m_dtrans_vector.size(); |
| | + m_spec.m_anchor_array = new int[size]; |
| | + m_spec.m_accept_vector = new Vector(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + m_spec.m_accept_vector.addElement(dtrans.m_accept); |
| | + m_spec.m_anchor_array[i] = dtrans.m_anchor; |
| | + dtrans.m_accept = null; |
| | + } |
| | + |
| | + /* Allocate column map. */ |
| | + m_spec.m_col_map = new int[m_spec.m_dtrans_ncols]; |
| | + for (i = 0; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + m_spec.m_col_map[i] = -1; |
| | + } |
| | + |
| | + /* Process columns for reduction. */ |
| | + for (reduced_ncols = 0; ; ++reduced_ncols) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + for (i = 0; i < reduced_ncols; ++i) |
| | + { |
| | + CUtility.ASSERT(-1 != m_spec.m_col_map[i]); |
| | + } |
| | + } |
| | + |
| | + for (i = reduced_ncols; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + if (-1 == m_spec.m_col_map[i]) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (i >= m_spec.m_dtrans_ncols) |
| | + { |
| | + break; |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == set.get(i)); |
| | + CUtility.ASSERT(-1 == m_spec.m_col_map[i]); |
| | + } |
| | + |
| | + set.set(i); |
| | + |
| | + m_spec.m_col_map[i] = reduced_ncols; |
| | + |
| | + /* UNDONE: Optimize by doing all comparisons in one batch. */ |
| | + for (j = i + 1; j < m_spec.m_dtrans_ncols; ++j) |
| | + { |
| | + if (-1 == m_spec.m_col_map[j] && true == col_equiv(i,j)) |
| | + { |
| | + m_spec.m_col_map[j] = reduced_ncols; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /* Reduce columns. */ |
| | + k = 0; |
| | + for (i = 0; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + if (set.get(i)) |
| | + { |
| | + ++k; |
| | + |
| | + set.clear(i); |
| | + |
| | + j = m_spec.m_col_map[i]; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(j <= i); |
| | + } |
| | + |
| | + if (j == i) |
| | + { |
| | + continue; |
| | + } |
| | + |
| | + col_copy(j,i); |
| | + } |
| | + } |
| | + m_spec.m_dtrans_ncols = reduced_ncols; |
| | + /* truncate m_dtrans at proper length (freeing extra) */ |
| | + trunc_col(); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(k == reduced_ncols); |
| | + } |
| | + |
| | + /* Allocate row map. */ |
| | + nrows = m_spec.m_dtrans_vector.size(); |
| | + m_spec.m_row_map = new int[nrows]; |
| | + for (i = 0; i < nrows; ++i) |
| | + { |
| | + m_spec.m_row_map[i] = -1; |
| | + } |
| | + |
| | + /* Process rows to reduce. */ |
| | + for (reduced_nrows = 0; ; ++reduced_nrows) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + for (i = 0; i < reduced_nrows; ++i) |
| | + { |
| | + CUtility.ASSERT(-1 != m_spec.m_row_map[i]); |
| | + } |
| | + } |
| | + |
| | + for (i = reduced_nrows; i < nrows; ++i) |
| | + { |
| | + if (-1 == m_spec.m_row_map[i]) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (i >= nrows) |
| | + { |
| | + break; |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == set.get(i)); |
| | + CUtility.ASSERT(-1 == m_spec.m_row_map[i]); |
| | + } |
| | + |
| | + set.set(i); |
| | + |
| | + m_spec.m_row_map[i] = reduced_nrows; |
| | + |
| | + /* UNDONE: Optimize by doing all comparisons in one batch. */ |
| | + for (j = i + 1; j < nrows; ++j) |
| | + { |
| | + if (-1 == m_spec.m_row_map[j] && true == row_equiv(i,j)) |
| | + { |
| | + m_spec.m_row_map[j] = reduced_nrows; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /* Reduce rows. */ |
| | + k = 0; |
| | + for (i = 0; i < nrows; ++i) |
| | + { |
| | + if (set.get(i)) |
| | + { |
| | + ++k; |
| | + |
| | + set.clear(i); |
| | + |
| | + j = m_spec.m_row_map[i]; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(j <= i); |
| | + } |
| | + |
| | + if (j == i) |
| | + { |
| | + continue; |
| | + } |
| | + |
| | + row_copy(j,i); |
| | + } |
| | + } |
| | + m_spec.m_dtrans_vector.setSize(reduced_nrows); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + /*System.out.println("k = " + k + "\nreduced_nrows = " + reduced_nrows + "");*/ |
| | + CUtility.ASSERT(k == reduced_nrows); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: fix_dtrans |
| | + Description: Updates CDTrans table after minimization |
| | + using groups, removing redundant transition table states. |
| | + **************************************************************/ |
| | + private void fix_dtrans |
| | + ( |
| | + ) |
| | + { |
| | + Vector new_vector; |
| | + int i; |
| | + int size; |
| | + Vector dtrans_group; |
| | + CDTrans first; |
| | + int c; |
| | + |
| | + new_vector = new Vector(); |
| | + |
| | + size = m_spec.m_state_dtrans.length; |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + if (CDTrans.F != m_spec.m_state_dtrans[i]) |
| | + { |
| | + m_spec.m_state_dtrans[i] = m_ingroup[m_spec.m_state_dtrans[i]]; |
| | + } |
| | + } |
| | + |
| | + size = m_group.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + dtrans_group = (Vector) m_group.elementAt(i); |
| | + first = (CDTrans) dtrans_group.elementAt(0); |
| | + new_vector.addElement(first); |
| | + |
| | + for (c = 0; c < m_spec.m_dtrans_ncols; ++c) |
| | + { |
| | + if (CDTrans.F != first.m_dtrans[c]) |
| | + { |
| | + first.m_dtrans[c] = m_ingroup[first.m_dtrans[c]]; |
| | + } |
| | + } |
| | + } |
| | + |
| | + m_group = null; |
| | + m_spec.m_dtrans_vector = new_vector; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: minimize |
| | + Description: Removes redundant transition table states. |
| | + **************************************************************/ |
| | + private void minimize |
| | + ( |
| | + ) |
| | + { |
| | + Vector dtrans_group; |
| | + Vector new_group; |
| | + int i; |
| | + int j; |
| | + int old_group_count; |
| | + int group_count; |
| | + CDTrans next; |
| | + CDTrans first; |
| | + int goto_first; |
| | + int goto_next; |
| | + int c; |
| | + int group_size; |
| | + boolean added; |
| | + |
| | + init_groups(); |
| | + |
| | + group_count = m_group.size(); |
| | + old_group_count = group_count - 1; |
| | + |
| | + while (old_group_count != group_count) |
| | + { |
| | + old_group_count = group_count; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_group.size() == group_count); |
| | + } |
| | + |
| | + for (i = 0; i < group_count; ++i) |
| | + { |
| | + dtrans_group = (Vector) m_group.elementAt(i); |
| | + |
| | + group_size = dtrans_group.size(); |
| | + if (group_size <= 1) |
| | + { |
| | + continue; |
| | + } |
| | + |
| | + new_group = new Vector(); |
| | + added = false; |
| | + |
| | + first = (CDTrans) dtrans_group.elementAt(0); |
| | + for (j = 1; j < group_size; ++j) |
| | + { |
| | + next = (CDTrans) dtrans_group.elementAt(j); |
| | + |
| | + for (c = 0; c < m_spec.m_dtrans_ncols; ++c) |
| | + { |
| | + goto_first = first.m_dtrans[c]; |
| | + goto_next = next.m_dtrans[c]; |
| | + |
| | + if (goto_first != goto_next |
| | + && (goto_first == CDTrans.F |
| | + || goto_next == CDTrans.F |
| | + || m_ingroup[goto_next] != m_ingroup[goto_first])) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(dtrans_group.elementAt(j) == next); |
| | + } |
| | + |
| | + dtrans_group.removeElementAt(j); |
| | + --j; |
| | + --group_size; |
| | + new_group.addElement(next); |
| | + if (false == added) |
| | + { |
| | + added = true; |
| | + ++group_count; |
| | + m_group.addElement(new_group); |
| | + } |
| | + m_ingroup[next.m_label] = m_group.size() - 1; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_group.contains(new_group) |
| | + == true); |
| | + CUtility.ASSERT(m_group.contains(dtrans_group) |
| | + == true); |
| | + CUtility.ASSERT(dtrans_group.contains(first) |
| | + == true); |
| | + CUtility.ASSERT(dtrans_group.contains(next) |
| | + == false); |
| | + CUtility.ASSERT(new_group.contains(first) |
| | + == false); |
| | + CUtility.ASSERT(new_group.contains(next) |
| | + == true); |
| | + CUtility.ASSERT(dtrans_group.size() == group_size); |
| | + CUtility.ASSERT(i == m_ingroup[first.m_label]); |
| | + CUtility.ASSERT((m_group.size() - 1) |
| | + == m_ingroup[next.m_label]); |
| | + } |
| | + |
| | + break; |
| | + } |
| | + } |
| | + } |
| | + } |
| | + } |
| | + |
| | + System.out.println(m_group.size() + " states after removal of redundant states."); |
| | + |
| | + if (m_spec.m_verbose |
| | + && true == CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println(); |
| | + System.out.println("States grouped as follows after minimization"); |
| | + pgroups(); |
| | + } |
| | + |
| | + fix_dtrans(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: init_groups |
| | + Description: |
| | + **************************************************************/ |
| | + private void init_groups |
| | + ( |
| | + ) |
| | + { |
| | + int i; |
| | + int j; |
| | + int group_count; |
| | + int size; |
| | + CAccept accept; |
| | + CDTrans dtrans; |
| | + Vector dtrans_group; |
| | + CDTrans first; |
| | + boolean group_found; |
| | + |
| | + m_group = new Vector(); |
| | + group_count = 0; |
| | + |
| | + size = m_spec.m_dtrans_vector.size(); |
| | + m_ingroup = new int[size]; |
| | + |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + group_found = false; |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(i == dtrans.m_label); |
| | + CUtility.ASSERT(false == group_found); |
| | + CUtility.ASSERT(group_count == m_group.size()); |
| | + } |
| | + |
| | + for (j = 0; j < group_count; ++j) |
| | + { |
| | + dtrans_group = (Vector) m_group.elementAt(j); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == group_found); |
| | + CUtility.ASSERT(0 < dtrans_group.size()); |
| | + } |
| | + |
| | + first = (CDTrans) dtrans_group.elementAt(0); |
| | + |
| | + if (CUtility.SLOW_DEBUG) |
| | + { |
| | + CDTrans check; |
| | + int k; |
| | + int s; |
| | + |
| | + s = dtrans_group.size(); |
| | + CUtility.ASSERT(0 < s); |
| | + |
| | + for (k = 1; k < s; ++k) |
| | + { |
| | + check = (CDTrans) dtrans_group.elementAt(k); |
| | + CUtility.ASSERT(check.m_accept == first.m_accept); |
| | + } |
| | + } |
| | + |
| | + if (first.m_accept == dtrans.m_accept) |
| | + { |
| | + dtrans_group.addElement(dtrans); |
| | + m_ingroup[i] = j; |
| | + group_found = true; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(j == m_ingroup[dtrans.m_label]); |
| | + } |
| | + |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (false == group_found) |
| | + { |
| | + dtrans_group = new Vector(); |
| | + dtrans_group.addElement(dtrans); |
| | + m_ingroup[i] = m_group.size(); |
| | + m_group.addElement(dtrans_group); |
| | + ++group_count; |
| | + } |
| | + } |
| | + |
| | + if (m_spec.m_verbose |
| | + && true == CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println("Initial grouping:"); |
| | + pgroups(); |
| | + System.out.println(); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: pset |
| | + **************************************************************/ |
| | + private void pset |
| | + ( |
| | + Vector dtrans_group |
| | + ) |
| | + { |
| | + int i; |
| | + int size; |
| | + CDTrans dtrans; |
| | + |
| | + size = dtrans_group.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + dtrans = (CDTrans) dtrans_group.elementAt(i); |
| | + System.out.print(dtrans.m_label + " "); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: pgroups |
| | + **************************************************************/ |
| | + private void pgroups |
| | + ( |
| | + ) |
| | + { |
| | + int i; |
| | + int dtrans_size; |
| | + int group_size; |
| | + |
| | + group_size = m_group.size(); |
| | + for (i = 0; i < group_size; ++i) |
| | + { |
| | + System.out.print("\tGroup " + i + " {"); |
| | + pset((Vector) m_group.elementAt(i)); |
| | + System.out.println("}"); |
| | + System.out.println(); |
| | + } |
| | + |
| | + System.out.println(); |
| | + dtrans_size = m_spec.m_dtrans_vector.size(); |
| | + for (i = 0; i < dtrans_size; ++i) |
| | + { |
| | + System.out.println("\tstate " + i |
| | + + " is in group " |
| | + + m_ingroup[i]); |
| | + } |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CNfa2Dfa |
| | + **************************************************************/ |
| | +class CNfa2Dfa |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + private CSpec m_spec; |
| | + private int m_unmarked_dfa; |
| | + private CLexGen m_lexGen; |
| | + |
| | + /*************************************************************** |
| | + Constants |
| | + **************************************************************/ |
| | + private static final int NOT_IN_DSTATES = -1; |
| | + |
| | + /*************************************************************** |
| | + Function: CNfa2Dfa |
| | + **************************************************************/ |
| | + CNfa2Dfa |
| | + ( |
| | + ) |
| | + { |
| | + reset(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: set |
| | + Description: |
| | + **************************************************************/ |
| | + private void set |
| | + ( |
| | + CLexGen lexGen, |
| | + CSpec spec |
| | + ) |
| | + { |
| | + m_lexGen = lexGen; |
| | + m_spec = spec; |
| | + m_unmarked_dfa = 0; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: reset |
| | + Description: |
| | + **************************************************************/ |
| | + private void reset |
| | + ( |
| | + ) |
| | + { |
| | + m_lexGen = null; |
| | + m_spec = null; |
| | + m_unmarked_dfa = 0; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: make_dfa |
| | + Description: High-level access function to module. |
| | + **************************************************************/ |
| | + void make_dfa |
| | + ( |
| | + CLexGen lexGen, |
| | + CSpec spec |
| | + ) |
| | + { |
| | + int i; |
| | + |
| | + reset(); |
| | + set(lexGen,spec); |
| | + |
| | + make_dtrans(); |
| | + free_nfa_states(); |
| | + |
| | + if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println(m_spec.m_dfa_states.size() |
| | + + " DFA states in original machine."); |
| | + } |
| | + |
| | + free_dfa_states(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: make_dtrans |
| | + Description: Creates uncompressed CDTrans transition table. |
| | + **************************************************************/ |
| | + private void make_dtrans |
| | + ( |
| | + ) |
| | + /* throws java.lang.CloneNotSupportedException*/ |
| | + { |
| | + CDfa next; |
| | + CDfa dfa; |
| | + CBunch bunch; |
| | + int i; |
| | + int nextstate; |
| | + int size; |
| | + CDTrans dtrans; |
| | + CNfa nfa; |
| | + int istate; |
| | + int nstates; |
| | + |
| | + System.out.print("Working on DFA states."); |
| | + |
| | + /* Reference passing type and initializations. */ |
| | + bunch = new CBunch(); |
| | + m_unmarked_dfa = 0; |
| | + |
| | + /* Allocate mapping array. */ |
| | + nstates = m_spec.m_state_rules.length; |
| | + m_spec.m_state_dtrans = new int[nstates]; |
| | + |
| | + for (istate = 0; nstates > istate; ++istate) |
| | + { |
| | + /* CSA bugfix: if we skip all zero size rules, then |
| | + an specification with no rules produces an illegal |
| | + lexer (0 states) instead of a lexer that rejects |
| | + everything (1 nonaccepting state). [27-Jul-1999] |
| | + if (0 == m_spec.m_state_rules[istate].size()) |
| | + { |
| | + m_spec.m_state_dtrans[istate] = CDTrans.F; |
| | + continue; |
| | + } |
| | + */ |
| | + |
| | + /* Create start state and initialize fields. */ |
| | + bunch.m_nfa_set = (Vector) m_spec.m_state_rules[istate].clone(); |
| | + sortStates(bunch.m_nfa_set); |
| | + |
| | + bunch.m_nfa_bit = new SparseBitSet(); |
| | + |
| | + /* Initialize bit set. */ |
| | + size = bunch.m_nfa_set.size(); |
| | + for (i = 0; size > i; ++i) |
| | + { |
| | + nfa = (CNfa) bunch.m_nfa_set.elementAt(i); |
| | + bunch.m_nfa_bit.set(nfa.m_label); |
| | + } |
| | + |
| | + bunch.m_accept = null; |
| | + bunch.m_anchor = CSpec.NONE; |
| | + bunch.m_accept_index = CUtility.INT_MAX; |
| | + |
| | + e_closure(bunch); |
| | + add_to_dstates(bunch); |
| | + |
| | + m_spec.m_state_dtrans[istate] = m_spec.m_dtrans_vector.size(); |
| | + |
| | + /* Main loop of CDTrans creation. */ |
| | + while (null != (dfa = get_unmarked())) |
| | + { |
| | + System.out.print("."); |
| | + System.out.flush(); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == dfa.m_mark); |
| | + } |
| | + |
| | + /* Get first unmarked node, then mark it. */ |
| | + dfa.m_mark = true; |
| | + |
| | + /* Allocate new CDTrans, then initialize fields. */ |
| | + dtrans = new CDTrans(m_spec.m_dtrans_vector.size(),m_spec); |
| | + dtrans.m_accept = dfa.m_accept; |
| | + dtrans.m_anchor = dfa.m_anchor; |
| | + |
| | + /* Set CDTrans array for each character transition. */ |
| | + for (i = 0; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(0 <= i); |
| | + CUtility.ASSERT(m_spec.m_dtrans_ncols > i); |
| | + } |
| | + |
| | + /* Create new dfa set by attempting character transition. */ |
| | + move(dfa.m_nfa_set,dfa.m_nfa_bit,i,bunch); |
| | + if (null != bunch.m_nfa_set) |
| | + { |
| | + e_closure(bunch); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT((null == bunch.m_nfa_set |
| | + && null == bunch.m_nfa_bit) |
| | + || (null != bunch.m_nfa_set |
| | + && null != bunch.m_nfa_bit)); |
| | + } |
| | + |
| | + /* Create new state or set state to empty. */ |
| | + if (null == bunch.m_nfa_set) |
| | + { |
| | + nextstate = CDTrans.F; |
| | + } |
| | + else |
| | + { |
| | + nextstate = in_dstates(bunch); |
| | + |
| | + if (NOT_IN_DSTATES == nextstate) |
| | + { |
| | + nextstate = add_to_dstates(bunch); |
| | + } |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(nextstate < m_spec.m_dfa_states.size()); |
| | + } |
| | + |
| | + dtrans.m_dtrans[i] = nextstate; |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_spec.m_dtrans_vector.size() == dfa.m_label); |
| | + } |
| | + |
| | + m_spec.m_dtrans_vector.addElement(dtrans); |
| | + } |
| | + } |
| | + |
| | + System.out.println(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: free_dfa_states |
| | + **************************************************************/ |
| | + private void free_dfa_states |
| | + ( |
| | + ) |
| | + { |
| | + m_spec.m_dfa_states = null; |
| | + m_spec.m_dfa_sets = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: free_nfa_states |
| | + **************************************************************/ |
| | + private void free_nfa_states |
| | + ( |
| | + ) |
| | + { |
| | + /* UNDONE: Remove references to nfas from within dfas. */ |
| | + /* UNDONE: Don't free CAccepts. */ |
| | + |
| | + m_spec.m_nfa_states = null; |
| | + m_spec.m_nfa_start = null; |
| | + m_spec.m_state_rules = null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: e_closure |
| | + Description: Alters and returns input set. |
| | + **************************************************************/ |
| | + private void e_closure |
| | + ( |
| | + CBunch bunch |
| | + ) |
| | + { |
| | + Stack nfa_stack; |
| | + int size; |
| | + int i; |
| | + CNfa state; |
| | + |
| | + /* Debug checks. */ |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != bunch); |
| | + CUtility.ASSERT(null != bunch.m_nfa_set); |
| | + CUtility.ASSERT(null != bunch.m_nfa_bit); |
| | + } |
| | + |
| | + bunch.m_accept = null; |
| | + bunch.m_anchor = CSpec.NONE; |
| | + bunch.m_accept_index = CUtility.INT_MAX; |
| | + |
| | + /* Create initial stack. */ |
| | + nfa_stack = new Stack(); |
| | + size = bunch.m_nfa_set.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + state = (CNfa) bunch.m_nfa_set.elementAt(i); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(bunch.m_nfa_bit.get(state.m_label)); |
| | + } |
| | + |
| | + nfa_stack.push(state); |
| | + } |
| | + |
| | + /* Main loop. */ |
| | + while (false == nfa_stack.empty()) |
| | + { |
| | + state = (CNfa) nfa_stack.pop(); |
| | + |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + if (null != state.m_accept) |
| | + { |
| | + System.out.println("Looking at accepting state " + state.m_label |
| | + + " with <" |
| | + + (new String(state.m_accept.m_action,0, |
| | + state.m_accept.m_action_read)) |
| | + + ">"); |
| | + } |
| | + } |
| | + |
| | + if (null != state.m_accept |
| | + && state.m_label < bunch.m_accept_index) |
| | + { |
| | + bunch.m_accept_index = state.m_label; |
| | + bunch.m_accept = state.m_accept; |
| | + bunch.m_anchor = state.m_anchor; |
| | + |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println("Found accepting state " + state.m_label |
| | + + " with <" |
| | + + (new String(state.m_accept.m_action,0, |
| | + state.m_accept.m_action_read)) |
| | + + ">"); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != bunch.m_accept); |
| | + CUtility.ASSERT(CSpec.NONE == bunch.m_anchor |
| | + || 0 != (bunch.m_anchor & CSpec.END) |
| | + || 0 != (bunch.m_anchor & CSpec.START)); |
| | + } |
| | + } |
| | + |
| | + if (CNfa.EPSILON == state.m_edge) |
| | + { |
| | + if (null != state.m_next) |
| | + { |
| | + if (false == bunch.m_nfa_set.contains(state.m_next)) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == bunch.m_nfa_bit.get(state.m_next.m_label)); |
| | + } |
| | + |
| | + bunch.m_nfa_bit.set(state.m_next.m_label); |
| | + bunch.m_nfa_set.addElement(state.m_next); |
| | + nfa_stack.push(state.m_next); |
| | + } |
| | + } |
| | + |
| | + if (null != state.m_next2) |
| | + { |
| | + if (false == bunch.m_nfa_set.contains(state.m_next2)) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(false == bunch.m_nfa_bit.get(state.m_next2.m_label)); |
| | + } |
| | + |
| | + bunch.m_nfa_bit.set(state.m_next2.m_label); |
| | + bunch.m_nfa_set.addElement(state.m_next2); |
| | + nfa_stack.push(state.m_next2); |
| | + } |
| | + } |
| | + } |
| | + } |
| | + |
| | + if (null != bunch.m_nfa_set) |
| | + { |
| | + sortStates(bunch.m_nfa_set); |
| | + } |
| | + |
| | + return; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: move |
| | + Description: Returns null if resulting NFA set is empty. |
| | + **************************************************************/ |
| | + void move |
| | + ( |
| | + Vector nfa_set, |
| | + SparseBitSet nfa_bit, |
| | + int b, |
| | + CBunch bunch |
| | + ) |
| | + { |
| | + int size; |
| | + int index; |
| | + CNfa state; |
| | + |
| | + bunch.m_nfa_set = null; |
| | + bunch.m_nfa_bit = null; |
| | + |
| | + size = nfa_set.size(); |
| | + for (index = 0; index < size; ++index) |
| | + { |
| | + state = (CNfa) nfa_set.elementAt(index); |
| | + |
| | + if (b == state.m_edge |
| | + || (CNfa.CCL == state.m_edge |
| | + && true == state.m_set.contains(b))) |
| | + { |
| | + if (null == bunch.m_nfa_set) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null == bunch.m_nfa_bit); |
| | + } |
| | + |
| | + bunch.m_nfa_set = new Vector(); |
| | + /*bunch.m_nfa_bit |
| | + = new SparseBitSet(m_spec.m_nfa_states.size());*/ |
| | + bunch.m_nfa_bit = new SparseBitSet(); |
| | + } |
| | + |
| | + bunch.m_nfa_set.addElement(state.m_next); |
| | + /*System.out.println("Size of bitset: " + bunch.m_nfa_bit.size()); |
| | + System.out.println("Reference index: " + state.m_next.m_label); |
| | + System.out.flush();*/ |
| | + bunch.m_nfa_bit.set(state.m_next.m_label); |
| | + } |
| | + } |
| | + |
| | + if (null != bunch.m_nfa_set) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != bunch.m_nfa_bit); |
| | + } |
| | + |
| | + sortStates(bunch.m_nfa_set); |
| | + } |
| | + |
| | + return; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: sortStates |
| | + **************************************************************/ |
| | + private void sortStates |
| | + ( |
| | + Vector nfa_set |
| | + ) |
| | + { |
| | + CNfa elem; |
| | + int begin; |
| | + int size; |
| | + int index; |
| | + int value; |
| | + int smallest_index; |
| | + int smallest_value; |
| | + CNfa begin_elem; |
| | + |
| | + size = nfa_set.size(); |
| | + for (begin = 0; begin < size; ++begin) |
| | + { |
| | + elem = (CNfa) nfa_set.elementAt(begin); |
| | + smallest_value = elem.m_label; |
| | + smallest_index = begin; |
| | + |
| | + for (index = begin + 1; index < size; ++index) |
| | + { |
| | + elem = (CNfa) nfa_set.elementAt(index); |
| | + value = elem.m_label; |
| | + |
| | + if (value < smallest_value) |
| | + { |
| | + smallest_index = index; |
| | + smallest_value = value; |
| | + } |
| | + } |
| | + |
| | + begin_elem = (CNfa) nfa_set.elementAt(begin); |
| | + elem = (CNfa) nfa_set.elementAt(smallest_index); |
| | + nfa_set.setElementAt(elem,begin); |
| | + nfa_set.setElementAt(begin_elem,smallest_index); |
| | + } |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.print("NFA vector indices: "); |
| | + |
| | + for (index = 0; index < size; ++index) |
| | + { |
| | + elem = (CNfa) nfa_set.elementAt(index); |
| | + System.out.print(elem.m_label + " "); |
| | + } |
| | + System.out.println(); |
| | + } |
| | + |
| | + return; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: get_unmarked |
| | + Description: Returns next unmarked DFA state. |
| | + **************************************************************/ |
| | + private CDfa get_unmarked |
| | + ( |
| | + ) |
| | + { |
| | + int size; |
| | + CDfa dfa; |
| | + |
| | + size = m_spec.m_dfa_states.size(); |
| | + while (m_unmarked_dfa < size) |
| | + { |
| | + dfa = (CDfa) m_spec.m_dfa_states.elementAt(m_unmarked_dfa); |
| | + |
| | + if (false == dfa.m_mark) |
| | + { |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.print("*"); |
| | + System.out.flush(); |
| | + } |
| | + |
| | + if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println("---------------"); |
| | + System.out.print("working on DFA state " |
| | + + m_unmarked_dfa |
| | + + " = NFA states: "); |
| | + m_lexGen.print_set(dfa.m_nfa_set); |
| | + System.out.println(); |
| | + } |
| | + |
| | + return dfa; |
| | + } |
| | + |
| | + ++m_unmarked_dfa; |
| | + } |
| | + |
| | + return null; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + function: add_to_dstates |
| | + Description: Takes as input a CBunch with details of |
| | + a dfa state that needs to be created. |
| | + 1) Allocates a new dfa state and saves it in |
| | + the appropriate CSpec vector. |
| | + 2) Initializes the fields of the dfa state |
| | + with the information in the CBunch. |
| | + 3) Returns index of new dfa. |
| | + **************************************************************/ |
| | + private int add_to_dstates |
| | + ( |
| | + CBunch bunch |
| | + ) |
| | + { |
| | + CDfa dfa; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != bunch.m_nfa_set); |
| | + CUtility.ASSERT(null != bunch.m_nfa_bit); |
| | + CUtility.ASSERT(null != bunch.m_accept |
| | + || CSpec.NONE == bunch.m_anchor); |
| | + } |
| | + |
| | + /* Allocate, passing CSpec so dfa label can be set. */ |
| | + dfa = CAlloc.newCDfa(m_spec); |
| | + |
| | + /* Initialize fields, including the mark field. */ |
| | + dfa.m_nfa_set = (Vector) bunch.m_nfa_set.clone(); |
| | + dfa.m_nfa_bit = (SparseBitSet) bunch.m_nfa_bit.clone(); |
| | + dfa.m_accept = bunch.m_accept; |
| | + dfa.m_anchor = bunch.m_anchor; |
| | + dfa.m_mark = false; |
| | + |
| | + /* Register dfa state using BitSet in CSpec Hashtable. */ |
| | + m_spec.m_dfa_sets.put(dfa.m_nfa_bit,dfa); |
| | + /*registerCDfa(dfa);*/ |
| | + |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.print("Registering set : "); |
| | + m_lexGen.print_set(dfa.m_nfa_set); |
| | + System.out.println(); |
| | + } |
| | + |
| | + return dfa.m_label; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: in_dstates |
| | + **************************************************************/ |
| | + private int in_dstates |
| | + ( |
| | + CBunch bunch |
| | + ) |
| | + { |
| | + CDfa dfa; |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.print("Looking for set : "); |
| | + m_lexGen.print_set(bunch.m_nfa_set); |
| | + } |
| | + |
| | + dfa = (CDfa) m_spec.m_dfa_sets.get(bunch.m_nfa_bit); |
| | + |
| | + if (null != dfa) |
| | + { |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println(" FOUND!"); |
| | + } |
| | + |
| | + return dfa.m_label; |
| | + } |
| | + |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println(" NOT FOUND!"); |
| | + } |
| | + return NOT_IN_DSTATES; |
| | + } |
| | + |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CAlloc |
| | + **************************************************************/ |
| | +class CAlloc |
| | +{ |
| | + /*************************************************************** |
| | + Function: newCDfa |
| | + **************************************************************/ |
| | + static CDfa newCDfa |
| | + ( |
| | + CSpec spec |
| | + ) |
| | + { |
| | + CDfa dfa; |
| | + |
| | + dfa = new CDfa(spec.m_dfa_states.size()); |
| | + spec.m_dfa_states.addElement(dfa); |
| | + |
| | + return dfa; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: newCNfaPair |
| | + Description: |
| | + **************************************************************/ |
| | + static CNfaPair newCNfaPair |
| | + ( |
| | + ) |
| | + { |
| | + CNfaPair pair = new CNfaPair(); |
| | + |
| | + return pair; |
| | + } |
| | + /*************************************************************** |
| | + Function: newNLPair |
| | + Description: return a new CNfaPair that matches a new |
| | + line: (\r\n?|[\n\uu2028\uu2029]) |
| | + Added by CSA 8-Aug-1999, updated 10-Aug-1999 |
| | + **************************************************************/ |
| | + static CNfaPair newNLPair(CSpec spec) { |
| | + CNfaPair pair = newCNfaPair(); |
| | + pair.m_end=newCNfa(spec); // newline accepting state |
| | + pair.m_start=newCNfa(spec); // new state with two epsilon edges |
| | + pair.m_start.m_next = newCNfa(spec); |
| | + pair.m_start.m_next.m_edge = CNfa.CCL; |
| | + pair.m_start.m_next.m_set = new CSet(); |
| | + pair.m_start.m_next.m_set.add('\n'); |
| | + if (spec.m_dtrans_ncols-CSpec.NUM_PSEUDO > 2029) { |
| | + pair.m_start.m_next.m_set.add(2028); /*U+2028 is LS, the line separator*/ |
| | + pair.m_start.m_next.m_set.add(2029); /*U+2029 is PS, the paragraph sep.*/ |
| | + } |
| | + pair.m_start.m_next.m_next = pair.m_end; // accept '\n', U+2028, or U+2029 |
| | + pair.m_start.m_next2 = newCNfa(spec); |
| | + pair.m_start.m_next2.m_edge = '\r'; |
| | + pair.m_start.m_next2.m_next = newCNfa(spec); |
| | + pair.m_start.m_next2.m_next.m_next = pair.m_end; // accept '\r'; |
| | + pair.m_start.m_next2.m_next.m_next2 = newCNfa(spec); |
| | + pair.m_start.m_next2.m_next.m_next2.m_edge = '\n'; |
| | + pair.m_start.m_next2.m_next.m_next2.m_next = pair.m_end; // accept '\r\n'; |
| | + return pair; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: newCNfa |
| | + Description: |
| | + **************************************************************/ |
| | + static CNfa newCNfa |
| | + ( |
| | + CSpec spec |
| | + ) |
| | + { |
| | + CNfa p; |
| | + |
| | + /* UNDONE: Buffer this? */ |
| | + |
| | + p = new CNfa(); |
| | + |
| | + /*p.m_label = spec.m_nfa_states.size();*/ |
| | + spec.m_nfa_states.addElement(p); |
| | + p.m_edge = CNfa.EPSILON; |
| | + |
| | + return p; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: Main |
| | + Description: Top-level lexical analyzer generator function. |
| | + **************************************************************/ |
| | +public class Main |
| | +{ |
| | + /*************************************************************** |
| | + Function: main |
| | + **************************************************************/ |
| | + public static void main |
| | + ( |
| | + String arg[] |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CLexGen lg; |
| | + |
| | + if (arg.length < 1) |
| | + { |
| | + System.out.println("Usage: JLex.Main <filename>"); |
| | + return; |
| | + } |
| | + |
| | + /* Note: For debuging, it may be helpful to remove the try/catch |
| | + block and permit the Exception to propagate to the top level. |
| | + This gives more information. */ |
| | + try |
| | + { |
| | + lg = new CLexGen(arg[0]); |
| | + lg.generate(); |
| | + } |
| | + catch (Error e) |
| | + { |
| | + System.out.println(e.getMessage()); |
| | + } |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CDTrans |
| | + **************************************************************/ |
| | +class CDTrans |
| | +{ |
| | + /************************************************************* |
| | + Member Variables |
| | + ***********************************************************/ |
| | + int m_dtrans[]; |
| | + CAccept m_accept; |
| | + int m_anchor; |
| | + int m_label; |
| | + |
| | + /************************************************************* |
| | + Constants |
| | + ***********************************************************/ |
| | + static final int F = -1; |
| | + |
| | + /************************************************************* |
| | + Function: CTrans |
| | + ***********************************************************/ |
| | + CDTrans |
| | + ( |
| | + int label, |
| | + CSpec spec |
| | + ) |
| | + { |
| | + m_dtrans = new int[spec.m_dtrans_ncols]; |
| | + m_accept = null; |
| | + m_anchor = CSpec.NONE; |
| | + m_label = label; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CDfa |
| | + **************************************************************/ |
| | +class CDfa |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + ***********************************************************/ |
| | + int m_group; |
| | + boolean m_mark; |
| | + CAccept m_accept; |
| | + int m_anchor; |
| | + Vector m_nfa_set; |
| | + SparseBitSet m_nfa_bit; |
| | + int m_label; |
| | + |
| | + /*************************************************************** |
| | + Function: CDfa |
| | + **************************************************************/ |
| | + CDfa |
| | + ( |
| | + int label |
| | + ) |
| | + { |
| | + m_group = 0; |
| | + m_mark = false; |
| | + |
| | + m_accept = null; |
| | + m_anchor = CSpec.NONE; |
| | + |
| | + m_nfa_set = null; |
| | + m_nfa_bit = null; |
| | + |
| | + m_label = label; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CAccept |
| | + **************************************************************/ |
| | +class CAccept |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + char m_action[]; |
| | + int m_action_read; |
| | + int m_line_number; |
| | + |
| | + /*************************************************************** |
| | + Function: CAccept |
| | + **************************************************************/ |
| | + CAccept |
| | + ( |
| | + char action[], |
| | + int action_read, |
| | + int line_number |
| | + ) |
| | + { |
| | + int elem; |
| | + |
| | + m_action_read = action_read; |
| | + |
| | + m_action = new char[m_action_read]; |
| | + for (elem = 0; elem < m_action_read; ++elem) |
| | + { |
| | + m_action[elem] = action[elem]; |
| | + } |
| | + |
| | + m_line_number = line_number; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: CAccept |
| | + **************************************************************/ |
| | + CAccept |
| | + ( |
| | + CAccept accept |
| | + ) |
| | + { |
| | + int elem; |
| | + |
| | + m_action_read = accept.m_action_read; |
| | + |
| | + m_action = new char[m_action_read]; |
| | + for (elem = 0; elem < m_action_read; ++elem) |
| | + { |
| | + m_action[elem] = accept.m_action[elem]; |
| | + } |
| | + |
| | + m_line_number = accept.m_line_number; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: mimic |
| | + **************************************************************/ |
| | + void mimic |
| | + ( |
| | + CAccept accept |
| | + ) |
| | + { |
| | + int elem; |
| | + |
| | + m_action_read = accept.m_action_read; |
| | + |
| | + m_action = new char[m_action_read]; |
| | + for (elem = 0; elem < m_action_read; ++elem) |
| | + { |
| | + m_action[elem] = accept.m_action[elem]; |
| | + } |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CAcceptAnchor |
| | + **************************************************************/ |
| | +class CAcceptAnchor |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + CAccept m_accept; |
| | + int m_anchor; |
| | + |
| | + /*************************************************************** |
| | + Function: CAcceptAnchor |
| | + **************************************************************/ |
| | + CAcceptAnchor |
| | + ( |
| | + ) |
| | + { |
| | + m_accept = null; |
| | + m_anchor = CSpec.NONE; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CNfaPair |
| | + **************************************************************/ |
| | +class CNfaPair |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + CNfa m_start; |
| | + CNfa m_end; |
| | + |
| | + /*************************************************************** |
| | + Function: CNfaPair |
| | + **************************************************************/ |
| | + CNfaPair |
| | + ( |
| | + ) |
| | + { |
| | + m_start = null; |
| | + m_end = null; |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CInput |
| | + Description: |
| | + **************************************************************/ |
| | +class CInput |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + private java.io.BufferedReader m_input; /* JLex specification file. */ |
| | + |
| | + boolean m_eof_reached; /* Whether EOF has been encountered. */ |
| | + boolean m_pushback_line; |
| | + |
| | + char m_line[]; /* Line buffer. */ |
| | + int m_line_read; /* Number of bytes read into line buffer. */ |
| | + int m_line_index; /* Current index into line buffer. */ |
| | + |
| | + int m_line_number; /* Current line number. */ |
| | + |
| | + /*************************************************************** |
| | + Constants |
| | + **************************************************************/ |
| | + static final boolean EOF = true; |
| | + static final boolean NOT_EOF = false; |
| | + |
| | + /*************************************************************** |
| | + Function: CInput |
| | + Description: |
| | + **************************************************************/ |
| | + CInput |
| | + ( |
| | + java.io.Reader input |
| | + ) |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != input); |
| | + } |
| | + |
| | + /* Initialize input stream. */ |
| | + m_input = new java.io.BufferedReader(input); |
| | + |
| | + /* Initialize buffers and index counters. */ |
| | + m_line = null; |
| | + m_line_read = 0; |
| | + m_line_index = 0; |
| | + |
| | + /* Initialize state variables. */ |
| | + m_eof_reached = false; |
| | + m_line_number = 0; |
| | + m_pushback_line = false; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: getLine |
| | + Description: Returns true on EOF, false otherwise. |
| | + Guarantees not to return a blank line, or a line |
| | + of zero length. |
| | + **************************************************************/ |
| | + boolean getLine |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + String lineStr; |
| | + int elem; |
| | + |
| | + /* Has EOF already been reached? */ |
| | + if (m_eof_reached) |
| | + { |
| | + return EOF; |
| | + } |
| | + |
| | + /* Pushback current line? */ |
| | + if (m_pushback_line) |
| | + { |
| | + m_pushback_line = false; |
| | + |
| | + /* Check for empty line. */ |
| | + for (elem = 0; elem < m_line_read; ++elem) |
| | + { |
| | + if (false == CUtility.isspace(m_line[elem])) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + /* Nonempty? */ |
| | + if (elem < m_line_read) |
| | + { |
| | + m_line_index = 0; |
| | + return NOT_EOF; |
| | + } |
| | + } |
| | + |
| | + while (true) |
| | + { |
| | + if (null == (lineStr = m_input.readLine())) |
| | + { |
| | + m_eof_reached = true; |
| | + m_line_index = 0; |
| | + return EOF; |
| | + } |
| | + m_line = (lineStr + "\n").toCharArray(); |
| | + m_line_read=m_line.length; |
| | + ++m_line_number; |
| | + |
| | + /* Check for empty lines and discard them. */ |
| | + elem = 0; |
| | + while (CUtility.isspace(m_line[elem])) |
| | + { |
| | + ++elem; |
| | + if (elem == m_line_read) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (elem < m_line_read) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + m_line_index = 0; |
| | + return NOT_EOF; |
| | + } |
| | +} |
| | + |
| | +/******************************************************** |
| | + Class: Utility |
| | + *******************************************************/ |
| | +class CUtility |
| | +{ |
| | + /******************************************************** |
| | + Constants |
| | + *******************************************************/ |
| | + static final boolean DEBUG = true; |
| | + static final boolean SLOW_DEBUG = true; |
| | + static final boolean DUMP_DEBUG = true; |
| | + /*static final boolean DEBUG = false; |
| | + static final boolean SLOW_DEBUG = false; |
| | + static final boolean DUMP_DEBUG = false;*/ |
| | + static final boolean DESCENT_DEBUG = false; |
| | + static final boolean OLD_DEBUG = false; |
| | + static final boolean OLD_DUMP_DEBUG = false; |
| | + static final boolean FOODEBUG = false; |
| | + static final boolean DO_DEBUG = false; |
| | + |
| | + /******************************************************** |
| | + Constants: Integer Bounds |
| | + *******************************************************/ |
| | + static final int INT_MAX = 2147483647; |
| | + |
| | + static final int MAX_SEVEN_BIT = 127; |
| | + static final int MAX_EIGHT_BIT = 255; |
| | + static final int MAX_SIXTEEN_BIT=65535; |
| | + |
| | + /******************************************************** |
| | + Function: enter |
| | + Description: Debugging routine. |
| | + *******************************************************/ |
| | + static void enter |
| | + ( |
| | + String descent, |
| | + char lexeme, |
| | + int token |
| | + ) |
| | + { |
| | + System.out.println("Entering " + descent |
| | + + " [lexeme: " + lexeme |
| | + + "] [token: " + token + "]"); |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: leave |
| | + Description: Debugging routine. |
| | + *******************************************************/ |
| | + static void leave |
| | + ( |
| | + String descent, |
| | + char lexeme, |
| | + int token |
| | + ) |
| | + { |
| | + System.out.println("Leaving " + descent |
| | + + " [lexeme:" + lexeme |
| | + + "] [token:" + token + "]"); |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: ASSERT |
| | + Description: Debugging routine. |
| | + *******************************************************/ |
| | + static void ASSERT |
| | + ( |
| | + boolean expr |
| | + ) |
| | + { |
| | + if (DEBUG && false == expr) |
| | + { |
| | + System.out.println("Assertion Failed"); |
| | + throw new Error("Assertion Failed."); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: doubleSize |
| | + **************************************************************/ |
| | + static char[] doubleSize |
| | + ( |
| | + char oldBuffer[] |
| | + ) |
| | + { |
| | + char newBuffer[] = new char[2 * oldBuffer.length]; |
| | + int elem; |
| | + |
| | + for (elem = 0; elem < oldBuffer.length; ++elem) |
| | + { |
| | + newBuffer[elem] = oldBuffer[elem]; |
| | + } |
| | + |
| | + return newBuffer; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: doubleSize |
| | + **************************************************************/ |
| | + static byte[] doubleSize |
| | + ( |
| | + byte oldBuffer[] |
| | + ) |
| | + { |
| | + byte newBuffer[] = new byte[2 * oldBuffer.length]; |
| | + int elem; |
| | + |
| | + for (elem = 0; elem < oldBuffer.length; ++elem) |
| | + { |
| | + newBuffer[elem] = oldBuffer[elem]; |
| | + } |
| | + |
| | + return newBuffer; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: hex2bin |
| | + *******************************************************/ |
| | + static char hex2bin |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if ('0' <= c && '9' >= c) |
| | + { |
| | + return (char) (c - '0'); |
| | + } |
| | + else if ('a' <= c && 'f' >= c) |
| | + { |
| | + return (char) (c - 'a' + 10); |
| | + } |
| | + else if ('A' <= c && 'F' >= c) |
| | + { |
| | + return (char) (c - 'A' + 10); |
| | + } |
| | + |
| | + CError.impos("Bad hexidecimal digit" + c); |
| | + return 0; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: ishexdigit |
| | + *******************************************************/ |
| | + static boolean ishexdigit |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if (('0' <= c && '9' >= c) |
| | + || ('a' <= c && 'f' >= c) |
| | + || ('A' <= c && 'F' >= c)) |
| | + { |
| | + return true; |
| | + } |
| | + |
| | + return false; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: oct2bin |
| | + *******************************************************/ |
| | + static char oct2bin |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if ('0' <= c && '7' >= c) |
| | + { |
| | + return (char) (c - '0'); |
| | + } |
| | + |
| | + CError.impos("Bad octal digit " + c); |
| | + return 0; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: isoctdigit |
| | + *******************************************************/ |
| | + static boolean isoctdigit |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if ('0' <= c && '7' >= c) |
| | + { |
| | + return true; |
| | + } |
| | + |
| | + return false; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: isspace |
| | + *******************************************************/ |
| | + static boolean isspace |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if ('\b' == c |
| | + || '\t' == c |
| | + || '\n' == c |
| | + || '\f' == c |
| | + || '\r' == c |
| | + || ' ' == c) |
| | + { |
| | + return true; |
| | + } |
| | + |
| | + return false; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: isnewline |
| | + *******************************************************/ |
| | + static boolean isnewline |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + if ('\n' == c |
| | + || '\r' == c) |
| | + { |
| | + return true; |
| | + } |
| | + |
| | + return false; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: bytencmp |
| | + Description: Compares up to n elements of |
| | + byte array a[] against byte array b[]. |
| | + The first byte comparison is made between |
| | + a[a_first] and b[b_first]. Comparisons continue |
| | + until the null terminating byte '\0' is reached |
| | + or until n bytes are compared. |
| | + Return Value: Returns 0 if arrays are the |
| | + same up to and including the null terminating byte |
| | + or up to and including the first n bytes, |
| | + whichever comes first. |
| | + *******************************************************/ |
| | + static int bytencmp |
| | + ( |
| | + byte a[], |
| | + int a_first, |
| | + byte b[], |
| | + int b_first, |
| | + int n |
| | + ) |
| | + { |
| | + int elem; |
| | + |
| | + for (elem = 0; elem < n; ++elem) |
| | + { |
| | + /*System.out.print((char) a[a_first + elem]); |
| | + System.out.print((char) b[b_first + elem]);*/ |
| | + |
| | + if ('\0' == a[a_first + elem] && '\0' == b[b_first + elem]) |
| | + { |
| | + /*System.out.println("return 0");*/ |
| | + return 0; |
| | + } |
| | + if (a[a_first + elem] < b[b_first + elem]) |
| | + { |
| | + /*System.out.println("return 1");*/ |
| | + return 1; |
| | + } |
| | + else if (a[a_first + elem] > b[b_first + elem]) |
| | + { |
| | + /*System.out.println("return -1");*/ |
| | + return -1; |
| | + } |
| | + } |
| | + |
| | + /*System.out.println("return 0");*/ |
| | + return 0; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: charncmp |
| | + *******************************************************/ |
| | + static int charncmp |
| | + ( |
| | + char a[], |
| | + int a_first, |
| | + char b[], |
| | + int b_first, |
| | + int n |
| | + ) |
| | + { |
| | + int elem; |
| | + |
| | + for (elem = 0; elem < n; ++elem) |
| | + { |
| | + if ('\0' == a[a_first + elem] && '\0' == b[b_first + elem]) |
| | + { |
| | + return 0; |
| | + } |
| | + if (a[a_first + elem] < b[b_first + elem]) |
| | + { |
| | + return 1; |
| | + } |
| | + else if (a[a_first + elem] > b[b_first + elem]) |
| | + { |
| | + return -1; |
| | + } |
| | + } |
| | + |
| | + return 0; |
| | + } |
| | +} |
| | + |
| | +/******************************************************** |
| | + Class: CError |
| | + *******************************************************/ |
| | +class CError |
| | +{ |
| | + /******************************************************** |
| | + Function: impos |
| | + Description: |
| | + *******************************************************/ |
| | + static void impos |
| | + ( |
| | + String message |
| | + ) |
| | + { |
| | + System.out.println("JLex Error: " + message); |
| | + } |
| | + |
| | + /******************************************************** |
| | + Constants |
| | + Description: Error codes for parse_error(). |
| | + *******************************************************/ |
| | + static final int E_BADEXPR = 0; |
| | + static final int E_PAREN = 1; |
| | + static final int E_LENGTH = 2; |
| | + static final int E_BRACKET = 3; |
| | + static final int E_BOL = 4; |
| | + static final int E_CLOSE = 5; |
| | + static final int E_NEWLINE = 6; |
| | + static final int E_BADMAC = 7; |
| | + static final int E_NOMAC = 8; |
| | + static final int E_MACDEPTH = 9; |
| | + static final int E_INIT = 10; |
| | + static final int E_EOF = 11; |
| | + static final int E_DIRECT = 12; |
| | + static final int E_INTERNAL = 13; |
| | + static final int E_STATE = 14; |
| | + static final int E_MACDEF = 15; |
| | + static final int E_SYNTAX = 16; |
| | + static final int E_BRACE = 17; |
| | + static final int E_DASH = 18; |
| | + static final int E_ZERO = 19; |
| | + static final int E_BADCTRL = 20; |
| | + |
| | + /******************************************************** |
| | + Constants |
| | + Description: String messages for parse_error(); |
| | + *******************************************************/ |
| | + static final String errmsg[] = |
| | + { |
| | + "Malformed regular expression.", |
| | + "Missing close parenthesis.", |
| | + "Too many regular expressions or expression too long.", |
| | + "Missing [ in character class.", |
| | + "^ must be at start of expression or after [.", |
| | + "+ ? or * must follow an expression or subexpression.", |
| | + "Newline in quoted string.", |
| | + "Missing } in macro expansion.", |
| | + "Macro does not exist.", |
| | + "Macro expansions nested too deeply.", |
| | + "JLex has not been successfully initialized.", |
| | + "Unexpected end-of-file found.", |
| | + "Undefined or badly-formed JLex directive.", |
| | + "Internal JLex error.", |
| | + "Unitialized state name.", |
| | + "Badly formed macro definition.", |
| | + "Syntax error.", |
| | + "Missing brace at start of lexical action.", |
| | + "Special character dash - in character class [...] must\n" |
| | + + "\tbe preceded by start-of-range character.", |
| | + "Zero-length regular expression.", |
| | + "Illegal \\^C-style escape sequence (character following caret must\n" |
| | + + "\tbe alphabetic).", |
| | + }; |
| | + |
| | + /******************************************************** |
| | + Function: parse_error |
| | + Description: |
| | + *******************************************************/ |
| | + static void parse_error |
| | + ( |
| | + int error_code, |
| | + int line_number |
| | + ) |
| | + { |
| | + System.out.println("Error: Parse error at line " |
| | + + line_number + "."); |
| | + System.out.println("Description: " + errmsg[error_code]); |
| | + throw new Error("Parse error."); |
| | + } |
| | +} |
| | + |
| | +/******************************************************** |
| | + Class: CSet |
| | + *******************************************************/ |
| | +class CSet |
| | +{ |
| | + /******************************************************** |
| | + Member Variables |
| | + *******************************************************/ |
| | + private SparseBitSet m_set; |
| | + private boolean m_complement; |
| | + |
| | + /******************************************************** |
| | + Function: CSet |
| | + *******************************************************/ |
| | + CSet |
| | + ( |
| | + ) |
| | + { |
| | + m_set = new SparseBitSet(); |
| | + m_complement = false; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: complement |
| | + *******************************************************/ |
| | + void complement |
| | + ( |
| | + ) |
| | + { |
| | + m_complement = true; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: add |
| | + *******************************************************/ |
| | + void add |
| | + ( |
| | + int i |
| | + ) |
| | + { |
| | + m_set.set(i); |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: addncase |
| | + *******************************************************/ |
| | + void addncase // add, ignoring case. |
| | + ( |
| | + char c |
| | + ) |
| | + { |
| | + /* Do this in a Unicode-friendly way. */ |
| | + /* (note that duplicate adds have no effect) */ |
| | + add(c); |
| | + add(Character.toLowerCase(c)); |
| | + add(Character.toTitleCase(c)); |
| | + add(Character.toUpperCase(c)); |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: contains |
| | + *******************************************************/ |
| | + boolean contains |
| | + ( |
| | + int i |
| | + ) |
| | + { |
| | + boolean result; |
| | + |
| | + result = m_set.get(i); |
| | + |
| | + if (m_complement) |
| | + { |
| | + return (false == result); |
| | + } |
| | + |
| | + return result; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: mimic |
| | + *******************************************************/ |
| | + void mimic |
| | + ( |
| | + CSet set |
| | + ) |
| | + { |
| | + m_complement = set.m_complement; |
| | + m_set = (SparseBitSet) set.m_set.clone(); |
| | + } |
| | + |
| | + /** Map set using character classes [CSA] */ |
| | + void map(CSet set, int[] mapping) { |
| | + m_complement = set.m_complement; |
| | + m_set.clearAll(); |
| | + for (Enumeration e=set.m_set.elements(); e.hasMoreElements(); ) { |
| | + int old_value =((Integer)e.nextElement()).intValue(); |
| | + if (old_value<mapping.length) // skip unmapped characters |
| | + m_set.set(mapping[old_value]); |
| | + } |
| | + } |
| | +} |
| | + |
| | +/******************************************************** |
| | + Class: CNfa |
| | + *******************************************************/ |
| | +class CNfa |
| | +{ |
| | + /******************************************************** |
| | + Member Variables |
| | + *******************************************************/ |
| | + int m_edge; /* Label for edge type: |
| | + character code, |
| | + CCL (character class), |
| | + [STATE, |
| | + SCL (state class),] |
| | + EMPTY, |
| | + EPSILON. */ |
| | + |
| | + CSet m_set; /* Set to store character classes. */ |
| | + CNfa m_next; /* Next state (or null if none). */ |
| | + |
| | + CNfa m_next2; /* Another state with type == EPSILON |
| | + and null if not used. |
| | + The NFA construction should result in two |
| | + outgoing edges only if both are EPSILON edges. */ |
| | + |
| | + CAccept m_accept; /* Set to null if nonaccepting state. */ |
| | + int m_anchor; /* Says if and where pattern is anchored. */ |
| | + |
| | + int m_label; |
| | + |
| | + SparseBitSet m_states; |
| | + |
| | + /******************************************************** |
| | + Constants |
| | + *******************************************************/ |
| | + static final int NO_LABEL = -1; |
| | + |
| | + /******************************************************** |
| | + Constants: Edge Types |
| | + Note: Edge transitions on one specific character |
| | + are labelled with the character Ascii (Unicode) |
| | + codes. So none of the constants below should |
| | + overlap with the natural character codes. |
| | + *******************************************************/ |
| | + static final int CCL = -1; |
| | + static final int EMPTY = -2; |
| | + static final int EPSILON = -3; |
| | + |
| | + /******************************************************** |
| | + Function: CNfa |
| | + *******************************************************/ |
| | + CNfa |
| | + ( |
| | + ) |
| | + { |
| | + m_edge = EMPTY; |
| | + m_set = null; |
| | + m_next = null; |
| | + m_next2 = null; |
| | + m_accept = null; |
| | + m_anchor = CSpec.NONE; |
| | + m_label = NO_LABEL; |
| | + m_states = null; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: mimic |
| | + Description: Converts this NFA state into a copy of |
| | + the input one. |
| | + *******************************************************/ |
| | + void mimic |
| | + ( |
| | + CNfa nfa |
| | + ) |
| | + { |
| | + m_edge = nfa.m_edge; |
| | + |
| | + if (null != nfa.m_set) |
| | + { |
| | + if (null == m_set) |
| | + { |
| | + m_set = new CSet(); |
| | + } |
| | + m_set.mimic(nfa.m_set); |
| | + } |
| | + else |
| | + { |
| | + m_set = null; |
| | + } |
| | + |
| | + m_next = nfa.m_next; |
| | + m_next2 = nfa.m_next2; |
| | + m_accept = nfa.m_accept; |
| | + m_anchor = nfa.m_anchor; |
| | + |
| | + if (null != nfa.m_states) |
| | + { |
| | + m_states = (SparseBitSet) nfa.m_states.clone(); |
| | + } |
| | + else |
| | + { |
| | + m_states = null; |
| | + } |
| | + } |
| | +} |
| | + |
| | +/*************************************************************** |
| | + Class: CLexGen |
| | + **************************************************************/ |
| | +class CLexGen |
| | +{ |
| | + /*************************************************************** |
| | + Member Variables |
| | + **************************************************************/ |
| | + private java.io.Reader m_instream; /* JLex specification file. */ |
| | + private java.io.PrintWriter m_outstream; /* Lexical analyzer source file. */ |
| | + |
| | + private CInput m_input; /* Input buffer class. */ |
| | + |
| | + private Hashtable m_tokens; /* Hashtable that maps characters to their |
| | + corresponding lexical code for |
| | + the internal lexical analyzer. */ |
| | + private CSpec m_spec; /* Spec class holds information |
| | + about the generated lexer. */ |
| | + private boolean m_init_flag; /* Flag set to true only upon |
| | + successful initialization. */ |
| | + |
| | + private CMakeNfa m_makeNfa; /* NFA machine generator module. */ |
| | + private CNfa2Dfa m_nfa2dfa; /* NFA to DFA machine (transition table) |
| | + conversion module. */ |
| | + private CMinimize m_minimize; /* Transition table compressor. */ |
| | + private CSimplifyNfa m_simplifyNfa; /* NFA simplifier using char classes */ |
| | + private CEmit m_emit; /* Output module that emits source code |
| | + into the generated lexer file. */ |
| | + |
| | + |
| | + /******************************************************** |
| | + Constants |
| | + *******************************************************/ |
| | + private static final boolean ERROR = false; |
| | + private static final boolean NOT_ERROR = true; |
| | + private static final int BUFFER_SIZE = 1024; |
| | + |
| | + /******************************************************** |
| | + Constants: Token Types |
| | + *******************************************************/ |
| | + static final int EOS = 1; |
| | + static final int ANY = 2; |
| | + static final int AT_BOL = 3; |
| | + static final int AT_EOL = 4; |
| | + static final int CCL_END = 5; |
| | + static final int CCL_START = 6; |
| | + static final int CLOSE_CURLY = 7; |
| | + static final int CLOSE_PAREN = 8; |
| | + static final int CLOSURE = 9; |
| | + static final int DASH = 10; |
| | + static final int END_OF_INPUT = 11; |
| | + static final int L = 12; |
| | + static final int OPEN_CURLY = 13; |
| | + static final int OPEN_PAREN = 14; |
| | + static final int OPTIONAL = 15; |
| | + static final int OR = 16; |
| | + static final int PLUS_CLOSE = 17; |
| | + |
| | + /*************************************************************** |
| | + Function: CLexGen |
| | + **************************************************************/ |
| | + CLexGen |
| | + ( |
| | + String filename |
| | + ) |
| | + throws java.io.FileNotFoundException, java.io.IOException |
| | + { |
| | + /* Successful initialization flag. */ |
| | + m_init_flag = false; |
| | + |
| | + /* Open input stream. */ |
| | + m_instream = new java.io.FileReader(filename); |
| | + if (null == m_instream) |
| | + { |
| | + System.out.println("Error: Unable to open input file " |
| | + + filename + "."); |
| | + return; |
| | + } |
| | + |
| | + /* Open output stream. */ |
| | + m_outstream |
| | + = new java.io.PrintWriter(new java.io.BufferedWriter( |
| | + new java.io.FileWriter(filename + ".java"))); |
| | + if (null == m_outstream) |
| | + { |
| | + System.out.println("Error: Unable to open output file " |
| | + + filename + ".java."); |
| | + return; |
| | + } |
| | + |
| | + /* Create input buffer class. */ |
| | + m_input = new CInput(m_instream); |
| | + |
| | + /* Initialize character hash table. */ |
| | + m_tokens = new Hashtable(); |
| | + m_tokens.put(new Character('$'),new Integer(AT_EOL)); |
| | + m_tokens.put(new Character('('),new Integer(OPEN_PAREN)); |
| | + m_tokens.put(new Character(')'),new Integer(CLOSE_PAREN)); |
| | + m_tokens.put(new Character('*'),new Integer(CLOSURE)); |
| | + m_tokens.put(new Character('+'),new Integer(PLUS_CLOSE)); |
| | + m_tokens.put(new Character('-'),new Integer(DASH)); |
| | + m_tokens.put(new Character('.'),new Integer(ANY)); |
| | + m_tokens.put(new Character('?'),new Integer(OPTIONAL)); |
| | + m_tokens.put(new Character('['),new Integer(CCL_START)); |
| | + m_tokens.put(new Character(']'),new Integer(CCL_END)); |
| | + m_tokens.put(new Character('^'),new Integer(AT_BOL)); |
| | + m_tokens.put(new Character('{'),new Integer(OPEN_CURLY)); |
| | + m_tokens.put(new Character('|'),new Integer(OR)); |
| | + m_tokens.put(new Character('}'),new Integer(CLOSE_CURLY)); |
| | + |
| | + /* Initialize spec structure. */ |
| | + m_spec = new CSpec(this); |
| | + |
| | + /* Nfa to dfa converter. */ |
| | + m_nfa2dfa = new CNfa2Dfa(); |
| | + m_minimize = new CMinimize(); |
| | + m_makeNfa = new CMakeNfa(); |
| | + m_simplifyNfa = new CSimplifyNfa(); |
| | + |
| | + m_emit = new CEmit(); |
| | + |
| | + /* Successful initialization flag. */ |
| | + m_init_flag = true; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: generate |
| | + Description: |
| | + **************************************************************/ |
| | + void generate |
| | + ( |
| | + ) |
| | + throws java.io.IOException, java.io.FileNotFoundException |
| | + { |
| | + if (false == m_init_flag) |
| | + { |
| | + CError.parse_error(CError.E_INIT,0); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + CUtility.ASSERT(m_init_flag); |
| | + } |
| | + |
| | + /*m_emit.emit_imports(m_spec,m_outstream);*/ |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Processing first section -- user code."); |
| | + } |
| | + userCode(); |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Processing second section -- " |
| | + + "JLex declarations."); |
| | + } |
| | + userDeclare(); |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Processing third section -- lexical rules."); |
| | + } |
| | + userRules(); |
| | + if (CUtility.DO_DEBUG) |
| | + { |
| | + print_header(); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Outputting lexical analyzer code."); |
| | + } |
| | + m_emit.emit(m_spec,m_outstream); |
| | + |
| | + if (m_spec.m_verbose && true == CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + details(); |
| | + } |
| | + |
| | + m_outstream.close(); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: userCode |
| | + Description: Process first section of specification, |
| | + echoing it into output file. |
| | + **************************************************************/ |
| | + private void userCode |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int count = 0; |
| | + |
| | + if (false == m_init_flag) |
| | + { |
| | + CError.parse_error(CError.E_INIT,0); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + CError.parse_error(CError.E_EOF,0); |
| | + } |
| | + |
| | + while (true) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + /* Eof reached. */ |
| | + CError.parse_error(CError.E_EOF,0); |
| | + } |
| | + |
| | + if (2 <= m_input.m_line_read |
| | + && '%' == m_input.m_line[0] |
| | + && '%' == m_input.m_line[1]) |
| | + { |
| | + /* Discard remainder of line. */ |
| | + m_input.m_line_index = m_input.m_line_read; |
| | + return; |
| | + } |
| | + |
| | + m_outstream.print(new String(m_input.m_line,0, |
| | + m_input.m_line_read)); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: getName |
| | + **************************************************************/ |
| | + private char[] getName |
| | + ( |
| | + ) |
| | + { |
| | + char buffer[]; |
| | + int elem; |
| | + |
| | + /* Skip white space. */ |
| | + while (m_input.m_line_index < m_input.m_line_read |
| | + && true == CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + } |
| | + |
| | + /* No name? */ |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + CError.parse_error(CError.E_DIRECT,0); |
| | + } |
| | + |
| | + /* Determine length. */ |
| | + elem = m_input.m_line_index; |
| | + while (elem < m_input.m_line_read |
| | + && false == CUtility.isnewline(m_input.m_line[elem])) |
| | + { |
| | + ++elem; |
| | + } |
| | + |
| | + /* Allocate non-terminated buffer of exact length. */ |
| | + buffer = new char[elem - m_input.m_line_index]; |
| | + |
| | + /* Copy. */ |
| | + elem = 0; |
| | + while (m_input.m_line_index < m_input.m_line_read |
| | + && false == CUtility.isnewline(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + buffer[elem] = m_input.m_line[m_input.m_line_index]; |
| | + ++elem; |
| | + ++m_input.m_line_index; |
| | + } |
| | + |
| | + return buffer; |
| | + } |
| | + |
| | + private final int CLASS_CODE = 0; |
| | + private final int INIT_CODE = 1; |
| | + private final int EOF_CODE = 2; |
| | + private final int INIT_THROW_CODE = 3; |
| | + private final int YYLEX_THROW_CODE = 4; |
| | + private final int EOF_THROW_CODE = 5; |
| | + private final int EOF_VALUE_CODE = 6; |
| | + |
| | + /*************************************************************** |
| | + Function: packCode |
| | + Description: |
| | + **************************************************************/ |
| | + private char[] packCode |
| | + ( |
| | + char start_dir[], |
| | + char end_dir[], |
| | + char prev_code[], |
| | + int prev_read, |
| | + int specified |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(INIT_CODE == specified |
| | + || CLASS_CODE == specified |
| | + || EOF_CODE == specified |
| | + || EOF_VALUE_CODE == specified |
| | + || INIT_THROW_CODE == specified |
| | + || YYLEX_THROW_CODE == specified |
| | + || EOF_THROW_CODE == specified); |
| | + } |
| | + |
| | + if (0 != CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + start_dir, |
| | + 0, |
| | + start_dir.length - 1)) |
| | + { |
| | + CError.parse_error(CError.E_INTERNAL,0); |
| | + } |
| | + |
| | + if (null == prev_code) |
| | + { |
| | + prev_code = new char[BUFFER_SIZE]; |
| | + prev_read = 0; |
| | + } |
| | + |
| | + if (prev_read >= prev_code.length) |
| | + { |
| | + prev_code = CUtility.doubleSize(prev_code); |
| | + } |
| | + |
| | + m_input.m_line_index = start_dir.length - 1; |
| | + while (true) |
| | + { |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + } |
| | + |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + end_dir, |
| | + 0, |
| | + end_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = end_dir.length - 1; |
| | + |
| | + switch (specified) |
| | + { |
| | + case CLASS_CODE: |
| | + m_spec.m_class_read = prev_read; |
| | + break; |
| | + |
| | + case INIT_CODE: |
| | + m_spec.m_init_read = prev_read; |
| | + break; |
| | + |
| | + case EOF_CODE: |
| | + m_spec.m_eof_read = prev_read; |
| | + break; |
| | + |
| | + case EOF_VALUE_CODE: |
| | + m_spec.m_eof_value_read = prev_read; |
| | + break; |
| | + |
| | + case INIT_THROW_CODE: |
| | + m_spec.m_init_throw_read = prev_read; |
| | + break; |
| | + |
| | + case YYLEX_THROW_CODE: |
| | + m_spec.m_yylex_throw_read = prev_read; |
| | + break; |
| | + |
| | + case EOF_THROW_CODE: |
| | + m_spec.m_eof_throw_read = prev_read; |
| | + break; |
| | + |
| | + default: |
| | + CError.parse_error(CError.E_INTERNAL,m_input.m_line_number); |
| | + break; |
| | + } |
| | + |
| | + return prev_code; |
| | + } |
| | + } |
| | + |
| | + while (m_input.m_line_index < m_input.m_line_read) |
| | + { |
| | + prev_code[prev_read] = m_input.m_line[m_input.m_line_index]; |
| | + ++prev_read; |
| | + ++m_input.m_line_index; |
| | + |
| | + if (prev_read >= prev_code.length) |
| | + { |
| | + prev_code = CUtility.doubleSize(prev_code); |
| | + } |
| | + } |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Member Variables: JLex directives. |
| | + **************************************************************/ |
| | + private char m_state_dir[] = { |
| | + '%', 's', 't', |
| | + 'a', 't', 'e', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_char_dir[] = { |
| | + '%', 'c', 'h', |
| | + 'a', 'r', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_line_dir[] = { |
| | + '%', 'l', 'i', |
| | + 'n', 'e', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_cup_dir[] = { |
| | + '%', 'c', 'u', |
| | + 'p', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_class_dir[] = { |
| | + '%', 'c', 'l', |
| | + 'a', 's', 's', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_implements_dir[] = { |
| | + '%', 'i', 'm', 'p', 'l', 'e', 'm', 'e', 'n', 't', 's', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_function_dir[] = { |
| | + '%', 'f', 'u', |
| | + 'n', 'c', 't', |
| | + 'i', 'o', 'n', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_type_dir[] = { |
| | + '%', 't', 'y', |
| | + 'p', 'e', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_integer_dir[] = { |
| | + '%', 'i', 'n', |
| | + 't', 'e', 'g', |
| | + 'e', 'r', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_intwrap_dir[] = { |
| | + '%', 'i', 'n', |
| | + 't', 'w', 'r', |
| | + 'a', 'p', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_full_dir[] = { |
| | + '%', 'f', 'u', |
| | + 'l', 'l', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_unicode_dir[] = { |
| | + '%', 'u', 'n', |
| | + 'i', 'c', 'o', |
| | + 'd', 'e', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_ignorecase_dir[] = { |
| | + '%', 'i', 'g', |
| | + 'n', 'o', 'r', |
| | + 'e', 'c', 'a', |
| | + 's', 'e', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_notunix_dir[] = { |
| | + '%', 'n', 'o', |
| | + 't', 'u', 'n', |
| | + 'i', 'x', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_init_code_dir[] = { |
| | + '%', 'i', 'n', |
| | + 'i', 't', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_init_code_end_dir[] = { |
| | + '%', 'i', 'n', |
| | + 'i', 't', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_init_throw_code_dir[] = { |
| | + '%', 'i', 'n', |
| | + 'i', 't', 't', |
| | + 'h', 'r', 'o', |
| | + 'w', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_init_throw_code_end_dir[] = { |
| | + '%', 'i', 'n', |
| | + 'i', 't', 't', |
| | + 'h', 'r', 'o', |
| | + 'w', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_yylex_throw_code_dir[] = { |
| | + '%', 'y', 'y', 'l', |
| | + 'e', 'x', 't', |
| | + 'h', 'r', 'o', |
| | + 'w', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_yylex_throw_code_end_dir[] = { |
| | + '%', 'y', 'y', 'l', |
| | + 'e', 'x', 't', |
| | + 'h', 'r', 'o', |
| | + 'w', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_code_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_code_end_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_value_code_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', 'v', 'a', |
| | + 'l', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_value_code_end_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', 'v', 'a', |
| | + 'l', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_throw_code_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', 't', 'h', |
| | + 'r', 'o', 'w', |
| | + '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_eof_throw_code_end_dir[] = { |
| | + '%', 'e', 'o', |
| | + 'f', 't', 'h', |
| | + 'r', 'o', 'w', |
| | + '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_class_code_dir[] = { |
| | + '%', '{', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_class_code_end_dir[] = { |
| | + '%', '}', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_yyeof_dir[] = { |
| | + '%', 'y', 'y', |
| | + 'e', 'o', 'f', |
| | + '\0' |
| | + }; |
| | + |
| | + private char m_public_dir[] = { |
| | + '%', 'p', 'u', |
| | + 'b', 'l', 'i', |
| | + 'c', '\0' |
| | + }; |
| | + |
| | + /*************************************************************** |
| | + Function: userDeclare |
| | + Description: |
| | + **************************************************************/ |
| | + private void userDeclare |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int elem; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + /* End-of-file. */ |
| | + CError.parse_error(CError.E_EOF, |
| | + m_input.m_line_number); |
| | + } |
| | + |
| | + while (false == m_input.getLine()) |
| | + { |
| | + /* Look for double percent. */ |
| | + if (2 <= m_input.m_line_read |
| | + && '%' == m_input.m_line[0] |
| | + && '%' == m_input.m_line[1]) |
| | + { |
| | + /* Mess around with line. */ |
| | + m_input.m_line_read -= 2; |
| | + System.arraycopy(m_input.m_line, 2, |
| | + m_input.m_line, 0, m_input.m_line_read); |
| | + |
| | + m_input.m_pushback_line = true; |
| | + /* Check for and discard empty line. */ |
| | + if (0 == m_input.m_line_read |
| | + || '\n' == m_input.m_line[0]) |
| | + { |
| | + m_input.m_pushback_line = false; |
| | + } |
| | + |
| | + return; |
| | + } |
| | + |
| | + if (0 == m_input.m_line_read) |
| | + { |
| | + continue; |
| | + } |
| | + |
| | + if ('%' == m_input.m_line[0]) |
| | + { |
| | + /* Special lex declarations. */ |
| | + if (1 >= m_input.m_line_read) |
| | + { |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + continue; |
| | + } |
| | + |
| | + switch (m_input.m_line[1]) |
| | + { |
| | + case '{': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_class_code_dir, |
| | + 0, |
| | + m_class_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_class_code = packCode(m_class_code_dir, |
| | + m_class_code_end_dir, |
| | + m_spec.m_class_code, |
| | + m_spec.m_class_read, |
| | + CLASS_CODE); |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'c': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_char_dir, |
| | + 0, |
| | + m_char_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_char_dir.length; |
| | + m_spec.m_count_chars = true; |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_class_dir, |
| | + 0, |
| | + m_class_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = m_class_dir.length; |
| | + m_spec.m_class_name = getName(); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_cup_dir, |
| | + 0, |
| | + m_cup_dir.length - 1)) |
| | + { |
| | + /* Set Java CUP compatibility to ON. */ |
| | + m_input.m_line_index = m_cup_dir.length; |
| | + m_spec.m_cup_compatible = true; |
| | + // this is what %cup does: [CSA, 27-Jul-1999] |
| | + m_spec.m_implements_name = |
| | + "java_cup.runtime.Scanner".toCharArray(); |
| | + m_spec.m_function_name = |
| | + "next_token".toCharArray(); |
| | + m_spec.m_type_name = |
| | + "java_cup.runtime.Symbol".toCharArray(); |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'e': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_eof_code_dir, |
| | + 0, |
| | + m_eof_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_eof_code = packCode(m_eof_code_dir, |
| | + m_eof_code_end_dir, |
| | + m_spec.m_eof_code, |
| | + m_spec.m_eof_read, |
| | + EOF_CODE); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_eof_value_code_dir, |
| | + 0, |
| | + m_eof_value_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_eof_value_code = packCode(m_eof_value_code_dir, |
| | + m_eof_value_code_end_dir, |
| | + m_spec.m_eof_value_code, |
| | + m_spec.m_eof_value_read, |
| | + EOF_VALUE_CODE); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_eof_throw_code_dir, |
| | + 0, |
| | + m_eof_throw_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_eof_throw_code = packCode(m_eof_throw_code_dir, |
| | + m_eof_throw_code_end_dir, |
| | + m_spec.m_eof_throw_code, |
| | + m_spec.m_eof_throw_read, |
| | + EOF_THROW_CODE); |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'f': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_function_dir, |
| | + 0, |
| | + m_function_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_function_dir.length; |
| | + m_spec.m_function_name = getName(); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_full_dir, |
| | + 0, |
| | + m_full_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = m_full_dir.length; |
| | + m_spec.m_dtrans_ncols = CUtility.MAX_EIGHT_BIT + 1; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'i': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_integer_dir, |
| | + 0, |
| | + m_integer_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_integer_dir.length; |
| | + m_spec.m_integer_type = true; |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_intwrap_dir, |
| | + 0, |
| | + m_intwrap_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_integer_dir.length; |
| | + m_spec.m_intwrap_type = true; |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_init_code_dir, |
| | + 0, |
| | + m_init_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_init_code = packCode(m_init_code_dir, |
| | + m_init_code_end_dir, |
| | + m_spec.m_init_code, |
| | + m_spec.m_init_read, |
| | + INIT_CODE); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_init_throw_code_dir, |
| | + 0, |
| | + m_init_throw_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_init_throw_code = packCode(m_init_throw_code_dir, |
| | + m_init_throw_code_end_dir, |
| | + m_spec.m_init_throw_code, |
| | + m_spec.m_init_throw_read, |
| | + INIT_THROW_CODE); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_implements_dir, |
| | + 0, |
| | + m_implements_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = m_implements_dir.length; |
| | + m_spec.m_implements_name = getName(); |
| | + break; |
| | + } |
| | + else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_ignorecase_dir, |
| | + 0, |
| | + m_ignorecase_dir.length-1)) |
| | + { |
| | + /* Set m_ignorecase to ON. */ |
| | + m_input.m_line_index = m_ignorecase_dir.length; |
| | + m_spec.m_ignorecase = true; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'l': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_line_dir, |
| | + 0, |
| | + m_line_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_line_dir.length; |
| | + m_spec.m_count_lines = true; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'n': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_notunix_dir, |
| | + 0, |
| | + m_notunix_dir.length - 1)) |
| | + { |
| | + /* Set line counting to ON. */ |
| | + m_input.m_line_index = m_notunix_dir.length; |
| | + m_spec.m_unix = false; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'p': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_public_dir, |
| | + 0, |
| | + m_public_dir.length - 1)) |
| | + { |
| | + /* Set public flag. */ |
| | + m_input.m_line_index = m_public_dir.length; |
| | + m_spec.m_public = true; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 's': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_state_dir, |
| | + 0, |
| | + m_state_dir.length - 1)) |
| | + { |
| | + /* Recognize state list. */ |
| | + m_input.m_line_index = m_state_dir.length; |
| | + saveStates(); |
| | + break; |
| | + } |
| | + |
| | + /* Undefined directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 't': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_type_dir, |
| | + 0, |
| | + m_type_dir.length - 1)) |
| | + { |
| | + /* Set Java CUP compatibility to ON. */ |
| | + m_input.m_line_index = m_type_dir.length; |
| | + m_spec.m_type_name = getName(); |
| | + break; |
| | + } |
| | + |
| | + /* Undefined directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'u': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_unicode_dir, |
| | + 0, |
| | + m_unicode_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = m_unicode_dir.length; |
| | + m_spec.m_dtrans_ncols= CUtility.MAX_SIXTEEN_BIT + 1; |
| | + break; |
| | + } |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + case 'y': |
| | + if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_yyeof_dir, |
| | + 0, |
| | + m_yyeof_dir.length - 1)) |
| | + { |
| | + m_input.m_line_index = m_yyeof_dir.length; |
| | + m_spec.m_yyeof = true; |
| | + break; |
| | + } else if (0 == CUtility.charncmp(m_input.m_line, |
| | + 0, |
| | + m_yylex_throw_code_dir, |
| | + 0, |
| | + m_yylex_throw_code_dir.length - 1)) |
| | + { |
| | + m_spec.m_yylex_throw_code = packCode(m_yylex_throw_code_dir, |
| | + m_yylex_throw_code_end_dir, |
| | + m_spec.m_yylex_throw_code, |
| | + m_spec.m_yylex_throw_read, |
| | + YYLEX_THROW_CODE); |
| | + break; |
| | + } |
| | + |
| | + |
| | + /* Bad directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + |
| | + default: |
| | + /* Undefined directive. */ |
| | + CError.parse_error(CError.E_DIRECT, |
| | + m_input.m_line_number); |
| | + break; |
| | + } |
| | + } |
| | + else |
| | + { |
| | + /* Regular expression macro. */ |
| | + m_input.m_line_index = 0; |
| | + saveMacro(); |
| | + } |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.println("Line number " |
| | + + m_input.m_line_number + ":"); |
| | + System.out.print(new String(m_input.m_line, |
| | + 0,m_input.m_line_read)); |
| | + } |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: userRules |
| | + Description: Processes third section of JLex |
| | + specification and creates minimized transition table. |
| | + **************************************************************/ |
| | + private void userRules |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int code; |
| | + |
| | + if (false == m_init_flag) |
| | + { |
| | + CError.parse_error(CError.E_INIT,0); |
| | + } |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + /* UNDONE: Need to handle states preceding rules. */ |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Creating NFA machine representation."); |
| | + } |
| | + m_makeNfa.allocate_BOL_EOF(m_spec); |
| | + m_makeNfa.thompson(this,m_spec,m_input); |
| | + |
| | + m_simplifyNfa.simplify(m_spec); |
| | + |
| | + /*print_nfa();*/ |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(END_OF_INPUT == m_spec.m_current_token); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Creating DFA transition table."); |
| | + } |
| | + m_nfa2dfa.make_dfa(this,m_spec); |
| | + |
| | + if (CUtility.FOODEBUG) { |
| | + print_header(); |
| | + } |
| | + |
| | + if (m_spec.m_verbose) |
| | + { |
| | + System.out.println("Minimizing DFA transition table."); |
| | + } |
| | + m_minimize.min_dfa(m_spec); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: printccl |
| | + Description: Debugging routine that outputs readable form |
| | + of character class. |
| | + **************************************************************/ |
| | + private void printccl |
| | + ( |
| | + CSet set |
| | + ) |
| | + { |
| | + int i; |
| | + |
| | + System.out.print(" ["); |
| | + for (i = 0; i < m_spec.m_dtrans_ncols; ++i) |
| | + { |
| | + if (set.contains(i)) |
| | + { |
| | + System.out.print(interp_int(i)); |
| | + } |
| | + } |
| | + System.out.print(']'); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: plab |
| | + Description: |
| | + **************************************************************/ |
| | + private String plab |
| | + ( |
| | + CNfa state |
| | + ) |
| | + { |
| | + int index; |
| | + |
| | + if (null == state) |
| | + { |
| | + return (new String("--")); |
| | + } |
| | + |
| | + index = m_spec.m_nfa_states.indexOf(state); |
| | + |
| | + return ((new Integer(index)).toString()); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: interp_int |
| | + Description: |
| | + **************************************************************/ |
| | + private String interp_int |
| | + ( |
| | + int i |
| | + ) |
| | + { |
| | + switch (i) |
| | + { |
| | + case (int) '\b': |
| | + return (new String("\\b")); |
| | + |
| | + case (int) '\t': |
| | + return (new String("\\t")); |
| | + |
| | + case (int) '\n': |
| | + return (new String("\\n")); |
| | + |
| | + case (int) '\f': |
| | + return (new String("\\f")); |
| | + |
| | + case (int) '\r': |
| | + return (new String("\\r")); |
| | + |
| | + case (int) ' ': |
| | + return (new String("\\ ")); |
| | + |
| | + default: |
| | + return ((new Character((char) i)).toString()); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: print_nfa |
| | + Description: |
| | + **************************************************************/ |
| | + void print_nfa |
| | + ( |
| | + ) |
| | + { |
| | + int elem; |
| | + CNfa nfa; |
| | + int size; |
| | + Enumeration states; |
| | + Integer index; |
| | + int i; |
| | + int j; |
| | + int vsize; |
| | + String state; |
| | + |
| | + System.out.println("--------------------- NFA -----------------------"); |
| | + |
| | + size = m_spec.m_nfa_states.size(); |
| | + for (elem = 0; elem < size; ++elem) |
| | + { |
| | + nfa = (CNfa) m_spec.m_nfa_states.elementAt(elem); |
| | + |
| | + System.out.print("Nfa state " + plab(nfa) + ": "); |
| | + |
| | + if (null == nfa.m_next) |
| | + { |
| | + System.out.print("(TERMINAL)"); |
| | + } |
| | + else |
| | + { |
| | + System.out.print("--> " + plab(nfa.m_next)); |
| | + System.out.print("--> " + plab(nfa.m_next2)); |
| | + |
| | + switch (nfa.m_edge) |
| | + { |
| | + case CNfa.CCL: |
| | + printccl(nfa.m_set); |
| | + break; |
| | + |
| | + case CNfa.EPSILON: |
| | + System.out.print(" EPSILON "); |
| | + break; |
| | + |
| | + default: |
| | + System.out.print(" " + interp_int(nfa.m_edge)); |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (0 == elem) |
| | + { |
| | + System.out.print(" (START STATE)"); |
| | + } |
| | + |
| | + if (null != nfa.m_accept) |
| | + { |
| | + System.out.print(" accepting " |
| | + + ((0 != (nfa.m_anchor & CSpec.START)) ? "^" : "") |
| | + + "<" |
| | + + (new String(nfa.m_accept.m_action,0, |
| | + nfa.m_accept.m_action_read)) |
| | + + ">" |
| | + + ((0 != (nfa.m_anchor & CSpec.END)) ? "$" : "")); |
| | + } |
| | + |
| | + System.out.println(); |
| | + } |
| | + |
| | + states = m_spec.m_states.keys(); |
| | + while (states.hasMoreElements()) |
| | + { |
| | + state = (String) states.nextElement(); |
| | + index = (Integer) m_spec.m_states.get(state); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != state); |
| | + CUtility.ASSERT(null != index); |
| | + } |
| | + |
| | + System.out.println("State \"" + state |
| | + + "\" has identifying index " |
| | + + index.toString() + "."); |
| | + System.out.print("\tStart states of matching rules: "); |
| | + |
| | + i = index.intValue(); |
| | + vsize = m_spec.m_state_rules[i].size(); |
| | + |
| | + for (j = 0; j < vsize; ++j) |
| | + { |
| | + nfa = (CNfa) m_spec.m_state_rules[i].elementAt(j); |
| | + |
| | + System.out.print(m_spec.m_nfa_states.indexOf(nfa) + " "); |
| | + } |
| | + |
| | + System.out.println(); |
| | + } |
| | + |
| | + System.out.println("-------------------- NFA ----------------------"); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: getStates |
| | + Description: Parses the state area of a rule, |
| | + from the beginning of a line. |
| | + < state1, state2 ... > regular_expression { action } |
| | + Returns null on only EOF. Returns all_states, |
| | + initialied properly to correspond to all states, |
| | + if no states are found. |
| | + Special Notes: This function treats commas as optional |
| | + and permits states to be spread over multiple lines. |
| | + **************************************************************/ |
| | + private SparseBitSet all_states = null; |
| | + SparseBitSet getStates |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + int start_state; |
| | + int count_state; |
| | + SparseBitSet states; |
| | + String name; |
| | + Integer index; |
| | + int i; |
| | + int size; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + states = null; |
| | + |
| | + /* Skip white space. */ |
| | + while (CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + /* Must just be an empty line. */ |
| | + if (m_input.getLine()) |
| | + { |
| | + /* EOF found. */ |
| | + return null; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /* Look for states. */ |
| | + if ('<' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + |
| | + states = new SparseBitSet(); |
| | + |
| | + /* Parse states. */ |
| | + while (true) |
| | + { |
| | + /* We may have reached the end of the line. */ |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + /* EOF found. */ |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + return states; |
| | + } |
| | + } |
| | + |
| | + while (true) |
| | + { |
| | + /* Skip white space. */ |
| | + while (CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + /* EOF found. */ |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + return states; |
| | + } |
| | + } |
| | + } |
| | + |
| | + if (',' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + break; |
| | + } |
| | + |
| | + ++m_input.m_line_index; |
| | + } |
| | + |
| | + if ('>' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + if (m_input.m_line_index < m_input.m_line_read) |
| | + { |
| | + m_advance_stop = true; |
| | + } |
| | + return states; |
| | + } |
| | + |
| | + /* Read in state name. */ |
| | + start_state = m_input.m_line_index; |
| | + while (false == CUtility.isspace(m_input.m_line[m_input.m_line_index]) |
| | + && ',' != m_input.m_line[m_input.m_line_index] |
| | + && '>' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + /* End of line means end of state name. */ |
| | + break; |
| | + } |
| | + } |
| | + count_state = m_input.m_line_index - start_state; |
| | + |
| | + /* Save name after checking definition. */ |
| | + name = new String(m_input.m_line, |
| | + start_state, |
| | + count_state); |
| | + index = (Integer) m_spec.m_states.get(name); |
| | + if (null == index) |
| | + { |
| | + /* Uninitialized state. */ |
| | + System.out.println("Uninitialized State Name: " + name); |
| | + CError.parse_error(CError.E_STATE,m_input.m_line_number); |
| | + } |
| | + states.set(index.intValue()); |
| | + } |
| | + } |
| | + |
| | + if (null == all_states) |
| | + { |
| | + all_states = new SparseBitSet(); |
| | + |
| | + size = m_spec.m_states.size(); |
| | + for (i = 0; i < size; ++i) |
| | + { |
| | + all_states.set(i); |
| | + } |
| | + } |
| | + |
| | + if (m_input.m_line_index < m_input.m_line_read) |
| | + { |
| | + m_advance_stop = true; |
| | + } |
| | + return all_states; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: expandMacro |
| | + Description: Returns false on error, true otherwise. |
| | + *******************************************************/ |
| | + private boolean expandMacro |
| | + ( |
| | + ) |
| | + { |
| | + int elem; |
| | + int start_macro; |
| | + int end_macro; |
| | + int start_name; |
| | + int count_name; |
| | + String def; |
| | + int def_elem; |
| | + String name; |
| | + char replace[]; |
| | + int rep_elem; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + /* Check for macro. */ |
| | + if ('{' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + CError.parse_error(CError.E_INTERNAL,m_input.m_line_number); |
| | + return ERROR; |
| | + } |
| | + |
| | + start_macro = m_input.m_line_index; |
| | + elem = m_input.m_line_index + 1; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + CError.impos("Unfinished macro name"); |
| | + return ERROR; |
| | + } |
| | + |
| | + /* Get macro name. */ |
| | + start_name = elem; |
| | + while ('}' != m_input.m_line[elem]) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + CError.impos("Unfinished macro name at line " |
| | + + m_input.m_line_number); |
| | + return ERROR; |
| | + } |
| | + } |
| | + count_name = elem - start_name; |
| | + end_macro = elem; |
| | + |
| | + /* Check macro name. */ |
| | + if (0 == count_name) |
| | + { |
| | + CError.impos("Nonexistent macro name"); |
| | + return ERROR; |
| | + } |
| | + |
| | + /* Debug checks. */ |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(0 < count_name); |
| | + } |
| | + |
| | + /* Retrieve macro definition. */ |
| | + name = new String(m_input.m_line,start_name,count_name); |
| | + def = (String) m_spec.m_macros.get(name); |
| | + if (null == def) |
| | + { |
| | + /*CError.impos("Undefined macro \"" + name + "\".");*/ |
| | + System.out.println("Error: Undefined macro \"" + name + "\"."); |
| | + CError.parse_error(CError.E_NOMAC, m_input.m_line_number); |
| | + return ERROR; |
| | + } |
| | + if (CUtility.OLD_DUMP_DEBUG) |
| | + { |
| | + System.out.println("expanded escape: " + def); |
| | + } |
| | + |
| | + /* Replace macro in new buffer, |
| | + beginning by copying first part of line buffer. */ |
| | + replace = new char[m_input.m_line.length]; |
| | + for (rep_elem = 0; rep_elem < start_macro; ++rep_elem) |
| | + { |
| | + replace[rep_elem] = m_input.m_line[rep_elem]; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(rep_elem < replace.length); |
| | + } |
| | + } |
| | + |
| | + /* Copy macro definition. */ |
| | + if (rep_elem >= replace.length) |
| | + { |
| | + replace = CUtility.doubleSize(replace); |
| | + } |
| | + for (def_elem = 0; def_elem < def.length(); ++def_elem) |
| | + { |
| | + replace[rep_elem] = def.charAt(def_elem); |
| | + |
| | + ++rep_elem; |
| | + if (rep_elem >= replace.length) |
| | + { |
| | + replace = CUtility.doubleSize(replace); |
| | + } |
| | + } |
| | + |
| | + /* Copy last part of line. */ |
| | + if (rep_elem >= replace.length) |
| | + { |
| | + replace = CUtility.doubleSize(replace); |
| | + } |
| | + for (elem = end_macro + 1; elem < m_input.m_line_read; ++elem) |
| | + { |
| | + replace[rep_elem] = m_input.m_line[elem]; |
| | + |
| | + ++rep_elem; |
| | + if (rep_elem >= replace.length) |
| | + { |
| | + replace = CUtility.doubleSize(replace); |
| | + } |
| | + } |
| | + |
| | + /* Replace buffer. */ |
| | + m_input.m_line = replace; |
| | + m_input.m_line_read = rep_elem; |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.println(new String(m_input.m_line,0,m_input.m_line_read)); |
| | + } |
| | + return NOT_ERROR; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: saveMacro |
| | + Description: Saves macro definition of form: |
| | + macro_name = macro_definition |
| | + **************************************************************/ |
| | + private void saveMacro |
| | + ( |
| | + ) |
| | + { |
| | + int elem; |
| | + int start_name; |
| | + int count_name; |
| | + int start_def; |
| | + int count_def; |
| | + boolean saw_escape; |
| | + boolean in_quote; |
| | + boolean in_ccl; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + /* Macro declarations are of the following form: |
| | + macro_name macro_definition */ |
| | + |
| | + elem = 0; |
| | + |
| | + /* Skip white space preceding macro name. */ |
| | + while (CUtility.isspace(m_input.m_line[elem])) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* End of line has been reached, |
| | + and line was found to be empty. */ |
| | + return; |
| | + } |
| | + } |
| | + |
| | + /* Read macro name. */ |
| | + start_name = elem; |
| | + while (false == CUtility.isspace(m_input.m_line[elem]) |
| | + && '=' != m_input.m_line[elem]) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* Macro name but no associated definition. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + } |
| | + count_name = elem - start_name; |
| | + |
| | + /* Check macro name. */ |
| | + if (0 == count_name) |
| | + { |
| | + /* Nonexistent macro name. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + |
| | + /* Skip white space between name and definition. */ |
| | + while (CUtility.isspace(m_input.m_line[elem])) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* Macro name but no associated definition. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + } |
| | + |
| | + if ('=' == m_input.m_line[elem]) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* Macro name but no associated definition. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + } |
| | + else /* macro definition without = */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + |
| | + /* Skip white space between name and definition. */ |
| | + while (CUtility.isspace(m_input.m_line[elem])) |
| | + { |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* Macro name but no associated definition. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + } |
| | + |
| | + /* Read macro definition. */ |
| | + start_def = elem; |
| | + in_quote = false; |
| | + in_ccl = false; |
| | + saw_escape = false; |
| | + while (false == CUtility.isspace(m_input.m_line[elem]) |
| | + || true == in_quote |
| | + || true == in_ccl |
| | + || true == saw_escape) |
| | + { |
| | + if ('\"' == m_input.m_line[elem] && false == saw_escape) |
| | + { |
| | + in_quote = !in_quote; |
| | + } |
| | + |
| | + if ('\\' == m_input.m_line[elem] && false == saw_escape) |
| | + { |
| | + saw_escape = true; |
| | + } |
| | + else |
| | + { |
| | + saw_escape = false; |
| | + } |
| | + if (false == saw_escape && false == in_quote) { // CSA, 24-jul-99 |
| | + if ('[' == m_input.m_line[elem] && false == in_ccl) |
| | + in_ccl = true; |
| | + if (']' == m_input.m_line[elem] && true == in_ccl) |
| | + in_ccl = false; |
| | + } |
| | + |
| | + ++elem; |
| | + if (elem >= m_input.m_line_read) |
| | + { |
| | + /* End of line. */ |
| | + break; |
| | + } |
| | + } |
| | + count_def = elem - start_def; |
| | + |
| | + /* Check macro definition. */ |
| | + if (0 == count_def) |
| | + { |
| | + /* Nonexistent macro name. */ |
| | + CError.parse_error(CError.E_MACDEF,m_input.m_line_number); |
| | + } |
| | + |
| | + /* Debug checks. */ |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(0 < count_def); |
| | + CUtility.ASSERT(0 < count_name); |
| | + CUtility.ASSERT(null != m_spec.m_macros); |
| | + } |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.println("macro name \"" |
| | + + new String(m_input.m_line,start_name,count_name) |
| | + + "\"."); |
| | + System.out.println("macro definition \"" |
| | + + new String(m_input.m_line,start_def,count_def) |
| | + + "\"."); |
| | + } |
| | + |
| | + /* Add macro name and definition to table. */ |
| | + m_spec.m_macros.put(new String(m_input.m_line,start_name,count_name), |
| | + new String(m_input.m_line,start_def,count_def)); |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: saveStates |
| | + Description: Takes state declaration and makes entries |
| | + for them in state hashtable in CSpec structure. |
| | + State declaration should be of the form: |
| | + %state name0[, name1, name2 ...] |
| | + (But commas are actually optional as long as there is |
| | + white space in between them.) |
| | + **************************************************************/ |
| | + private void saveStates |
| | + ( |
| | + ) |
| | + { |
| | + int start_state; |
| | + int count_state; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + /* EOF found? */ |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + return; |
| | + } |
| | + |
| | + /* Debug checks. */ |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT('%' == m_input.m_line[0]); |
| | + CUtility.ASSERT('s' == m_input.m_line[1]); |
| | + CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read); |
| | + CUtility.ASSERT(0 <= m_input.m_line_index); |
| | + CUtility.ASSERT(0 <= m_input.m_line_read); |
| | + } |
| | + |
| | + /* Blank line? No states? */ |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + return; |
| | + } |
| | + |
| | + while (m_input.m_line_index < m_input.m_line_read) |
| | + { |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.println("line read " + m_input.m_line_read |
| | + + "\tline index = " + m_input.m_line_index); |
| | + } |
| | + |
| | + /* Skip white space. */ |
| | + while (CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + /* No more states to be found. */ |
| | + return; |
| | + } |
| | + } |
| | + |
| | + /* Look for state name. */ |
| | + start_state = m_input.m_line_index; |
| | + while (false == CUtility.isspace(m_input.m_line[m_input.m_line_index]) |
| | + && ',' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + /* End of line and end of state name. */ |
| | + break; |
| | + } |
| | + } |
| | + count_state = m_input.m_line_index - start_state; |
| | + |
| | + if (CUtility.OLD_DEBUG) |
| | + { |
| | + System.out.println("State name \"" |
| | + + new String(m_input.m_line,start_state,count_state) |
| | + + "\"."); |
| | + System.out.println("Integer index \"" |
| | + + m_spec.m_states.size() |
| | + + "\"."); |
| | + } |
| | + |
| | + /* Enter new state name, along with unique index. */ |
| | + m_spec.m_states.put(new String(m_input.m_line,start_state,count_state), |
| | + new Integer(m_spec.m_states.size())); |
| | + |
| | + /* Skip comma. */ |
| | + if (',' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + /* End of line. */ |
| | + return; |
| | + } |
| | + } |
| | + } |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: expandEscape |
| | + Description: Takes escape sequence and returns |
| | + corresponding character code. |
| | + *******************************************************/ |
| | + private char expandEscape |
| | + ( |
| | + ) |
| | + { |
| | + char r; |
| | + |
| | + /* Debug checks. */ |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_input.m_line_index < m_input.m_line_read); |
| | + CUtility.ASSERT(0 < m_input.m_line_read); |
| | + CUtility.ASSERT(0 <= m_input.m_line_index); |
| | + } |
| | + |
| | + if ('\\' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++m_input.m_line_index; |
| | + return m_input.m_line[m_input.m_line_index - 1]; |
| | + } |
| | + else |
| | + { |
| | + boolean unicode_escape = false; |
| | + ++m_input.m_line_index; |
| | + switch (m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + case 'b': |
| | + ++m_input.m_line_index; |
| | + return '\b'; |
| | + |
| | + case 't': |
| | + ++m_input.m_line_index; |
| | + return '\t'; |
| | + |
| | + case 'n': |
| | + ++m_input.m_line_index; |
| | + return '\n'; |
| | + |
| | + case 'f': |
| | + ++m_input.m_line_index; |
| | + return '\f'; |
| | + |
| | + case 'r': |
| | + ++m_input.m_line_index; |
| | + return '\r'; |
| | + |
| | + case '^': |
| | + ++m_input.m_line_index; |
| | + r=Character.toUpperCase(m_input.m_line[m_input.m_line_index]); |
| | + if (r<'@' || r>'Z') // non-fatal |
| | + CError.parse_error(CError.E_BADCTRL,m_input.m_line_number); |
| | + r = (char) (r - '@'); |
| | + ++m_input.m_line_index; |
| | + return r; |
| | + |
| | + case 'u': |
| | + unicode_escape = true; |
| | + case 'x': |
| | + ++m_input.m_line_index; |
| | + r = 0; |
| | + for (int i=0; i<(unicode_escape?4:2); i++) |
| | + if (CUtility.ishexdigit(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + r = (char) (r << 4); |
| | + r = (char) (r | CUtility.hex2bin(m_input.m_line[m_input.m_line_index])); |
| | + ++m_input.m_line_index; |
| | + } |
| | + else break; |
| | + |
| | + return r; |
| | + |
| | + default: |
| | + if (false == CUtility.isoctdigit(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + r = m_input.m_line[m_input.m_line_index]; |
| | + ++m_input.m_line_index; |
| | + } |
| | + else |
| | + { |
| | + r = 0; |
| | + for (int i=0; i<3; i++) |
| | + if (CUtility.isoctdigit(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + r = (char) (r << 3); |
| | + r = (char) (r | CUtility.oct2bin(m_input.m_line[m_input.m_line_index])); |
| | + ++m_input.m_line_index; |
| | + } |
| | + else break; |
| | + } |
| | + return r; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: packAccept |
| | + Description: Packages and returns CAccept |
| | + for action next in input stream. |
| | + *******************************************************/ |
| | + CAccept packAccept |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + CAccept accept; |
| | + char action[]; |
| | + int action_index; |
| | + int brackets; |
| | + boolean insinglequotes; |
| | + boolean indoublequotes; |
| | + boolean instarcomment; |
| | + boolean inslashcomment; |
| | + boolean escaped; |
| | + boolean slashed; |
| | + |
| | + action = new char[BUFFER_SIZE]; |
| | + action_index = 0; |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != this); |
| | + CUtility.ASSERT(null != m_outstream); |
| | + CUtility.ASSERT(null != m_input); |
| | + CUtility.ASSERT(null != m_tokens); |
| | + CUtility.ASSERT(null != m_spec); |
| | + } |
| | + |
| | + /* Get a new line, if needed. */ |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + return null; |
| | + } |
| | + } |
| | + |
| | + /* Look for beginning of action. */ |
| | + while (CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + |
| | + /* Get a new line, if needed. */ |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + CError.parse_error(CError.E_EOF,m_input.m_line_number); |
| | + return null; |
| | + } |
| | + } |
| | + } |
| | + |
| | + /* Look for brackets. */ |
| | + if ('{' != m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + CError.parse_error(CError.E_BRACE,m_input.m_line_number); |
| | + } |
| | + |
| | + /* Copy new line into action buffer. */ |
| | + brackets = 0; |
| | + insinglequotes = indoublequotes = inslashcomment = instarcomment = |
| | + escaped = slashed = false; |
| | + while (true) |
| | + { |
| | + action[action_index] = m_input.m_line[m_input.m_line_index]; |
| | + |
| | + /* Look for quotes. */ |
| | + if ((insinglequotes || indoublequotes) && escaped) |
| | + escaped=false; // only protects one char, but this is enough. |
| | + else if ((insinglequotes || indoublequotes) && |
| | + '\\' == m_input.m_line[m_input.m_line_index]) |
| | + escaped=true; |
| | + else if (!(insinglequotes || inslashcomment || instarcomment) && |
| | + '\"' == m_input.m_line[m_input.m_line_index]) |
| | + indoublequotes=!indoublequotes; // unescaped double quote. |
| | + else if (!(indoublequotes || inslashcomment || instarcomment) && |
| | + '\'' == m_input.m_line[m_input.m_line_index]) |
| | + insinglequotes=!insinglequotes; // unescaped single quote. |
| | + /* Look for comments. */ |
| | + if (instarcomment) { // inside "/*" comment; look for "*/" |
| | + if (slashed && '/' == m_input.m_line[m_input.m_line_index]) |
| | + instarcomment = slashed = false; |
| | + else // note that inside a star comment, slashed means starred |
| | + slashed = ('*' == m_input.m_line[m_input.m_line_index]); |
| | + } else if (!inslashcomment && !insinglequotes && !indoublequotes) { |
| | + // not in comment, look for /* or // |
| | + inslashcomment = |
| | + (slashed && '/' == m_input.m_line[m_input.m_line_index]); |
| | + instarcomment = |
| | + (slashed && '*' == m_input.m_line[m_input.m_line_index]); |
| | + slashed = ('/' == m_input.m_line[m_input.m_line_index]); |
| | + } |
| | + |
| | + /* Look for brackets. */ |
| | + if (!insinglequotes && !indoublequotes && |
| | + !instarcomment && !inslashcomment) { |
| | + if ('{' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + ++brackets; |
| | + } |
| | + else if ('}' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + --brackets; |
| | + |
| | + if (0 == brackets) |
| | + { |
| | + ++action_index; |
| | + ++m_input.m_line_index; |
| | + |
| | + break; |
| | + } |
| | + } |
| | + } |
| | + |
| | + ++action_index; |
| | + /* Double the buffer size, if needed. */ |
| | + if (action_index >= action.length) |
| | + { |
| | + action = CUtility.doubleSize(action); |
| | + } |
| | + |
| | + ++m_input.m_line_index; |
| | + /* Get a new line, if needed. */ |
| | + while (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + inslashcomment = slashed = false; |
| | + if (insinglequotes || indoublequotes) { // non-fatal |
| | + CError.parse_error(CError.E_NEWLINE,m_input.m_line_number); |
| | + insinglequotes = indoublequotes = false; |
| | + } |
| | + if (m_input.getLine()) |
| | + { |
| | + CError.parse_error(CError.E_SYNTAX,m_input.m_line_number); |
| | + return null; |
| | + } |
| | + } |
| | + } |
| | + |
| | + accept = new CAccept(action,action_index,m_input.m_line_number); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != accept); |
| | + } |
| | + |
| | + if (CUtility.DESCENT_DEBUG) |
| | + { |
| | + System.out.print("Accepting action:"); |
| | + System.out.println(new String(accept.m_action,0,accept.m_action_read)); |
| | + } |
| | + |
| | + return accept; |
| | + } |
| | + |
| | + /******************************************************** |
| | + Function: advance |
| | + Description: Returns code for next token. |
| | + *******************************************************/ |
| | + private boolean m_advance_stop = false; |
| | + int advance |
| | + ( |
| | + ) |
| | + throws java.io.IOException |
| | + { |
| | + boolean saw_escape = false; |
| | + Integer code; |
| | + |
| | + /*if (m_input.m_line_index > m_input.m_line_read) { |
| | + System.out.println("m_input.m_line_index = " + m_input.m_line_index); |
| | + System.out.println("m_input.m_line_read = " + m_input.m_line_read); |
| | + CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read); |
| | + }*/ |
| | + |
| | + if (m_input.m_eof_reached) |
| | + { |
| | + /* EOF has already been reached, |
| | + so return appropriate code. */ |
| | + |
| | + m_spec.m_current_token = END_OF_INPUT; |
| | + m_spec.m_lexeme = '\0'; |
| | + return m_spec.m_current_token; |
| | + } |
| | + |
| | + /* End of previous regular expression? |
| | + Refill line buffer? */ |
| | + if (EOS == m_spec.m_current_token |
| | + /* ADDED */ |
| | + || m_input.m_line_index >= m_input.m_line_read) |
| | + /* ADDED */ |
| | + { |
| | + if (m_spec.m_in_quote) |
| | + { |
| | + CError.parse_error(CError.E_SYNTAX,m_input.m_line_number); |
| | + } |
| | + |
| | + while (true) |
| | + { |
| | + if (false == m_advance_stop |
| | + || m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + if (m_input.getLine()) |
| | + { |
| | + /* EOF has already been reached, |
| | + so return appropriate code. */ |
| | + |
| | + m_spec.m_current_token = END_OF_INPUT; |
| | + m_spec.m_lexeme = '\0'; |
| | + return m_spec.m_current_token; |
| | + } |
| | + m_input.m_line_index = 0; |
| | + } |
| | + else |
| | + { |
| | + m_advance_stop = false; |
| | + } |
| | + |
| | + while (m_input.m_line_index < m_input.m_line_read |
| | + && true == CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + ++m_input.m_line_index; |
| | + } |
| | + |
| | + if (m_input.m_line_index < m_input.m_line_read) |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + } |
| | + |
| | + if (CUtility.DEBUG) { |
| | + CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read); |
| | + } |
| | + |
| | + while (true) |
| | + { |
| | + if (false == m_spec.m_in_quote |
| | + && '{' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + if (false == expandMacro()) |
| | + { |
| | + break; |
| | + } |
| | + |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + m_spec.m_current_token = EOS; |
| | + m_spec.m_lexeme = '\0'; |
| | + return m_spec.m_current_token; |
| | + } |
| | + } |
| | + else if ('\"' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + m_spec.m_in_quote = !m_spec.m_in_quote; |
| | + ++m_input.m_line_index; |
| | + |
| | + if (m_input.m_line_index >= m_input.m_line_read) |
| | + { |
| | + m_spec.m_current_token = EOS; |
| | + m_spec.m_lexeme = '\0'; |
| | + return m_spec.m_current_token; |
| | + } |
| | + } |
| | + else |
| | + { |
| | + break; |
| | + } |
| | + } |
| | + |
| | + if (m_input.m_line_index > m_input.m_line_read) { |
| | + System.out.println("m_input.m_line_index = " + m_input.m_line_index); |
| | + System.out.println("m_input.m_line_read = " + m_input.m_line_read); |
| | + CUtility.ASSERT(m_input.m_line_index <= m_input.m_line_read); |
| | + } |
| | + |
| | + /* Look for backslash, and corresponding |
| | + escape sequence. */ |
| | + if ('\\' == m_input.m_line[m_input.m_line_index]) |
| | + { |
| | + saw_escape = true; |
| | + } |
| | + else |
| | + { |
| | + saw_escape = false; |
| | + } |
| | + |
| | + if (false == m_spec.m_in_quote) |
| | + { |
| | + if (false == m_spec.m_in_ccl && |
| | + CUtility.isspace(m_input.m_line[m_input.m_line_index])) |
| | + { |
| | + /* White space means the end of |
| | + the current regular expression. */ |
| | + |
| | + m_spec.m_current_token = EOS; |
| | + m_spec.m_lexeme = '\0'; |
| | + return m_spec.m_current_token; |
| | + } |
| | + |
| | + /* Process escape sequence, if needed. */ |
| | + if (saw_escape) |
| | + { |
| | + m_spec.m_lexeme = expandEscape(); |
| | + } |
| | + else |
| | + { |
| | + m_spec.m_lexeme = m_input.m_line[m_input.m_line_index]; |
| | + ++m_input.m_line_index; |
| | + } |
| | + } |
| | + else |
| | + { |
| | + if (saw_escape |
| | + && (m_input.m_line_index + 1) < m_input.m_line_read |
| | + && '\"' == m_input.m_line[m_input.m_line_index + 1]) |
| | + { |
| | + m_spec.m_lexeme = '\"'; |
| | + m_input.m_line_index = m_input.m_line_index + 2; |
| | + } |
| | + else |
| | + { |
| | + m_spec.m_lexeme = m_input.m_line[m_input.m_line_index]; |
| | + ++m_input.m_line_index; |
| | + } |
| | + } |
| | + |
| | + code = (Integer) m_tokens.get(new Character(m_spec.m_lexeme)); |
| | + if (m_spec.m_in_quote || true == saw_escape) |
| | + { |
| | + m_spec.m_current_token = L; |
| | + } |
| | + else |
| | + { |
| | + if (null == code) |
| | + { |
| | + m_spec.m_current_token = L; |
| | + } |
| | + else |
| | + { |
| | + m_spec.m_current_token = code.intValue(); |
| | + } |
| | + } |
| | + |
| | + if (CCL_START == m_spec.m_current_token) m_spec.m_in_ccl = true; |
| | + if (CCL_END == m_spec.m_current_token) m_spec.m_in_ccl = false; |
| | + |
| | + if (CUtility.FOODEBUG) |
| | + { |
| | + System.out.println("Lexeme: " + m_spec.m_lexeme |
| | + + "\tToken: " + m_spec.m_current_token |
| | + + "\tIndex: " + m_input.m_line_index); |
| | + } |
| | + |
| | + return m_spec.m_current_token; |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: details |
| | + Description: High level debugging routine. |
| | + **************************************************************/ |
| | + private void details |
| | + ( |
| | + ) |
| | + { |
| | + Enumeration names; |
| | + String name; |
| | + String def; |
| | + Enumeration states; |
| | + String state; |
| | + Integer index; |
| | + int elem; |
| | + int size; |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** Macros **"); |
| | + names = m_spec.m_macros.keys(); |
| | + while (names.hasMoreElements()) |
| | + { |
| | + name = (String) names.nextElement(); |
| | + def = (String) m_spec.m_macros.get(name); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != name); |
| | + CUtility.ASSERT(null != def); |
| | + } |
| | + |
| | + System.out.println("Macro name \"" + name |
| | + + "\" has definition \"" |
| | + + def + "\"."); |
| | + } |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** States **"); |
| | + states = m_spec.m_states.keys(); |
| | + while (states.hasMoreElements()) |
| | + { |
| | + state = (String) states.nextElement(); |
| | + index = (Integer) m_spec.m_states.get(state); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != state); |
| | + CUtility.ASSERT(null != index); |
| | + } |
| | + |
| | + System.out.println("State \"" + state |
| | + + "\" has identifying index " |
| | + + index.toString() + "."); |
| | + } |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** Character Counting **"); |
| | + if (false == m_spec.m_count_chars) |
| | + { |
| | + System.out.println("Character counting is off."); |
| | + } |
| | + else |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_spec.m_count_lines); |
| | + } |
| | + |
| | + System.out.println("Character counting is on."); |
| | + } |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** Line Counting **"); |
| | + if (false == m_spec.m_count_lines) |
| | + { |
| | + System.out.println("Line counting is off."); |
| | + } |
| | + else |
| | + { |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(m_spec.m_count_lines); |
| | + } |
| | + |
| | + System.out.println("Line counting is on."); |
| | + } |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** Operating System Specificity **"); |
| | + if (false == m_spec.m_unix) |
| | + { |
| | + System.out.println("Not generating UNIX-specific code."); |
| | + System.out.println("(This means that \"\\r\\n\" is a " |
| | + + "newline, rather than \"\\n\".)"); |
| | + } |
| | + else |
| | + { |
| | + System.out.println("Generating UNIX-specific code."); |
| | + System.out.println("(This means that \"\\n\" is a " |
| | + + "newline, rather than \"\\r\\n\".)"); |
| | + } |
| | + |
| | + System.out.println(); |
| | + System.out.println("\t** Java CUP Compatibility **"); |
| | + if (false == m_spec.m_cup_compatible) |
| | + { |
| | + System.out.println("Generating CUP compatible code."); |
| | + System.out.println("(Scanner implements " |
| | + + "java_cup.runtime.Scanner.)"); |
| | + } |
| | + else |
| | + { |
| | + System.out.println("Not generating CUP compatible code."); |
| | + } |
| | + |
| | + if (CUtility.FOODEBUG) { |
| | + if (null != m_spec.m_nfa_states && null != m_spec.m_nfa_start) |
| | + { |
| | + System.out.println(); |
| | + System.out.println("\t** NFA machine **"); |
| | + print_nfa(); |
| | + } |
| | + } |
| | + |
| | + if (null != m_spec.m_dtrans_vector) |
| | + { |
| | + System.out.println(); |
| | + System.out.println("\t** DFA transition table **"); |
| | + /*print_header();*/ |
| | + } |
| | + |
| | + /*if (null != m_spec.m_accept_vector && null != m_spec.m_anchor_array) |
| | + { |
| | + System.out.println(); |
| | + System.out.println("\t** Accept States and Anchor Vector **"); |
| | + print_accept(); |
| | + }*/ |
| | + } |
| | + |
| | + /*************************************************************** |
| | + function: print_set |
| | + **************************************************************/ |
| | + void print_set |
| | + ( |
| | + Vector nfa_set |
| | + ) |
| | + { |
| | + int size; |
| | + int elem; |
| | + CNfa nfa; |
| | + |
| | + size = nfa_set.size(); |
| | + |
| | + if (0 == size) |
| | + { |
| | + System.out.print("empty "); |
| | + } |
| | + |
| | + for (elem = 0; elem < size; ++elem) |
| | + { |
| | + nfa = (CNfa) nfa_set.elementAt(elem); |
| | + /*System.out.print(m_spec.m_nfa_states.indexOf(nfa) + " ");*/ |
| | + System.out.print(nfa.m_label + " "); |
| | + } |
| | + } |
| | + |
| | + /*************************************************************** |
| | + Function: print_header |
| | + **************************************************************/ |
| | + private void print_header |
| | + ( |
| | + ) |
| | + { |
| | + Enumeration states; |
| | + int i; |
| | + int j; |
| | + int chars_printed=0; |
| | + CDTrans dtrans; |
| | + int last_transition; |
| | + String str; |
| | + CAccept accept; |
| | + String state; |
| | + Integer index; |
| | + |
| | + System.out.println("/*---------------------- DFA -----------------------"); |
| | + |
| | + states = m_spec.m_states.keys(); |
| | + while (states.hasMoreElements()) |
| | + { |
| | + state = (String) states.nextElement(); |
| | + index = (Integer) m_spec.m_states.get(state); |
| | + |
| | + if (CUtility.DEBUG) |
| | + { |
| | + CUtility.ASSERT(null != state); |
| | + CUtility.ASSERT(null != index); |
| | + } |
| | + |
| | + System.out.println("State \"" + state |
| | + + "\" has identifying index " |
| | + + index.toString() + "."); |
| | + |
| | + i = index.intValue(); |
| | + if (CDTrans.F != m_spec.m_state_dtrans[i]) |
| | + { |
| | + System.out.println("\tStart index in transition table: " |
| | + + m_spec.m_state_dtrans[i]); |
| | + } |
| | + else |
| | + { |
| | + System.out.println("\tNo associated transition states."); |
| | + } |
| | + } |
| | + |
| | + for (i = 0; i < m_spec.m_dtrans_vector.size(); ++i) |
| | + { |
| | + dtrans = (CDTrans) m_spec.m_dtrans_vector.elementAt(i); |
| | + |
| | + if (null == m_spec.m_accept_vector && null == m_spec.m_anchor_array) |
| | + { |
| | + if (null == dtrans.m_accept) |
| | + { |
| | + System.out.print(" * State " + i + " [nonaccepting]"); |
| | + } |
| | + else |
| | + { |
| | + System.out.print(" * State " + i |
| | + + " [accepting, line " |
| | + + dtrans.m_accept.m_line_number |
| | + + " <" |
| | + + (new String(dtrans.m_accept.m_action,0, |
| | + dtrans.m_accept.m_action_read)) |
| | + + ">]"); |
| | + if (CSpec.NONE != dtrans.m_anchor) |
| | + { |
| | + System.out.print(" Anchor: " |
| | + + ((0 != (dtrans.m_anchor & CSpec.START)) |
| | + ? "start " : "") |
| | + + ((0 != (dtrans.m_anchor & CSpec.END)) |
| | + ? "end " : "")); |
| | + } |
| | + } |
| | + } |
| | + else |
| | + { |
| | + accept = (CAccept) m_spec.m_accept_vector.elementAt(i); |
| | + |
| | + if (null == accept) |
| | + { |
| | + System.out.print(" * State " + i + " [nonaccepting]"); |
| | + } |
| | + else |
| | + { |
| | + System.out.print(" * State " + i |
| | + + " [accepting, line " |
| | + + accept.m_line_number |
| | + + " <" |
| | + + (new String(accept.m_action,0, |
| | + accept.m_action_read)) |
| | + + ">]"); |
| | + if (CSpec.NONE != m_spec.m_anchor_array[i]) |
| | + { |
| | + System.out.print(" Anchor: " |
| | + + ((0 != (m_spec.m_anchor_array[i] & CSpec.START)) |
| | + ? "start " : "") |
| | + + ((0 != (m_spec.m_anchor_array[i] & CSpec.END)) |
| | + ? "end " : "")); |
| | + } |
| | + } |
| | + } |
| | + |
| | + last_transition = -1; |
| | + for (j = 0; j < m_spec.m_dtrans_ncols; ++j) |
| | + { |
| | + if (CDTrans.F != dtrans.m_dtrans[j]) |
| | + { |
| | + if (last_transition != dtrans.m_dtrans[j]) |
| | + { |
| | + System.out.println(); |
| | + System.out.print(" * goto " + dtrans.m_dtrans[j] |
| | + + " on "); |
| | + chars_printed = 0; |
| | + } |
| | + |
| | + str = interp_int((int) j); |
| | + System.out.print(str); |
| | + |
| | + chars_printed = chars_printed + str.length(); |
| | + if (56 < chars_printed) |
| | + { |
| | + System.out.println(); |
| | + System.out.print(" * "); |
| | + chars_printed = 0; |
| | + } |
| | + |
| | + last_transition = dtrans.m_dtrans[j]; |
| | + } |
| | + } |
| | + System.out.println(); |
| | + } |
| | + System.out.println(" */"); |
| | + System.out.println(); |
| | + } |
| | +} |
| | + |
| | +/* |
| | + * SparseBitSet 25-Jul-1999. |
| | + * C. Scott Ananian <cananian@alumni.princeton.edu> |
| | + * |
| | + * Re-implementation of the standard java.util.BitSet to support sparse |
| | + * sets, which we need to efficiently support unicode character classes. |
| | + */ |
| | + |
| | +/** |
| | + * A set of bits. The set automatically grows as more bits are |
| | + * needed. |
| | + * |
| | + * @version 1.00, 25 Jul 1999 |
| | + * @author C. Scott Ananian |
| | + */ |
| | +final class SparseBitSet implements Cloneable { |
| | + /** Sorted array of bit-block offsets. */ |
| | + int offs[]; |
| | + /** Array of bit-blocks; each holding BITS bits. */ |
| | + long bits[]; |
| | + /** Number of blocks currently in use. */ |
| | + int size; |
| | + /** log base 2 of BITS, for the identity: x/BITS == x >> LG_BITS */ |
| | + static final private int LG_BITS = 6; |
| | + /** Number of bits in a block. */ |
| | + static final private int BITS = 1<<LG_BITS; |
| | + /** BITS-1, using the identity: x % BITS == x & (BITS-1) */ |
| | + static final private int BITS_M1 = BITS-1; |
| | + |
| | + /** |
| | + * Creates an empty set. |
| | + */ |
| | + public SparseBitSet() { |
| | + bits = new long[4]; |
| | + offs = new int [4]; |
| | + size = 0; |
| | + } |
| | + |
| | + /** |
| | + * Creates an empty set with the specified size. |
| | + * @param nbits the size of the set |
| | + */ |
| | + public SparseBitSet(int nbits) { |
| | + this(); |
| | + } |
| | + |
| | + /** |
| | + * Creates an empty set with the same size as the given set. |
| | + */ |
| | + public SparseBitSet(SparseBitSet set) { |
| | + bits = new long[set.size]; |
| | + offs = new int [set.size]; |
| | + size = 0; |
| | + } |
| | + |
| | + private void new_block(int bnum) { |
| | + new_block(bsearch(bnum), bnum); |
| | + } |
| | + private void new_block(int idx, int bnum) { |
| | + if (size==bits.length) { // resize |
| | + long[] nbits = new long[size*3]; |
| | + int [] noffs = new int [size*3]; |
| | + System.arraycopy(bits, 0, nbits, 0, size); |
| | + System.arraycopy(offs, 0, noffs, 0, size); |
| | + bits = nbits; |
| | + offs = noffs; |
| | + } |
| | + CUtility.ASSERT(size<bits.length); |
| | + insert_block(idx, bnum); |
| | + } |
| | + private void insert_block(int idx, int bnum) { |
| | + CUtility.ASSERT(idx<=size); |
| | + CUtility.ASSERT(idx==size || offs[idx]!=bnum); |
| | + System.arraycopy(bits, idx, bits, idx+1, size-idx); |
| | + System.arraycopy(offs, idx, offs, idx+1, size-idx); |
| | + offs[idx]=bnum; |
| | + bits[idx]=0; //clear them bits. |
| | + size++; |
| | + } |
| | + private int bsearch(int bnum) { |
| | + int l=0, r=size; // search interval is [l, r) |
| | + while (l<r) { |
| | + int p = (l+r)/2; |
| | + if (bnum<offs[p]) r=p; |
| | + else if (bnum>offs[p]) l=p+1; |
| | + else return p; |
| | + } |
| | + CUtility.ASSERT(l==r); |
| | + return l; // index at which the bnum *should* be, if it's not. |
| | + } |
| | + |
| | + /** |
| | + * Sets a bit. |
| | + * @param bit the bit to be set |
| | + */ |
| | + public void set(int bit) { |
| | + int bnum = bit >> LG_BITS; |
| | + int idx = bsearch(bnum); |
| | + if (idx >= size || offs[idx]!=bnum) |
| | + new_block(idx, bnum); |
| | + bits[idx] |= (1L << (bit & BITS_M1) ); |
| | + } |
| | + |
| | + /** |
| | + * Clears a bit. |
| | + * @param bit the bit to be cleared |
| | + */ |
| | + public void clear(int bit) { |
| | + int bnum = bit >> LG_BITS; |
| | + int idx = bsearch(bnum); |
| | + if (idx >= size || offs[idx]!=bnum) |
| | + new_block(idx, bnum); |
| | + bits[idx] &= ~(1L << (bit & BITS_M1) ); |
| | + } |
| | + |
| | + /** |
| | + * Clears all bits. |
| | + */ |
| | + public void clearAll() { |
| | + size = 0; |
| | + } |
| | + |
| | + /** |
| | + * Gets a bit. |
| | + * @param bit the bit to be gotten |
| | + */ |
| | + public boolean get(int bit) { |
| | + int bnum = bit >> LG_BITS; |
| | + int idx = bsearch(bnum); |
| | + if (idx >= size || offs[idx]!=bnum) |
| | + return false; |
| | + return 0 != ( bits[idx] & (1L << (bit & BITS_M1) ) ); |
| | + } |
| | + |
| | + /** |
| | + * Logically ANDs this bit set with the specified set of bits. |
| | + * @param set the bit set to be ANDed with |
| | + */ |
| | + public void and(SparseBitSet set) { |
| | + binop(this, set, AND); |
| | + } |
| | + |
| | + /** |
| | + * Logically ORs this bit set with the specified set of bits. |
| | + * @param set the bit set to be ORed with |
| | + */ |
| | + public void or(SparseBitSet set) { |
| | + binop(this, set, OR); |
| | + } |
| | + |
| | + /** |
| | + * Logically XORs this bit set with the specified set of bits. |
| | + * @param set the bit set to be XORed with |
| | + */ |
| | + public void xor(SparseBitSet set) { |
| | + binop(this, set, XOR); |
| | + } |
| | + |
| | + // BINARY OPERATION MACHINERY |
| | + private static interface BinOp { |
| | + public long op(long a, long b); |
| | + } |
| | + private static final BinOp AND = new BinOp() { |
| | + public final long op(long a, long b) { return a & b; } |
| | + }; |
| | + private static final BinOp OR = new BinOp() { |
| | + public final long op(long a, long b) { return a | b; } |
| | + }; |
| | + private static final BinOp XOR = new BinOp() { |
| | + public final long op(long a, long b) { return a ^ b; } |
| | + }; |
| | + private static final void binop(SparseBitSet a, SparseBitSet b, BinOp op) { |
| | + int nsize = a.size + b.size; |
| | + long[] nbits; |
| | + int [] noffs; |
| | + int a_zero, a_size; |
| | + // be very clever and avoid allocating more memory if we can. |
| | + if (a.bits.length < nsize) { // oh well, have to make working space. |
| | + nbits = new long[nsize]; |
| | + noffs = new int [nsize]; |
| | + a_zero = 0; a_size = a.size; |
| | + } else { // reduce, reuse, recycle! |
| | + nbits = a.bits; |
| | + noffs = a.offs; |
| | + a_zero = a.bits.length - a.size; a_size = a.bits.length; |
| | + System.arraycopy(a.bits, 0, a.bits, a_zero, a.size); |
| | + System.arraycopy(a.offs, 0, a.offs, a_zero, a.size); |
| | + } |
| | + // ok, crunch through and binop those sets! |
| | + nsize = 0; |
| | + for (int i=a_zero, j=0; i<a_size || j<b.size; ) { |
| | + long nb; int no; |
| | + if (i<a_size && (j>=b.size || a.offs[i] < b.offs[j])) { |
| | + nb = op.op(a.bits[i], 0); |
| | + no = a.offs[i]; |
| | + i++; |
| | + } else if (j<b.size && (i>=a_size || a.offs[i] > b.offs[j])) { |
| | + nb = op.op(0, b.bits[j]); |
| | + no = b.offs[j]; |
| | + j++; |
| | + } else { // equal keys; merge. |
| | + nb = op.op(a.bits[i], b.bits[j]); |
| | + no = a.offs[i]; |
| | + i++; j++; |
| | + } |
| | + if (nb!=0) { |
| | + nbits[nsize] = nb; |
| | + noffs[nsize] = no; |
| | + nsize++; |
| | + } |
| | + } |
| | + a.bits = nbits; |
| | + a.offs = noffs; |
| | + a.size = nsize; |
| | + } |
| | + |
| | + /** |
| | + * Gets the hashcode. |
| | + */ |
| | + public int hashCode() { |
| | + long h = 1234; |
| | + for (int i=0; i<size; i++) |
| | + h ^= bits[i] * offs[i]; |
| | + return (int)((h >> 32) ^ h); |
| | + } |
| | + |
| | + /** |
| | + * Calculates and returns the set's size |
| | + */ |
| | + public int size() { |
| | + return (size==0)?0:((1+offs[size-1]) << LG_BITS); |
| | + } |
| | + |
| | + /** |
| | + * Compares this object against the specified object. |
| | + * @param obj the object to commpare with |
| | + * @return true if the objects are the same; false otherwise. |
| | + */ |
| | + public boolean equals(Object obj) { |
| | + if ((obj != null) && (obj instanceof SparseBitSet)) |
| | + return equals(this, (SparseBitSet)obj); |
| | + return false; |
| | + } |
| | + /** |
| | + * Compares two SparseBitSets for equality. |
| | + * @return true if the objects are the same; false otherwise. |
| | + */ |
| | + public static boolean equals(SparseBitSet a, SparseBitSet b) { |
| | + for (int i=0, j=0; i<a.size || j<b.size; ) { |
| | + if (i<a.size && (j>=b.size || a.offs[i] < b.offs[j])) { |
| | + if (a.bits[i++]!=0) return false; |
| | + } else if (j<b.size && (i>=a.size || a.offs[i] > b.offs[j])) { |
| | + if (b.bits[j++]!=0) return false; |
| | + } else { // equal keys |
| | + if (a.bits[i++]!=b.bits[j++]) return false; |
| | + } |
| | + } |
| | + return true; |
| | + } |
| | + |
| | + /** |
| | + * Clones the SparseBitSet. |
| | + */ |
| | + public Object clone() { |
| | + try { |
| | + SparseBitSet set = (SparseBitSet)super.clone(); |
| | + set.bits = (long[]) bits.clone(); |
| | + set.offs = (int []) offs.clone(); |
| | + return set; |
| | + } catch (CloneNotSupportedException e) { |
| | + // this shouldn't happen, since we are Cloneable |
| | + throw new InternalError(); |
| | + } |
| | + } |
| | + |
| | + /** |
| | + * Return an <code>Enumeration</code> of <code>Integer</code>s |
| | + * which represent set bit indices in this SparseBitSet. |
| | + */ |
| | + public Enumeration elements() { |
| | + return new Enumeration() { |
| | + int idx=-1, bit=BITS; |
| | + { advance(); } |
| | + public boolean hasMoreElements() { |
| | + return (idx<size); |
| | + } |
| | + public Object nextElement() { |
| | + int r = bit + (offs[idx] << LG_BITS); |
| | + advance(); |
| | + return new Integer(r); |
| | + } |
| | + private void advance() { |
| | + while (idx<size) { |
| | + while (++bit<BITS) |
| | + if (0!=(bits[idx] & (1L<<bit))) |
| | + return; |
| | + idx++; bit=-1; |
| | + } |
| | + } |
| | + }; |
| | + } |
| | + /** |
| | + * Converts the SparseBitSet to a String. |
| | + */ |
| | + public String toString() { |
| | + StringBuffer sb = new StringBuffer(); |
| | + sb.append('{'); |
| | + for (Enumeration e=elements(); e.hasMoreElements(); ) { |
| | + if (sb.length() > 1) sb.append(", "); |
| | + sb.append(e.nextElement()); |
| | + } |
| | + sb.append('}'); |
| | + return sb.toString(); |
| | + } |
| | + |
| | + /** Check validity. */ |
| | + private boolean isValid() { |
| | + if (bits.length!=offs.length) return false; |
| | + if (size>bits.length) return false; |
| | + if (size!=0 && 0<=offs[0]) return false; |
| | + for (int i=1; i<size; i++) |
| | + if (offs[i] < offs[i-1]) |
| | + return false; |
| | + return true; |
| | + } |
| | + /** Self-test. */ |
| | + public static void main(String[] args) { |
| | + final int ITER = 500; |
| | + final int RANGE= 65536; |
| | + SparseBitSet a = new SparseBitSet(); |
| | + CUtility.ASSERT(!a.get(0) && !a.get(1)); |
| | + CUtility.ASSERT(!a.get(123329)); |
| | + a.set(0); CUtility.ASSERT(a.get(0) && !a.get(1)); |
| | + a.set(1); CUtility.ASSERT(a.get(0) && a.get(1)); |
| | + a.clearAll(); |
| | + CUtility.ASSERT(!a.get(0) && !a.get(1)); |
| | + java.util.Random r = new java.util.Random(); |
| | + java.util.Vector v = new java.util.Vector(); |
| | + for (int n=0; n<ITER; n++) { |
| | + int rr = ((r.nextInt()>>>1) % RANGE) << 1; |
| | + a.set(rr); v.addElement(new Integer(rr)); |
| | + // check that all the numbers are there. |
| | + CUtility.ASSERT(a.get(rr) && !a.get(rr+1) && !a.get(rr-1)); |
| | + for (int i=0; i<v.size(); i++) |
| | + CUtility.ASSERT(a.get(((Integer)v.elementAt(i)).intValue())); |
| | + } |
| | + SparseBitSet b = (SparseBitSet) a.clone(); |
| | + CUtility.ASSERT(a.equals(b) && b.equals(a)); |
| | + for (int n=0; n<ITER/2; n++) { |
| | + int rr = (r.nextInt()>>>1) % v.size(); |
| | + int m = ((Integer)v.elementAt(rr)).intValue(); |
| | + b.clear(m); v.removeElementAt(rr); |
| | + // check that numbers are removed properly. |
| | + CUtility.ASSERT(!b.get(m)); |
| | + } |
| | + CUtility.ASSERT(!a.equals(b)); |
| | + SparseBitSet c = (SparseBitSet) a.clone(); |
| | + SparseBitSet d = (SparseBitSet) a.clone(); |
| | + c.and(a); |
| | + CUtility.ASSERT(c.equals(a) && a.equals(c)); |
| | + c.xor(a); |
| | + CUtility.ASSERT(!c.equals(a) && c.size()==0); |
| | + d.or(b); |
| | + CUtility.ASSERT(d.equals(a) && !b.equals(d)); |
| | + d.and(b); |
| | + CUtility.ASSERT(!d.equals(a) && b.equals(d)); |
| | + d.xor(a); |
| | + CUtility.ASSERT(!d.equals(a) && !b.equals(d)); |
| | + c.or(d); c.or(b); |
| | + CUtility.ASSERT(c.equals(a) && a.equals(c)); |
| | + c = (SparseBitSet) d.clone(); |
| | + c.and(b); |
| | + CUtility.ASSERT(c.size()==0); |
| | + System.out.println("Success."); |
| | + } |
| | +} |
| | + |
| | +/************************************************************************ |
| | + JLEX COPYRIGHT NOTICE, LICENSE AND DISCLAIMER. |
| | + |
| | + Copyright 1996 by Elliot Joel Berk |
| | + |
| | + Permission to use, copy, modify, and distribute this software and its |
| | + documentation for any purpose and without fee is hereby granted, |
| | + provided that the above copyright notice appear in all copies and that |
| | + both the copyright notice and this permission notice and warranty |
| | + disclaimer appear in supporting documentation, and that the name of |
| | + Elliot Joel Berk not be used in advertising or publicity pertaining |
| | + to distribution of the software without specific, written prior permission. |
| | + |
| | + Elliot Joel Berk disclaims all warranties with regard to this software, |
| | + including all implied warranties of merchantability and fitness. In no event |
| | + shall Elliot Joel Berk be liable for any special, indirect or consequential |
| | + damages or any damages whatsoever resulting from loss of use, data or |
| | + profits, whether in an action of contract, negligence or other |
| | + tortious action, arising out of or in connection with the use or |
| | + performance of this software. |
| | + ***********************************************************************/ |
| | +// set emacs indentation |
| | +// Local Variables: |
| | +// c-basic-offset:2 |
| | +// End: |
| | |