From 0f1055b8d7f97d86c66fa602c17666bc2ff9c437 Mon Sep 17 00:00:00 2001 From: Constantin Jucovschi Date: Tue, 31 Mar 2009 06:18:54 -0400 Subject: Initial commit --- src/syntaxParser/java_cup/emit.java | 897 ++++++++++++++++++++++++++++++++++++ 1 file changed, 897 insertions(+) create mode 100644 src/syntaxParser/java_cup/emit.java (limited to 'src/syntaxParser/java_cup/emit.java') diff --git a/src/syntaxParser/java_cup/emit.java b/src/syntaxParser/java_cup/emit.java new file mode 100644 index 0000000..9db9014 --- /dev/null +++ b/src/syntaxParser/java_cup/emit.java @@ -0,0 +1,897 @@ +package java_cup; + +import java.io.PrintWriter; +import java.util.Stack; +import java.util.Enumeration; +import java.util.Date; + +/** + * This class handles emitting generated code for the resulting parser. + * The various parse tables must be constructed, etc. before calling any + * routines in this class.

+ * + * Three classes are produced by this code: + *

+ *
symbol constant class + *
this contains constant declarations for each terminal (and + * optionally each non-terminal). + *
action class + *
this non-public class contains code to invoke all the user actions + * that were embedded in the parser specification. + *
parser class + *
the specialized parser class consisting primarily of some user + * supplied general and initialization code, and the parse tables. + *

+ * + * Three parse tables are created as part of the parser class: + *

+ *
production table + *
lists the LHS non terminal number, and the length of the RHS of + * each production. + *
action table + *
for each state of the parse machine, gives the action to be taken + * (shift, reduce, or error) under each lookahead symbol.
+ *
reduce-goto table + *
when a reduce on a given production is taken, the parse stack is + * popped back a number of elements corresponding to the RHS of the + * production. This reveals a prior state, which we transition out + * of under the LHS non terminal symbol for the production (as if we + * had seen the LHS symbol rather than all the symbols matching the + * RHS). This table is indexed by non terminal numbers and indicates + * how to make these transitions. + *

+ * + * In addition to the method interface, this class maintains a series of + * public global variables and flags indicating how misc. parts of the code + * and other output is to be produced, and counting things such as number of + * conflicts detected (see the source code and public variables below for + * more details).

+ * + * This class is "static" (contains only static data and methods).

+ * + * @see java_cup.main + * @version last update: 11/25/95 + * @author Scott Hudson + */ + +/* Major externally callable routines here include: + symbols - emit the symbol constant class + parser - emit the parser class + + In addition the following major internal routines are provided: + emit_package - emit a package declaration + emit_action_code - emit the class containing the user's actions + emit_production_table - emit declaration and init for the production table + do_action_table - emit declaration and init for the action table + do_reduce_table - emit declaration and init for the reduce-goto table + + Finally, this class uses a number of public instance variables to communicate + optional parameters and flags used to control how code is generated, + as well as to report counts of various things (such as number of conflicts + detected). These include: + + prefix - a prefix string used to prefix names that would + otherwise "pollute" someone else's name space. + package_name - name of the package emitted code is placed in + (or null for an unnamed package. + symbol_const_class_name - name of the class containing symbol constants. + parser_class_name - name of the class for the resulting parser. + action_code - user supplied declarations and other code to be + placed in action class. + parser_code - user supplied declarations and other code to be + placed in parser class. + init_code - user supplied code to be executed as the parser + is being initialized. + scan_code - user supplied code to get the next Symbol. + start_production - the start production for the grammar. + import_list - list of imports for use with action class. + num_conflicts - number of conflicts detected. + nowarn - true if we are not to issue warning messages. + not_reduced - count of number of productions that never reduce. + unused_term - count of unused terminal symbols. + unused_non_term - count of unused non terminal symbols. + *_time - a series of symbols indicating how long various + sub-parts of code generation took (used to produce + optional time reports in main). +*/ + +public class emit { + + /*-----------------------------------------------------------*/ + /*--- Constructor(s) ----------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Only constructor is private so no instances can be created. */ + private emit() { } + + /*-----------------------------------------------------------*/ + /*--- Static (Class) Variables ------------------------------*/ + /*-----------------------------------------------------------*/ + + /** The prefix placed on names that pollute someone else's name space. */ + public static String prefix = "CUP$"; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Package that the resulting code goes into (null is used for unnamed). */ + public static String package_name = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Name of the generated class for symbol constants. */ + public static String symbol_const_class_name = "sym"; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Name of the generated parser class. */ + public static String parser_class_name = "parser"; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User declarations for direct inclusion in user action class. */ + public static String action_code = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User declarations for direct inclusion in parser class. */ + public static String parser_code = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User code for user_init() which is called during parser initialization. */ + public static String init_code = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User code for scan() which is called to get the next Symbol. */ + public static String scan_code = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The start production of the grammar. */ + public static production start_production = null; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** List of imports (Strings containing class names) to go with actions. */ + public static Stack import_list = new Stack(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Number of conflict found while building tables. */ + public static int num_conflicts = 0; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Do we skip warnings? */ + public static boolean nowarn = false; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Count of the number on non-reduced productions found. */ + public static int not_reduced = 0; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Count of unused terminals. */ + public static int unused_term = 0; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Count of unused non terminals. */ + public static int unused_non_term = 0; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /* Timing values used to produce timing report in main.*/ + + /** Time to produce symbol constant class. */ + public static long symbols_time = 0; + + /** Time to produce parser class. */ + public static long parser_time = 0; + + /** Time to produce action code class. */ + public static long action_code_time = 0; + + /** Time to produce the production table. */ + public static long production_table_time = 0; + + /** Time to produce the action table. */ + public static long action_table_time = 0; + + /** Time to produce the reduce-goto table. */ + public static long goto_table_time = 0; + + /* frankf 6/18/96 */ + protected static boolean _lr_values; + + /** whether or not to emit code for left and right values */ + public static boolean lr_values() {return _lr_values;} + protected static void set_lr_values(boolean b) { _lr_values = b;} + + /*-----------------------------------------------------------*/ + /*--- General Methods ---------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Build a string with the standard prefix. + * @param str string to prefix. + */ + protected static String pre(String str) { + return prefix + parser_class_name + "$" + str; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Emit a package spec if the user wants one. + * @param out stream to produce output on. + */ + protected static void emit_package(PrintWriter out) + { + /* generate a package spec if we have a name for one */ + if (package_name != null) { + out.println("package " + package_name + ";"); out.println(); + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Emit code for the symbol constant class, optionally including non terms, + * if they have been requested. + * @param out stream to produce output on. + * @param emit_non_terms do we emit constants for non terminals? + * @param sym_interface should we emit an interface, rather than a class? + */ + public static void symbols(PrintWriter out, + boolean emit_non_terms, boolean sym_interface) + { + terminal term; + non_terminal nt; + String class_or_interface = (sym_interface)?"interface":"class"; + + long start_time = System.currentTimeMillis(); + + /* top of file */ + out.println(); + out.println("//----------------------------------------------------"); + out.println("// The following code was generated by " + + version.title_str); + out.println("// " + new Date()); + out.println("//----------------------------------------------------"); + out.println(); + emit_package(out); + + /* class header */ + out.println("/** CUP generated " + class_or_interface + + " containing symbol constants. */"); + out.println("public " + class_or_interface + " " + + symbol_const_class_name + " {"); + + out.println(" /* terminals */"); + + /* walk over the terminals */ /* later might sort these */ + for (Enumeration e = terminal.all(); e.hasMoreElements(); ) + { + term = (terminal)e.nextElement(); + + /* output a constant decl for the terminal */ + out.println(" public static final int " + term.name() + " = " + + term.index() + ";"); + } + + /* do the non terminals if they want them (parser doesn't need them) */ + if (emit_non_terms) + { + out.println(); + out.println(" /* non terminals */"); + + /* walk over the non terminals */ /* later might sort these */ + for (Enumeration e = non_terminal.all(); e.hasMoreElements(); ) + { + nt = (non_terminal)e.nextElement(); + + /* output a constant decl for the terminal */ + out.println(" static final int " + nt.name() + " = " + + nt.index() + ";"); + } + } + + /* end of class */ + out.println("}"); + out.println(); + + symbols_time = System.currentTimeMillis() - start_time; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Emit code for the non-public class holding the actual action code. + * @param out stream to produce output on. + * @param start_prod the start production of the grammar. + */ + protected static void emit_action_code(PrintWriter out, production start_prod) + throws internal_error + { + production prod; + + long start_time = System.currentTimeMillis(); + + /* class header */ + out.println(); + out.println( + "/** Cup generated class to encapsulate user supplied action code.*/" + ); + out.println("class " + pre("actions") + " {"); + + /* user supplied code */ + if (action_code != null) + { + out.println(); + out.println(action_code); + } + + /* field for parser object */ + out.println(" private final "+parser_class_name+" parser;"); + + /* constructor */ + out.println(); + out.println(" /** Constructor */"); + out.println(" " + pre("actions") + "("+parser_class_name+" parser) {"); + out.println(" this.parser = parser;"); + out.println(" }"); + + /* action method head */ + out.println(); + out.println(" /** Method with the actual generated action code. */"); + out.println(" public final java_cup.runtime.Symbol " + + pre("do_action") + "("); + out.println(" int " + pre("act_num,")); + out.println(" java_cup.runtime.lr_parser " + pre("parser,")); + out.println(" java.util.Stack " + pre("stack,")); + out.println(" int " + pre("top)")); + out.println(" throws java.lang.Exception"); + out.println(" {"); + + /* declaration of result symbol */ + /* New declaration!! now return Symbol + 6/13/96 frankf */ + out.println(" /* Symbol object for return from actions */"); + out.println(" java_cup.runtime.Symbol " + pre("result") + ";"); + out.println(); + + /* switch top */ + out.println(" /* select the action based on the action number */"); + out.println(" switch (" + pre("act_num") + ")"); + out.println(" {"); + + /* emit action code for each production as a separate case */ + for (Enumeration p = production.all(); p.hasMoreElements(); ) + { + prod = (production)p.nextElement(); + + /* case label */ + out.println(" /*. . . . . . . . . . . . . . . . . . . .*/"); + out.println(" case " + prod.index() + ": // " + + prod.to_simple_string()); + + /* give them their own block to work in */ + out.println(" {"); + + /* create the result symbol */ + /*make the variable RESULT which will point to the new Symbol (see below) + and be changed by action code + 6/13/96 frankf */ + out.println(" " + prod.lhs().the_symbol().stack_type() + + " RESULT = null;"); + + /* Add code to propagate RESULT assignments that occur in + * action code embedded in a production (ie, non-rightmost + * action code). 24-Mar-1998 CSA + */ + for (int i=0; ireduce_goto table. */"); + out.println(" protected static final short[][] _reduce_table = "); + out.print (" unpackFromStrings("); + do_table_as_string(out, reduce_goto_table); + out.println(");"); + + /* do the public accessor method */ + out.println(); + out.println(" /** Access to reduce_goto table. */"); + out.println(" public short[][] reduce_table() {return _reduce_table;}"); + out.println(); + + goto_table_time = System.currentTimeMillis() - start_time; + } + + // print a string array encoding the given short[][] array. + protected static void do_table_as_string(PrintWriter out, short[][] sa) { + out.println("new String[] {"); + out.print(" \""); + int nchar=0, nbytes=0; + nbytes+=do_escaped(out, (char)(sa.length>>16)); + nchar =do_newline(out, nchar, nbytes); + nbytes+=do_escaped(out, (char)(sa.length&0xFFFF)); + nchar =do_newline(out, nchar, nbytes); + for (int i=0; i>16)); + nchar =do_newline(out, nchar, nbytes); + nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF)); + nchar =do_newline(out, nchar, nbytes); + for (int j=0; j 65500) { out.println("\", "); out.print(" \""); } + else if (nchar > 11) { out.println("\" +"); out.print(" \""); } + else return nchar+1; + return 0; + } + // output an escape sequence for the given character code. + protected static int do_escaped(PrintWriter out, char c) { + StringBuffer escape = new StringBuffer(); + if (c <= 0xFF) { + escape.append(Integer.toOctalString(c)); + while(escape.length() < 3) escape.insert(0, '0'); + } else { + escape.append(Integer.toHexString(c)); + while(escape.length() < 4) escape.insert(0, '0'); + escape.insert(0, 'u'); + } + escape.insert(0, '\\'); + out.print(escape.toString()); + + // return number of bytes this takes up in UTF-8 encoding. + if (c == 0) return 2; + if (c >= 0x01 && c <= 0x7F) return 1; + if (c >= 0x80 && c <= 0x7FF) return 2; + return 3; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Emit the parser subclass with embedded tables. + * @param out stream to produce output on. + * @param action_table internal representation of the action table. + * @param reduce_table internal representation of the reduce-goto table. + * @param start_st start state of the parse machine. + * @param start_prod start production of the grammar. + * @param compact_reduces do we use most frequent reduce as default? + * @param suppress_scanner should scanner be suppressed for compatibility? + */ + public static void parser( + PrintWriter out, + parse_action_table action_table, + parse_reduce_table reduce_table, + int start_st, + production start_prod, + boolean compact_reduces, + boolean suppress_scanner) + throws internal_error + { + long start_time = System.currentTimeMillis(); + + /* top of file */ + out.println(); + out.println("//----------------------------------------------------"); + out.println("// The following code was generated by " + + version.title_str); + out.println("// " + new Date()); + out.println("//----------------------------------------------------"); + out.println(); + emit_package(out); + + /* user supplied imports */ + for (int i = 0; i < import_list.size(); i++) + out.println("import " + import_list.elementAt(i) + ";"); + + /* class header */ + out.println(); + out.println("/** "+version.title_str+" generated parser."); + out.println(" * @version " + new Date()); + out.println(" */"); + out.println("public class " + parser_class_name + + " extends java_cup.runtime.lr_parser {"); + + /* constructors [CSA/davidm, 24-jul-99] */ + out.println(); + out.println(" /** Default constructor. */"); + out.println(" public " + parser_class_name + "() {super();}"); + if (!suppress_scanner) { + out.println(); + out.println(" /** Constructor which sets the default scanner. */"); + out.println(" public " + parser_class_name + + "(java_cup.runtime.Scanner s) {super(s);}"); + } + + /* emit the various tables */ + emit_production_table(out); + do_action_table(out, action_table, compact_reduces); + do_reduce_table(out, reduce_table); + + /* instance of the action encapsulation class */ + out.println(" /** Instance of action encapsulation class. */"); + out.println(" protected " + pre("actions") + " action_obj;"); + out.println(); + + /* action object initializer */ + out.println(" /** Action encapsulation object initializer. */"); + out.println(" protected void init_actions()"); + out.println(" {"); + out.println(" action_obj = new " + pre("actions") + "(this);"); + out.println(" }"); + out.println(); + + /* access to action code */ + out.println(" /** Invoke a user supplied parse action. */"); + out.println(" public java_cup.runtime.Symbol do_action("); + out.println(" int act_num,"); + out.println(" java_cup.runtime.lr_parser parser,"); + out.println(" java.util.Stack stack,"); + out.println(" int top)"); + out.println(" throws java.lang.Exception"); + out.println(" {"); + out.println(" /* call code in generated class */"); + out.println(" return action_obj." + pre("do_action(") + + "act_num, parser, stack, top);"); + out.println(" }"); + out.println(""); + + + /* method to tell the parser about the start state */ + out.println(" /** Indicates start state. */"); + out.println(" public int start_state() {return " + start_st + ";}"); + + /* method to indicate start production */ + out.println(" /** Indicates start production. */"); + out.println(" public int start_production() {return " + + start_production.index() + ";}"); + out.println(); + + /* methods to indicate EOF and error symbol indexes */ + out.println(" /** EOF Symbol index. */"); + out.println(" public int EOF_sym() {return " + terminal.EOF.index() + + ";}"); + out.println(); + out.println(" /** error Symbol index. */"); + out.println(" public int error_sym() {return " + terminal.error.index() + + ";}"); + out.println(); + + /* user supplied code for user_init() */ + if (init_code != null) + { + out.println(); + out.println(" /** User initialization code. */"); + out.println(" public void user_init() throws java.lang.Exception"); + out.println(" {"); + out.println(init_code); + out.println(" }"); + } + + /* user supplied code for scan */ + if (scan_code != null) + { + out.println(); + out.println(" /** Scan to get the next Symbol. */"); + out.println(" public java_cup.runtime.Symbol scan()"); + out.println(" throws java.lang.Exception"); + out.println(" {"); + out.println(scan_code); + out.println(" }"); + } + + /* user supplied code */ + if (parser_code != null) + { + out.println(); + out.println(parser_code); + } + + /* end of class */ + out.println("}"); + + /* put out the action code class */ + emit_action_code(out, start_prod); + + parser_time = System.currentTimeMillis() - start_time; + } + + /*-----------------------------------------------------------*/ +} -- cgit