#include "analyseur_syntaxyque.h"

int uniteCourante;
int afficheSyntaxyque = 0;
extern char yytext[100];
extern int nb_ligne;

void openSection( const char * section ) {
  affiche_balise_ouvrante( section, afficheSyntaxyque );
}

void closeSection( const char * section ) {
  affiche_balise_fermante( section, afficheSyntaxyque );
}

void elementConsome () {
	char token[128];
	char nom[128];
	nom_token( uniteCourante, nom, token );
	affiche_element(nom, token, afficheSyntaxyque);
}

void syntaxError()
{
  char token[128];
  char nom[128];
  nom_token( uniteCourante, nom, token );
  fprintf( stderr, "Erreur de syntax, proche de la ligne %d, et de l'unite courante '%s' (%d - %s)\n", nb_ligne, token, uniteCourante, nom );

  exit( 1 );
}

void syntaxErrorMsg( const char * msg )
{
  char token[128];
  char nom[128];
  nom_token( uniteCourante, nom, token );
  fprintf( stderr, "Erreur de syntax, proche de la ligne %d, et de l'unite courante '%s' (%d - %s)\n", nb_ligne, token, uniteCourante, nom );
  fprintf( stderr, "%s\n", msg );

  exit( 1 );
}

n_prog *programme() {
	openSection( __func__ );

	n_l_dec *herite_var = NULL;
	n_l_dec *herite_func = NULL;
	n_prog *sreturn = NULL;

	if( !est_premier( _optDecVariables_, uniteCourante ) 
		&& !est_premier( _listeDecFonctions_, uniteCourante ) 
		&& !est_suivant( _listeDecFonctions_, uniteCourante )) {
		syntaxError();
	} else {
		herite_var = optDecVariables();
		herite_func = listeDecFonctions();
	}

	closeSection( __func__ );
	sreturn = cree_n_prog(herite_var, herite_func);
	return sreturn;
}

n_l_dec *optDecVariables() {
	n_l_dec *sreturn = NULL;
	
	openSection( __func__ );
	
	if( est_premier( _listeDecVariables_, uniteCourante ) )
	{
		sreturn = listeDecVariables();

		if( uniteCourante == POINT_VIRGULE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "';' été attendu" );
		}
	} else if ( !est_suivant( _optDecVariables_, uniteCourante ) ) {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_l_dec *listeDecVariables() {
	openSection( __func__ );
	n_dec *herite_var = NULL;
	n_l_dec *herite_Liste_var = NULL;
	n_l_dec *sreturn = NULL;
	if( est_premier( _declarationVariable_, uniteCourante ) ) {
		herite_var = declarationVariable();
		herite_Liste_var = listeDecVariablesBis();
	} else {
		syntaxError();
	}
	closeSection( __func__ );
	sreturn = cree_n_l_dec(herite_var, herite_Liste_var);
	return sreturn;
}

n_l_dec *listeDecVariablesBis() {
	openSection( __func__ );
	n_dec *herite_dec_var = NULL;
	n_l_dec *herite_liste_var = NULL;
	n_l_dec *sreturn = NULL;
	if( uniteCourante == VIRGULE ) {
		elementConsome();
		uniteCourante = yylex();

		herite_dec_var = declarationVariable();
		herite_liste_var = listeDecVariablesBis();
		sreturn = cree_n_l_dec(herite_dec_var, herite_liste_var);
	} else if( !est_suivant( _listeDecVariablesBis_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_dec *declarationVariable() {
	openSection( __func__ );
	
	char *name = NULL;
	n_dec *sreturn = NULL;
	int taille = 0;

	if( uniteCourante == ENTIER ) {
		elementConsome();
		uniteCourante = yylex();

		if( uniteCourante == ID_VAR ) {
			name = duplique_chaine(yytext);

			elementConsome();
			uniteCourante = yylex();
			taille = optTailleTableau();
			if (taille == 0){
				
				sreturn = cree_n_dec_var(name);
			} 
			else 
				sreturn = cree_n_dec_tab(name, taille);

		} else {
			syntaxErrorMsg( "Un identificateur de variable été attendu" );
		}
	} else {
		syntaxErrorMsg( "'ENTIER' été attendu" );
	}

	closeSection( __func__ );
	return sreturn;
}

int optTailleTableau() {
	openSection( __func__ );
	int taille = 0;
	if( uniteCourante == CROCHET_OUVRANT ) {
		elementConsome();
		uniteCourante = yylex();

		if( uniteCourante == NOMBRE ) {
			elementConsome();
			taille = atoi(yytext);		
			uniteCourante = yylex();

			if( uniteCourante == CROCHET_FERMANT ) {
				elementConsome();
				uniteCourante = yylex();
			} else {
				syntaxErrorMsg( "']' été attendu" );
			}
		} else {
			syntaxErrorMsg( "Un nombre été attendu" );
		}
	} else if( !est_suivant( _optTailleTableau_, uniteCourante ) )
	{
		syntaxError();
	}

	closeSection( __func__ );
	return taille;
}

n_l_dec *listeDecFonctions() {
	openSection( __func__ );
	n_dec *herite_dec = NULL;
	n_l_dec *herite_Liste_dec = NULL;
	n_l_dec *sreturn = NULL;
	if( est_premier( _declarationFonction_, uniteCourante ) || est_premier( _listeDecFonctions_, uniteCourante ) ) {
		herite_dec = declarationFonction();
		herite_Liste_dec =listeDecFonctions();
		sreturn = cree_n_l_dec (herite_dec, herite_Liste_dec);
	} else if( !est_suivant( _listeDecFonctions_, uniteCourante ) ) {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_dec * declarationFonction() {
	openSection( __func__ );
	char *name;
	n_l_dec *param = NULL;
	n_l_dec *variables = NULL;
	n_instr *corps = NULL;
	n_dec *sreturn = NULL;
	if( uniteCourante == ID_FCT ) {
		name = duplique_chaine(yytext);
		elementConsome();
		uniteCourante = yylex();

		param = listeParam();
		variables = optDecVariables();
		corps = instructionBloc();
		
	} else {
		syntaxErrorMsg( "Un identificateur de fonction été attendu" );
	}

	closeSection( __func__ );

	sreturn = cree_n_dec_fonc(name,param,variables,corps);
	return sreturn;
}

n_l_dec *listeParam() {
	openSection( __func__ );
	n_l_dec *sreturn = NULL;
	if( uniteCourante == PARENTHESE_OUVRANTE ) {
		elementConsome();
		uniteCourante = yylex();

		sreturn = optListeDecVariables();

		if( uniteCourante == PARENTHESE_FERMANTE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "')' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'(' été attendu" );
	}

	closeSection( __func__ );
	return sreturn;
}

n_l_dec *optListeDecVariables() {
	openSection( __func__ );
	n_l_dec *sreturn = NULL;
	if( est_premier( _listeDecVariables_, uniteCourante ) ) {
		sreturn = listeDecVariables();
	} else if( !est_suivant( _optListeDecVariables_, uniteCourante ) ) {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_instr *instruction() {
	openSection( __func__ );
	n_instr *sreturn = NULL;

	if( est_premier( _instructionAffect_, uniteCourante ) ) {
		sreturn = instructionAffect();
	} else if( est_premier( _instructionBloc_, uniteCourante ) ) {
		sreturn = instructionBloc();
	} else if( est_premier( _instructionSi_, uniteCourante ) ) {
		sreturn = instructionSi();
	} else if( est_premier( _instructionTantque_, uniteCourante ) ) {
		sreturn = instructionTantque();
	} else if( est_premier( _instructionAppel_, uniteCourante ) ) {
		sreturn = instructionAppel();
	} else if( est_premier( _instructionRetour_, uniteCourante ) ) {
		sreturn = instructionRetour();
	} else if( est_premier( _instructionEcriture_, uniteCourante ) ) {
		sreturn = instructionEcriture();
	} else if( est_premier( _instructionPour_, uniteCourante ) ) {
		sreturn = instructionPour();
	} else if( est_premier( _instructionVide_, uniteCourante ) ) {
		sreturn = instructionVide();
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionAffect() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_var *herite_var = NULL;
	n_exp *herite_exp = NULL;
	if( est_premier( _var_, uniteCourante ) ) {
		
		herite_var = var();

		if( uniteCourante == EGAL ) {
			elementConsome();
			uniteCourante = yylex();

			herite_exp = expression();

			if( uniteCourante == POINT_VIRGULE ) {
				elementConsome();
				uniteCourante = yylex();
			} else {
				syntaxErrorMsg( "';' été attendu" );
			}
		} else {
			syntaxErrorMsg( "'=' été attendu" );
		}
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	sreturn = cree_n_instr_affect(herite_var, herite_exp);
	return sreturn;

}

n_instr *instructionBloc() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_l_instr *herite_list_inst = NULL;

	if( uniteCourante == ACCOLADE_OUVRANTE ) {
		elementConsome();
		uniteCourante = yylex();

		herite_list_inst = listeInstructions();

		if( uniteCourante == ACCOLADE_FERMANTE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "'}' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'{' été attendu" );
	}

	closeSection( __func__ );
	sreturn = cree_n_instr_bloc(herite_list_inst);
	return sreturn;
}

n_l_instr *listeInstructions() {
	openSection( __func__ );
	n_instr *instru = NULL;
	n_l_instr *listeInstru = NULL;
	n_l_instr *sreturn = NULL;
	if( est_premier( _instruction_, uniteCourante ) || est_premier( _listeInstructions_, uniteCourante ) ) {
		instru = instruction();
		listeInstru = listeInstructions();
		sreturn = cree_n_l_instr(instru, listeInstru);
	} else if( !est_suivant( _listeInstructions_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionSi() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_exp *test = NULL;
	n_instr *alors = NULL;
	n_instr *sinon = NULL;
	if( uniteCourante == SI ) {
		elementConsome();
		uniteCourante = yylex();

		test = expression();

		if( uniteCourante == ALORS ) {
			elementConsome();
			uniteCourante = yylex();

			alors = instructionBloc();
			sinon = optSinon();
		} else {
			syntaxErrorMsg( "'alors' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'si' été attendu" );
	}

	closeSection( __func__ );
	sreturn = cree_n_instr_si(test, alors, sinon);
	return sreturn;
}

n_instr *optSinon() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	if( uniteCourante == SINON ) {
		elementConsome();
		uniteCourante = yylex();

		sreturn = instructionBloc();
	} else if( !est_suivant( _optSinon_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionTantque() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_exp *test = NULL;
	n_instr *faire = NULL;

	if( uniteCourante == TANTQUE ) {
		elementConsome();
		uniteCourante = yylex();

		test = expression();

		if( uniteCourante == FAIRE ) {
			elementConsome();
			uniteCourante = yylex();

			faire =instructionBloc();
		} else {
			syntaxErrorMsg( "'faire' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'tantque' été attendu" );
	}

	sreturn = cree_n_instr_tantque(test, faire);
	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionAppel() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_appel *app = NULL;
	if( est_premier( _instructionAppel_, uniteCourante ) ) {
		app = appelFct();

		if( uniteCourante == POINT_VIRGULE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "';' été attendu" );
		}
	} else {
		syntaxError();
	}

	sreturn = cree_n_instr_appel(app);
	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionRetour() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_exp *expr = NULL;

	if( uniteCourante == RETOUR ) {
		elementConsome();
		uniteCourante = yylex();

		expr = expression();

		if( uniteCourante == POINT_VIRGULE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "';' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'retour' été attendu" );
	}
	sreturn = cree_n_instr_retour(expr);

	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionEcriture() {
	openSection( __func__ );
	n_instr *sreturn = NULL;
	n_exp *expr = NULL;
	if( uniteCourante == ECRIRE ) {
		elementConsome();
		uniteCourante = yylex();

		if( uniteCourante == PARENTHESE_OUVRANTE ) {
			elementConsome();
			uniteCourante = yylex();

			expr = expression();

			if( uniteCourante == PARENTHESE_FERMANTE ) {
				elementConsome();
				uniteCourante = yylex();

				if( uniteCourante == POINT_VIRGULE ) {
					elementConsome();
					uniteCourante = yylex();
				} else {
					syntaxErrorMsg( "';' été attendu" );
				}
			} else {
				syntaxErrorMsg( "')' été attendu" );
			}
		} else {
			syntaxErrorMsg( "'(' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'ecrire' été attendu" );
	}
	closeSection( __func__ );
	sreturn = cree_n_instr_ecrire(expr);
	return sreturn;
}

n_instr *instructionPour() {
	openSection( __func__ );
	n_instr *init = NULL;
	n_exp *test = NULL; 
	n_instr *incr = NULL;
	n_instr *faire = NULL;
	n_instr *sreturn = NULL;

	if( uniteCourante == POUR ) {
		elementConsome();
		uniteCourante = yylex();

		init = instructionAffect();
		test = expression();

		if( uniteCourante == POINT_VIRGULE ) {
			elementConsome();
			uniteCourante = yylex();

			incr = instructionAffect();

			if( uniteCourante == FAIRE ) {
				elementConsome();
				uniteCourante = yylex();

				faire = instructionBloc();

			} else {
				syntaxErrorMsg( "'faire' été attendu" );
			}

		} else {
			syntaxErrorMsg( "';' été attendu" );
		}
	} else {
		syntaxErrorMsg( "'pour' été attendu" );
	}

	sreturn = cree_n_instr_pour(init,test,incr,faire);
	closeSection( __func__ );
	return sreturn;
}

n_instr *instructionVide() {
	openSection( __func__ );

	n_instr * sreturn = NULL;
	if( uniteCourante == POINT_VIRGULE ) {
		elementConsome();
		uniteCourante = yylex();
	} else {
		syntaxErrorMsg( "';' été attendu" );
	}
	sreturn = cree_n_instr_vide();
	closeSection( __func__ );
	return sreturn;
}

n_exp *expression() {
	openSection( __func__ );
	n_exp *herite_conj = NULL;
    n_exp *sreturn = NULL;
	if( est_premier( _condition_, uniteCourante ) ) {
		herite_conj = condition();
		sreturn = expressionBis(herite_conj);
	} else {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_exp *expressionBis(n_exp *herite) {
	openSection( __func__ );
	n_exp *expression1 = NULL;
	n_exp *expression2 = NULL;
    n_exp *sreturn = herite;
	
	if( uniteCourante == INTERROGATION ) {
		elementConsome();
		uniteCourante = yylex();

		expression1 = expression();

		if( uniteCourante == DEUXPOINTS ) {
			elementConsome();
			uniteCourante = yylex();

			expression2 = expression();

			sreturn = cree_n_exp_op(cond, herite, expression1, expression2);
		} else {
			syntaxErrorMsg( "':' été attendu" );
		}
		
	} else if( !est_suivant( _expressionBis_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *condition() {
	openSection( __func__ );
	n_exp *herite_conj = NULL;
    n_exp *sreturn = NULL;
	if( est_premier( _conjonction_, uniteCourante ) ) {
		herite_conj = conjonction();
		sreturn = conditionBis(herite_conj);
	} else {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_exp *conditionBis(n_exp *herite) {
	openSection( __func__ );
	n_exp *conj = NULL;
    n_exp *sreturn = herite;
	
	if( uniteCourante == OU ) {
		elementConsome();
		uniteCourante = yylex();

		conj = conjonction();
		herite = cree_n_exp_op(ou, herite,conj, NULL);
		sreturn = conditionBis(herite);
	} else if( !est_suivant( _conditionBis_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *conjonction() {
	n_exp *sreturn = NULL;
	n_exp *herite_neg = NULL;
	openSection( __func__ );

	if( est_premier( _negation_, uniteCourante ) ) {
		herite_neg = negation();
		sreturn = conjonctionBis(herite_neg);
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *conjonctionBis(n_exp *herite) {
	openSection( __func__ );
	n_exp *sreturn = herite;
	n_exp *herite_neg = NULL;
	if( uniteCourante == ET ) {
		elementConsome();
		uniteCourante = yylex();
		herite_neg = negation();
		herite_neg = cree_n_exp_op(et, herite, herite_neg, NULL);
		sreturn = conjonctionBis(herite_neg);
	} else if( !est_suivant( _conjonctionBis_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *negation() {
	n_exp *sreturn = NULL;
	n_exp *expression = NULL;
	openSection( __func__ );

	if( uniteCourante == NON ) {
		elementConsome();
		uniteCourante = yylex();

		expression = comparaison();
		sreturn = cree_n_exp_op(non,expression,NULL, NULL);
	} else if (est_premier( _comparaison_, uniteCourante )) {
		sreturn  = comparaison();
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *comparaison() {
	openSection( __func__ );
	n_exp *sreturn = NULL;
	n_exp *herite_exp = NULL;
	if( est_premier( _expression_, uniteCourante ) ) {
		herite_exp = expArith();
		sreturn = comparaisonBis(herite_exp);
	} else {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_exp *comparaisonBis(n_exp *herite) {
	openSection( __func__ );
	n_exp *sreturn = herite;
	n_exp *herite_exp = NULL;
	if( uniteCourante == EGAL) {
		elementConsome();
		uniteCourante = yylex();

		herite_exp = expArith();
		herite_exp = cree_n_exp_op(egal,herite,herite_exp, NULL);
		sreturn = comparaisonBis(herite_exp);
	} else if( uniteCourante == INFERIEUR) {
		elementConsome();
		uniteCourante = yylex();

		herite_exp = expArith();
		herite_exp = cree_n_exp_op(inf,herite,herite_exp, NULL);
		sreturn = comparaisonBis(herite_exp);

	} else if( !est_suivant( _comparaisonBis_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *expArith()
{
	openSection( __func__ );

	n_exp *sreturn = NULL;
	n_exp *herite_fils = NULL;

	if( est_premier( _terme_, uniteCourante ) ) {
		herite_fils = terme();
		sreturn = expArithBis(herite_fils);
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *expArithBis(n_exp *herite) {
	openSection( __func__ );

	n_exp *s = NULL;
	n_exp *sreturn = NULL; 
	n_exp *herite_fils = NULL;

	if( uniteCourante == PLUS ) {
		elementConsome();
		uniteCourante = yylex();

		s = terme();
		herite_fils = cree_n_exp_op(plus, herite, s, NULL);
		sreturn = expArithBis(herite_fils);
	} else if( uniteCourante == MOINS) {
		elementConsome();
		uniteCourante = yylex();

		s = terme();
		herite_fils = cree_n_exp_op(moins, herite, s, NULL);
		sreturn = expArithBis(herite_fils);
	} else if( !est_suivant( _expArithBis_, uniteCourante ) ) {
		syntaxError();
	} else {
		sreturn = herite;
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *terme() {
	openSection( __func__ );

	n_exp *sreturn = NULL;
	n_exp *herite_fils = NULL;

	if( est_premier( _facteur_, uniteCourante ) ) {
		herite_fils = facteur();
		sreturn = termeBis(herite_fils);
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *termeBis(n_exp *herite) {
	openSection( __func__ );

	n_exp *s = NULL;
	n_exp *sreturn = NULL;
	n_exp *herite_fils = NULL;

	if( uniteCourante == FOIS ) {
		elementConsome();
		uniteCourante = yylex();

		s = facteur();
		herite_fils = cree_n_exp_op(fois, herite, s, NULL);
		sreturn = termeBis(herite_fils);
	} else if( uniteCourante == DIVISE) {
		elementConsome();
		uniteCourante = yylex();

		s = facteur();
		herite_fils = cree_n_exp_op(divise, herite, s, NULL);
		sreturn = termeBis(herite_fils);
	} else if( !est_suivant( _termeBis_, uniteCourante ) ) {
		syntaxError();
	} else {
		sreturn = herite;
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *facteur() {
	openSection( __func__ );

	n_exp *sreturn = NULL;

	if( uniteCourante == PARENTHESE_OUVRANTE ) {
		elementConsome();
		uniteCourante = yylex();

		sreturn = expression();

		if( uniteCourante == PARENTHESE_FERMANTE ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "')' été attendu" );
		}
	} else if( uniteCourante == NOMBRE ) {
		sreturn = cree_n_exp_entier(atoi(yytext));
		elementConsome();
		uniteCourante = yylex();
	} else if( est_premier( _appelFct_, uniteCourante ) ) {
		sreturn = cree_n_exp_appel(appelFct());
	} else if( est_premier( _var_, uniteCourante ) ) {
		sreturn = cree_n_exp_var(var());
	} else if( uniteCourante == LIRE ) {
		elementConsome();
		uniteCourante = yylex();
		sreturn = cree_n_exp_lire();

		if( uniteCourante == PARENTHESE_OUVRANTE ) {
			elementConsome();
			uniteCourante = yylex();

			if( uniteCourante == PARENTHESE_FERMANTE ) {
				elementConsome();
				uniteCourante = yylex();
			} else {
				syntaxErrorMsg( "')' été attendu" );
			}
		} else {
			syntaxErrorMsg( "'(' été attendu" );
		}
	} else {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_var *var() {
	openSection( __func__ );
	n_var *sreturn = NULL;
	n_exp *indice = NULL;
	if( uniteCourante == ID_VAR ) {
		char *appelName;
		appelName = duplique_chaine(yytext);
		elementConsome();
		uniteCourante = yylex();
		indice = optIndice();
		if (indice == NULL) 
			sreturn = cree_n_var_simple(appelName);
		else 
			sreturn = cree_n_var_indicee(appelName,indice);
	} else {
		syntaxErrorMsg( "Indice de variable été attendu" );
	}

	closeSection( __func__ );
	return sreturn;
}

n_exp *optIndice() {
	openSection( __func__ );
	n_exp *sreturn = NULL;

	if( uniteCourante == CROCHET_OUVRANT ) {
		elementConsome();
		uniteCourante = yylex();

		sreturn = expression();

		if( uniteCourante == CROCHET_FERMANT ) {
			elementConsome();
			uniteCourante = yylex();
		} else {
			syntaxErrorMsg( "']' été attendu" );
		}
	} else if( !est_suivant( _optIndice_, uniteCourante ) ) {
		syntaxError();
	}

	closeSection( __func__ );
	return sreturn;
}

n_appel *appelFct() {
	openSection( __func__ );

	n_l_exp *herite_fils = NULL;
	n_appel *sreturn = NULL;

	if( uniteCourante == ID_FCT ) {
		char *appelName;
		appelName = duplique_chaine(yytext);
		elementConsome();
		uniteCourante = yylex();

		if( uniteCourante == PARENTHESE_OUVRANTE ) {
			elementConsome();
			uniteCourante = yylex();

			herite_fils = listeExpressions();
			sreturn = cree_n_appel(appelName, herite_fils);


			if( uniteCourante == PARENTHESE_FERMANTE ) {
				elementConsome();
				uniteCourante = yylex();
			} else {
				syntaxErrorMsg( "')' été attendu" );
			}
		} else {
			syntaxErrorMsg( "'(' été attendu" );
		}
	} else {
		syntaxErrorMsg( "Identificateur de fonction été attendu" );
	}

	closeSection( __func__ );
	return sreturn;
}

n_l_exp *listeExpressions() {
	openSection( __func__ );

	n_l_exp *sreturn = NULL;
    n_exp *herite_exp = NULL;
    n_l_exp *expression_liste = NULL;

	if( est_premier( _expression_, uniteCourante ) || est_premier( _listeExpressionsBis_, uniteCourante ) ) {
		herite_exp = expression();
		expression_liste = listeExpressionsBis();
		sreturn = cree_n_l_exp(herite_exp,expression_liste);
	} else if( !est_suivant( _listeExpressions_, uniteCourante ) ) {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}

n_l_exp *listeExpressionsBis() {
	openSection( __func__ );
	n_l_exp *sreturn = NULL;
	n_exp *herite_exp = NULL;
	n_l_exp *herite_l_exp = NULL;  
	if( uniteCourante == VIRGULE ) {
		elementConsome();
		uniteCourante = yylex();

		herite_exp = expression();
		herite_l_exp = listeExpressionsBis();
		sreturn = cree_n_l_exp(herite_exp,herite_l_exp);
	} else if( !est_suivant( _listeExpressionsBis_, uniteCourante ) ) {
		syntaxError();
	}
	closeSection( __func__ );
	return sreturn;
}