0001: package java_cup;
0002:
0003: import java.io.PrintWriter;
0004: import java.util.Stack;
0005: import java.util.Enumeration;
0006: import java.util.Date;
0007:
0008: /**
0009: * This class handles emitting generated code for the resulting parser.
0010: * The various parse tables must be constructed, etc. before calling any
0011: * routines in this class.<p>
0012: *
0013: * Three classes are produced by this code:
0014: * <dl>
0015: * <dt> symbol constant class
0016: * <dd> this contains constant declarations for each terminal (and
0017: * optionally each non-terminal).
0018: * <dt> action class
0019: * <dd> this non-public class contains code to invoke all the user actions
0020: * that were embedded in the parser specification.
0021: * <dt> parser class
0022: * <dd> the specialized parser class consisting primarily of some user
0023: * supplied general and initialization code, and the parse tables.
0024: * </dl><p>
0025: *
0026: * Three parse tables are created as part of the parser class:
0027: * <dl>
0028: * <dt> production table
0029: * <dd> lists the LHS non terminal number, and the length of the RHS of
0030: * each production.
0031: * <dt> action table
0032: * <dd> for each state of the parse machine, gives the action to be taken
0033: * (shift, reduce, or error) under each lookahead symbol.<br>
0034: * <dt> reduce-goto table
0035: * <dd> when a reduce on a given production is taken, the parse stack is
0036: * popped back a number of elements corresponding to the RHS of the
0037: * production. This reveals a prior state, which we transition out
0038: * of under the LHS non terminal symbol for the production (as if we
0039: * had seen the LHS symbol rather than all the symbols matching the
0040: * RHS). This table is indexed by non terminal numbers and indicates
0041: * how to make these transitions.
0042: * </dl><p>
0043: *
0044: * In addition to the method interface, this class maintains a series of
0045: * public global variables and flags indicating how misc. parts of the code
0046: * and other output is to be produced, and counting things such as number of
0047: * conflicts detected (see the source code and public variables below for
0048: * more details).<p>
0049: *
0050: * This class is "static" (contains only static data and methods).<p>
0051: *
0052: * @see java_cup.main
0053: * @version last update: 11/25/95
0054: * @author Scott Hudson
0055: */
0056:
0057: /* Major externally callable routines here include:
0058: symbols - emit the symbol constant class
0059: parser - emit the parser class
0060:
0061: In addition the following major internal routines are provided:
0062: emit_package - emit a package declaration
0063: emit_action_code - emit the class containing the user's actions
0064: emit_production_table - emit declaration and init for the production table
0065: do_action_table - emit declaration and init for the action table
0066: do_reduce_table - emit declaration and init for the reduce-goto table
0067:
0068: Finally, this class uses a number of public instance variables to communicate
0069: optional parameters and flags used to control how code is generated,
0070: as well as to report counts of various things (such as number of conflicts
0071: detected). These include:
0072:
0073: prefix - a prefix string used to prefix names that would
0074: otherwise "pollute" someone else's name space.
0075: package_name - name of the package emitted code is placed in
0076: (or null for an unnamed package.
0077: symbol_const_class_name - name of the class containing symbol constants.
0078: parser_class_name - name of the class for the resulting parser.
0079: action_code - user supplied declarations and other code to be
0080: placed in action class.
0081: parser_code - user supplied declarations and other code to be
0082: placed in parser class.
0083: init_code - user supplied code to be executed as the parser
0084: is being initialized.
0085: scan_code - user supplied code to get the next Symbol.
0086: start_production - the start production for the grammar.
0087: import_list - list of imports for use with action class.
0088: num_conflicts - number of conflicts detected.
0089: nowarn - true if we are not to issue warning messages.
0090: not_reduced - count of number of productions that never reduce.
0091: unused_term - count of unused terminal symbols.
0092: unused_non_term - count of unused non terminal symbols.
0093: *_time - a series of symbols indicating how long various
0094: sub-parts of code generation took (used to produce
0095: optional time reports in main).
0096: */
0097:
0098: public class emit {
0099:
0100: /*-----------------------------------------------------------*/
0101: /*--- Constructor(s) ----------------------------------------*/
0102: /*-----------------------------------------------------------*/
0103:
0104: /** Only constructor is private so no instances can be created. */
0105: private emit() {
0106: }
0107:
0108: /*-----------------------------------------------------------*/
0109: /*--- Static (Class) Variables ------------------------------*/
0110: /*-----------------------------------------------------------*/
0111:
0112: /** The prefix placed on names that pollute someone else's name space. */
0113: public static String prefix = "CUP$";
0114:
0115: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0116:
0117: /** Package that the resulting code goes into (null is used for unnamed). */
0118: public static String package_name = null;
0119:
0120: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0121:
0122: /** Name of the generated class for symbol constants. */
0123: public static String symbol_const_class_name = "sym";
0124:
0125: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0126:
0127: /** Name of the generated parser class. */
0128: public static String parser_class_name = "parser";
0129:
0130: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0131:
0132: /** TUM changes; proposed by Henning Niss 20050628: Type arguments for class declaration */
0133: public static String class_type_argument = null;
0134:
0135: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0136:
0137: /** User declarations for direct inclusion in user action class. */
0138: public static String action_code = null;
0139:
0140: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0141:
0142: /** User declarations for direct inclusion in parser class. */
0143: public static String parser_code = null;
0144:
0145: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0146:
0147: /** User code for user_init() which is called during parser initialization. */
0148: public static String init_code = null;
0149:
0150: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0151:
0152: /** User code for scan() which is called to get the next Symbol. */
0153: public static String scan_code = null;
0154:
0155: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0156:
0157: /** The start production of the grammar. */
0158: public static production start_production = null;
0159:
0160: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0161:
0162: /** List of imports (Strings containing class names) to go with actions. */
0163: public static Stack import_list = new Stack();
0164:
0165: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0166:
0167: /** Number of conflict found while building tables. */
0168: public static int num_conflicts = 0;
0169:
0170: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0171:
0172: /** Do we skip warnings? */
0173: public static boolean nowarn = false;
0174:
0175: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0176:
0177: /** Count of the number on non-reduced productions found. */
0178: public static int not_reduced = 0;
0179:
0180: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0181:
0182: /** Count of unused terminals. */
0183: public static int unused_term = 0;
0184:
0185: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0186:
0187: /** Count of unused non terminals. */
0188: public static int unused_non_term = 0;
0189:
0190: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0191:
0192: /* Timing values used to produce timing report in main.*/
0193:
0194: /** Time to produce symbol constant class. */
0195: public static long symbols_time = 0;
0196:
0197: /** Time to produce parser class. */
0198: public static long parser_time = 0;
0199:
0200: /** Time to produce action code class. */
0201: public static long action_code_time = 0;
0202:
0203: /** Time to produce the production table. */
0204: public static long production_table_time = 0;
0205:
0206: /** Time to produce the action table. */
0207: public static long action_table_time = 0;
0208:
0209: /** Time to produce the reduce-goto table. */
0210: public static long goto_table_time = 0;
0211:
0212: /* frankf 6/18/96 */
0213: protected static boolean _lr_values;
0214:
0215: /** whether or not to emit code for left and right values */
0216: public static boolean lr_values() {
0217: return _lr_values;
0218: }
0219:
0220: protected static void set_lr_values(boolean b) {
0221: _lr_values = b;
0222: }
0223:
0224: //Hm Added clear to clear all static fields
0225: public static void clear() {
0226: _lr_values = true;
0227: action_code = null;
0228: import_list = new Stack();
0229: init_code = null;
0230: not_reduced = 0;
0231: num_conflicts = 0;
0232: package_name = null;
0233: parser_class_name = "parser";
0234: parser_code = null;
0235: scan_code = null;
0236: start_production = null;
0237: symbol_const_class_name = "sym";
0238: unused_non_term = 0;
0239: unused_term = 0;
0240: }
0241:
0242: /*-----------------------------------------------------------*/
0243: /*--- General Methods ---------------------------------------*/
0244: /*-----------------------------------------------------------*/
0245:
0246: /** Build a string with the standard prefix.
0247: * @param str string to prefix.
0248: */
0249: protected static String pre(String str) {
0250: return prefix + parser_class_name + "$" + str;
0251: }
0252:
0253: /**
0254: * TUM changes; proposed by Henning Niss 20050628
0255: * Build a string with the specified type arguments,
0256: * if present, otherwise an empty string.
0257: */
0258: protected static String typeArgument() {
0259: return class_type_argument == null ? "" : "<"
0260: + class_type_argument + ">";
0261: }
0262:
0263: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0264:
0265: /** Emit a package spec if the user wants one.
0266: * @param out stream to produce output on.
0267: */
0268: protected static void emit_package(PrintWriter out) {
0269: /* generate a package spec if we have a name for one */
0270: if (package_name != null) {
0271: out.println("package " + package_name + ";");
0272: out.println();
0273: }
0274: }
0275:
0276: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0277:
0278: /** Emit code for the symbol constant class, optionally including non terms,
0279: * if they have been requested.
0280: * @param out stream to produce output on.
0281: * @param emit_non_terms do we emit constants for non terminals?
0282: * @param sym_interface should we emit an interface, rather than a class?
0283: */
0284: public static void symbols(PrintWriter out, boolean emit_non_terms,
0285: boolean sym_interface) {
0286: terminal term;
0287: non_terminal nt;
0288: String class_or_interface = (sym_interface) ? "interface"
0289: : "class";
0290:
0291: long start_time = System.currentTimeMillis();
0292:
0293: /* top of file */
0294: out.println();
0295: out
0296: .println("//----------------------------------------------------");
0297: out.println("// The following code was generated by "
0298: + version.title_str);
0299: out.println("// " + new Date());
0300: out
0301: .println("//----------------------------------------------------");
0302: out.println();
0303: emit_package(out);
0304:
0305: /* class header */
0306: out.println("/** CUP generated " + class_or_interface
0307: + " containing symbol constants. */");
0308: out.println("public " + class_or_interface + " "
0309: + symbol_const_class_name + " {");
0310:
0311: out.println(" /* terminals */");
0312:
0313: /* walk over the terminals *//* later might sort these */
0314: for (Enumeration e = terminal.all(); e.hasMoreElements();) {
0315: term = (terminal) e.nextElement();
0316:
0317: /* output a constant decl for the terminal */
0318: out.println(" public static final int " + term.name()
0319: + " = " + term.index() + ";");
0320: }
0321:
0322: /* do the non terminals if they want them (parser doesn't need them) */
0323: if (emit_non_terms) {
0324: out.println();
0325: out.println(" /* non terminals */");
0326:
0327: /* walk over the non terminals *//* later might sort these */
0328: for (Enumeration e = non_terminal.all(); e
0329: .hasMoreElements();) {
0330: nt = (non_terminal) e.nextElement();
0331:
0332: // ****
0333: // TUM Comment: here we could add a typesafe enumeration
0334: // ****
0335:
0336: /* output a constant decl for the terminal */
0337: out.println(" static final int " + nt.name() + " = "
0338: + nt.index() + ";");
0339: }
0340: }
0341:
0342: /* end of class */
0343: out.println("}");
0344: out.println();
0345:
0346: symbols_time = System.currentTimeMillis() - start_time;
0347: }
0348:
0349: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0350:
0351: /** Emit code for the non-public class holding the actual action code.
0352: * @param out stream to produce output on.
0353: * @param start_prod the start production of the grammar.
0354: */
0355: protected static void emit_action_code(PrintWriter out,
0356: production start_prod) throws internal_error {
0357: production prod;
0358:
0359: long start_time = System.currentTimeMillis();
0360:
0361: /* class header */
0362: out.println();
0363: out
0364: .println("/** Cup generated class to encapsulate user supplied action code.*/");
0365: /* TUM changes; proposed by Henning Niss 20050628: added type arguement */
0366: out.println("class " + pre("actions") + typeArgument() + " {");
0367: /* user supplied code */
0368: if (action_code != null) {
0369: out.println();
0370: out.println(action_code);
0371: }
0372:
0373: /* field for parser object */
0374: /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */
0375: out.println(" private final " + parser_class_name
0376: + typeArgument() + " parser;");
0377:
0378: /* constructor */
0379: out.println();
0380: out.println(" /** Constructor */");
0381: /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */
0382: out.println(" " + pre("actions") + "(" + parser_class_name
0383: + typeArgument() + " parser) {");
0384: out.println(" this.parser = parser;");
0385: out.println(" }");
0386:
0387: /* action method head */
0388: out.println();
0389: out
0390: .println(" /** Method with the actual generated action code. */");
0391: out.println(" public final java_cup.runtime.Symbol "
0392: + pre("do_action") + "(");
0393: out
0394: .println(" int "
0395: + pre("act_num,"));
0396: out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
0397: out.println(" java.util.Stack " + pre("stack,"));
0398: out.println(" int " + pre("top)"));
0399: out.println(" throws java.lang.Exception");
0400: out.println(" {");
0401:
0402: /* declaration of result symbol */
0403: /* New declaration!! now return Symbol
0404: 6/13/96 frankf */
0405: out
0406: .println(" /* Symbol object for return from actions */");
0407: out.println(" java_cup.runtime.Symbol " + pre("result")
0408: + ";");
0409: out.println();
0410:
0411: /* switch top */
0412: out
0413: .println(" /* select the action based on the action number */");
0414: out.println(" switch (" + pre("act_num") + ")");
0415: out.println(" {");
0416:
0417: /* emit action code for each production as a separate case */
0418: for (Enumeration p = production.all(); p.hasMoreElements();) {
0419: prod = (production) p.nextElement();
0420:
0421: /* case label */
0422: out
0423: .println(" /*. . . . . . . . . . . . . . . . . . . .*/");
0424: out.println(" case " + prod.index() + ": // "
0425: + prod.to_simple_string());
0426:
0427: /* give them their own block to work in */
0428: out.println(" {");
0429:
0430: /**
0431: * TUM 20060608 intermediate result patch
0432: */
0433: String result = "null";
0434: if (prod instanceof action_production) {
0435: int lastResult = ((action_production) prod)
0436: .getIndexOfIntermediateResult();
0437: if (lastResult != -1) {
0438: result = "("
0439: + prod.lhs().the_symbol().stack_type()
0440: + ") "
0441: + "((java_cup.runtime.Symbol) "
0442: + emit.pre("stack")
0443: +
0444: // TUM 20050917
0445: ((lastResult == 1) ? ".peek()"
0446: : (".elementAt(" + emit.pre("top")
0447: + "-" + (lastResult - 1) + ")"))
0448: + ").value";
0449: }
0450: }
0451:
0452: /* create the result symbol */
0453: /*make the variable RESULT which will point to the new Symbol (see below)
0454: and be changed by action code
0455: 6/13/96 frankf */
0456: out.println(" "
0457: + prod.lhs().the_symbol().stack_type()
0458: + " RESULT =" + result + ";");
0459:
0460: /* Add code to propagate RESULT assignments that occur in
0461: * action code embedded in a production (ie, non-rightmost
0462: * action code). 24-Mar-1998 CSA
0463: */
0464: for (int i = prod.rhs_length() - 1; i >= 0; i--) {
0465: // only interested in non-terminal symbols.
0466: if (!(prod.rhs(i) instanceof symbol_part))
0467: continue;
0468: symbol s = ((symbol_part) prod.rhs(i)).the_symbol();
0469: if (!(s instanceof non_terminal))
0470: continue;
0471: // skip this non-terminal unless it corresponds to
0472: // an embedded action production.
0473: if (((non_terminal) s).is_embedded_action == false)
0474: continue;
0475: // OK, it fits. Make a conditional assignment to RESULT.
0476: int index = prod.rhs_length() - i - 1; // last rhs is on top.
0477: // set comment to inform about where the intermediate result came from
0478: out.println(" "
0479: + "// propagate RESULT from " + s.name());
0480: // // look out, whether the intermediate result is null or not
0481: // out.println(" " + "if ( " +
0482: // "((java_cup.runtime.Symbol) " + emit.pre("stack") +
0483: // // TUM 20050917
0484: // ((index==0)?".peek()":(".elementAt(" + emit.pre("top") + "-" + index + ")"))+
0485: // ").value != null )");
0486:
0487: // TUM 20060608: even when its null: who cares?
0488:
0489: // store the intermediate result into RESULT
0490: out.println(" "
0491: + "RESULT = "
0492: + "("
0493: + prod.lhs().the_symbol().stack_type()
0494: + ") "
0495: + "((java_cup.runtime.Symbol) "
0496: + emit.pre("stack")
0497: +
0498: // TUM 20050917
0499: ((index == 0) ? ".peek()" : (".elementAt("
0500: + emit.pre("top") + "-" + index + ")"))
0501: + ").value;");
0502: break;
0503: }
0504:
0505: /* if there is an action string, emit it */
0506: if (prod.action() != null
0507: && prod.action().code_string() != null
0508: && !prod.action().equals(""))
0509: out.println(prod.action().code_string());
0510:
0511: /* here we have the left and right values being propagated.
0512: must make this a command line option.
0513: frankf 6/18/96 */
0514:
0515: /* Create the code that assigns the left and right values of
0516: the new Symbol that the production is reducing to */
0517: if (emit.lr_values()) {
0518: int loffset;
0519: String leftstring, rightstring;
0520: // TUM 20050917
0521: //int roffset = 0;
0522: rightstring = "((java_cup.runtime.Symbol)"
0523: + emit.pre("stack") +
0524: // TUM 20050917
0525: //".elementAt(" + emit.pre("top") + "-" + roffset + "))"+
0526: ".peek()" +
0527: // TUM 20060327 removed .right
0528: ")";
0529: if (prod.rhs_length() == 0)
0530: leftstring = rightstring;
0531: else {
0532: loffset = prod.rhs_length() - 1;
0533: leftstring = "((java_cup.runtime.Symbol)"
0534: + emit.pre("stack") +
0535: // TUM 20050917
0536: ((loffset == 0) ? (".peek()")
0537: : (".elementAt(" + emit.pre("top")
0538: + "-" + loffset + ")")) +
0539: // TUM 20060327 removed .left
0540: ")";
0541: }
0542: // out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
0543: out.println(" " + pre("result")
0544: + " = parser.getSymbolFactory().newSymbol("
0545: + "\"" + prod.lhs().the_symbol().name() + "\","
0546: + prod.lhs().the_symbol().index() + ", "
0547: + leftstring + ", " + rightstring
0548: + ", RESULT);");
0549: } else {
0550: // out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
0551: out.println(" " + pre("result")
0552: + " = parser.getSymbolFactory().newSymbol("
0553: + "\"" + prod.lhs().the_symbol().name() + "\","
0554: + prod.lhs().the_symbol().index()
0555: + ", RESULT);");
0556: }
0557:
0558: /* end of their block */
0559: out.println(" }");
0560:
0561: /* if this was the start production, do action for accept */
0562: if (prod == start_prod) {
0563: out.println(" /* ACCEPT */");
0564: out.println(" " + pre("parser")
0565: + ".done_parsing();");
0566: }
0567:
0568: /* code to return lhs symbol */
0569: out.println(" return " + pre("result") + ";");
0570: out.println();
0571: }
0572:
0573: /* end of switch */
0574: out.println(" /* . . . . . .*/");
0575: out.println(" default:");
0576: out.println(" throw new Exception(");
0577: out.println(" \"Invalid action number found in "
0578: + "internal parse table\");");
0579: out.println();
0580: out.println(" }");
0581:
0582: /* end of method */
0583: out.println(" }");
0584:
0585: /* end of class */
0586: out.println("}");
0587: out.println();
0588:
0589: action_code_time = System.currentTimeMillis() - start_time;
0590: }
0591:
0592: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0593:
0594: /** Emit the production table.
0595: * @param out stream to produce output on.
0596: */
0597: protected static void emit_production_table(PrintWriter out) {
0598: production all_prods[];
0599: production prod;
0600:
0601: long start_time = System.currentTimeMillis();
0602:
0603: /* collect up the productions in order */
0604: all_prods = new production[production.number()];
0605: for (Enumeration p = production.all(); p.hasMoreElements();) {
0606: prod = (production) p.nextElement();
0607: all_prods[prod.index()] = prod;
0608: }
0609:
0610: // make short[][]
0611: short[][] prod_table = new short[production.number()][2];
0612: for (int i = 0; i < production.number(); i++) {
0613: prod = all_prods[i];
0614: // { lhs symbol , rhs size }
0615: prod_table[i][0] = (short) prod.lhs().the_symbol().index();
0616: prod_table[i][1] = (short) prod.rhs_length();
0617: }
0618: /* do the top of the table */
0619: out.println();
0620: out.println(" /** Production table. */");
0621: out
0622: .println(" protected static final short _production_table[][] = ");
0623: out.print(" unpackFromStrings(");
0624: do_table_as_string(out, prod_table);
0625: out.println(");");
0626:
0627: /* do the public accessor method */
0628: out.println();
0629: out.println(" /** Access to production table. */");
0630: out.println(" public short[][] production_table() "
0631: + "{return _production_table;}");
0632:
0633: production_table_time = System.currentTimeMillis() - start_time;
0634: }
0635:
0636: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0637:
0638: /** Emit the action table.
0639: * @param out stream to produce output on.
0640: * @param act_tab the internal representation of the action table.
0641: * @param compact_reduces do we use the most frequent reduce as default?
0642: */
0643: protected static void do_action_table(PrintWriter out,
0644: parse_action_table act_tab, boolean compact_reduces)
0645: throws internal_error {
0646: parse_action_row row;
0647: parse_action act;
0648: int red;
0649:
0650: long start_time = System.currentTimeMillis();
0651:
0652: /* collect values for the action table */
0653: short[][] action_table = new short[act_tab.num_states()][];
0654: /* do each state (row) of the action table */
0655: for (int i = 0; i < act_tab.num_states(); i++) {
0656: /* get the row */
0657: row = act_tab.under_state[i];
0658:
0659: /* determine the default for the row */
0660: if (compact_reduces)
0661: row.compute_default();
0662: else
0663: row.default_reduce = -1;
0664:
0665: /* make temporary table for the row. */
0666: short[] temp_table = new short[2 * parse_action_row.size()];
0667: int nentries = 0;
0668:
0669: /* do each column */
0670: for (int j = 0; j < parse_action_row.size(); j++) {
0671: /* extract the action from the table */
0672: act = row.under_term[j];
0673:
0674: /* skip error entries these are all defaulted out */
0675: if (act.kind() != parse_action.ERROR) {
0676: /* first put in the symbol index, then the actual entry */
0677:
0678: /* shifts get positive entries of state number + 1 */
0679: if (act.kind() == parse_action.SHIFT) {
0680: /* make entry */
0681: temp_table[nentries++] = (short) j;
0682: temp_table[nentries++] = (short) (((shift_action) act)
0683: .shift_to().index() + 1);
0684: }
0685:
0686: /* reduce actions get negated entries of production# + 1 */
0687: else if (act.kind() == parse_action.REDUCE) {
0688: /* if its the default entry let it get defaulted out */
0689: red = ((reduce_action) act).reduce_with()
0690: .index();
0691: if (red != row.default_reduce) {
0692: /* make entry */
0693: temp_table[nentries++] = (short) j;
0694: temp_table[nentries++] = (short) (-(red + 1));
0695: }
0696: } else if (act.kind() == parse_action.NONASSOC) {
0697: /* do nothing, since we just want a syntax error */
0698: }
0699: /* shouldn't be anything else */
0700: else
0701: throw new internal_error(
0702: "Unrecognized action code "
0703: + act.kind()
0704: + " found in parse table");
0705: }
0706: }
0707:
0708: /* now we know how big to make the row */
0709: action_table[i] = new short[nentries + 2];
0710: System.arraycopy(temp_table, 0, action_table[i], 0,
0711: nentries);
0712:
0713: /* finish off the row with a default entry */
0714: action_table[i][nentries++] = -1;
0715: if (row.default_reduce != -1)
0716: action_table[i][nentries++] = (short) (-(row.default_reduce + 1));
0717: else
0718: action_table[i][nentries++] = 0;
0719: }
0720:
0721: /* finish off the init of the table */
0722: out.println();
0723: out.println(" /** Parse-action table. */");
0724: out
0725: .println(" protected static final short[][] _action_table = ");
0726: out.print(" unpackFromStrings(");
0727: do_table_as_string(out, action_table);
0728: out.println(");");
0729:
0730: /* do the public accessor method */
0731: out.println();
0732: out.println(" /** Access to parse-action table. */");
0733: out
0734: .println(" public short[][] action_table() {return _action_table;}");
0735:
0736: action_table_time = System.currentTimeMillis() - start_time;
0737: }
0738:
0739: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0740:
0741: /** Emit the reduce-goto table.
0742: * @param out stream to produce output on.
0743: * @param red_tab the internal representation of the reduce-goto table.
0744: */
0745: protected static void do_reduce_table(PrintWriter out,
0746: parse_reduce_table red_tab) {
0747: lalr_state goto_st;
0748: parse_action act;
0749:
0750: long start_time = System.currentTimeMillis();
0751:
0752: /* collect values for reduce-goto table */
0753: short[][] reduce_goto_table = new short[red_tab.num_states()][];
0754: /* do each row of the reduce-goto table */
0755: for (int i = 0; i < red_tab.num_states(); i++) {
0756: /* make temporary table for the row. */
0757: short[] temp_table = new short[2 * parse_reduce_row.size()];
0758: int nentries = 0;
0759: /* do each entry in the row */
0760: for (int j = 0; j < parse_reduce_row.size(); j++) {
0761: /* get the entry */
0762: goto_st = red_tab.under_state[i].under_non_term[j];
0763:
0764: /* if we have none, skip it */
0765: if (goto_st != null) {
0766: /* make entries for the index and the value */
0767: temp_table[nentries++] = (short) j;
0768: temp_table[nentries++] = (short) goto_st.index();
0769: }
0770: }
0771: /* now we know how big to make the row. */
0772: reduce_goto_table[i] = new short[nentries + 2];
0773: System.arraycopy(temp_table, 0, reduce_goto_table[i], 0,
0774: nentries);
0775:
0776: /* end row with default value */
0777: reduce_goto_table[i][nentries++] = -1;
0778: reduce_goto_table[i][nentries++] = -1;
0779: }
0780:
0781: /* emit the table. */
0782: out.println();
0783: out.println(" /** <code>reduce_goto</code> table. */");
0784: out
0785: .println(" protected static final short[][] _reduce_table = ");
0786: out.print(" unpackFromStrings(");
0787: do_table_as_string(out, reduce_goto_table);
0788: out.println(");");
0789:
0790: /* do the public accessor method */
0791: out.println();
0792: out
0793: .println(" /** Access to <code>reduce_goto</code> table. */");
0794: out
0795: .println(" public short[][] reduce_table() {return _reduce_table;}");
0796: out.println();
0797:
0798: goto_table_time = System.currentTimeMillis() - start_time;
0799: }
0800:
0801: // print a string array encoding the given short[][] array.
0802: protected static void do_table_as_string(PrintWriter out,
0803: short[][] sa) {
0804: out.println("new String[] {");
0805: out.print(" \"");
0806: int nchar = 0, nbytes = 0;
0807: nbytes += do_escaped(out, (char) (sa.length >> 16));
0808: nchar = do_newline(out, nchar, nbytes);
0809: nbytes += do_escaped(out, (char) (sa.length & 0xFFFF));
0810: nchar = do_newline(out, nchar, nbytes);
0811: for (int i = 0; i < sa.length; i++) {
0812: nbytes += do_escaped(out, (char) (sa[i].length >> 16));
0813: nchar = do_newline(out, nchar, nbytes);
0814: nbytes += do_escaped(out, (char) (sa[i].length & 0xFFFF));
0815: nchar = do_newline(out, nchar, nbytes);
0816: for (int j = 0; j < sa[i].length; j++) {
0817: // contents of string are (value+2) to allow for common -1, 0 cases
0818: // (UTF-8 encoding is most efficient for 0<c<0x80)
0819: nbytes += do_escaped(out, (char) (2 + sa[i][j]));
0820: nchar = do_newline(out, nchar, nbytes);
0821: }
0822: }
0823: out.print("\" }");
0824: }
0825:
0826: // split string if it is very long; start new line occasionally for neatness
0827: protected static int do_newline(PrintWriter out, int nchar,
0828: int nbytes) {
0829: if (nbytes > 65500) {
0830: out.println("\", ");
0831: out.print(" \"");
0832: } else if (nchar > 11) {
0833: out.println("\" +");
0834: out.print(" \"");
0835: } else
0836: return nchar + 1;
0837: return 0;
0838: }
0839:
0840: // output an escape sequence for the given character code.
0841: protected static int do_escaped(PrintWriter out, char c) {
0842: StringBuffer escape = new StringBuffer();
0843: if (c <= 0xFF) {
0844: escape.append(Integer.toOctalString(c));
0845: while (escape.length() < 3)
0846: escape.insert(0, '0');
0847: } else {
0848: escape.append(Integer.toHexString(c));
0849: while (escape.length() < 4)
0850: escape.insert(0, '0');
0851: escape.insert(0, 'u');
0852: }
0853: escape.insert(0, '\\');
0854: out.print(escape.toString());
0855:
0856: // return number of bytes this takes up in UTF-8 encoding.
0857: if (c == 0)
0858: return 2;
0859: if (c >= 0x01 && c <= 0x7F)
0860: return 1;
0861: if (c >= 0x80 && c <= 0x7FF)
0862: return 2;
0863: return 3;
0864: }
0865:
0866: /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
0867:
0868: /** Emit the parser subclass with embedded tables.
0869: * @param out stream to produce output on.
0870: * @param action_table internal representation of the action table.
0871: * @param reduce_table internal representation of the reduce-goto table.
0872: * @param start_st start state of the parse machine.
0873: * @param start_prod start production of the grammar.
0874: * @param compact_reduces do we use most frequent reduce as default?
0875: * @param suppress_scanner should scanner be suppressed for compatibility?
0876: */
0877: public static void parser(PrintWriter out,
0878: parse_action_table action_table,
0879: parse_reduce_table reduce_table, int start_st,
0880: production start_prod, boolean compact_reduces,
0881: boolean suppress_scanner) throws internal_error {
0882: long start_time = System.currentTimeMillis();
0883:
0884: /* top of file */
0885: out.println();
0886: out
0887: .println("//----------------------------------------------------");
0888: out.println("// The following code was generated by "
0889: + version.title_str);
0890: out.println("// " + new Date());
0891: out
0892: .println("//----------------------------------------------------");
0893: out.println();
0894: emit_package(out);
0895:
0896: /* user supplied imports */
0897: for (int i = 0; i < import_list.size(); i++)
0898: out.println("import " + import_list.elementAt(i) + ";");
0899:
0900: /* class header */
0901: out.println();
0902: out.println("/** " + version.title_str + " generated parser.");
0903: out.println(" * @version " + new Date());
0904: out.println(" */");
0905: /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */
0906: out.println("public class " + parser_class_name
0907: + typeArgument()
0908: + " extends java_cup.runtime.lr_parser {");
0909:
0910: /* constructors [CSA/davidm, 24-jul-99] */
0911: out.println();
0912: out.println(" /** Default constructor. */");
0913: out.println(" public " + parser_class_name + "() {super();}");
0914: if (!suppress_scanner) {
0915: out.println();
0916: out
0917: .println(" /** Constructor which sets the default scanner. */");
0918: out.println(" public " + parser_class_name
0919: + "(java_cup.runtime.Scanner s) {super(s);}");
0920: // TUM 20060327 added SymbolFactory aware constructor
0921: out.println();
0922: out
0923: .println(" /** Constructor which sets the default scanner. */");
0924: out
0925: .println(" public "
0926: + parser_class_name
0927: + "(java_cup.runtime.Scanner s, java_cup.runtime.SymbolFactory sf) {super(s,sf);}");
0928: }
0929:
0930: /* emit the various tables */
0931: emit_production_table(out);
0932: do_action_table(out, action_table, compact_reduces);
0933: do_reduce_table(out, reduce_table);
0934:
0935: /* instance of the action encapsulation class */
0936: out.println(" /** Instance of action encapsulation class. */");
0937: out.println(" protected " + pre("actions") + " action_obj;");
0938: out.println();
0939:
0940: /* action object initializer */
0941: out
0942: .println(" /** Action encapsulation object initializer. */");
0943: out.println(" protected void init_actions()");
0944: out.println(" {");
0945: /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */
0946: out.println(" action_obj = new " + pre("actions")
0947: + typeArgument() + "(this);");
0948: out.println(" }");
0949: out.println();
0950:
0951: /* access to action code */
0952: out.println(" /** Invoke a user supplied parse action. */");
0953: out.println(" public java_cup.runtime.Symbol do_action(");
0954: out.println(" int act_num,");
0955: out.println(" java_cup.runtime.lr_parser parser,");
0956: out.println(" java.util.Stack stack,");
0957: out.println(" int top)");
0958: out.println(" throws java.lang.Exception");
0959: out.println(" {");
0960: out.println(" /* call code in generated class */");
0961: out.println(" return action_obj." + pre("do_action(")
0962: + "act_num, parser, stack, top);");
0963: out.println(" }");
0964: out.println("");
0965:
0966: /* method to tell the parser about the start state */
0967: out.println(" /** Indicates start state. */");
0968: out.println(" public int start_state() {return " + start_st
0969: + ";}");
0970:
0971: /* method to indicate start production */
0972: out.println(" /** Indicates start production. */");
0973: out.println(" public int start_production() {return "
0974: + start_production.index() + ";}");
0975: out.println();
0976:
0977: /* methods to indicate EOF and error symbol indexes */
0978: out.println(" /** <code>EOF</code> Symbol index. */");
0979: out.println(" public int EOF_sym() {return "
0980: + terminal.EOF.index() + ";}");
0981: out.println();
0982: out.println(" /** <code>error</code> Symbol index. */");
0983: out.println(" public int error_sym() {return "
0984: + terminal.error.index() + ";}");
0985: out.println();
0986:
0987: /* user supplied code for user_init() */
0988: if (init_code != null) {
0989: out.println();
0990: out.println(" /** User initialization code. */");
0991: out
0992: .println(" public void user_init() throws java.lang.Exception");
0993: out.println(" {");
0994: out.println(init_code);
0995: out.println(" }");
0996: }
0997:
0998: /* user supplied code for scan */
0999: if (scan_code != null) {
1000: out.println();
1001: out.println(" /** Scan to get the next Symbol. */");
1002: out.println(" public java_cup.runtime.Symbol scan()");
1003: out.println(" throws java.lang.Exception");
1004: out.println(" {");
1005: out.println(scan_code);
1006: out.println(" }");
1007: }
1008:
1009: /* user supplied code */
1010: if (parser_code != null) {
1011: out.println();
1012: out.println(parser_code);
1013: }
1014:
1015: /* end of class */
1016: out.println("}");
1017:
1018: /* put out the action code class */
1019: emit_action_code(out, start_prod);
1020:
1021: parser_time = System.currentTimeMillis() - start_time;
1022: }
1023:
1024: /*-----------------------------------------------------------*/
1025: }
|