unit syntaxe;
(* Analyseur syntaxique de PetitBasic. *)

interface

type	TYPE_ERREUR_SYNTAXIQUE =

	(
		ANALYSEUR_SYNTAXIQUE_OKAY,

	(* erreurs d'ordres g‚n‚rals *)

		ERREUR_ANALYSEUR_LEXICAL,
		MANQUE_MEMOIRE,
		ERREUR_DE_SYNTAXE,		(* fourre tout *)

	(* erreurs de l'analyseur syntaxique d'expressions num‚riques *)

		ENTIER_TROP_GRAND,
		ATTEND_NUMERIQUE,
		ATTEND_PARENTHESE_DROITE,

	(* erreurs de l'analyseur syntaxique d'expressions chaines *)

		ATTEND_CHAINE,

	(* erreurs de l'analyseur syntaxique d'expressions logiques *)

		ATTEND_OPERATEUR_RELATIONNEL,
		ATTEND_CROCHET_DROIT,

	(* erreurs de l'analyseur syntaxique d'instructions *)

		INSTRUCTION_NUL,
		NUMERO_LIGNE_INCORRECT,
		ATTEND_THEN,
		ATTEND_NUMERO_LIGNE,
		ATTEND_VARIABLE_NUMERIQUE,
		ATTEND_EGAL,
		ATTEND_TO,
		ATTEND_VARIABLE,
		CARACTERE_EN_TROP
	);

var	erreur_syntaxique	: TYPE_ERREUR_SYNTAXIQUE;

procedure	initialise_analyseur_syntaxique (l : string);
procedure	termine_analyseur_syntaxique;
procedure 	explique_erreur_syntaxique;

implementation

uses lexical;

var     initialise	: boolean;
	ligne		: string;

procedure initialise_analyseur_syntaxique (l : string);
(* Pr‚pare l'analyseur syntaxique … une nouvelle ligne, et pr‚pare aussi l'
 * l'analyseur lexical, en cas d'erreur de ce dernier, la detection se fera
 * au premier appel de la fonction prend_instruction.
 *)

begin
	initialise := true;
	ligne := l;
	initialise_analyseur_lexical(l);
end;

procedure termine_analyseur_syntaxique;
(* Stoppe l'analyseur syntaxique. *)

begin
	if not initialise then begin
		writeln('Erreur Interne: ',
			'Analyseur syntaxique non initialis‚!');
		halt;
	end else begin
		initialise := false;
		ligne := '';
		termine_analyseur_lexical;
	end;
end;

procedure explique_erreur_syntaxique;
(* En cas d'erreur, ‚crit … l'‚cran une explication, la ligne en question, et
 * indique o— est l'erreur.  Cette proc‚dure doit ˆtre appel‚, dans son
 * contexte juste aprŠs l'erreur, en particulier l'analyseur lexical doit
 * rester dans l'‚tat o— il ‚tait lors de l'analyse syntaxique, puisque c'est
 * grace … celui-ci que l'on peut savoir exactement o— s'est pass‚ l'erreur.
 * De plus l'erreur peut aussi ˆtre du … l'analyseur lexical.
 *)

const	LISTE_EXPLICATIONS : array [2..18] of string =
	(
		'Pas assez de m‚moire pour l''analyseur syntaxique!',
		'Erreur de syntaxe!',

		'Entier trop grand (un entier est entre -32767 et 32767)!',
		'Attend une valeur num‚rique!',
		'ParenthŠse droite manquante!',

		'Attend une valeur chaine!',

		'Attend un op‚rateur relationnel',
		'Crochet droit manquant!',

		'Instruction nul, cela est ill‚gal!',
		'Num‚ro de ligne incorrect (doit ˆtre entre 0 et 65535)!',
		'Attend un then pour la construction if then else!',
		'Attend un num‚ro de ligne!',
		'Attend une variable num‚rique!',
		'Attend un op‚rateur ‚gal!',
		'Attend un to pour la construction for to!',
		'Attend une variable pour l''affectation!',
		'CaractŠre(s) en trop sur la ligne!'
	);

var	i	: integer;

begin
	if erreur_syntaxique = ERREUR_ANALYSEUR_LEXICAL then
		explique_erreur_lexicale
	else if erreur_syntaxique <> ANALYSEUR_SYNTAXIQUE_OKAY then begin
		write('Erreur Syntaxique: ');
		writeln(LISTE_EXPLICATIONS[ord(erreur_syntaxique)]);
		writeln(ligne);

		remet_lexeme;	(* fait pointer sur le d‚but de l'erreur *)

		for i := 1 to lit_index - 1 do
			write(' ');

		writeln('^');
	end;
end;

begin
	initialise := false;
end.

