%{
import de.dhbwstuttgart.typeinference.Menge;
class JavaParser{
public Menge path = new Menge();
%}

%token <Token> ABSTRACT
%token <Token> BOOLEAN
%token BREAK
%token CASE
%token CATCH
%token <Token> CHAR
%token CLASS
%token CONTINUE
%token DEFAULT
%token DO
%token ELSE
%token <Token> EXTENDS
%token FINALLY
%token FOR
%token IF
%token <Token> INSTANCEOF
%token <Token> INT
%token <Token> NEW
%token <Token> PRIVATE
%token <Token> PROTECTED
%token <Token> PUBLIC
%token RETURN
%token <Token> STATIC
%token SUPER
%token SWITCH
%token <Token> THIS
%token THROW
%token <Token> THROWS
%token TRY
%token <Token> VOID
%token WHILE
%token <Token> INTLITERAL
%token <Token> BOOLLITERAL
%token JNULL
%token <Token> CHARLITERAL
%token <Token> STRINGLITERAL
%token <Token>  IDENTIFIER
%token EQUAL
%token LESSEQUAL
%token GREATEREQUAL
%token NOTEQUAL
%token LOGICALOR
%token LOGICALAND
%token <Token> INCREMENT
%token <Token> DECREMENT
%token SHIFTLEFT
%token SHIFTRIGHT
%token UNSIGNEDSHIFTRIGHT
%token SIGNEDSHIFTRIGHT
%token PLUSEQUAL
%token MINUSEQUAL
%token TIMESEQUAL
%token DIVIDEEQUAL
%token ANDEQUAL
%token OREQUAL
%token XOREQUAL
%token MODULOEQUAL
%token SHIFTLEFTEQUAL
%token SIGNEDSHIFTRIGHTEQUAL
%token UNSIGNEDSHIFTRIGHTEQUAL
%token BRACE
%token RELOP
%token OP
%token EOF

%type <Class> classdeclaration
%type <ClassBody> classbody
%type <InstVarDecl> fielddeclaration
%type <Method> methodheader
%type <Method> methoddeclaration
%type <Method> methoddeclarator
%type <ClassBody> classbodydeclarations
%type <FieldDecl> classbodydeclaration
%type <FieldDecl> classmemberdeclaration
%type <InstVarDecl> variabledeclarators
%type <DeclId> variabledeclarator
%type <DeclId> variabledeclaratorid
%type <UsedId> simplename
%type <UsedId> qualifiedname
%type <UsedId> name
%type <UsedId> super
%type <UsedId> classtype
%type <UsedId> classorinterfacetype
%type <BaseType> integraltype
%type <BaseType> numerictype
%type <BaseType> primitivetype
%type <RefType> referencetype
%type <RefType> classtypelist
%type <Type > type
%type <Modifiers> modifiers
%type <Modifier> modifier
%type <Block> block
%type <Block> methodbody
%type <Block> blockstatements
%type <LocalVarDecl> localvariabledeclarationstatement
%type <LocalVarDecl> localvariabledeclaration
%type <ExceptionList> throws
%type <FormalParameter> formalparameter
%type <ParameterList> formalparameterlist
%type <Literal> literal
%type <Expr> primarynonewarray
%type <Expr> primary
%type <Expr> postfixexpression
%type <Expr> unaryexpressionnotplusminus
%type <Expr> unaryexpression
%type <Expr> multiplicativeexpression
%type <Expr> additiveexpression
%type <Expr> shiftexpression
%type <Expr> relationalexpression
%type <Expr> equalityexpression
%type <Expr> andexpression
%type <Expr> exclusiveorexpression
%type <Expr> inclusiveorexpression
%type <Expr> conditionalandexpression
%type <Expr> conditionalorexpression
%type <Expr> conditionalexpression
%type <Expr> assignmentexpression
%type <Expr> expression
%type <Expr> statementexpression
%type <Expr> preincrementexpression
%type <Expr> predecrementexpression
%type <Expr> postincrementexpression
%type <Expr> postdecrementexpression
%type <ExprStmt> expressionstatement
%type <ExprStmt> variableinitializer
%type <Statement> statementwithouttrailingsubstatement
%type <Statement> blockstatement
%type <Statement> statement
%type <Statement> statementnoshortif
%type <WhileStmt> whilestatement
%type <WhileStmt> whilestatementnoshortif
%type <IfStmt> ifthenstatement
%type <IfStmt> ifthenelsestatement
%type <IfStmt> ifthenelsestatementnoshortif
%type <EmptyStmt> emptystatement
%type <Return> returnstatement
%type <NewClass> classinstancecreationexpression
%type <SourceFile> compilationunit
%type <SourceFile> typedeclarations
%type <Assign> assignment
%type <Operator> assignmentoperator
%type <UsedId> lefthandside
%type <ArgumentList> argumentlist
%type <MethodCall> methodinvocation
%type <Class> typedeclaration
%type <FieldDecl> constructordeclaration
%type <Constructor> constructordeclarator
%type <Block> constructorbody
%type <Statement> explicitconstructorinvocation
%type <Method> staticinitializer
%type <CastExpr> castexpression
%type <ParaList> paralist
%left ','
%%

compilationunit                  :typedeclarations
					{
						$$=$1;
					}

typedeclarations                 :typedeclaration
					{
						SourceFile Scfile = new SourceFile();
						Scfile.set_Class($1);
						$$=Scfile;
					}
				 |typedeclarations typedeclaration
					{
						$1.set_Class($2);
						$$=$1;
					}

name				:qualifiedname
					{
						$$=$1;
					}
				    |simplename
					{
						$$=$1;
					}

typedeclaration                  :classdeclaration
					{
						$$=$1;
					}

qualifiedname                    : name '.' IDENTIFIER
					{
						$1.set_Name($3.getLexem());
						$$=$1;
					}

simplename                       : IDENTIFIER
					{
						UsedId UI = new UsedId();
						UI.set_Name( $1.getLexem() );
						$$ = UI;
					}

classdeclaration 		 : CLASS IDENTIFIER classbody
					{
						MyCompiler.Debug("P->Neue Klasse: " + $2.getLexem(), 3);
						Class C = new Class();
						ClassDeclId CDI = new ClassDeclId();
						CDI.set_classname( $2.getLexem() );
						C.set_ClassDeclId( CDI );
						C.set_ClassBody($3);
						$$ = C;
					}

                 		 | modifiers CLASS IDENTIFIER classbody
					{
						Class Cmod = new Class();
						ClassDeclId CDImod = new ClassDeclId();
						CDImod.set_Modifiers($1);
						CDImod.set_classname($3.getLexem());
						Cmod.set_ClassDeclId(CDImod);
						Cmod.set_ClassBody($4);
						$$ = Cmod;
					}

                 		 | CLASS IDENTIFIER super classbody
					{
						Class Csup = new Class();
						ClassDeclId CDIsup = new ClassDeclId();
						CDIsup.set_classname($2.getLexem());
						Csup.set_ClassDeclId(CDIsup);
						Csup.set_UsedId($3);
						Csup.set_ClassBody($4);
						$$ = Csup;
					}

				|modifiers CLASS IDENTIFIER super classbody
					{
						Class Cmodsup = new Class();
 						ClassDeclId CDImodsup = new ClassDeclId();
						CDImodsup.set_Modifiers($1);
						CDImodsup.set_classname($3.getLexem());
						Cmodsup.set_ClassDeclId(CDImodsup);
						Cmodsup.set_UsedId($4);
						Cmodsup.set_ClassBody($5);
						$$ = Cmodsup;
					}
				| modifiers CLASS IDENTIFIER '<'paralist'>'classbody
					{
						Class Cmod = new Class();
						ClassDeclId CDImod = new ClassDeclId();
						CDImod.set_Modifiers($1);
						CDImod.set_classname($3.getLexem());
						Cmod.set_ClassDeclId(CDImod);
						Cmod.set_ParaList($5.get_ParaList());
						Cmod.set_ClassBody($7);
						$$ = Cmod;
					}

				 |CLASS IDENTIFIER '<' paralist	'>'classbody
				 	{
						Class C = new Class();
						ClassDeclId CDI = new ClassDeclId();
						CDI.set_classname($2.getLexem());
						C.set_ClassDeclId(CDI);
						C.set_ClassBody($6);
						C.set_ParaList($4.get_ParaList());
						$$ = C;
					}

			         | CLASS IDENTIFIER '<' paralist '>'super classbody
					{
						MyCompiler.Debug( "Klassendefinition: Basisklassen-Parameter = " + $4.get_ParaList(), 3 );
						MyCompiler.Debug( "Klassendefinition: Superklassen-Parameter = " + $6.get_ParaList(), 3 );
						MyCompiler.Debug( "Klassendefinition: Superklassen-Parameter = " + $6.get_ParaList().hashCode(), 3 );
						Class Csup = new Class();
						ClassDeclId CDIsup = new ClassDeclId();
						CDIsup.set_classname($2.getLexem());
						Csup.set_ClassDeclId(CDIsup);
						Csup.set_ParaList($4.get_ParaList());
						Csup.set_UsedId($6);
						Csup.set_ClassBody($7);
						$$ = Csup;
					}

				|modifiers CLASS IDENTIFIER '<'paralist'>'super classbody
					{
						Class Cmodsup = new Class();
						ClassDeclId CDImodsup = new ClassDeclId();
						CDImodsup.set_Modifiers($1);
						CDImodsup.set_classname($3.getLexem());
						Cmodsup.set_ClassDeclId(CDImodsup);
						Cmodsup.set_ParaList($5.get_ParaList());
						Cmodsup.set_UsedId($7);
						Cmodsup.set_ClassBody($8);
						$$ = Cmodsup;
					}


paralist			: IDENTIFIER
					{
						ParaList pl = new ParaList();
						pl.paralist.addElement( new TyploseVariable($1.getLexem()) );
                        MyCompiler.Debug( "IDENTIFIER --> Paralist für " + $1.getLexem() + " TV", 3 );
						$$ = pl;
					}

                    | IDENTIFIER '<' paralist '>'
					{
						ParaList pl = new ParaList();
                        RefType t = new RefType( $1.getLexem() );
                        t.set_ParaList( $3.get_ParaList() );
                        pl.paralist.addElement(t);
                        MyCompiler.Debug( "IDENTIFIER '<' paralist '>' --> Paralist für " + $1.getLexem() + ": RefType", 3 );
						$$ = pl;
                                        }

                    | paralist ',' IDENTIFIER
                    {
                    	$1.paralist.addElement(new TyploseVariable($3.getLexem()));
                    	MyCompiler.Debug( "paralist ',' IDENTIFIER --> Paralist für " + $3.getLexem() + ": TV", 3 );
                    	MyCompiler.Debug( "paralist: " + $1.paralist, 3 );
                    	$$=$1;
                    }
                    
                    | paralist ',' IDENTIFIER '<' paralist '>'
                    {
                        RefType t = new RefType( $3.getLexem() );
                        t.set_ParaList( $5.get_ParaList() );
                        $1.paralist.addElement(t);
                        MyCompiler.Debug( "paralist ',' IDENTIFIER '<' paralist '>' --> Paralist für " + $3.getLexem() + ": RefType", 3 );
                        $$=$1;
                    }

classbody                        : '{' '}'
				        {
						ClassBody CB = new ClassBody();
						$$ = CB;
					}

				 | '{'classbodydeclarations '}'
				        {
						$$ = $2;
					}

modifiers                        :modifier
					{
						Modifiers Mod = new Modifiers();
						Mod.modifier.addElement($1);
						$$ = Mod;
				  	}
				 |modifiers modifier
					{
						$1.modifier.addElement($2);
						$$ = $1;
					}

super                            :EXTENDS classtype
					{
						$$ = $2;
					}

classbodydeclarations            :  classbodydeclaration
				        {
						ClassBody CB = new ClassBody();
						CB.set_FieldDecl( $1 );
						$$=CB;
					}
				 |  classbodydeclarations classbodydeclaration
				        {
						$1.set_FieldDecl($2);
						$$ = $1;
					}


modifier                         :  PUBLIC
					{
						Public Pub = new Public();
						$$=Pub;
					}
				 |  PROTECTED
					{
						Protected Pro = new Protected();
						$$=Pro;
					}
                                 |  PRIVATE
					{
						Private Pri = new Private();
						$$=Pri;
					}
                                 |  STATIC
					{
						Static Sta = new Static();
						$$=Sta;
					}
                                 |  ABSTRACT
				        {
						Abstract Abs = new Abstract();
						$$=Abs;
					}

classtype : classorinterfacetype
            {
                $$ = $1;
            }
			| classorinterfacetype	'<'paralist'>'
			{
				$1.set_ParaList($3.get_ParaList());
				
				/* otth: originale (also diese) Parameterliste retten */
				((UsedId)$1).vParaOrg = new Menge( $3.get_ParaList() );
				
				$$ = $1;
			}

classbodydeclaration             : classmemberdeclaration
				 	{
						$$=$1;
					}
				 | staticinitializer
					{
						$$=$1;
					}
				 | constructordeclaration
					{
						$$=$1;
					}

classorinterfacetype :  name
				        {
					        $$=$1;
					    }

classmemberdeclaration :    fielddeclaration
				            {
						        $$=$1;
					        }
				 |  methoddeclaration
					{
						$$=$1;
					}

staticinitializer                : STATIC block
					{
						Method STAT = new Method();
						DeclId DST = new DeclId();
						DST.set_Name($1.getLexem());
						STAT.set_DeclId(DST);
						Static ST = new Static();
						Modifiers MOD = new Modifiers();
						MOD.modifier.addElement(ST);
						STAT.set_Modifiers(MOD);
						STAT.set_Block($2);
						$$=STAT;
					}

constructordeclaration           : constructordeclarator constructorbody
				 	{
						$1.set_Block($2);
						$$ = $1;
					}
				 |  modifiers constructordeclarator constructorbody
					{
						$2.set_Block($3);
						$2.set_Modifiers($1);
						$$ = $2;
					}

fielddeclaration : type variabledeclarators ';'
				 {
				    MyCompiler.Debug("T->Parser->fielddeclaration ...: type " + $1, 5);
					$2.set_Type($1);
				    $$ = $2;
				 }

 				 | modifiers type variabledeclarators ';'
					{
						$3.set_Type($2);
					 	for(int i=0;i<($3.declid.size());i++)
						{
							$3.declid.setElementAt((((DeclId)($3.declid.elementAt(i))).modifiers=$1),i);
						}
						$$ = $3;
					}

methoddeclaration   : methodheader methodbody
				    {
						$1.set_Block($2);
						$$=$1;
					}

block                              : '{' '}'

					{
						Block Bl = new Block();
						$$=Bl;
					}

				   | '{' blockstatements '}'
					{
						$$=$2;
					}

constructordeclarator		   :  simplename '(' ')'
				        {
						Constructor CON = new Constructor();
						DeclId DIDCon = new DeclId();
						DIDCon.set_Name($1.get_Name_1Element());
						CON.set_DeclId(DIDCon);
						$$=CON;
					}
				   |  simplename '('formalparameterlist')'
				        {
						Constructor CONpara = new Constructor();
						DeclId DIconpara = new DeclId();
						DIconpara.set_Name($1.get_Name_1Element());
						CONpara.set_DeclId(DIconpara);
						CONpara.set_ParaList($3);
						$$=CONpara;
					}

constructorbody			   :  '{' '}'
					{
						Block CBL = new Block();
						$$=CBL;
					}
				   |   '{' explicitconstructorinvocation '}'
				   	{
						Block CBLexpl = new Block();
						CBLexpl.set_Statement($2);
						$$=CBLexpl;
					}
				   |   '{' blockstatements '}'
				        {
						$$=$2;
					}
				   |  '{'explicitconstructorinvocation blockstatements '}'
					{
						Block CBes = new Block();
						CBes.set_Statement($2);
						for(int j=0;j<$3.statements.size();j++)
						{
							CBes.set_Statement((Statement)$3.statements.elementAt(j));
						}
						$$=CBes;
					}

throws				   : THROWS classtypelist
					{
						ExceptionList EL = new ExceptionList();
						EL.set_addElem($2);
						$$=EL;
					}

methodheader	    : type methoddeclarator
					{
						$2.set_ReturnType($1);
						$$=$2;
					}
				    | modifiers type methoddeclarator
				    {
						$3.set_Modifiers($1);
						$3.set_ReturnType($2);
						$$=$3;
					}
				    | type methoddeclarator throws
					{
						$2.set_ReturnType($1);
						$2.set_ExceptionList($3);
						$$=$2;
					}
				    | modifiers type methoddeclarator throws
				    {
						$3.set_Modifiers($1);
						$3.set_ReturnType($2);
						$3.set_ExceptionList($4);
						$$=$3;
					}
				    | VOID methoddeclarator
					{
						Type Voit = new Type();
						Voit.set_Type($1.getLexem());
						$2.set_ReturnType(Voit);
						$$=$2;
					}
				    | modifiers VOID methoddeclarator
					{
						Type voit = new Type();
						voit.set_Type($2.getLexem());
						$3.set_Modifiers($1);
						$3.set_ReturnType(voit);
						$$=$3;
					}
                    | VOID methoddeclarator throws
					{
						Type voyt = new Type();
						voyt.set_Type($1.getLexem());
						$2.set_ReturnType(voyt);
						$2.set_ExceptionList($3);
						$$=$2;
					}
				    | modifiers VOID methoddeclarator throws
					{
						Type voyd = new Type();
						voyd.set_Type($2.getLexem());
						$3.set_Modifiers($1);
						$3.set_ReturnType(voyd);
						$3.set_ExceptionList($4);
						$$=$3;
					}

type                : primitivetype
 					{
						$$=$1;
					}
				    |referencetype
					{
						$$=$1;
					}

variabledeclarators : variabledeclarator
					{
						InstVarDecl IVD = new InstVarDecl();
						IVD.declid.addElement( $1 );
						$$ = IVD;
					}
				    | variabledeclarators ',' variabledeclarator
					{
						$1.declid.addElement($3);
						$$=$1;
					}

methodbody          : block
			        {
						$$=$1;
					}

blockstatements     : blockstatement
					{
						Block Blstat = new Block();
						Blstat.set_Statement($1);
						$$=Blstat;
					}

				    | blockstatements blockstatement
	  			    {
						$1.set_Statement($2);
						$$=$1;
					}

formalparameterlist :formalparameter
					{
						ParameterList PL = new ParameterList();
						PL.set_AddParameter($1);
						$$ = PL;
					}
				     |formalparameterlist ',' formalparameter
					{
						$1.set_AddParameter($3);
						$$ = $1;
					}

explicitconstructorinvocation        : THIS '(' ')' ';'
				        {
						This THCON = new This();
						$$=THCON;
					}
				     |THIS '(' argumentlist ')' ';'
					{
						This THCONargl = new This();
						THCONargl.set_ArgumentList($3);
						$$=THCONargl;
					}
				    // |SUPER '(' ')' ';'
				    // |SUPER '(' argumentlist ')' ';'

classtypelist : classtype
				{
				    RefType RT = new RefType();
					RT.set_UsedId($1);
					RT.set_Type(RT.used.get_Name_1Element());
					$$=RT;
				 }
              | classtypelist ',' classtype
				{
				    $1.set_UsedId($3);
					$1.set_Type($1.used.get_Name_1Element());
					$$=$1;
				}

methoddeclarator    :IDENTIFIER '(' ')'
				    {
						Method met = new Method();
						DeclId DImethod = new DeclId();
						DImethod.set_Name($1.getLexem());
						met.set_DeclId(DImethod);
						$$ = met;
					}
				    |IDENTIFIER '(' formalparameterlist ')'
					{
					    Method met_para = new Method();
						DeclId Dimet_para = new DeclId();
						Dimet_para.set_Name($1.getLexem());
						met_para.set_DeclId(Dimet_para);
						met_para.set_ParaList($3);
						$$ = met_para;
					}

primitivetype                        :BOOLEAN
					{
						BooleanType BT = new BooleanType();
						BT.set_Type($1.getLexem());
						$$=BT;
					}
				     |numerictype
				        {
						$$=$1;
					}

referencetype                        :classorinterfacetype
					{
						MyCompiler.Debug("T->Parser->referenctype: " + $1, 5);
						RefType RT = new RefType();
						RT.set_UsedId($1);
						RT.set_Type(RT.used.get_Name_1Element());
						$$=RT;
					}

variabledeclarator  : variabledeclaratorid
					{
						$$=$1;
					}

				    | variabledeclaratorid '=' variableinitializer
					{
						$1.set_Wert($3);
						$$=$1;
					}

	                | '<' paralist'>' variabledeclaratorid '=' variableinitializer
					{
						$4.set_Wert($6);
						$4.set_Paratyp($2.get_ParaList());
						$$=$4;
					}

blockstatement                       :localvariabledeclarationstatement
					{
						$$=$1;
					}
				     |statement
				        {
						$$=$1;
					}

funtype				: funtypeortype '(' funtypelist ')'
					{

					}

funtypelist			: funtypeortype
					{

					}
					| funtypelist ',' funtypeortype
					{

					}

funtypeortype		: funtype
					{

					}
					| type
					{
					$$=$1;
					}

formalparameter     : funtype variabledeclaratorid
				      {
						FormalParameter FP = new FormalParameter();
						FP.set_Type($1);
						FP.set_DeclId($2);
						$$=FP;
					  }

                      /* otth: Methodenargumente koennen hiermit auch polymorph sein. */
                      | funtype '<'paralist'>' variabledeclaratorid
				      {
                        /* Parameterliste setzen */
                        $5.set_Paratyp($3.get_ParaList());

						FormalParameter FP = new FormalParameter();
						FP.set_Type($1);
						FP.set_DeclId($5);
						$$=FP;

						MyCompiler.Debug("P->Polymorphes Methodenargument hinzugefuegt: Name = " + $5.get_Name() + " Typ = " + $1.get_Type(), 3);
					  }

argumentlist                         : expression
					{
						ArgumentList AL = new ArgumentList();
						AL.expr.addElement($1);
						$$=AL;
					}
				     |argumentlist ',' expression
				        {
						$1.expr.addElement($3);
						$$=$1;
					}

numerictype                          :integraltype
					{
						$$=$1;
					}

variabledeclaratorid                 :IDENTIFIER
					{
						DeclId DI = new DeclId();
						DI.set_Name($1.getLexem());
						$$=DI;
					}

variableinitializer                  :expression
					{
						$$=$1;
					}

localvariabledeclarationstatement    :localvariabledeclaration ';'
				        {
						$$=$1;
					}

statement                            :statementwithouttrailingsubstatement
					{
						$$=$1;
					}
				     |ifthenstatement
					{
						$$=$1;
					}
				     |ifthenelsestatement
					{
						$$=$1;
					}
				     |whilestatement
					{
						$$=$1;
					}

expression                           :assignmentexpression
					{
						$$=$1;
					}
				     |classinstancecreationexpression
					{
						$$=$1;
					}

integraltype                         :INT
					{
						IntegerType IT = new IntegerType();
						IT.set_Type($1.getLexem());
						$$=IT;
					}
                                     | CHAR
					{
						CharacterType CT = new CharacterType();
						CT.set_Type($1.getLexem());
						$$=CT;
					}

localvariabledeclaration             : type variabledeclarators
					{
						MyCompiler.Debug("P -> Lokale Variable angelegt!", 3);
						LocalVarDecl LVD = new LocalVarDecl();
						LVD.set_Type($1);
						LVD.declid=$2.declid;
						$$ = LVD;
					}

statementwithouttrailingsubstatement : block
				        {
						$$=$1;
					}
				  |  emptystatement
					{
						$$=$1;
					}
				  |  expressionstatement
					{
						$$=$1;
					}
				  |  returnstatement
					{
						$$=$1;
					}

ifthenstatement                   : IF '(' expression ')' statement
				        {
						IfStmt Ifst = new IfStmt();
						Ifst.set_Expr($3);
						Ifst.set_Then_block($5);
						$$=Ifst;
					}

ifthenelsestatement               : IF '('expression ')'statementnoshortif ELSE statement
				        {
						IfStmt IfstElst = new IfStmt();
						IfstElst.set_Expr($3);
						IfstElst.set_Then_block($5);
						IfstElst.set_Else_block($7);
						$$=IfstElst;
					}

whilestatement                    : WHILE '(' expression ')' statement
					{
						WhileStmt Whlst = new WhileStmt();
						Whlst.set_Expr($3);
						Whlst.set_Loop_block($5);
						$$=Whlst;
					}

assignmentexpression	          : conditionalexpression
					{
						$$=$1;
					}
				  |  assignment
					{
						$$=$1;
					}

emptystatement			  : ';'
					{
						EmptyStmt Empst = new EmptyStmt();
						$$=Empst;
					}

expressionstatement               : statementexpression ';'
					{
						$$=$1;
					}

returnstatement                   :  RETURN ';'
				        {
						Return ret = new Return();
						$$= ret;
					}
				  |  RETURN expression ';'
					{
						Return retexp = new Return();
						retexp.set_ReturnExpr($2);
						$$=retexp;
					}

statementnoshortif		 :statementwithouttrailingsubstatement
					{
						$$=$1;
					}
				 | ifthenelsestatementnoshortif
					{
						$$=$1;
					}
				 | whilestatementnoshortif
					{
						$$=$1;
					}

conditionalexpression            :conditionalorexpression
					{
						$$=$1;
					}
			//	 | conditionalorexpression '?' expression ':' conditionalexpression

assignment                       :lefthandside assignmentoperator assignmentexpression
					{
						MyCompiler.Debug("\nParser --> Zuweisung1!\n", 3);
						Assign Ass = new Assign();
						LocalOrFieldVar LOFV = new LocalOrFieldVar();
						LOFV.set_UsedId($1);
						if( $2 == null )
						{
							MyCompiler.Debug("\nParser --> Zuweisung1 --> " + $3 + " \n", 3);
							Ass.set_Expr( LOFV,$3 );
						}
						else
						{
							Binary Bin = new Binary();
							Bin.set_Expr1(LOFV);
							Bin.set_Operator($2);
							Bin.set_Expr2($3);
							MyCompiler.Debug("\nParser --> Zuweisung1 --> Binary\n", 3);
							Ass.set_Expr( LOFV, Bin );
						}
						$$=Ass;
					}
				 | lefthandside assignmentoperator classinstancecreationexpression
					{
						Assign Ass =new Assign();
						LocalOrFieldVar LOFV = new LocalOrFieldVar();
						LOFV.set_UsedId($1);
						if($2==null)
						{
							Ass.set_Expr(LOFV,$3);
						}
						else
						{
							 Binary Bin = new Binary();
							 Bin.set_Expr1(LOFV);
							 Bin.set_Operator($2);
							 Bin.set_Expr2($3);
							 Ass.set_Expr(LOFV,Bin);
						}
						$$=Ass;
					}

statementexpression              :assignment
					{
						$$=$1;
					}
				 | preincrementexpression
					{
						$$=$1;
					}
				 | predecrementexpression
					{
						$$=$1;
					}
				 | postincrementexpression
					{
						$$=$1;
					}
				 | postdecrementexpression
					{
						$$=$1;
					}
				 | methodinvocation
					{
						$$=$1;
					}
/*				 | classinstancecreationexpression
					{
						$$=$1;
					}
*/

ifthenelsestatementnoshortif     :IF '(' expression ')' statementnoshortif
				  ELSE statementnoshortif
				       {
						IfStmt IfElno = new IfStmt();
						IfElno.set_Expr($3);
						IfElno.set_Then_block($5);
						IfElno.set_Else_block($7);
						$$=IfElno;
					}

whilestatementnoshortif          :WHILE '(' expression ')' statementnoshortif
					{
						WhileStmt Whstno = new WhileStmt();
						Whstno.set_Expr($3);
						Whstno.set_Loop_block($5);
						$$=Whstno;
					}

conditionalorexpression          : conditionalandexpression
					{
						$$=$1;
					}
				 | conditionalorexpression LOGICALOR conditionalandexpression
					{
						Binary LogOr = new Binary();
			       			OrOp OrO = new OrOp();
						LogOr.set_Expr1($1);
						LogOr.set_Expr2($3);
						LogOr.set_Operator(OrO);
						$$=LogOr;
			       		}


lefthandside                     :name
					{
						$$=$1;
					}

assignmentoperator               : '='
					{
						$$=null;
					}
				 | TIMESEQUAL
					{
						TimesOp TEO = new TimesOp();
						$$=TEO;
					}
				 | DIVIDEEQUAL
					{
						DivideOp DEO = new DivideOp();
						$$=DEO;
					}
				 | MODULOEQUAL
					{
						ModuloOp MEO = new ModuloOp();
						$$=MEO;
					}
				 | PLUSEQUAL
					{
						PlusOp PEO = new PlusOp();
						$$=PEO;
					}
				 | MINUSEQUAL
					{
						MinusOp MEO = new MinusOp();
						$$=MEO;
					}
			//	 | SHIFTLEFTEQUAL
			//	 | SIGNEDSHIFTRIGHTEQUAL
			//       | UNSIGNEDSHIFTRIGHTEQUAL
			//       | ANDEQUAL
			//       | XOREQUAL
			//       | OREQUAL

preincrementexpression         :INCREMENT unaryexpression
					{
						PreIncExpr PRINC = new PreIncExpr();
						PRINC.set_Expr($2);
						$$=PRINC;
					}

predecrementexpression         :DECREMENT unaryexpression
					{
						PreDecExpr PRDEC = new PreDecExpr();
						PRDEC.set_Expr($2);
						$$=PRDEC;
					}

postincrementexpression        :postfixexpression INCREMENT
					{
						PostIncExpr PIE = new PostIncExpr();
						PIE.set_Expr($1);
						$$=PIE;
					}

postdecrementexpression        :postfixexpression DECREMENT
					{
						PostDecExpr PDE = new PostDecExpr();
						PDE.set_Expr($1);
						$$=PDE;
					}

methodinvocation               :name '(' ')'
					{
						MethodCall MC = new MethodCall();
						MC.set_UsedId($1);
						$$=MC;
					}
			       | name '('argumentlist')'
					{
						MethodCall MCarg = new MethodCall();
						MCarg.set_UsedId($1);
						MCarg.set_ArgumentList($3);
						$$=MCarg;
					}
			       | primary '.' IDENTIFIER '(' ')'
					{
						MethodCall MCpr = new MethodCall();
						$1.usedid.set_Name($3.getLexem());
						MCpr.set_UsedId($1.get_UsedId());
						$$=MCpr;
					}
			       | primary '.' IDENTIFIER	'('argumentlist ')'
					{
						MethodCall MCPA = new MethodCall();
						$1.usedid.set_Name($3.getLexem());
						MCPA.set_UsedId($1.get_UsedId());
						MCPA.set_ArgumentList($5);
						$$=MCPA;
					}
                          //   | SUPER '.' IDENTIFIER '(' ')'
			  //   | SUPER '.' IDENTIFIER '('argumentlist')'

classinstancecreationexpression : NEW classtype '(' ')'
					{
						NewClass NC = new NewClass();
						NC.set_UsedId($2);
						$$=NC;
					}
                               | NEW classtype '(' argumentlist ')'
					{
						NewClass NCarg = new NewClass();
						NCarg.set_UsedId($2);
						NCarg.set_ArgumentList($4);
						$$=NCarg;
					}

conditionalandexpression       : inclusiveorexpression
					{
						$$=$1;
					}
			       | conditionalandexpression LOGICALAND inclusiveorexpression
					{
						Binary And = new Binary();
						AndOp AndO = new AndOp();
						And.set_Expr1($1);
						And.set_Expr2($3);
						And.set_Operator(AndO);
						$$=And;
					}

/*
fieldaccess                    :primary '.' IDENTIFIER
			         | SUPER '.' IDENTIFIER
*/

unaryexpression		       : preincrementexpression
					{
						$$=$1;
					}
			       | predecrementexpression
					{
						$$=$1;
					}
			       | '+' unaryexpression
				     {
					PositivExpr POSEX=new PositivExpr();
					UnaryPlus UP= new UnaryPlus();
					POSEX.set_UnaryPlus(UP);
					POSEX.set_Expr($2);
					$$=POSEX;
				     }
			       | '-' unaryexpression
				     {
					NegativeExpr NEGEX=new NegativeExpr();
					UnaryMinus UM=new UnaryMinus();
					NEGEX.set_UnaryMinus(UM);
					NEGEX.set_Expr($2);
					$$=NEGEX;
				     }
			       | unaryexpressionnotplusminus
					{
						$$=$1;
					}

postfixexpression              :primary
					{
						$$=$1;
					}
			       | name
					{
						LocalOrFieldVar Postincexpr = new LocalOrFieldVar();
						Postincexpr.set_UsedId($1);
						$$=Postincexpr;
					}
			       | postincrementexpression
					{
						$$=$1;
					}
			       | postdecrementexpression
					{
						$$=$1;
					}

primary			       : primarynonewarray
					{
						$$=$1;
					}

inclusiveorexpression	       : exclusiveorexpression
					{
						$$=$1;
					}
			       | inclusiveorexpression '|' exclusiveorexpression

primarynonewarray	       : literal
					{
						$$=$1;
					}
			       | THIS
					{
						This T = new This();
						UsedId UT = new UsedId();
						UT.set_Name($1.getLexem());
						T.set_UsedId(UT);
						$$=T;
					}

			       | '('expression')'
				 	{
						$$=$2;
					}
/*
		               | classinstancecreationexpression
					{
						$$=$1;
					}
			       | fieldaccess
*/
			       | methodinvocation
					{
						$$=$1;
					}

unaryexpressionnotplusminus     : postfixexpression					{$$=$1;}
	                     // | '~' unaryexpression
				| '!' unaryexpression					{NotExpr NE=new NotExpr();
											 UnaryNot UN=new UnaryNot();
											 NE.set_UnaryNot(UN);
											 NE.set_Expr($2);
											 $$=NE;
											}
				| castexpression					{$$=$1;}

exclusiveorexpression           :andexpression 						{$$=$1;}
				| exclusiveorexpression '^' andexpression 		//{
											//
											//}

literal				: INTLITERAL						{IntLiteral IL = new IntLiteral();
											IL.set_Int($1.String2Int());
											$$ = IL;
											}

				| BOOLLITERAL						{BoolLiteral BL = new BoolLiteral();
											 BL.set_Bool($1.String2Bool());
											 $$ = BL;
											}
				| CHARLITERAL						{CharLiteral CL = new CharLiteral();
											CL.set_Char($1.CharInString());
											$$=CL;
											}
				| STRINGLITERAL
					{
						StringLiteral ST = new StringLiteral();
						ST.set_String($1.get_String());
						$$=ST;
					}
				| JNULL;
					{
						Null NN = new Null();
						$$=NN;
					}

castexpression			: '(' primitivetype ')' unaryexpression
					{
						CastExpr CaEx=new CastExpr();
						CaEx.set_Type($2);
						CaEx.set_Expr($4);
						$$=CaEx;
					}
 				//| '(' expression ')' unaryexpressionnotplusminus

andexpression                   :equalityexpression
					{
						$$=$1;
					}
				| andexpression '&' equalityexpression
					{
					}

equalityexpression              : relationalexpression
					{
						$$=$1;
					}
				| equalityexpression EQUAL relationalexpression
					{
						Binary EQ = new Binary();
						EqualOp EO = new EqualOp();
						EQ.set_Expr1($1);
						EQ.set_Expr2($3);
						EQ.set_Operator(EO);
						$$=EQ;
					}
				| equalityexpression NOTEQUAL relationalexpression
					{
						Binary NEQ = new Binary();
						NotEqualOp NEO = new NotEqualOp();
						NEQ.set_Expr1($1);
						NEQ.set_Expr2($3);
						NEQ.set_Operator(NEO);
						$$=NEQ;
					}

relationalexpression		: shiftexpression
					{
						$$=$1;
					}
				| relationalexpression '<' shiftexpression
					{
						Binary LO = new Binary();
						LessOp LOO = new LessOp();
						LO.set_Expr1($1);
						LO.set_Expr2($3);
						LO.set_Operator(LOO);
						$$=LO;
					}
				| relationalexpression '>' shiftexpression
					{
						Binary GO = new Binary();
						GreaterOp GOO = new GreaterOp();
						GO.set_Expr1($1);
						GO.set_Expr2($3);
						GO.set_Operator( GOO );
						$$=GO;
					}
				| relationalexpression LESSEQUAL shiftexpression
					{
						Binary LE = new Binary();
						LessEquOp LEO = new LessEquOp();
						LE.set_Expr1($1);
						LE.set_Expr2($3);
						LE.set_Operator(LEO);
						$$=LE;
					}
				| relationalexpression GREATEREQUAL shiftexpression
					{
						Binary GE = new Binary();
						GreaterEquOp GEO = new GreaterEquOp();
						GE.set_Expr1($1);
						GE.set_Expr2($3);
						GE.set_Operator(GEO);
						$$=GE;
					}
				| relationalexpression INSTANCEOF referencetype
					{
						InstanceOf ISO=new InstanceOf();
						ISO.set_Expr($1);
						ISO.set_Type($3);
						$$=ISO;
					}

shiftexpression			: additiveexpression
					{
						$$=$1;
					}

additiveexpression              :multiplicativeexpression
					{
						$$=$1;
					}
				| additiveexpression '+' multiplicativeexpression
					{
						Binary AD = new Binary();
						PlusOp PO = new PlusOp();
						AD.set_Expr1($1);
						AD.set_Expr2($3);
						AD.set_Operator(PO);
						$$=AD;
					}
				| additiveexpression '-' multiplicativeexpression
					{
						Binary MI = new Binary();
						MinusOp MO = new MinusOp();
						MI.set_Expr1($1);
						MI.set_Expr2($3);
						MI.set_Operator(MO);
						$$=MI;
					}

multiplicativeexpression	: unaryexpression
					{
						$$=$1;
					}
				| multiplicativeexpression '*' unaryexpression
					{
						Binary ML = new Binary();
					        TimesOp TO = new TimesOp();
						ML.set_Expr1($1);
						ML.set_Expr2($3);
						ML.set_Operator(TO);
						$$=ML;
					}
				| multiplicativeexpression '/' unaryexpression
				  {
					Binary DV = new Binary();
					DivideOp DO = new DivideOp();
					DV.set_Expr1($1);
					DV.set_Expr2($3);
					DV.set_Operator(DO);
					$$ = DV;
				  }
				| multiplicativeexpression '%' unaryexpression
				  {
					Binary MD = new Binary();
					ModuloOp MO = new ModuloOp();
					MD.set_Expr1($1);
					MD.set_Expr2($3);
					MD.set_Operator(MO);
					$$ =MD;
				  }

/* OTTH: Methodenparametertypen müssen nicht mehr angegeben werden */

formalparameter     : variabledeclaratorid
					{
						MyCompiler.Debug("\nFunktionsdeklaration mit typlosen Parametern: " + $1.name, 3);

						FormalParameter FP = new FormalParameter();

						Type T = new TyploseVariable(""); /* otth: Name wird automatisch berechnet */
                        MyCompiler.Debug("\n--> berechneter Name: " + T.get_Type(), 3);

						FP.set_Type( T );
						FP.set_DeclId($1);

						$$=FP;
					}

%%