class Ausdruck {
	
	// Lösung Teil a)
	
	String basisBlock;
	Ausdruck linkerOperand;
	Ausdruck rechterOperand;
    
	// Lösung Teil b) und c)
	
	/*
	Konstruktor für einen zusammengesetzten Ausdruck
	*/
	Ausdruck(String t, Ausdruck lOperand, Ausdruck rOperand) {
		basisBlock = t;
		linkerOperand = lOperand;
		rechterOperand = rOperand;
		if ((istNatuerlicheZahl(basisBlock)) &&
		    ((linkerOperand != null) ||
		     (rechterOperand != null)))
			System.err.println("'"+basisBlock+"' ist eine natürliche Zahl und darf keine Operanden haben.");
		else if ((istErlaubterOperator(basisBlock)) &&
			 ((linkerOperand == null) ||
		          (rechterOperand == null)))
			System.err.println("Der Operator '"+basisBlock+"' muss genau zwei Operanden haben.");
		else if ((!(istNatuerlicheZahl(basisBlock))) &&
			 (!(istErlaubterOperator(basisBlock))))
			System.err.println("'"+basisBlock+"' ist weder eine natürliche Zahl, noch ein erlaubter Operator "+
					   "und somit kein zulässiger Ausdruck.");
	}
	
	/*
	Konstruktor für einen atomaren Ausdruck (d.h. eine natürliche Zahl).
	*/
	Ausdruck(String zahl) {
		this(zahl,null,null);
	}
	

	boolean istNatuerlicheZahl(String zeichenkette) {
		for (int i=0; i<zeichenkette.length(); i++)
			if ((zeichenkette.charAt(i)<'0') ||
			    (zeichenkette.charAt(i)>'9')) return false;
		return true;
	}

	boolean istErlaubterOperator(String zeichenkette) {
		if (zeichenkette.equals("*"))
			return true;
		else return false;
	}
	
	// Teil d)
	
        public String toString() {
		if (istNatuerlicheZahl(basisBlock))
			return "Ausdruck( "+basisBlock+" )";
		else return "Ausdruck( op = "+basisBlock+", links = "+
			linkerOperand.toString()+", rechts = "+
			rechterOperand.toString()+" )";
	}
    
	// Teil e)
	
	int berechneWert() {
		if (istNatuerlicheZahl(basisBlock))
			return Integer.parseInt(basisBlock);
		else return linkerOperand.berechneWert() *
			    rechterOperand.berechneWert();
	}
    
	// Teil f)
	
	/* mit while-do: */
	static int exp(int a, int b) {
		if (b==0) return 1;
		else {
			int ergebnis=a;
			int i=1;
			/*
			while (i<b) {
				ergebnis *= a;
				i++;
			}
			*/
			// kürzer:
			while (i++ < b) ergebnis *= a;
				
			return ergebnis;
		}
	}
    
	/* mit do-while: */
	static int exp2(int a, int b) {
		if (b==0) return 1;
		else {
			int ergebnis=1;
			int i=1;
			/*
			do {
				ergebnis *= a;
				i++;
			}
			while (i<=b);
			*/
			// kürzer:
			do ergebnis *= a;
			while (++i <= b);
				
			return ergebnis;
		}
	}

	
	/* eventuell mit for */
	static int exp3(int a, int b) {
		int ergebnis=1;
		for (int i=1; i<= b; i++)
			ergebnis *= a;
		return ergebnis;
	}
	
	/* und noch eine Möglichkeit? */
	static int exp4(int a, int b) {
		if (b==0) return 1;
		else return exp4(a,b-1)*a;
	}

	/* Nun müsste man noch istErlaubterOperator und berechneWert anpassen, um den neuen Operator zu berücksichtigen:

	boolean istErlaubterOperator(String zeichenkette) {
		if ((zeichenkette.equals("*")) || (zeichenkette.equals("**")))
			return true;
		else return false;
	}
	
	int berechneWert() {
		if (istNatuerlicheZahl(basisBlock))
			return Integer.parseInt(basisBlock);
		else if (basisBlock.equals("*"))
			return linkerOperand.berechneWert() *
			    rechterOperand.berechneWert();
		else return exp(linkerOperand.berechneWert(),rechterOperand.berechneWert());
	}
	
	*/
	
	/* 
	Zum Testen: ein paar Beispielaufrufe
	*/
	public static void main(String[] args) {

		Ausdruck a=new Ausdruck("42");
		Ausdruck b=new Ausdruck("120");
		Ausdruck falsch1=new Ausdruck("5bla7");
		Ausdruck falsch2=new Ausdruck("*");
		Ausdruck zusammen1=new Ausdruck("*",a,b);
		Ausdruck zusammen2=new Ausdruck("*",zusammen1,b);
		Ausdruck falsch3=new Ausdruck("*",a,null);
		Ausdruck falsch4=new Ausdruck("42",null,a);
		Ausdruck c=new Ausdruck("10",null,null);
		System.out.println();
		
		System.out.println("Ausdruck a: "+a.toString());
		System.out.println("Ausdruck b: "+b.toString());
		System.out.println("Ausdruck zusammen1: "+zusammen1.toString());
		System.out.println("Ausdruck zusammen2: "+zusammen2.toString());
		System.out.println("Ausdruck c: "+c.toString());
		System.out.println();
		
		System.out.println("Wert von Ausdruck a: "+a.berechneWert());
		System.out.println("Wert von Ausdruck b: "+b.berechneWert());
		System.out.println("Wert von Ausdruck zusammen1: "+zusammen1.berechneWert());
		System.out.println("Wert von Ausdruck zusammen2: "+zusammen2.berechneWert());
		System.out.println("Wert von Ausruck c: "+c.berechneWert());
		System.out.println();
		
		System.out.println("3**4, Version 1: "+exp(3,4));
		System.out.println("3**4, Version 2: "+exp2(3,4));
		System.out.println("3**4, Version 3: "+exp3(3,4));
		System.out.println("3**4, Version 4: "+exp4(3,4));
		
	}
}
