public class Print
{
private static String subscriptsPrefix="static final";
private static String constructorsClass=null;
private static String constructorsKludge=null;
private static String staticsClass="";
private static String lion=null;
private static int lionNumber=0;
private static String[] tray=null;
private static String quoteMark="\"";
private static String pryntLeft="System.out.println(java.util.Arrays.deepToString(new Object[]{";
private static String pryntRight="}).replaceFirst(\"\\\\[(.*)\\\\]\",\"$1\"));";
private static String pryntRightNoCommas="}).replaceFirst(\"\\\\[(.*)\\\\]\",\"$1\").replace(',',' ') );";



	private static String getLine( java.io.BufferedReader inTextFile )throws java.lang.Exception
	{
	String lion=inTextFile.readLine();
	return lion;
	}



	private static String addBackslashes( String x )
	{
	int ell=x.length();
	String temp="";
		for( int j=0;j<ell;j++ )
		{
		char c=x.charAt(j);
		if( c=='\"' || c=='\\' )temp+='\\';
		temp+=c;
		}
	return temp;
	}



	private static String nameAndValue( String x )
	{
	return quoteMark+addBackslashes( x )+quoteMark+","+x;
	}



	private static String macroExpandPrint()
	{
	int trayLength=tray.length;
	if(trayLength==1) return "System.out.println();";

	String temp="";
	temp+=nameAndValue( tray[1] );
	for( int j=2;j<trayLength;j++ )temp+=","+nameAndValue( tray[j] );
	if( temp.matches(".*\\Q;\\E.*") )throw new Error( "Suspicious semi-colon in print macro at line "+lionNumber );
	return pryntLeft+temp+pryntRight;
	}



	private static String macExpPri()
	{
	int trayLength=tray.length;
	if(trayLength==1) return "System.out.println();";

	String temp="";
	temp+=tray[1];
	for( int j=2;j<trayLength;j++ )temp+=","+tray[j];
	if( temp.matches(".*\\Q;\\E.*") )throw new Error( "Suspicious semi-colon in pri macro at line "+lionNumber );
	return pryntLeft+temp+pryntRight;
	}



	private static String mEP()
	{
	int trayLength=tray.length;
	if(trayLength==1) return "System.out.println();";

	String temp="";
	temp+=tray[1];
	for( int j=2;j<trayLength;j++ )temp+=","+tray[j];
	if( temp.matches(".*\\Q;\\E.*") )throw new Error( "Suspicious semi-colon in pri macro at line "+lionNumber );
	return pryntLeft+temp+pryntRightNoCommas;
	}



	private static String gatherRemainder( int k )
	{
	int finger=0;
		for(int j=0;j<=k;j++)
		{
		finger=lion.indexOf( tray[j],finger );
		if( j<k )finger+=tray[j].length();
		}
	return lion.substring( finger );
	}



	public static void manage( java.io.InputStream inFile, java.io.PrintStream outFile )throws java.lang.Exception
	{
	int unrequited=0;
	boolean lonelyCurly=false;
	constructorsClass=null;
	constructorsKludge=null;
	staticsClass="";

	java.util.Hashtable<String,String> insideHash=new java.util.Hashtable<String,String>();

	java.util.Hashtable<String,String> macroHash=new java.util.Hashtable<String,String>();

	java.util.Hashtable<String,String> signatureHash=new java.util.Hashtable<String,String>();

	java.util.Hashtable<String,Integer> countHash=new java.util.Hashtable<String,Integer>();

	java.util.Stack<String> stack=new java.util.Stack<String>();

	java.io.BufferedReader inTextFile=new java.io.BufferedReader( new java.io.InputStreamReader( inFile ) );

	java.io.PrintWriter outTextFile=new java.io.PrintWriter( outFile );

		for( ;; )
		{
		lion=getLine( inTextFile );
		if( lion==null )break;

		java.util.Enumeration<String> e=insideHash.keys();
			for( ;e.hasMoreElements(); )
			{
			String kee=e.nextElement();
			String valEwe=insideHash.get( kee );
			lion=lion.replaceAll( kee,valEwe );
			}

		tray=lion.trim().split( "\\p{Blank}+" );
		int trayLength=tray.length;
		lionNumber=lionNumber+1;

			if( trayLength==0 )
			{
			outTextFile.println( lion );
			}



			else if( tray[0].equals( "print" ) )
			{
			String temp=macroExpandPrint();
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "pri" ) )
			{
			String temp=macExpPri();
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "pr" ) )
			{
			String temp=mEP();
			outTextFile.println( temp );
			}



			else if( tray[0].equals("yourClass") || tray[0].equals("yourInterface") )
			{
			if( trayLength<=2 )throw new Error("too few arguments for yourInterface at line "+lionNumber);
			String interfaceName=tray[1];
			String signature=gatherRemainder( 2 );
			signatureHash.put( interfaceName,signature );
			if( signature.matches(".*\\Q;\\E.*") )throw new Error( "Suspicious semi-colon in yourInterface macro at line "+lionNumber );
			outTextFile.println( "" );
			}



			else if( tray[0].equals("myClass") || tray[0].equals("myInterface") )
			{
			if( trayLength<=2 )throw new Error("too few arguments for myInterface at line "+lionNumber);
			String interfaceName=tray[1];
			String signature=gatherRemainder( 2 );
			signatureHash.put( interfaceName,signature );
			if( signature.matches(".*\\Q;\\E.*") )throw new Error( "Suspicious semi-colon in myInterface macro at line "+lionNumber );
			outTextFile.println( "public interface "+interfaceName+"{"+signature+";}" );
			}



			else if( tray[0].equals( "function" ) )
			{
			if( trayLength<=3 )throw new Error("too few arguments for function at line "+lionNumber);
			String interfaceList=tray[1];
			String[] interfaceArray=tray[1].split(",");
			String variableName=tray[2];
			String narrowName=variableName.toUpperCase();
			String wideName=null;
			if( interfaceArray.length>1 )wideName=narrowName; else wideName=tray[1];
			String body=gatherRemainder( 3 );
			String signature=signatureHash.get( interfaceArray[0] );
			if( signature==null )throw new Error("no such interface as "+interfaceArray[0]+" at line "+lionNumber);
			outTextFile.println(
			"class "+narrowName+" implements "+interfaceList+"{public "+signature+"{"+body+"}}"
			+wideName+" "+variableName+"=new "+narrowName+"();"
			);
			}



			else if( tray[0].equals( "beginFunction" ) )
			{
			if( trayLength!=3 )throw new Error("wrong number of arguments for beginFunction at line "+lionNumber);
			String interfaceList=tray[1];
			String[] interfaceArray=tray[1].split(",");
			String variableName=tray[2];
			String narrowName=variableName.toUpperCase();
			String wideName=null;
			if( interfaceArray.length>1 )wideName=narrowName; else wideName=tray[1];
			stack.push( variableName );
			stack.push( wideName );
			stack.push( narrowName );
			stack.push( "beginFunction" );
			String signature=signatureHash.get( interfaceArray[0] );
			if( signature==null )throw new Error("no such interface as "+interfaceArray[0]+" at line "+lionNumber);
			outTextFile.println( "class "+narrowName+" implements "+interfaceList+"{public "+signature+"{" );
			}



			else if( tray[0].equals( "endFunction" ) )
			{
			if( trayLength!=1 )throw new Error("wrong number of arguments for endFunction at line "+lionNumber);
			if( stack.size()<4 )throw new Error("stack is too small at line "+lionNumber);
			String stackLabel=stack.pop();
			if( !stackLabel.equals("beginFunction") )throw new Error(stackLabel+" and endFunction cannot agree at line "+lionNumber);
			String narrowName=stack.pop();
			String wideName=stack.pop();
			String variableName=stack.pop();
			outTextFile.println( "}} "+wideName+" "+variableName+"=new "+narrowName+"();" );
			}



			else if( tray[0].equals( "deleteUnderscores" ) )
			{
			if( trayLength<=1 )throw new Error("too few arguments for deleteUnderscores at line "+lionNumber);
			String temp=gatherRemainder( 1 );
			temp=temp.replaceAll("_","");
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "doubleBackslashes" ) )
			{
			if( trayLength<=1 )throw new Error("too few arguments for doubleBackslashes at line "+lionNumber);
			String temp=gatherRemainder( 1 );
			temp=temp.replaceAll("\\\\","\\\\\\\\");
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "milliseconds" ) )
			{
			if( trayLength!=2 )throw new Error("wrong number of arguments for milliseconds at line "+lionNumber);
			String temp="long " + tray[1] + "=System.currentTimeMillis();";
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "swap" ) )
			{
			if( trayLength!=4 )throw new Error("wrong number of arguments for swap at line "+lionNumber);
			String temp=tray[3]+"="+tray[1]+"; "+tray[1]+"="+tray[2]+"; "+tray[2]+"="+tray[3]+";";
			outTextFile.println( "{ "+temp+" }" );
			}



			else if( tray[0].equals( "let" ) )
			{
			outTextFile.println( Let.let( constructorsClass, staticsClass, lionNumber, lion, tray ) );
			}



			else if( tray[0].equals( "sns" ) )
			{
			outTextFile.println( Sns.sns( lionNumber, lion, tray ) );
			}



			else if( tray.length>=2 && tray[0].equals( "(" ) && tray[1].equals( "setq" ) && tray[trayLength-1].equals( ")" ) )
			{
			outTextFile.println( Lisp.lisp( lionNumber, lion, tray ) );
			}



			else if( tray.length>=2 && tray[0].equals( "(" ) && tray[1].equals( "dotimes" ) && tray[trayLength-1].equals( ")" ) )
			{
			unrequited++;
			outTextFile.println( Lisp.lisp( lionNumber, lion, tray ) );
			}



			else if( trayLength==1 && tray[0].equals( ")" ) && unrequited>0 )
			{
			outTextFile.println( "} // To keep the right paren use \")//\" without the quotes." );
			unrequited--;
			}



			else if( tray[0].equals( "staticsClass" ) )
			{
			if( tray.length==2 )
			staticsClass=tray[1]+".";
			else if( tray.length==1 )
			staticsClass="";
			else throw new Error("wrong number of arguments for staticsClass at line "+lionNumber);
			outTextFile.println( "" );
			}



			else if( tray[0].equals( "constructorsClass" ) )
			{
				if( tray.length==2 )
				{
				constructorsClass=tray[1];
				constructorsKludge=constructorsClass.replaceAll( "\\.","Dot" );
				}
				else
				{
				throw new Error("wrong number of arguments for constructorsClass at line "+lionNumber);
				}
			outTextFile.println( "" );
			}



			else if( tray[0].equals( "mutate" ) )
			{
			outTextFile.println( Mutate.mutate( constructorsClass, staticsClass, lionNumber, lion, tray ) );
			}



			else if( tray[0].equals( "makeTemps" ) )
			{
			if( tray.length!=2 )throw new Error("wrong number of arguments for makeTemps at line "+lionNumber);
			String stem="temporary";
			String manyS=tray[1];
			Integer manyI=Integer.valueOf( manyS );
			int manyInt=(int)manyI;
			String temp="";
				for( int j=0;j<manyInt;j++ )
				{
				temp+=constructorsClass+" "+stem+j+constructorsKludge+"=new "+constructorsClass+"();";
				}
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "next" ) && tray.length==2 )
			{
			String variableName=tray[1];
			if( stack.size()<3 )throw new Error("stack is too small at line "+lionNumber);
			String stackLabel=stack.pop();
			if( !stackLabel.equals("for") )throw new Error("next without for at line "+lionNumber);
			String oldName=stack.pop();
			String oldLionNumber=stack.pop();
			if( !oldName.equals( variableName ) )throw new Error("disagreement of for's variable at line "+oldLionNumber+" from next's variable at line "+lionNumber);
			outTextFile.println( "}" );
			}



			else if( tray.length==6 && tray[0].equals("for") && tray[2].equals("=") && tray[4].equals("to") )
			{
				for( int j=stack.size()-1;j>=2;j-- )
				{
				if( stack.get(j).equals("beginFunction") )break;
				if( stack.get(j).equals("for") && stack.get(j-1).equals(tray[1]) )throw new Error("two nested for's use the same variable at lines "+stack.get(j-2)+" and "+lionNumber);
				}
			stack.push( ""+lionNumber );
			stack.push( tray[1] );
			stack.push( "for" );
			outTextFile.println( "for(int "+tray[1]+"="+tray[3]+";"+tray[1]+"<="+tray[5]+";"+tray[1]+"++){" );
			}



			else if( tray.length==8 && tray[0].equals("for") && tray[2].equals("=") && tray[4].equals("to") && tray[6].equals("step") )
			{
				for( int j=stack.size()-1;j>=2;j-- )
				{
				if( stack.get(j).equals("beginFunction") )break;
				if( stack.get(j).equals("for") && stack.get(j-1).equals(tray[1]) )throw new Error("two nested for's use the same variable at lines "+stack.get(j-2)+" and "+lionNumber);
				}
			stack.push( ""+lionNumber );
			stack.push( tray[1] );
			stack.push( "for" );
			outTextFile.println( "for(int "+tray[1]+" = "+tray[3]+" ; ( "+tray[7]+" >=0 && "+tray[1]+" <= "+tray[5]+" ) || ( "+tray[7]+" <=0 && "+tray[1]+" >= "+tray[5]+" ) ; "+tray[1]+"+="+tray[7]+" ) {" );
			}



			else if( tray[0].equals( "firstly" ) )
			{
			String oldCode="";
			for( int j=1;j<trayLength;j++ )oldCode+=tray[j]+" ";
			stack.push( ""+lionNumber );
			stack.push( oldCode );
			stack.push( "firstly" );
			outTextFile.println( oldCode );
			}



			else if( tray[0].equals( "lastly" ) )
			{
			String newCode="";
			for( int j=1;j<trayLength;j++ )newCode+=tray[j]+" ";
			if( stack.size()<3 )throw new Error("stack is too small at line "+lionNumber);
			String stackLabel=stack.pop();
			if( !stackLabel.equals("firstly") )throw new Error("lastly without firstly at line "+lionNumber);
			String oldCode=stack.pop();
			String oldLionNumber=stack.pop();
			if( !oldCode.equals( newCode ) )throw new Error("disagreement of firstly's code at line "+oldLionNumber+" from lastly's code at line "+lionNumber);
			outTextFile.println( "" );
			}



			else if(  trayLength==1 && tray[0].equals( "lonelyCurly" ) )
			{
			lonelyCurly=true;
			outTextFile.println( "" );
			}



			else if( lonelyCurly && trayLength==1 && tray[0].equals( "{" ) )
			{
			stack.push( "{" );
			outTextFile.println( "{" );
			}



			else if( lonelyCurly && trayLength==1 && tray[0].equals( "}" ) )
			{
			if( stack.size()<1 )throw new Error("stack is too small at line "+lionNumber);
			String stackLabel=stack.pop();
			if( !stackLabel.equals("{") )throw new Error("lonely close curly without lonely open curly at line "+lionNumber);
			outTextFile.println( "}" );
			}



			else if( trayLength==2 && tray[0].equals( "go" ) )
			{
			if( !stack.empty() )throw new Error( "stack is not empty at the go at line "+lionNumber );
			outTextFile.println( "import static java.lang.Math.*;public class "+tray[1]+"{public static void main(String[] args){" );
			}



			else if( trayLength==1 && tray[0].equals( "stop" ) )
			{
			if( !stack.empty() )throw new Error( "stack is not empty at the stop at line "+lionNumber );
			outTextFile.println( "}}" );
			}



			else if( tray[0].equals( "enforce" ) )
			{
			String temp="";
				for( int j=1;j<trayLength;j++ )
				{
				String x=tray[j];
				String y=addBackslashes( x );
				temp+="if( !( "+x+" ) ){ throw new Error( "+quoteMark+y+" is not true"+quoteMark+" ); };";
				}
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "forbid" ) )
			{
			String temp="";
				for( int j=1;j<trayLength;j++ )
				{
				String x=tray[j];
				String y=addBackslashes( x );
				temp+="if( "+x+" ){ throw new Error( "+quoteMark+y+quoteMark+" ); };";
				}
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "subscripts" ) && trayLength>3 )
			{
			String temp=subscriptsPrefix+" int ";
				for( int j=3;j<trayLength;j++ )
				{
				temp+=tray[j]+"="+(j-3);
				if( j<trayLength-1 )temp+=","; else temp+="; ";
				}
			temp+=subscriptsPrefix+" String[] "+tray[2]+"={";
				for( int j=3;j<trayLength;j++ )
				{
				temp+=quoteMark+tray[j]+quoteMark;
				if( j<trayLength-1 )temp+=",";
				}
			temp+="}; ";
			temp+=subscriptsPrefix+" int "+tray[1]+"="+( trayLength-3 )+";";
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "subscriptsPrefix" ) )
			{
			String temp=" ";
			for( int j=1;j<trayLength;j++ )temp+=tray[j]+" ";
			subscriptsPrefix=temp;
			outTextFile.println( "" );
			}



			else if( tray[0].equals( "prin" ) )
			{
			String temp=gatherRemainder( 1 );
			temp=temp.replaceAll("\\\\","\\\\\\\\");
			temp= "System.out.println( \"" + temp + "\" );" ;
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "define" ) )
			{
				if( macroHash.containsKey( tray[1] ) )
				{
				throw new Error( tray[1]+" is being defined again at line "+lionNumber );
				}
				else
				{
				macroHash.put( tray[1],gatherRemainder( 2 ) );
				countHash.put( tray[1],-1 );
				outTextFile.println( "" );
				}
			}


			else if( tray[0].equals( "defineCounted" ) )
			{
				if( macroHash.containsKey( tray[1] ) )
				{
				throw new Error( tray[1]+" is being defined again at line "+lionNumber );
				}
				else
				{
				macroHash.put( tray[1],gatherRemainder( 3 ) );
				countHash.put( tray[1],new Integer( tray[2] ) );
				outTextFile.println( "" );
				}
			}



			else if( tray[0].equals( "unDefine" ) )
			{
				if( macroHash.containsKey( tray[1] ) )
				{
				macroHash.remove( tray[1] );
				countHash.remove( tray[1] );
				outTextFile.println( "" );
				}
				else
				{
				throw new Error( "cannot unDefine "+tray[1]+" at line "+lionNumber+" because it is not defined" );
				}
			}



			else if( tray[0].equals( "keyValue" ) )
			{
			String word="\\b"+tray[1]+"\\b";
				if( insideHash.containsKey( word ) )
				{
				throw new Error( tray[1]+" is being keyValued again at line "+lionNumber );
				}
				else
				{
				insideHash.put( word,gatherRemainder( 2 ) );
				outTextFile.println( "" );
				}
			}



			else if( tray[0].equals( "unKeyValue" ) )
			{
			String word="\\b"+tray[1]+"\\b";
				if( insideHash.containsKey( word ) )
				{
				insideHash.remove( word );
				outTextFile.println( "" );
				}
				else
				{
				throw new Error( "cannot unKeyValue "+tray[1]+" at line "+lionNumber+" because it was not keyValued" );
				}
			}



			else if( tray[0].equals( "push" ) )
			{
			if( trayLength<2 )throw new Error( "insufficient length at line "+lionNumber+", must be 2 or more" );
			String temp="";
				for( int j=2;j<trayLength;j++ )
				{
				temp+=tray[1]+"=new Link( "+tray[1]+",\""+tray[j]+"\","+tray[j]+" ); ";
				}
			outTextFile.println( temp );
			}



			else if( tray[0].equals( "pop" ) )
			{
			if( trayLength<2 )throw new Error( "insufficient length at line "+lionNumber+", must be 2 or more" );
			if( trayLength%2!=0 )throw new Error( "odd length at line "+lionNumber+", must be even" );
			String temp="";
				for( int j=trayLength-2;j>=2;j-=2 )
				{
				temp+=tray[j]+" "+tray[j+1]+"=("+tray[j]+")"+tray[1]+".value; "+tray[1]+"="+tray[1]+".pointer; ";
				}
			outTextFile.println( temp );
			}



			else
			{
			String attempt=macroHash.get( tray[0] );
				if( attempt!=null )
				{
				Integer count=countHash.get( tray[0] );
				if( count!=-1 )if( count!=tray.length-1 )throw new Error( "wrong number of arguments at line "+lionNumber );
						for( int j=trayLength-1;j>0;j-- )
						{
						String lookFor="\\$"+j;
						String useInstead=java.util.regex.Matcher.quoteReplacement( tray[j] );
						attempt=attempt.replaceAll( lookFor,useInstead );
						}
				outTextFile.println( attempt );
				}
				else
				{
				outTextFile.println( lion );
				}
			}

		}
	if( !stack.empty() )throw new Error("stack is not empty at end of .pri file");
	outTextFile.flush();
	}



	public static void main( String[] args )throws java.lang.Exception
	{
	manage( System.in, System.out );
	}
}

