protected static void emit_action_code()

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;
    }