in util/src/main/java/java_cup/emit.java [327:494]
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("@SuppressWarnings (\"unchecked\") 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; i<prod.rhs_length(); i++) {
// only interested in non-terminal symbols.
if (!(prod.rhs(i) instanceof symbol_part)) continue;
symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
if (!(s instanceof non_terminal)) continue;
// skip this non-terminal unless it corresponds to
// an embedded action production.
if (((non_terminal)s).is_embedded_action == false) continue;
// OK, it fits. Make a conditional assignment to RESULT.
int index = prod.rhs_length() - i - 1; // last rhs is on top.
out.println(" " + "// propagate RESULT from " +
s.name());
out.println(" " + "if ( " +
"((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ emit.pre("top") + "-" + index + ")).value != null )");
out.println(" " + "RESULT = " +
"(" + prod.lhs().the_symbol().stack_type() + ") " +
"((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ emit.pre("top") + "-" + index + ")).value;");
}
/* if there is an action string, emit it */
if (prod.action() != null && prod.action().code_string() != null &&
!prod.action().equals(""))
out.println(prod.action().code_string());
/* here we have the left and right values being propagated.
must make this a command line option.
frankf 6/18/96 */
/* Create the code that assigns the left and right values of
the new Symbol that the production is reducing to */
if (emit.lr_values()) {
int loffset;
String leftstring, rightstring;
int roffset = 0;
rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
emit.pre("top") + "-" + roffset + ")).right";
if (prod.rhs_length() == 0)
leftstring = rightstring;
else {
loffset = prod.rhs_length() - 1;
leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
emit.pre("top") + "-" + loffset + ")).left";
}
out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
prod.lhs().the_symbol().index() + "/*" +
prod.lhs().the_symbol().name() + "*/" +
", " + leftstring + ", " + rightstring + ", RESULT);");
} else {
out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
prod.lhs().the_symbol().index() + "/*" +
prod.lhs().the_symbol().name() + "*/" +
", RESULT);");
}
/* end of their block */
out.println(" }");
/* if this was the start production, do action for accept */
if (prod == start_prod)
{
out.println(" /* ACCEPT */");
out.println(" " + pre("parser") + ".done_parsing();");
}
/* code to return lhs symbol */
out.println(" return " + pre("result") + ";");
out.println();
}
/* end of switch */
out.println(" /* . . . . . .*/");
out.println(" default:");
out.println(" throw new Exception(");
out.println(" \"Invalid action number found in " +
"internal parse table\");");
out.println();
out.println(" }");
/* end of method */
out.println(" }");
/* end of class */
out.println("}");
out.println();
action_code_time = System.currentTimeMillis() - start_time;
}