/// \file

%{ 
    // -*- Mode : c++ -*-
    //
    // SUMMARY  :      
    // USAGE    :        
    // ORG      : 
    // AUTHOR   : Frederic Hecht
    // E-MAIL   : hecht@ann.jussieu.fr
    //
    
    /*
     
     This file is part of Freefem++
     
     Freefem++ is free software; you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation; either version 2.1 of the License, or
     (at your option) any later version.
     
     Freefem++  is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
     
     You should have received a copy of the GNU Lesser General Public License
     along with Freefem++; if not, write to the Free Software
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     */
    
#include "config-wrapper.h"
#define eflval yylval 
#include <iostream>
#include  <complex>
#include <string>
  // for reset cout,cin  in windows  dll
#ifdef _WIN32
#include <ext/stdio_filebuf.h>
#include <iostream>
#include <cstdio>
#endif

#include "error.hpp"
class Iden;
#include "strversionnumber.hpp"
#include "InitFunct.hpp"
#ifdef __MWERKS__
#ifdef __INTEL__
#include <malloc.h>
#else
#include <alloca.h>
#endif
#endif
#include "AFunction.hpp"
//  to reserve space to graphical pointer function
#include "rgraph.hpp"
#include "RNM.hpp"
#include "fem.hpp"
#include "FESpacen.hpp" 
#include "FESpace.hpp" 
#include "MeshPoint.hpp"

#include "lgfem.hpp" 
#include "lex.hpp"
#include "environment.hpp"

    extern FILE *ThePlotStream;
    extern KN<String> *pkarg;

class Routine;
bool load(string s);

 template <class R,int d> class FE;
 template <class R,int d,int i> class FE_;

extern mylex *zzzfff;
// modif FH for window to have 1 dll  for mpi and none mpi ..
extern  void (*initparallele)(int &, char **&);
extern  void (*init_lgparallele)();
extern  void (*end_parallele)();
// 
#ifdef HAVE_LIBARPACK
  void init_eigenvalue();
#endif
   
  aType dcltype;
const int nbembtype=10;
aType rettype[nbembtype];
Block * routineinblock[nbembtype]; // Add FH july 2005 pb clean on return 
int kkembtype=-1;
int inloopcount=0;
Block *currentblock;
// Add FH july 2005 
//  problem clean variable after break,continue and return.
const int sizeStackOfLoop=100; 
Block * StackOfLoop[sizeStackOfLoop];
// end ADD
double CPUcompileInit =0;
//class pfes;
C_F0  fespacetype;
bool fespacecomplex;
int fespacedim;
extern int UnShowAlloc;
int ShowAlloc(const char *s,size_t &);
inline int yylex()  {return zzzfff->scan();}
inline int lineno() {return zzzfff->lineno();}

extern bool withrgraphique;
inline void fingraphique()
 { if(withrgraphique) 
   { withrgraphique=false;
    rattente(1);
    closegraphique();
  }}

void lgerror (const char* s) ;


 // mpi ptr to function ... 
void (*initparallele)(int &argc, char **& argv)=0 ;
void (*init_lgparallele)()=0;
void (*end_parallele)()=0;
%}

%union{ 
 double dnum;
 long lnum;
 char * str;
 char oper[8];
 CC_F0 cexp;
 Routine   *routine;
 AC_F0 args;
 aType type;
 CListOfInst cinst;
 Block * block; 
 ListOfId *clist_id;
/* ListCatch * clist_Catchs;*/
}

/* BISON Declarations */

%type <cinst>   input
%type <cinst>   instructions
%type <cexp>   instruction
%type  <cexp>  try
%type  <cexp>  catchs
/* %type  <cexp>  throw */
%type <cexp>  declaration 
%type <cexp>  declaration_for
%type <cexp>  list_of_dcls
%type <cexp>  fespace_def
%type <cexp>  fespace_def_list
%type <cexp>   Expr
%type <cexp>   no_comma_expr
%type <cexp>   sub_script_expr
%type <cexp>   no_ternary_expr
%type <cexp>   no_set_expr
%type <cexp>   unary_expr
%type <cexp>   pow_expr
%type <cexp>   primary
%type <oper>   unop
%type <args>  parameters
%type <args>  array 
%type <args>  parameters_list
%type  <cexp> begin
%type  <cexp> end
%type  <clist_id> list_of_id_args
%type  <clist_id> list_of_id1
%type <cexp>  spaceIDs
%type <cexp>  spaceIDa
%type <cexp>  spaceIDb
%type <cexp> ID_space
%type <cexp>  ID_array_space
%type <args> bornes;
%type <args>   border_expr;
%type <type>   type_of_dcl;
%type <str> id;
%type <str> fespace123;

/* Add precedence rules to solve dangling else s/r conflict */

%nonassoc IF
%nonassoc ELSE

%left <oper> ','
%right <oper> '=' SET
%left  <oper> LTLT GTGT
%left  <oper> OR '|' 
%left  <oper> AND '&'  
%left  <oper> EQ NE
%left  <oper>  '<' '>' LE GE 
%left  <oper>  '+' '-'
%left  <oper> '*' '/'  '%' DOTSTAR DOTSLASH
%right <oper> UNARY PLUSPLUS MOINSMOINS '!'
%right <oper>  '^' '\''
%right <oper>  '_' 
%left  <oper>  '(' '[' '.'

%token <oper> ')'  ']' 
 
%token <lnum> LNUM
%token <dnum> DNUM
%token <dnum> CNUM
%token <str> ID
%token <str> FESPACEID
%token <str> IDPARAM
%token <str> STRING

%token ENDOFFILE
%token INCLUDE
%token LOAD
%token BIDON 

%token FOR
%token WHILE
%token IF
%token ELSE
%token BREAK
%token CONTINUE
%token RETURN
%token TRY
%token CATCH
%token THROW

%token <type> TYPE
%token <type> FUNCTION
%token <str> FESPACE
%token <str> FESPACE1
%token <str> FESPACE3


%token DOTSTAR
%token DOTSLASH
%token AND
%token OR
%token EQ
%token NE
%token LE
%token GE
%token PLUSPLUS
%token MOINSMOINS
%token SET
%token LTLT
%token PLUSEQ
%token MOINSEQ
%token MULEQ
%token DIVEQ
%token DOTMULEQ
%token DOTDIVEQ
%token GTGT
%token ARROW
%token BORDER
%token CURVE
%token SOLVE

%% 

start:   input ENDOFFILE {
		        const char *  magicffglut="#!ffglutdata3.1\n";// for complex and vector 3d plot 
			//FFCS: divert stream to FFCS
                        if(ThePlotStream) ffapi::fwriteinit(magicffglut,strlen(magicffglut),1,ThePlotStream);	            
                        size_t sizestack = currentblock->size()+1024 ; //  before close 
                        $1+=currentblock->close(currentblock);
                        if(verbosity>2 || mpirank==0) cout << " sizestack + 1024 =" << sizestack << "  ( " << sizestack-1024 <<" )\n" ;   
                        size_t lg0,lg1;                       
                        int NbPtr = ShowAlloc("init execution ",lg0); // number of un delele ptr
			UnShowAlloc =0;// add FH for parallee
                        if(verbosity>2  || mpirank==0) cout << endl;  
                        { Stack stack = newStack(sizestack);
                        double CPUcompile= CPUtime();
                        try {                  
                          $1.eval(stack);}
                        catch ( E_exception & e)  {
                          cerr << e.what() << " ,  mpirank " << mpirank << endl;
                          return 1; }
                        catch( Error & err) {
                          cerr << err.what() << endl;
			  cerr << " err code " << err.errcode() << " ,  mpirank " << mpirank << endl;
                          return err.errcode();
                        }
                         catch( ...) { cerr << "Strange catch exception ???\n"; 
                          cerr << " at exec line  " << TheCurrentLine << " ,  mpirank " << mpirank << endl;
                          return 1; 
                         }

                        if(verbosity)  cout << "times: compile "<< CPUcompile-CPUcompileInit <<"s, execution " 
			    <<  CPUtime()-CPUcompile  <<"s,  mpirank:" << mpirank << endl;
                        deleteStack(stack);
                        //debugstack.clear() 
                        } 
                        fingraphique();
			//FFCS: divert stream to FFCS
			if(ThePlotStream) {ffapi::ff_pclose(ThePlotStream); ThePlotStream=0;}
			UnShowAlloc =1;
                        NbPtr = ShowAlloc("end execution -- ",lg1) - NbPtr;
                        
			    if (NbPtr) { cout << " ######## We forget of deleting   " << NbPtr 
			                      << " Nb pointer,   " <<  lg1-lg0 << "Bytes " << " ,  mpirank " << mpirank <<endl;}
  return 0;}
;

input:   instructions 
;
         
instructions:  instruction   {$$=$1;;;}
        | instructions  instruction   { $$= ($1+=$2) }         
        ;

/* Function arguments list */

list_of_id_args:   { $$=new ListOfId();}
            | id                      { $$ = new ListOfId(); $$->push_back(UnId($1))}
            | id '=' no_comma_expr    { $$ = new ListOfId(); $$->push_back(UnId($1,$3)) }
            | FESPACE id              { $$ = new ListOfId(); $$->push_back(UnId($2,Find($1),atype<FE<double,2> **>()))}
            | FESPACE '&' id              { $$ = new ListOfId(); $$->push_back(UnId($3,Find($1),atype<FE<double,2> **>(),true))}
            | FESPACE3 id              { $$ = new ListOfId(); $$->push_back(UnId($2,Find($1),atype<FE<double,3> **>()))}
            | FESPACE3 '&' id              { $$ = new ListOfId(); $$->push_back(UnId($3,Find($1),atype<FE<double,3> **>(),true))}
            | type_of_dcl id          { $$ = new ListOfId(); $$->push_back(UnId($2,C_F0(),$1->right())) }
            | type_of_dcl '&' id      { $$ = new ListOfId(); $$->push_back(UnId($3,C_F0(),$1,true)) }
            | '[' list_of_id_args ']' { $$ = new ListOfId(); $$->push_back(UnId($2)) }
            | list_of_id_args ',' id                     { $$ = $1; $$->push_back(UnId($3)) }
            | list_of_id_args ',''[' list_of_id_args ']' { $$ = $1; $$->push_back(UnId($4)) }
            | list_of_id_args ',' id '=' no_comma_expr   { $$ = $1; $$->push_back(UnId($3,$5)) }
            | list_of_id_args ',' FESPACE id             { $$ = $1; $$->push_back(UnId($4,Find($3),atype<FE<double,2> **>())) }
            | list_of_id_args ',' FESPACE '&' id             { $$ = $1; $$->push_back(UnId($5,Find($3),atype<FE<double,2> **>(),true)) }
            | list_of_id_args ',' FESPACE3 id             { $$ = $1; $$->push_back(UnId($4,Find($3),atype<FE<double,3> **>())) }
            | list_of_id_args ',' FESPACE3 '&' id             { $$ = $1; $$->push_back(UnId($5,Find($3),atype<FE<double,3> **>(),true)) }
            | list_of_id_args ',' type_of_dcl id         { $$ = $1; $$->push_back(UnId($4,C_F0(),$3->right())) }
            | list_of_id_args ',' type_of_dcl '&' id     { $$ = $1; $$->push_back(UnId($5,C_F0(),$3,true)) }
;

list_of_id1:  id                      { $$ = new ListOfId(); $$->push_back(UnId($1)); }
            | list_of_id1 ',' id      { $$=$1  ; $$->push_back(UnId($3)); }
;
         
id: ID | FESPACE|FESPACE3|FESPACE1; 

/* <<list_of_dcls>> */

list_of_dcls:    ID                         {$$=currentblock->NewVar<LocalVariable>($1,dcltype)}   
              |  ID '='   no_comma_expr     {$$=currentblock->NewVar<LocalVariable>($1,dcltype,$3)}
              |  ID  '(' parameters_list ')' {$$=currentblock->NewVar<LocalVariable>($1,dcltype,$3);
                                              $3.destroy()}
              |  list_of_dcls ',' list_of_dcls  {$$=C_F0($1,$3)}
                           
              
;


parameters_list:
	   no_set_expr {$$=$1} 
	|  FESPACE  ID  {$$=Find($1)} 
	|  FESPACE1  ID  {$$=Find($1)} 
	|  FESPACE3  ID  {$$=Find($1)} 
	|  ID '=' no_set_expr { $$=make_pair<const char *,const C_F0>($1,$3)} 	
	| parameters_list ',' no_set_expr { $$ = ($1 += $3) }
	| parameters_list ',' id '=' no_set_expr { $$= ($1+= make_pair<const char *,const C_F0>($3,$5))}
; 

/* <<type_of_dcl>> */

type_of_dcl:   TYPE 
             | TYPE '[' TYPE ']' {$$=TypeArray($1,$3)}
             | TYPE '[' TYPE ']' '[' TYPE ']' {$$=TypeArray(TypeArray($1,$3),$6)} // Add FH mars 2012 
             | TYPE '[' TYPE ',' TYPE ']' {$$=TypeArray($1,$3,$5)}
             | TYPE '[' TYPE ',' TYPE ']' '[' TYPE ']' {$$=TypeArray(TypeArray($1,$3,$5),$8)}
             | TYPE '<' TYPE '>' {$$=TypeTemplate($1,$3)}
	     | TYPE '<' TYPE '>' '[' TYPE ']' {$$=TypeArray(TypeTemplate($1,$3),$6)}
	     | TYPE '<' TYPE '>' '[' TYPE ',' TYPE ']' {$$=TypeArray(TypeTemplate($1,$3),$6,$8)}
			    
             
;

/* <<ID_space>> */

ID_space:
ID                                  { $$ =  NewFEvariable($1,currentblock,fespacetype,fespacecomplex,fespacedim); }
  |  ID '[' no_set_expr ']'              { $$ =  NewFEarray($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim); }
  |  ID '=' no_set_expr                  { $$ =  NewFEvariable($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim) }
  |  '[' list_of_id1 ']'                 { $$ =  NewFEvariable($2,currentblock,fespacetype,fespacecomplex,fespacedim) }
  |  '[' list_of_id1 ']' '[' no_set_expr ']'  { $$ =  NewFEarray($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }
  |  '[' list_of_id1 ']' '=' no_set_expr { $$ =  NewFEvariable($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }
; 
ID_array_space:
 ID '(' no_set_expr ')'              { $$ =  NewFEarray($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim); }
  |  '[' list_of_id1 ']' '(' no_set_expr ')'  { $$ =  NewFEarray($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }

;

/* <<fespace>> */

fespace123: FESPACE { fespacedim=2} |FESPACE1 { fespacedim=1} | FESPACE3 { fespacedim=3};
fespace:  fespace123 {fespacecomplex=false;  fespacetype = Find($1);}
        | fespace123 '<' TYPE '>' {
             if ($3 != typevarreal && $3 != typevarcomplex) lgerror (" type of finite element <real> or <complex>");
             fespacecomplex=($3==typevarcomplex);
             fespacetype = Find($1);}
;        
spaceIDa  :      ID_array_space {  $$ = $1  } 
            |    spaceIDa ',' ID_array_space { $$=C_F0($1,$3);} ;
            
spaceIDb  :      ID_space {  $$ = $1  } 
            |    spaceIDb ',' ID_space { $$=C_F0($1,$3);} ;

spaceIDs :    fespace               spaceIDb    { $$=0;  $$ = $2} 
           |  fespace '[' TYPE ']'  spaceIDa    { $$=0;  $$ = $5}
;

/* <<fespace_def>> */

fespace_def:
   ID '(' parameters_list ')'  {$$=currentblock->NewVar<LocalVariableFES,size_t>($1,typeFESpace($3),$3,dimFESpaceImage($3));
     $3.destroy(); };
     
fespace_def_list:  fespace_def
                 | fespace_def_list ',' fespace_def {$$=C_F0($1,$3)}
;
    
/* <<declaration>> */

declaration:   type_of_dcl {dcltype=$1} list_of_dcls ';' {$$=$3} /* see [[list_of_dcls]] */
             | FESPACEID  fespace_def_list    ';' {$$=$2}  
             | spaceIDs ';'{ $$=$1} 
             | FUNCTION ID '=' Expr ';' {$$=currentblock->NewID($1,$2,$4);} 
             | FUNCTION type_of_dcl ID  '(' list_of_id_args ')' 
                   {   /* use the stack to store the prev return type*/
                      assert(kkembtype+1<nbembtype);
                      rettype[++kkembtype] = $2->right();
                      routineinblock[kkembtype] = currentblock;
                      $<routine>5=new Routine($1,$2->right(),$3,$5,currentblock);
		      // routineinblock[kkembtype]->Add($3,"(",$<routine>5); //pas recursif pour l'instanat test  FH 27 dec 2008
                     // cout << " \n after new routine \n " << endl;                      
                      }
                    '{' instructions'}' 
                     { currentblock=$<routine>5->Set($9);
                       currentblock->Add($3,"(",$<routine>5); //pas recursif pour l'instant test  FH 27 dec 2008
                       kkembtype--;
                       $$=0;
                    
                        }
             | FUNCTION ID '(' list_of_id_args ')' 
                      {Block::open(currentblock); $1->SetArgs($4);}
                   '='   no_comma_expr  ';' 
                      {  $<cinst>$=currentblock->close(currentblock);
                         $$=currentblock->NewID($1,$2,$8,*$4);
                         delete $4; //  FH 23032005
                         } 
;              

begin: '{'  {  Block::open(currentblock)};
end:   '}'  {  $$=currentblock->close(currentblock)};

for_loop:  FOR {ffassert(inloopcount<sizeStackOfLoop);  // modif FH july 2005
                StackOfLoop[inloopcount++]=currentblock;};
while_loop:  WHILE {ffassert(inloopcount<sizeStackOfLoop);
                StackOfLoop[inloopcount++]=currentblock;}; // modif FH july 2005
                

declaration_for: 
    type_of_dcl {dcltype=$1; Block::open(currentblock);  }
               list_of_dcls {$$=$3};

try: TRY { Block::open(currentblock) };

/* <<instruction>> */

instruction:   ';' {$$=0;} 
         | INCLUDE  STRING  {zzzfff->input($2);$$= 0; }
         | LOAD  STRING  {load($2);$$= 0; }
         |  try  '{' instructions '}' catchs {$$=Try($3,$5,currentblock->close(currentblock));}
         |  Expr  ';' {$$=$1}  
         |  declaration  {$$=$1} 
         |  for_loop  '(' Expr ';' Expr ';' Expr ')' instruction {inloopcount--; $$=For($3,$5,$7,$9)} 
         |  for_loop  '(' declaration_for ';' Expr ';' Expr ')' instruction 
                {inloopcount--; 
                $$=C_F0(For($3,$5,$7,$9),currentblock->close(currentblock))}
                 
         |  while_loop '(' Expr ')' instruction {inloopcount--;$$=While($3,$5)}
         |  IF '(' Expr ')'   instruction  {$$=FIf($3,$5)}
         |  IF '(' Expr ')'   instruction  ELSE instruction {$$=FIf($3,$5,$7)}
         |  begin  instructions end { 
                      $$=C_F0(new E_block($2,$3),atype<void>()) }
         |  BORDER  ID   border_expr { /* <<BORDER_ID>> */
                      $$=0;currentblock->NewID(atype<const E_Border *>(),$2,C_F0(TheOperators,"[border]",$3))} 
         |  BORDER  ID   '['  array ']' ';' {
                      $$=0;currentblock->NewID(atype<const E_Border *>(),$2,C_F0(TheOperators,"[border]",$4))} 
                               
         |  BREAK ';' {
                    if(inloopcount) 
                      $$= C_F0(new E_throw(E_exception::e_break),atype<void>()); 
                    else lgerror("break not in loop") }
         |  CONTINUE ';' { 
                    if(inloopcount)
                        $$= C_F0(new E_throw(E_exception::e_continue),atype<void>()) ;
                    else lgerror("continue not in loop")}
         |  RETURN  Expr ';' { 
                    if (kkembtype>=0)
                      $$= C_F0(new E_throw(E_exception::e_return,(rettype[kkembtype]->CastTo($2)).OnReturn()) ,atype<void>());
                     else lgerror(" return not in routine ") }

;
catchs:  
  CATCH '(' '.' '.' '.'  ')' instruction {$$ =  $7; }
;

bornes: '(' ID '=' Expr ',' Expr ')' { 
   Block::open(currentblock);
   $$ = currentblock->NewVar<LocalVariable>($2,atype<double*>());
   $$+= $4;
   $$+= $6 }
;

/* <<border_expr>> */

border_expr:   bornes instruction {   
   $$ = ($1 += $2);
   currentblock->close(currentblock)} 
 ;

Expr:	 
         no_comma_expr 
       | Expr ',' Expr {$$=C_F0(TheOperators,$2,$1,$3);}
;

	
unop:
	  '-' 
	| '+' 
	| '!' 
	| PLUSPLUS 
	| MOINSMOINS 
;

no_comma_expr:
      no_set_expr 
	| no_set_expr '=' no_comma_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_set_expr PLUSEQ no_comma_expr {$$=C_F0(TheOperators,"+=",$1,$3)}
	| no_set_expr MOINSEQ no_comma_expr {$$=C_F0(TheOperators,"-=",$1,$3)}
	| no_set_expr MULEQ no_comma_expr {$$=C_F0(TheOperators,"*=",$1,$3)}
	| no_set_expr DIVEQ no_comma_expr {$$=C_F0(TheOperators,"/=",$1,$3)}
	| no_set_expr DOTMULEQ no_comma_expr {$$=C_F0(TheOperators,".*=",$1,$3)}
	| no_set_expr DOTDIVEQ no_comma_expr {$$=C_F0(TheOperators,"./=",$1,$3)}
;


no_set_expr:
	no_ternary_expr
	| no_ternary_expr '?' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"?:",$1,$3,$5)}
        | no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"::",$1,$3)}
	| no_ternary_expr ':' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"::",$1,$3,$5)} 	
			    
;
no_ternary_expr:
	  unary_expr 
	| no_ternary_expr '*' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr DOTSTAR no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr DOTSLASH no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '/' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '%' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '+' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '-' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr LTLT no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr GTGT no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '&' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr AND no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '|' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr OR no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '<' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr LE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr '>' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr GE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr EQ no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	| no_ternary_expr NE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
	
;

sub_script_expr:  
	    no_ternary_expr {$$=$1} 
    |   ':' {$$=C_F0(TheOperators,":")}			    
    |   no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,":",$1,$3)}
    |   no_ternary_expr ':' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,":",$1,$3,$5)} 

;
  
parameters:  {$$=0} 
	|   FESPACE {$$=Find($1)} 
	|   FESPACE1 {$$=Find($1)} 
	|   FESPACE3 {$$=Find($1)} 
	|  id '=' no_set_expr { $$=make_pair<const char *,const C_F0>($1,$3)} 	
	|   sub_script_expr {$$=$1} 
	| parameters ',' FESPACE { $$ = ($1 += Find($3)) }
	| parameters ',' FESPACE1 { $$ = ($1 += Find($3)) }
	| parameters ',' FESPACE3 { $$ = ($1 += Find($3)) }
	| parameters ',' sub_script_expr { $$ = ($1 += $3) }
	| parameters ',' id '=' no_set_expr { $$= ($1+= make_pair<const char *,const C_F0>($3,$5)) } 
; 

array:   no_comma_expr {$$=$1} 
       | array ',' no_comma_expr {$$ = ($1 += $3) };
     
    
unary_expr:
    pow_expr   
  | unop  pow_expr %prec UNARY {$$=C_F0(TheOperators,$1,$2)} 
;   

pow_expr: primary
  |      primary  '^' unary_expr   {$$=C_F0(TheOperators,$2,$1,$3)} 
  |      primary  '_' unary_expr   {$$=C_F0(TheOperators,$2,$1,$3)} 
  |      primary '\''              {$$=C_F0(TheOperators,$2,$1)} 
;

primary:  
           ID           {$$=Find($1);}
  |        LNUM         {$$= CConstant($1)}
  |        DNUM         {$$= CConstant($1)}
  |        CNUM         {$$= CConstant(complex<double>(0,$1))}
  |        STRING {$$= CConstant<const char *>($1)}
  |        primary '('  parameters ')'  {$$=C_F0($1,$2,$3);}
  |        primary '[' sub_script_expr ']'    {$$=C_F0($1,$2,$3)}
  |        primary '[' sub_script_expr ',' sub_script_expr ']'  {$$=C_F0($1,$2,$3,$5)}
  |        primary '['  ']'        {$$=C_F0($1,"[]")}
  |        primary '.'  ID       { $$=C_F0($1,$3) ;}
  |        FESPACE '.'  ID       { $$=C_F0(Find($1),$3) ;}
  |        FESPACE '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
  |        FESPACE1 '.'  ID       { $$=C_F0(Find($1),$3) ;}
  |        FESPACE1 '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
  |        FESPACE3 '.'  ID       { $$=C_F0(Find($1),$3) ;}
  |        FESPACE3 '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
  |        primary PLUSPLUS      {$$=C_F0(TheRightOperators,$2,$1)} 
  |        primary MOINSMOINS    {$$=C_F0(TheRightOperators,$2,$1)} 
  |        TYPE '('  Expr ')' {
             if ($1->right()->CastingFrom($3.left()) ) 
                $$=$1->right()->CastTo($3)  ;
             else { $$=$1->right()->Find("<--",basicAC_F0_wa($3));
             if (!$$.left()) { cerr << " no wait to change " << $3.left()->right()->name() << " in " << 
                                        $1->right()->name() << endl;
                                CompileError(" Error in type(exp) "); }
             }
            }
  |        '(' Expr ')' {$$=$2}
  |        '[' array  ']' { $$=C_F0(TheOperators,"[]",$2)} 

;


%% 


#include <fstream>
using namespace std;
// bool lgdebug;
// bool lexdebug;
void ForDebug();
void ForDebug()
{
  int i=0;
  i++;
}
//extern void ShowAlloc(const char *s, size_t lg);
//extern void ShowNbAlloc(const char *s);
void init_lgfem() ;
void init_lgmesh() ;
void init_lgmesh3() ;
void init_algo();
bool withrgraphique = false;
//string  StrVersionNumber();

/// Called by mainff() and activates the bison parser by calling yyparse()
int Compile()
{
  extern   YYSTYPE *plglval;  // modif FH 
  plglval = &lglval;
  int retvalue=0;
  //  int ok;
  
  currentblock=0;
  Block::open(currentblock);  
  try {
    UnShowAlloc =0;
    retvalue=yyparse (); //  compile
    
    if    (retvalue==0)  
      {
	if(currentblock) 
	  {
	    retvalue=1;
	    if(!mpirank) cerr <<  "Error:a block is not close" << endl; 
	  }     
	else {
	  if( verbosity  ) 
	    { 
	      UnShowAlloc =1;
	      cerr << " CodeAlloc : nb ptr  "<< CodeAlloc::nb << ",  size :"  <<  CodeAlloc::lg 
		   << " mpirank: " <<mpirank << endl    ;
	      if(!mpirank) cerr <<  "Bien: On a fini Normalement" << endl; 
	    }
	}
      }
  }

  catch (Error & e) 
    {
      retvalue=e.errcode();
      if(mpirank ==0)
	cerr << "error " << e.what() 
	     << "\n code = "<<  retvalue << " mpirank: " <<mpirank  << endl;
    }
  catch(std::ios_base::failure & e)
    {
      cerr << "std  catch io failure \n what : " << e.what() << endl;; 
      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank  << endl; 
    }
  catch(std::exception & e)
    {
      cerr << "std  catch exception \n what : " << e.what() << endl;; 
      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank  << endl; 
      
    }
  catch(...)
    {
      cerr << "Strange catch exception ???\n"; 
      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank << endl; 
    }
  return retvalue; 
}
static void SetcppIo()
{

#ifdef _WIN32XXXX
  freopen("conin$", "r", stdin);
  freopen("conout$", "w", stdout);
  using namespace __gnu_cxx;
  //  stdio_filebuf<char> * ccout = new stdio_filebuf<char>(stdout, std::ios_base::out);
  static  stdio_filebuf<char> ccout(stdout, std::ios_base::out);
  static  stdio_filebuf<char> ccin(stdin, std::ios_base::in);
   //stdio_filebuf<char> *ccin= new stdio_filebuf<char>(stdin, std::ios_base::in);
   
   cout.rdbuf(&ccout);
   cin.rdbuf(&ccin);
   cerr.rdbuf(&ccout);
   cout << " -- SetcppIo --" << endl; 
#endif
   ios::sync_with_stdio();
}

// pour l'environement.
extern const char *  prognamearg;
extern  bool echo_edp;

/// Called by mymain() and calls Compile() to run the FF language parser
int mainff (int  argc, char **argv)
{
    
   ffapi::init(); 
  if(argc)  
    prognamearg=argv[0];

    int vvold=verbosity; 
    if(mpirank !=0) verbosity=0;

  // ALH - 14/10/8 - This breaks FFCS output redirection
#ifndef ENABLE_FFCS
  SetcppIo();
#endif

  GetEnvironment();   
    vvold=verbosity; 
    if(mpirank !=0) verbosity=0; 
  //  size_t lg000;
 // ShowAlloc("begin main ",lg000);
  int retvalue=0;

   if (initparallele)initparallele(argc,argv);

  CPUcompileInit= CPUtime();
  withrgraphique = false;
   atexit(ForDebug);
//  AllFunctions::maptype  xlocal;
//  local=&xlocal;
  lexdebug = false;
  lgdebug = false;

  char *  cc= new char [1024];
  //  istream * ccin=0;
  if ( ! (getprog(cc,argc,argv) >0)  ) 
    {
      cout << "-- FreeFem++ v" << StrVersionNumber() << " (error parameter!)\n"  ;
      if(ThePlotStream) {pclose(ThePlotStream); ThePlotStream=0;}  
      return 1; 
    }
   
  if(verbosity && (mpirank==0)) { 
      cout << "-- FreeFem++ v" << StrVersionNumber() << endl;
      if(verbosity>1) cout << "   file :" << cc << " " << " verbosity= " << verbosity << endl;
  }
    
    KN<String> karg(argc);
    for(int i=0;i< argc;++i)
	karg[i]=argv[i];
    pkarg= &karg;

  zzzfff = Newlex(cout,echo_edp);
  
  
/*  
  ccin= new ifstream(cc);
  if (argc >1 && (ccin!=0) )  
     ccin= new ifstream(argv[1]),throwassert(ccin);
  if (ccin!=0) 
    zzzfff = new  mylex(*ccin,cout) ;
  else 
    zzzfff = new  mylex(cin,cout) ;
*/    
//  les motsclefs    
   zzzfff->Add("include",INCLUDE);
   zzzfff->Add("load",LOAD);
   zzzfff->Add("while",WHILE);
   zzzfff->Add("for",FOR);
   zzzfff->Add("if",IF);
   zzzfff->Add("else",ELSE);
   zzzfff->Add("end",ENDOFFILE);
   zzzfff->Add("break",BREAK);
   zzzfff->Add("continue",CONTINUE);
   zzzfff->Add("return",RETURN);
   zzzfff->Add("border",BORDER);
   zzzfff->Add("fespace",FESPACEID);
   zzzfff->Add("try",TRY);
   zzzfff->Add("catch",CATCH);
   zzzfff->Add("throw",THROW);
//   Init_map_type();
   if(verbosity>2 || (mpirank==0 ) ) cout << " Load: ";
   callInitsFunct() ; //  init for dynamique libs ...
  // init_lgfem() ;
   init_lgmesh() ;
   init_lgmesh3() ;
   init_algo();

#ifdef HAVE_LIBARPACK
   init_eigenvalue();
#endif   

   if(init_lgparallele)  init_lgparallele(); 
  //  callInitsFunct() ; //  init for dynamique libs ...

   if(verbosity>2 || mpirank==0)  cout << endl;
  zzzfff->input(cc);
  EnvironmentLoad(); // just before compile
  verbosity=vvold; 
    
  retvalue= Compile();
   // cout << " xxxxx " <<  retvalue << " " << ThePlotStream << endl;

  if(end_parallele) end_parallele();

  //  currentblock->close(currentblock).eval(thestack);
  fingraphique();
  // FFCS: divert stream to FFCS
  if(ThePlotStream){
    ffapi::ff_pclose(ThePlotStream);
    ThePlotStream=0;
  }
  Destroylex( zzzfff);
  
   // ClearMem();
  return retvalue;
}

/* FFCS: emacs configuration for this file */
 
/*!
 * Local Variables:
 * mode:antlr
 * ispell-local-dictionary:"british"
 * coding:utf-8
 * End:
 */
