
using System.Collections;

COMPILER Liss

/********************************************************************
*			SCANNER					    *
*********************************************************************/


// Variable types

const int undef = 0, boolean = 1, integer = 2, array = 3, sets = 4, sequence = 5;

public int elseT = 1, whileT = 1, forT = 1;	// tells how many IfThenElse/while/for exists
public int arrayNum = 1, open=1, level = 0;
public SymbolTable SymTab;
public VM_Code genCode;
public Resolver Resolver;
public string output = "";
public string functions = "";
public string varDeclCode = "";


IGNORECASE

CHARACTERS 
letter = 'A'..'Z' + 'a'..'z'.
digit  = '0'..'9'.
comchar1  = ANY - '/' - '*'.
comchar2  = ANY - '\n'.


TOKENS
ident = letter { letter | digit }.
number = digit { digit }.

PRAGMAS
comment =   ( "/*" {'/' | comchar1 | '*' {'*'} comchar1} '*' {'*'} '/' ) |
			( "//" {comchar2} '\n' ) |
			( "//" {comchar2} '\r' '\n' ) |
			( "--" {comchar2} '\r' '\n' ) |
			( "--" {comchar2} '\n' ).	(.	SymTab.AddComments(la.val); .)

IGNORE '\r' + '\n' + '\t'


/********************************************************************
*			PARSER					    *
*********************************************************************/


PRODUCTIONS

/*--------------------------- PRODUCTION FOR GRAMMAR NAME -----------------*/

Liss									(.	string varDeclCode1 = "", libs = "",
													statCode1 = "", statCode = "";
											genCode.writeLiss();	.)
= "program" ident 						(. 	output += SymTab.GetComments() + genCode.WriteMain();	.)
	'{'									(.	output += "{\n";
											SymTab.IncIdent();
											output += SymTab.GetComments();	.)
           ["Declarations"				(.	SymTab.InicEnv();	.)
	 	  { Decls<out varDeclCode1>		(.	varDeclCode += varDeclCode1;	.) }]

	   "Statements"
		  {Statement<out statCode1>		(.	statCode += statCode1 + "\n";	.)	}
		  
	'}'									(.	if (SymTab.checkCaduceus())
												libs = genCode.WriteCaduceusLib() + "\n";
											else
												libs = genCode.WriteLib() + "\n";
											
											output = libs 
													+ functions
													+ output
													+ varDeclCode + "\n"
													+ statCode
												/*	+ SymTab.PrintIdent() + genCode.WriteEnd()  TODO */
													+ SymTab.GetComments() + "}\n";
											
											SymTab.DecIdent();	.).



/* -------------------------- Declarations -------------------------------*/


Decls<out string code>			(.	code = "";
									string fun = "", com = SymTab.GetComments();	.)
=    VarDecl<out code>			(.	code = com + code + ";\n";	.)
   | SubProgDef<out fun>		(.	functions += com + fun + "\n";	.).


/* -------------------------- Variables declaration ----------------------*/



VarDecl<out string code>	(.	int type = undef, init, endT; code = ""; 
				  				string tpname = "", name = "";
								Object obj = null;	
								init = SymTab.getSizeTable();
								ArrayList VarDecls = new ArrayList();	.)
= OneDecl<out type, out name>
							(.	VarDecls.Add(name);	.)

{ ',' OneDecl<out type, out name>
							(.	VarDecls.Add(name);	.)	}

  "->" Type<out type,out tpname,out obj>
							(.	endT = SymTab.getSizeTable();
								SymTab.errorsType(type,init,endT);	  
					   	   		if (type == array)
									SymTab.validateArray(obj);
								SymTab.UpdateEntry(type,tpname,init,endT);
								code = SymTab.declLineArray(VarDecls, type, level);
							.) 
								
								';'.



OneDecl<out int type, out string name>		(.	type = undef;
												string code1 = "";
												Object obj = null;	.)
=  ident									(.	name = t.val;
												SymTab.AddEntry(name,level);	.)
	[ ":=" InicVar<out type, out obj, out code1>
											(.	SymTab.UpdateEntry(name, type, obj);	.)
	]										(.	SymTab.UpdateEntry(name, code1);	.)
	
	.



/*-------------------------- Types Declarations --------------------------*/


Type<out int type,out string name,out object obj> 
							(.	name = "";
								obj = new object();	.)
= 							(.	type = undef;	.)
( "INTEGER"					(.	name = "Integer";
								type = integer;	.)
| "BOOLEAN"					(.	name = "Boolean";
								type = boolean;	.)
| Array<out name,out obj>	(.	type = array;	.)
| "SET"						(.	name = "Set";
								type = sets;	.)
| "SEQUENCE"				(.	name = "Sequence";
								type = sequence;	.)).



Array<out string name,out object dim>
						(. int num, size = 0; 			.)
=
 "ARRAY" "size" number				(.	SymTab.initDimensions();
										size = Convert.ToInt32(t.val);
										SymTab.AddDimension(size);
										name = "Array_" + arrayNum;	 .)
										
			{ ',' number			(.	num = Convert.ToInt32(t.val); 
										size = size * num; 
						   				SymTab.AddDimension(num);		.) }
						   				
									(.	dim = SymTab.returnDimensions();
										if (SymTab.validateBraces(dim))
										{
											SymTab.AddLineTable(arrayNum,size,dim);
		  									arrayNum++;				
										}	.).		
	

/* ------------------------------ InicVar ---------------------------- */


InicVar<out int type, out Object obj,out string code>
										(.	obj = new Object(); code = "";
											string sign = ""; type = undef; 
											int num;	.)
											
=  Constant<out sign,out num, out type, out code>
										(.	if (sign.Equals("-"))
												obj = -num;
											else
												obj = num;	.)
  | ArrayDef<out obj, out code>			(.	obj = SymTab.isVector(); 
						   					type = array;	.)
  | SetDef<out obj>						(.	type = sets;	.)
  | SequenceDef<out obj>				(.	type = sequence;	.).



Constant<out string sign,out int num,out int type, out string code>
									(.	num = 0; type = undef; code = "";
										sign = "";	.)
=  [ Sign<out sign> ] number		(.	type = integer;
										num = Convert.ToInt32(t.val);
										code = sign + t.val;	.)
 |  "true"							(.	type = boolean;
										num = 1;	
										code = "1";	.)
 | "false"							(.	type = boolean;
								   	   	num = 0;
								   	   	code = "0";	.)
 .


/* --------------------------------- Arrays Definition ----------------------------- */


ArrayDef<out object obj, out string code> 	(. string code1 = "";
							obj = new object();
							SymTab.newLine();
							SymTab.newBraces();
							SymTab.newInitArray();	
							SymTab.newOneDim();		.)
= '[' OneOrMoreList<out obj, out code1> 			 ']'	(.	code = "{" + code1 + "}";	.). 



OneOrMoreList<out object obj, out string code>
						(. obj = new object(); string code1 = "", code2 = ""; code = "";	.)
= '[' 						(. open++; 				.) 	
   OneOrMoreList<out obj, out code1> 			
  ']' 						(. open--; 
						   	if (open == 1) 
						   	{
								obj = SymTab.returnInitArray();
								SymTab.AddLine(obj);      
								SymTab.newInitArray();
							}
							code = "{" + code1 + "}";	.)
   { ',' 
	'[' 					(. open++; 				.)
             OneOrMoreList<out obj, out code2> 	
	  ']'			 		(. open--; 
						    if (open == 1) 
						    {
								obj = SymTab.returnInitArray();
								SymTab.AddLine(obj);
								SymTab.newInitArray();	
							}
							code += ", {" + code2 + "}";
											.)}
 | OneOrMoreNum<out obj, out code>		(. SymTab.AddNumBraces(open);
						   SymTab.AddArray(obj);
						   SymTab.AddOneDim(obj);		.).



OneOrMoreNum<out object obj, out string code>	(. int num; code = "";
						   obj = new Object();		
						   SymTab.initList();  	 	.) 
= number	 				(. 
						   num = Convert.ToInt32(t.val); 
						   SymTab.addList(num);
						   code += t.val;	.)
 { ',' number		 			(. num = Convert.ToInt32(t.val);
                        	       SymTab.addList(num);
                        	       code += "," + t.val;	.)
 }						(. obj = SymTab.returnList();	.).



/* --------------------- */


SequenceDef<out Object code>
						(.	ArrayList valinit = new ArrayList();
						   	code = new Object();	.)
						   	
= "<<" number 			(.	valinit.Add(Convert.ToInt32(t.val));	.)
							
   { ',' number 		(.	valinit.Add(Convert.ToInt32(t.val));	.)

   } ">>"				(.	code = valinit;	.).



/* --------------------------------- Sets Definition ----------------------------- */


SetDef<out Object code>			(.	ArrayList tree = new ArrayList(), 
											treeL = new ArrayList(),
											treeR = new ArrayList();
									code = new Object();	.)

= '{'
  [
	ident '|' 
        Tree<out treeL>			(.	tree.AddRange(treeL);	.)
        { "||" Tree<out treeR>	(.	tree.Insert(0, "||");
        							tree.AddRange(treeR);	.) }
  ]
 '}'							(.	code = tree;	.).


Tree<out ArrayList tree>		(.	ArrayList treeL = new ArrayList(),
											treeR = new ArrayList();
									tree = new ArrayList();	.)

= Tree2<out treeL> 				(.	tree.AddRange(treeL);	.)
  { "&&" Tree2<out treeR>		(.	tree.Insert(0, "&&");
        							tree.AddRange(treeR);	.) }.


Tree2<out ArrayList tree>		(.	string op;
									int type;
									tree = new ArrayList();	.)
												
= ident
  RelOp<out op, out type>		
  number						(.	tree.Add(SymTab.Operator(op));
  									tree.Add("x");
									tree.Add(t.val);	.).




/* -------------------------------- Arithmetic and Logic Operations ------------------------------------  */


Statement<out string code> 	(.	code = ""; string com = SymTab.GetComments();
								int type = undef;	.)					
=	( 

IF (Resolver.IsVarDecl())
   VarDecl<out code>			(. if (level == 0)
									SemErr("Invalid global variable declaration!");	.)
 | Assignment<out code>			(.	code += ";\n";	.)
 | WriteStatement<out code>
 | Conditional<out code>
 | Read<out code>				(.	code = SymTab.PrintIdent() + code + ";\n";
 									if (SymTab.checkCaduceus())
 										code = SymTab.genCaduceusCom() +
 												code + SymTab.PrintIdent() + "*/\n";	.)
 | SucOrPred<out code>			(.	code = SymTab.PrintIdent() + code + ";\n";	.)
 | Copy<out type,out code>		(.	code = SymTab.PrintIdent() + code + ";\n";	.)
 
 )								(.	code = com + code;	.).



/* ------------------ Sucessor or Predecessor  ------------ */

SucOrPred<out string code>		(.	code = "";	
									int type; 
									string name="", op = ""; 	.)
						   
= ("succ" 			(.	op += "++";		.)
   | 
   "pred"			(.	op += "--";		.)
   ) '(' 					
		ident		(.	name = t.val;
						type = SymTab.findType(t.val);
						SymTab.Expect(type,integer);
						SymTab.CheckVar(name, level);
						code = op + SymTab.GetCorrectName(name);				.)
	   ')' ';'.



/* ------------------------------- Write the containts of variable ------------------------------------- */

WriteStatement<out string code>
						(. int type=undef, init, endT; 
						   string code2 = "", code_ln = "", com = "";
						   code = "";	.)
= (     ( "write" 			        )
  |    ( "writeLn"				(. code_ln += SymTab.PrintIdent() + genCode.printLn();	.)))
 '(' 
	[     	Expression<out type, out code2>
						(. 	init = SymTab.getSizeTable();
							code += SymTab.print(code2, level) + code_ln;
							endT = SymTab.getSizeTable();
							if (init != endT)
								varDeclCode += SymTab.declLine(init, endT, level) + ";\n";	.)
	]

 ')'		(.	com = SymTab.GetComments();	.)
 
 ';'		(.	if (code2 == "")
 						code = code_ln;
 						
 				if (SymTab.checkCaduceus())
 					code = SymTab.genCaduceusCom() +
 							code + SymTab.PrintIdent() + "*/\n";
 				code = com + code;	.).


/* ------------------------------ Assignament ---------------------------------------------------------- */

Assignment<out string code>		(.	code = "";
									int type = undef, type1=undef, type2, init, endT; 
									string name="", code2 = "", code_array = "";	.)
							   
= (( Designator<out type1, out type2, out code, out name>
									
  ( '=' Expression<out type, out code2>
  
						(.	if (type1 != type)
								SemErr("Bad attribution! Wrong types!");

							if (type == array)
							{
								init = SymTab.getSizeTable();
								code_array = SymTab.AssignArray(code, code2, level);
								endT = SymTab.getSizeTable();
								if (init != endT)
									varDeclCode += SymTab.declLine(init, endT, level) + ";\n";
								if (code_array == "")
									SemErr("Bad attribution! Arrays with different dimensions!");
								code = code_array;
							}
							else if (type != sets)
							{ 
								code = SymTab.PrintIdent() + code + " = " + code2;
							}								
							else
								code = SymTab.PrintIdent() + genCode.AssignSet(code2, code);
						.)
						
  | '(' 							(. 	SymTab.ValidCall(name,level,1); 	.)
	Arguments<name, out code2>		(.	code = SymTab.PrintIdent() + code + "(" + code2 + ")";			.)
    ')'							 ) )
    
   |  ( Cons<out type, out code> 
   |    Tail<out type, out code> 		
   |    Delete<out type, out code>  
   )		(.	code = SymTab.PrintIdent() + code;	.)	)						';'	.



/* ----------------------- Arguments of a subprogram ------------------------- */


Arguments<string name, out string code>
			              (. 
					 code = "";
					 int argCount = 0;
					 string code2;						.)
  =  [ OneArg<name,argCount, out code>    
				       (. argCount++;  							.)
       { ',' OneArg<name,argCount, out code2>
				       (. argCount++; 		
					  code += "," + code2; 					.)
       }
     ]					(.	if (argCount != SymTab.nParam(name))
                                  SemErr("Wrong number of parameters in '" + name + "'");
							code = SymTab.GetCorrectArg(name, code, level);	.)
  .

OneArg<string name, int argCount, out string code> 
						(.	int argType;	.)
				      
  =  Expression<out argType, out code>   
						(.	SymTab.Compatible(argCount, argType, name);	.).



/* ---------------------------- Designator -------------------------------------------------------- */


Designator<out int type, out int type2, out string code, out string name> 
									(. code =""; 
									   string code2 = "";	.)		

=  ident	  							(. 
									name = t.val;	
									type = SymTab.findType(name); 
									type2 = SymTab.findType(name);
									if (type == undef && ! SymTab.getClass(name).Equals("subProgram"))
										SemErr("Variable " + name + " isn't defined!");
									SymTab.CheckVar(name, level);
									code += SymTab.GetCorrectName(name); .)
										
[ "[" 									(.	if ( (type != array) && (type != sequence) )
												SemErr("Wrong type!");		.)

	Elem<name, out code2, out type>		(.	if ( SymTab.findType(name) == sequence )
												code = genCode.IndexSequence(code2, SymTab.GetCorrectName(name));
											else
												code += code2;	.)
										
  "]"
] .


Elem<string name, out string code,out int type2> 
								  (. code = ""; type2 = undef;
								     string code1 = "", code2 = "";
								     int num = 0, type, type3;
								     SymTab.initIndexes();
								     type3 = SymTab.findType(name);				.)
								     
= Expression<out type, out code1>		 (. 
									if (type3 == sequence)
										code = code1;
									else
										code = "[" + code1 + "]";
									SymTab.Expect(integer, type);
								    num++;			.)
  { ',' Expression<out type, out code2>    	 (. 
  									SymTab.Expect(integer, type);
								    num++;
								    if (type3 == array)
								      code += "[" + code2 + "]";			   		
								    else
								      SemErr("Invalid Expression");				.) }
								 
								 (. SymTab.validateIndex(name,num);
								    type2 = integer;				.).


/* -------------------------------- Expression ------------------------------------------------------ */


Expression<out int type, out string code>
									(. string op = "",code2; 
									   int type1=undef,type2=undef;	.)
=  SimpleExpression<out type, out code> 		
[ RelOp<out op,out type1> 						
   SimpleExpression<out type2, out code2>		(. 
   									if (type1 != sets)
   									{
										if (type != type2)
											SemErr("Bad attribution! Wrong types!"); 
									   	code  += SymTab.Operator(op) + code2;	     
									}
									else
									{
     								    if (type1 != type2)
											SemErr("Bad attribution! Wrong types!");
										else
											code = genCode.IsInSet(code, code2);
									}	
									type = boolean;	// to indicate that the result is boolean
									.)
].


/* ------------------------------ SimpleExpression -------------------------------------------------*/


SimpleExpression<out int type, out string code>
									(. code=""; 
									   string sign="", op="", oper="", code2 = "", code1 = "";
									   int type1;	.)
									   
=  Term<sign,op,out type, out code1> 	(.	code += code1;	.)
	 { AddOp<out op,out type1>					(.  
	 									if (type != type1)
											SemErr("Bad Attribution! Wrong Types!"); 
									    else
				    	    		    	  oper   = op;
																.)
	   Term<sign,op,out type, out code2>	(.  
	   									if (type != type1)
											SemErr("Wrong Types!"); 
									    else 
									      	if (type != sets) 
  						    			    	code += SymTab.Operator(oper) + code2;
									      	else
											{
								 	  	 		code = genCode.UnionSet(code, code2);
											}
									    			     		.)}.



/* ----------------------------- Term ---------------------------------------------------------------- */


Term<string sign,string op,out int type, out string code>
				   	       			(.	int type1 = undef; code = "";
										string code1 = "", code2 = "";	
										type = undef;	.)
										
=  Factor<sign,out type, out code1>		(.	code += code1;	.)
{ MulOp<out op,out type1> 				(.	if (type != type1)	
												SemErr("Wrong Types!");	.)
												
  Factor<sign,out type, out code2>		(.	if (type != type1)
												SemErr("Wrong Types!"); 
											else
												if (type != sets) 
									     			code += SymTab.Operator(op) + code2;
									   			else
										  		{
										   			code = genCode.InterceptionSet(code, code2);
										  		}	 
										  .) }.
	



/* ---------------------------- Factor --------------------------------------------------------------- */


Factor<string sign,out int type, out string code>
									(.	type = undef; int num, type2, init, endT; 
										string name = "", code1 = "";
										code = ""; Object obj = new Object();	.)
										
=  Constant<out sign,out num,out type,out code>			
 | Designator<out type, out type2, out code, out name>		
   [ '('								(.	SymTab.ValidCall(name,level,0);	.)
	Arguments<name, out code1> 				
     ')'								(.	code += "(" + code1 + ")";	.) ]		

 | '(' 				
      Expression<out type, out code1>	(.	code += "(" + code1 + ")";	.)
   ')'

 | '!' Factor<sign,out type, out code1>	(.	code = "!" + code1;	.)

 | SetDef<out obj>						(.	init = SymTab.getSizeTable();
 											name = SymTab.genVar();
 											SymTab.AddEntry(name,level);
 											SymTab.UpdateEntry(name, sets, obj);
											SymTab.UpdateEntry(name, "");
 											endT = SymTab.getSizeTable();
											varDeclCode += SymTab.declLine(init, endT, level) + ";\n";
											type = sets;
											code = name;	.)
 | Tail<out type,out code>
 | Head<out type,out code>
 | Member<out type,out code>
 | IsEmpty<out type,out code> 
 | Length<out code>						(.	type = integer;	.).		


/* ------------------ SequenceOper ------------------- */



Tail<out int type, out string code>
						(.	type = undef;
							code = "";				
							int type2 = undef;	.)
						   
 = "tail" '('  Expression<out type2, out code>	
		 				(.	type = sequence;
							SymTab.Expect(sequence,type2);
							code = genCode.Tail(code);				
						.)
           ')'.


Head<out int type, out string code>
						(. type = undef;
						   code = "";
						   int type2 = undef;	.)
						   
 = "head" '('  Expression<out type2, out code>	
		 				(. type = integer;
						   SymTab.Expect(sequence,type2);
						   code = genCode.Head(code);		.)  ')' .


/* ******************** JOIN *********************/

Cons<out int type, out string code>
						(.	type = undef;
							code = "";
							int type2 = undef;
							string name = "";	.)
						   
 = "cons" '(' 
 		Expression<out type, out code> 
 		
 		','
        ident	        (.	name = t.val;
							type2 = SymTab.findType(name);
							if (type2 == undef)
								SemErr("Variable '" + name + "' isn't defined!");  
							SymTab.CheckVar(name, level);
							code = genCode.Cons(code, SymTab.GetCorrectName(name));	.)
	   ')'.


/*************************** DELETE *********/


Delete<out int type, out string code>
						(. type = undef;
						   code = "";
						   int type2 = undef;	
						   string name = "";				.)
						   
 = "del" '('
 		Expression<out type, out code>
 		
 		','
        ident			(.	name = t.val; 
							type2 = SymTab.findType(name);
							SymTab.Expect(integer,type);
							if (type2 == undef)
								SemErr("Variable '" + name + "' isn't defined!");  
							type = sequence;
							SymTab.CheckVar(name, level);
							code = genCode.Delete(code,SymTab.GetCorrectName(name));	.)
	   ')'.




Copy<out int type, out string code>
						(. type = undef;
						   code = "";
						   int type1 = undef, type2 = undef;	
						   string src = "", dest = "";	.)
						   
 = "copy" '(' ident		(.	src = t.val;		
							type1 = SymTab.findType(src);
							SymTab.Expect(sequence,type1);
							if (type1 == undef)
								SemErr("Variable '" + src + "' isn't defined!");
							SymTab.CheckVar(src, level);	.)
	  ',' 	
              ident		(.	dest = t.val; 
							type2 = SymTab.findType(dest);

							SymTab.Expect(sequence,type2);

							if (type2 == undef)
								SemErr("Variable '" + dest + "' isn't defined!");  
							type = sequence;
							
							SymTab.CheckVar(dest, level);
							
							code = genCode.Copy(SymTab.GetCorrectName(src), SymTab.GetCorrectName(dest));	.)
	   ')' ';'.

/************************ MEMBER **************/

Member<out int type, out string code>
  						(. type = undef;
						   code = "";
						   int type2 = undef;	
						   string name = "";	.)
						   
 = "IsMember" '(' 
 		Expression<out type, out code> 
 		','
        ident			(.	name = t.val; 
							type2 = SymTab.findType(name);
							SymTab.Expect(integer,type);
							if (type2 == undef)
								SemErr("Variable '" + name + "' isn't defined!");  
							type = boolean;
							SymTab.CheckVar(name, level);
							code = genCode.IsMember(code, SymTab.GetCorrectName(name));		.)
	   ')' .


/************************* IsEmpty ************/

IsEmpty<out int type, out string code>
  						(. type = undef;
						   code = "";	.)
						   
 = "isEmpty" '(' Expression<out type, out code>  
                				
                		(. SymTab.Expect(sequence,type);
						   type = boolean;
						   code += genCode.IsEmpty(code);	.)
	   ')' .


/**********************************************/

Length<out string code>		(. 
								code = "";
								string name = "";				
								int type = undef;				.)
=
 "Length" '(' ident 		(.	name = t.val;				
								type = SymTab.findType(name);
								if ((type != array) && (type != sequence))
									SemErr("Invalid type!"); 
								SymTab.CheckVar(name, level);
								code = SymTab.Length(SymTab.GetCorrectName(name));	.)
	  ')'.

/* ------------------------------------ Sign ------------------------------------------- */


Sign<out string sign>		(.	sign = "";		.)
=  '+' 						(.	sign = t.val;	.)
| '-' 						(.	sign = t.val;	.)
.



/* ---------------------------- AddOp, MulOp, RelOp -------------------------------------------------------- */



AddOp<out string op, out int type>		(. op = ""; 	type = undef;	.)
=  '+'									(. op = "ADD";	type = integer; .) 
| '-' 									(. op = "SUB";	type = integer; .)
| "||"									(. op = "OR";	type = boolean; .)
| "++"									(. op = "++";   type = sets; 	.)
.	



MulOp<out string op, out int type>		(. op = ""; 	type = undef;	.)
=  '*'			 						(. op = "MUL";	type = integer; .)
| '/'		 							(. op = "DIV";	type = integer; .)
| "&&"				 					(. op = "AND";	type = boolean; .)
| "**"									(. op = "**";   type = sets;	.)
.		



RelOp<out string op,out int type>		(. op = ""; 		type = undef;	.)
=  "==" 								(. op = "EQUAL";	type = boolean;	.)
| "!=" 									(. op = "NOT";		type = boolean; .)
| '<'		  							(. op = "INF";		type = boolean; .)
| "<="									(. op = "INFEQ";	type = boolean;	.)
| ">="									(. op = "SUPEQ";	type = boolean;	.)
| '>'  									(. op = "SUP"; 		type = boolean; .)
| "<<"									(. op = "<<"; 		type = sets;	.)
.



/* -------------------------- Conditionals Expressions ------------------------------ */


Conditional<out string code>				(. code = "";	.)
=  IfThenElse<out code>
 | ForStatement<out code>
 | WhileStatement<out code> .


/******************
*   IfThenElse    *
******************/


IfThenElse<out string code>				(.	int type; code = "";
									   		string code1, code3="", code2="";	.)
									   		
= "if" Expression<out type, out code1>
									(.	SymTab.Expect(boolean, type);
									  	code = SymTab.PrintIdent() + "if (" + code1 + ")\n"; 
									  	code += SymTab.GetComments();
									  	elseT++;	.)
									   
   "then" '{'						(.	code += SymTab.PrintIdent() + "{\n";
   										SymTab.IncIdent();	.)
   
   BlockStat<out code2>				(.	code += code2;
   										code += SymTab.GetComments();	.)
   
   '}' 								(.	SymTab.DecIdent();
   										code += SymTab.PrintIdent() + "}\n";	.)
   												
   Else<out code3> 					(.	code += code3;	.).


Else<out string code>				(. 	code = ""; string code1 = "";	.)	
    = "else" 						(.	code += SymTab.GetComments()
    											+ SymTab.PrintIdent() + "else\n";	.)
    '{'								(.	code += SymTab.PrintIdent() + "{\n";
    									SymTab.IncIdent();	.)
    	BlockStat<out code1>		(.	code += code1 + SymTab.GetComments();
   										SymTab.DecIdent();	.)
   							'}'		(.	code += SymTab.PrintIdent() + "}\n";	.)
    | .


// ------------------- BlockStat


BlockStat<out string code>		(.	string code1 = "";
									code = "";	.)
									
=  { Statement<out code1> 		(.	code += code1;	.)				 }.



/******************
*        For      *
******************/


ForStatement<out string code>		(.	string	code1 = "", lim1 = "", lim2 = "", inc = "",
												name, var, step = "", sat = ""; 
							     		code = ""; 
							     		int type;
							     		int actual_identation = SymTab.GetCurIdent();	.)
=  "for" '(' 
             Interval<out code, out lim1, out lim2, out name, out var>  
         ')'
         			
       Step<name, out step, out inc>		(.	name = SymTab.GetCorrectName(name);
       											type = SymTab.findType(var);
       								if (type != array)
       								{
       									code = SymTab.PrintIdent();
       									if ( (step == "stepUp") || (step == "") )
       									{
       										if (inc == "")
       											inc = "1";
	       									code += "for(" + name + "=" + lim1 + "; "
	       											+ name + "<=" + lim2 + "; " 
	       											+ name + "+=" + inc + ")\n";
	       								}
      									else
       	   									code += "for(" + name + "=" + lim2 + "; "
	       											+ name + ">=" + lim1 + "; " 
	       											+ name + "-=" + inc + ")\n";
       									code += SymTab.GetComments();
       								}	.)
       
       Satisfy<out sat>			(.	if( sat != "" )
       								{
       									SymTab.IncIdent();
       									code += SymTab.GetComments();
   										code += SymTab.PrintIdent() + sat;
       								}	.)
 							  		 
	'{'							(.	if ( ! ((sat == "") && (type == array)) )
										code += SymTab.PrintIdent() + "{\n";
									
									SymTab.IncIdent();	.)
	
	BlockStat<out code1>		(.	code += code1;
									code += SymTab.GetComments();	.)
	
	'}'		  					(.	SymTab.DecIdent();
									code += SymTab.PrintIdent() + "}\n";	.)
	
								(.	if ( (sat != "") && (type == array) )
									{
										SymTab.DecIdent();
										code += SymTab.PrintIdent() + "}\n";
										
									}
									
									SymTab.DecIdent(SymTab.GetCurIdent() - actual_identation);
									.).


//----------------------------

Interval<out string code, out string lim1, out string lim2, out string name, out string var>
							(.	int type, type2 = undef, init, endT; code = ""; var = "";
								lim1 = ""; lim2 = "";	.)
= 
  ident 					(.	name = t.val;
  								SymTab.CheckVar(name, level);	.)
  
	(	"in" Range<out lim1, out lim2>
							
		| "inArray"  ident		(.	init = SymTab.getSizeTable();
									type = SymTab.findType(t.val);
									SymTab.Expect(array, type);
									var = t.val;
									SymTab.CheckVar(var, level);
									code = SymTab.ForEach(name, var, level);
									endT = SymTab.getSizeTable();
									if (init != endT)
										varDeclCode += SymTab.declLine(init, endT, level) + ";\n";	.)
								 
		| "inFunction" ident    (.	var = t.val;
                                    if (! (SymTab.getClass(var)).Equals("subProgram"))
										SemErr("Expected subProgram!");	.)
							
           '(' 					(.	type = SymTab.findType(name);
 							  		type2 = SymTab.findType(var);
							  		if (type2 != type) 
							 			SemErr("Types mismatch! ");	.)
							 			
		Arguments<var, out code>
		
            ')' ["with" ]				)
.


// -------------------- Range


Range<out string lim1, out string lim2>	
							(.	int type;
								lim1 = ""; lim2 = "";	.)
							   
= ( number 					(.	lim1 = t.val;				.)
								
  | ident					(.	type = SymTab.findType(t.val);
								SymTab.Expect(integer,type);
								lim1 = t.val;
								SymTab.CheckVar(lim1, level);
								lim1 = SymTab.GetCorrectName(lim1);		.))
  ".." 
  
 ( number					(.	lim2 = t.val;	 			.)
 
 | ident					(.	type = SymTab.findType(t.val);
								SymTab.Expect(integer,type);
								lim2 = t.val;
								SymTab.CheckVar(lim2, level);
								lim2 = SymTab.GetCorrectName(lim2);	.)
								)
 .




/************************************
*  	STEP	/	SATISFY	    *
************************************/


Step<string name, out string step, out string val>
							(.	step = "";	val = "";.)
							    
=  ( ("stepUp" 				(. 	step += "stepUp";	.))

  | ( "stepDown"			(.	step += "stepDown";	.)))
  
	number					(.	val += t.val;			.)
 | .


Satisfy<out string code>		(.	string code1 = "";
									code=""; int type=undef;	.)

= "satisfying" Expression<out type, out code1>
								(.	SymTab.Expect(boolean,type);
									code = "if (" + code1 + ")\n";		.)
 |
 . 





/******************
*        While    *
******************/


WhileStatement<out string code>	(. 	int type; code = "";
									string code1, code2;	.)
							   		
=  ("WHILE")					(.	code = SymTab.PrintIdent() + "while ";  
							   		whileT++;					.)
                      '(' 
                          Expression<out type, out code1>
                         		(.	if (type != 1)
										SemErr("Invalid type! Expected type is boolean!"); 	   .)
										
                      ')'		(.	code += "(" + code1 + ")\n";
                      				code += SymTab.GetComments();	.)
                      
                    '{'  		(.	code += SymTab.PrintIdent() + "{\n"; 
                    				SymTab.IncIdent();	.)
                    				
                    BlockStat<out code2> 
                    			(.	code += code2;
                    				code += SymTab.GetComments();	.)

                    '}'			(.	SymTab.DecIdent();
                    				code += SymTab.PrintIdent() + "}\n";	.).



/* -------------------------------------------------- Read ------------------------------- */
	
Read<out string code>		(.	string name="";			.)
= "read"
	"(" ident				(.	name = t.val;
								SymTab.CheckVar(name, level);
								code = genCode.Read(SymTab.GetCorrectName(name));	.)
  	")"
  ';'.



/* ----------------------------------------------- SubProgDef ------------------------------ */

SubProgDef<out string code>		(.	string codearg = "", code2 = "", code4 = "", codeInit = "",
											typeStr = "", name="", stat_code = "",
											name_res = "", fun_type = "void "; 
									int type = undef, type1 = undef, init, endT; 
									code = "";
									object obj = new object();
						   			string varDeclCodeTMP = varDeclCode; varDeclCode = "";
						   			string actualFunTMP = SymTab.GetActFun();
						   			int identationTMP = SymTab.GetCurIdent();
						   			SymTab.SetCurIdent(0);	.)
									
= "subProgram"  ident					(.	SymTab.SetActFun(t.val);
						   					SymTab.OpenScope();
											level++;
						   					name = t.val;	.)
						   			
  '('		 							(.	SymTab.initDimensions2();	.)
      FormalArgs<out codearg>		
  ')'			
           [ "::" Type<out type,out typeStr, out obj> 
           				(.	switch (type)
           					{
								case(1): fun_type = "int ";
										 break;
								case(2): fun_type = "int ";
										 break;
								case(3): fun_type = "int * ";
											
											init = SymTab.getSizeTable();
											name_res = SymTab.genVar();
											SymTab.AddEntry(name_res,type,typeStr,level,obj);
											endT = SymTab.getSizeTable();
											SymTab.errorsType(type,init,endT);
											SymTab.validateArray(obj);
											SymTab.UpdateEntry(type,name,init,endT);

											ArrayList dim = SymTab.returnDim(name_res);
											int array_size = 0;

											foreach(int el in dim)
												array_size += el;

											SymTab.IncIdent();
											varDeclCode += SymTab.PrintIdent() + "int * " + name_res +
															" = malloc(sizeof(int) * " +
															array_size + ");\n";
											SymTab.DecIdent();

										 break;
								case(4): fun_type = "set ";
										 break;
								case(5): fun_type = "list ";
										 break; 
								default: break;
							}
           				
           				.)
           ]
						(.  SymTab.AddEntryFun(name,SymTab.findSize(typeStr),level,typeStr, obj);
						    SymTab.UpdateEntry(name);
						    
						    SymTab.offset = SymTab.findSize(name) + SymTab.sizeDimensions(name); 
						     				.)	
			(.	codeInit += SymTab.PrintIdent() + fun_type + name;
  				codeInit += SymTab.GetComments();	.)
  '{'  		(.	code += SymTab.PrintIdent() + "{\n";
  				SymTab.IncIdent();
  				code += SymTab.GetComments();	.)
  
  ["Declarations" { Decls<out code2>	(. varDeclCode += code2;	.)	}	]	
       
	"Statements"
	{
  		Statement<out code2>	(.	stat_code += code2 + "\n";	.) }
								(.	SymTab.localF++;	.)
						
	[ ReturnStatement<name, out type1,out code4>
						(.	if (typeStr.Length == 0)
								SemErr("Invalid return!");		
						   	if (type != type1)
								SemErr("Invalid return!");		
							else
							if (type == array)
						   	{
								init = SymTab.getSizeTable();
								stat_code += SymTab.AssignArray(name_res, code4, level) + ";\n";
								endT = SymTab.getSizeTable();
								if (init != endT)
									varDeclCode += SymTab.declLine(init, endT, level) + ";\n";
						   		
						   		stat_code += SymTab.PrintIdent() + "return " + name_res + ";\n";
						   	}
						   	else
						   		stat_code += SymTab.PrintIdent() + "return " + code4 + ";\n";
						   		
						   		.)
        ]		(.	stat_code += SymTab.GetComments();	.)
  '}'		
						(.	SymTab.offset = 0;
						   	if (typeStr.Length == 0 && code4.Length != 0)
								SemErr("Invalid Return!");
						   	else if (typeStr.Length != 0 && code4.Length == 0)
								SemErr("Missing Return!");
						   	
						   	SymTab.DecIdent();
						   	
						   	code = codeInit + "(" + SymTab.getArgDecl(name, codearg) + ")" + "\n"
						   					+ code;
						   	
						   	code += varDeclCode + "\n" + stat_code + SymTab.PrintIdent();
							code += "}\n";
   							varDeclCode = varDeclCodeTMP;
   							SymTab.SetActFun(actualFunTMP);
							code = SymTab.substArg(code, name, level);
						   	SymTab.SetCurIdent(identationTMP);
						   	SymTab.CloseScope(level);
						   	level--;				  	.).


FormalArgs<out string code> 
= 						(.	string code2 = ""; code = "";
							SymTab.initDimensions();
							SymTab.initArgs();				.)
  [
   OneParam<out code> 
  { ';' OneParam<out code2> 	(.	code += ", " + code2;	.)
  } ].


OneParam<out string code>		(.	int type; code = "";
						   			string name, typeStr; 
						   			object dim;	.)
						   			
=  ident 						(.	name = t.val;	
						   			SymTab.AddArg(name);	.)
   "->" 
   Type<out type,out typeStr,out dim>
						(. 	SymTab.AddDimension2(typeStr);
						   	SymTab.AddEntry(name,type,typeStr,-level,dim);
						   	if (type == array)
						   	{
						   		string array_dim = "";
						   		foreach(int el in (ArrayList) dim)
						   			array_dim += "[" + el + "]";
						   		code += "int " + name + array_dim;
						   	}
						   	else if (type == sequence)
						   		code += "list " + name;
						   	else if (type == sets)
						   		code += "set " + name;
						   	else 
						   		code += "int " + name;
						   		.).


ReturnStatement<string name, out int type, out string code>
						(.	type = undef; code = SymTab.GetComments();
							string code1 = "";	.)

= "return" Expression<out type, out code1> 	(.	code += code1 + SymTab.GetComments();	.)	";"
						.

/************************/

END Liss.
