unit lexical;
(* Analyseur lexical de PetitBasic. *)

(* Liste des lexŠmes reconnus par l'analyseur lexical.
 *
 *	Identificateurs.
 *
 *
 *
 *		entier:	(a..z | A..Z)(a..z | A..Z | 0..9)*%
 *
 *		r‚el:   (a..z | A..Z)(a..z | A..Z | 0..9)*
 *			(a..z | A..Z)(a..z | A..Z | 0..9)*!
 *
 *		chaine:	(a..z | A..Z)(a..z | A..Z | 0..9)*$
 *
 *	Literaux.
 *
 *		entier:	0 | (1..9)(0..9)*
 *
 *		r‚el:	0 | (1..9)(0..9)*.(0..9)+[e | E [+ | -] (0..9)+]
 *
 *		chaine:	"({tous caractŠres ASCII sauf guillemet} | "")*"
 *
 *	Op‚rateurs.
 *
 *		binaire	num‚rique:	* | / |	mod | +	| -
 *
 *		unaire num‚rique:  	+ | -
 *
 *		binaire	chaine:		+
 *
 *		relationnel:		< | <= | > | >=	| = | <>
 *
 *		binaire	logique:	and | or | xor
 *
 *		unaire logique:		not
 *
 *	S‚parateurs:
 *
 *		( | ) |	[ | ]
 *
 *	Commentaires:	'
 *
 *	Mots cl‚s:
 *
 *		if | then | else
 *		gosub |	return
 *		while |	wend
 *		for | to | next
 *		goto
 *		let
 *		end
 *		rem
 *		input |	print
 *
 *	Commandes:
 *
 *		list
 *		new | run
 *		load | save
 *		system
 *
 * En plus de ces lexŠmes, trois sortes	de pseudo-lexŠmes sont d‚finis:
 * FIN_DE_LIGNE, ERREUR, et PAS_TROUVE.	 FIN_DE_LIGNE indique que l'on est
 * arriv‚ en fin de ligne.  ERREUR indique une erreur, il faut consulter la
 * variable globale erreur_lexicale pour plus d'information, celle-ci est
 * initialis‚ par chaque appel … prend_lexeme.	Et enfin PAS_TROUVE est
 * utilis‚ de fa‡on interne pour la recherche de mots r‚serv‚s,	et n'est donc
 * de ce fait jamais renvoy‚ par prend_lexeme.
 *)

interface

type	TYPE_LEXEMES = (

	(* identificateurs *)

		IDENTIFICATEUR_ENTIER,
		IDENTIFICATEUR_REEL,
		IDENTIFICATEUR_CHAINE,

	(* lit‚raux *)

		LITERAL_ENTIER,
		LITERAL_REEL,
		LITERAL_CHAINE,

	(* op‚rateurs num‚riques et chaine, binaires et	unaires	*)

		OPERATEUR_MULTIPLICATION,	(* '*' *)
		OPERATEUR_DIVISION,		(* '/' *)
		OPERATEUR_MODULO,		(* 'mod' *)
		OPERATEUR_ADDITION,		(* '+' *)
		OPERATEUR_SOUSTRACTION,		(* '-' *)

	(* op‚rateurs relationnels *)

		OPERATEUR_PLUS_PETIT,		(* '<' *)
		OPERATEUR_PLUS_PETIT_EGAL,	(* '<='	*)
		OPERATEUR_PLUS_GRAND,		(* '>' *)
		OPERATEUR_PLUS_GRAND_EGAL,	(* '>='	*)
		OPERATEUR_EGAL,			(* '=' *)
		OPERATEUR_DIFFERENT,		(* '<>'	*)

	(* op‚rateurs logiques binaires	et unaire *)

		OPERATEUR_ET, 			(* 'and' *)
		OPERATEUR_OU,			(* 'or'	*)
		OPERATEUR_OU_EXCLUSIF,		(* 'xor'*)
		OPERATEUR_NON,			(* 'not' *)

	(* s‚parateurs *)

		SEPARATEUR_PARENTHESE_GAUCHE,	(* '(' *)
		SEPARATEUR_PARENTHESE_DROITE,	(* ')' *)
		SEPARATEUR_CROCHET_GAUCHE,	(* '[' *)
		SEPARATEUR_CROCHET_DROIT,	(* ']' *)

	(* commentaires *)

		COMMENTAIRE_APOSTROPHE,		(* ''''	*)

	(* mots	cl‚s *)

		MOT_CLE_IF,		    	(* 'if'	*)
		MOT_CLE_THEN,		    	(* 'then' *)
		MOT_CLE_ELSE,		    	(* 'else' *)
		MOT_CLE_GOSUB,			(* 'gosub' *)
		MOT_CLE_RETURN,			(* 'return' *)
		MOT_CLE_WHILE,			(* 'while' *)
		MOT_CLE_WEND,			(* 'wend' *)
		MOT_CLE_FOR,			(* 'for' *)
		MOT_CLE_TO,		    	(* 'to'	*)
		MOT_CLE_NEXT,		    	(* 'next' *)
		MOT_CLE_GOTO,		    	(* 'goto' *)
		MOT_CLE_LET,		    	(* 'let' *)
		MOT_CLE_END,		    	(* 'end' *)
		MOT_CLE_REM,			(* 'rem' *)
		MOT_CLE_INPUT,    		(* 'input' *)
		MOT_CLE_PRINT,			(* 'print' *)

	(* commandes *)

		COMMANDE_LIST,			(* 'list' *)
		COMMANDE_NEW,			(* 'new' *)
		COMMANDE_RUN,			(* 'run' *)
		COMMANDE_LOAD,			(* 'load' *)
		COMMANDE_SAVE,			(* 'save' *)
		COMMANDE_SYSTEM,		(* 'system' *)

	(* pseudo-lexŠmes *)

		FIN_DE_LIGNE,
		ERREUR,
		PAS_TROUVE
	);

	TYPE_ERREURS_LEXICALES =
	(
		ANALYSEUR_LEXICAL_OKAY,
		EXPOSANT_MANQUANT,
		MANQUE_GUILLEMET,
		CHAINE_TROP_LONGUE,
		LEXEME_NON_RECONNU
	);

var	erreur_lexicale	: TYPE_ERREURS_LEXICALES;
	lexeme		: string;

procedure 	initialise_analyseur_lexical (l : string);
procedure	termine_analyseur_lexical;

function	prend_lexeme : TYPE_LEXEMES;
procedure 	remet_lexeme;
function	lit_index : integer;

procedure	explique_erreur_lexicale;

function 	nom_lexeme (t : TYPE_LEXEMES) : string;

implementation

uses outils;

var     initialise	: boolean;
	ligne		: string;
	index		: integer;
	ancien_index	: integer;
	longueur	: integer;

procedure initialise_analyseur_lexical (l : string);
(* Pr‚pare l'analyseur lexical … lire une nouvelle ligne. *)

begin
	lexeme := '';
	initialise := true;
	ligne := l;
	index := 1;
	ancien_index := -1;
	longueur := length(l);
end;

procedure termine_analyseur_lexical;
(* Arrˆte l'analyseur lexical.  L'index mis … z‚ro permet de detecter des
 * appels … prend_lexeme sans initialisation pr‚alable de l'analyseur
 * lexical.
 *)

begin
	if not initialise then begin
		writeln('Erreur Interne: ',
			'Analyseur lexical non initialis‚!');
		halt;
	end else begin
		lexeme := '';
		initialise := false;
		ligne := '';
		index := 0;
		ancien_index := -1;
		longueur := 0;
	end;
end;

function prend_lexeme : TYPE_LEXEMES;
(* Prend un lexŠme, met … jour la variable lexeme, et renvoie le type du
 * lexŠme ainsi trouv‚.  Renvoie FIN_DE_LIGNE si on est arriv‚ en fin de
 * ligne, ou ERREUR en cas d'erreur, auquel cas erreur_lexicale apporte des
 * pr‚cisions.
 *)

procedure accepte_caractere;
(* Accepte un caractŠre: l'ajoute … la variable lexeme et incr‚mente index.
 *)

begin
	lexeme := lexeme + ligne[index];
	index := index + 1;
end;

procedure lit_entier;
(* Si le premier caractŠre d'un	lexŠme est un nombre, alors cela doit ˆtre un
 * entier, ou peut-ˆtre	mˆme un	r‚el.  L'entier	peut ˆtre plus grand que
 * 32767 sign‚ ou 65535	non sign‚, la v‚rification ne se fait pas ici, mais
 * avec	la fonction chaine_a_entier ou chaine_a_numero.
 *)

begin
	if ligne[index]	= '0' then
		accepte_caractere
	else
		while (index <=	longueur) and est_un_nombre(ligne[index]) do
			accepte_caractere;
end;

function lit_reel : TYPE_LEXEMES;
(* Lit un r‚el si r‚el il y a, cette fonction est … utiliser en	compl‚ment de
 * lit_entier, en effet	un r‚el	est un entier plus des chiffres	aprŠs la
 * virgule et un exposant optionnel.  Aussi cette fonction cherche s'il	y a
 * un point d‚cimal, puis lit les chiffres aprŠs la virgule, et	enfin lit l'
 * exposant optionnel.	Elle renvoie LITERAL_ENTIER si elle ne trouve pas de
 * nombre r‚el,	LITERAL_REEL si	un r‚el	correct	a ‚t‚ lu, ou ERREUR si une
 * erreur est survenue.
 *)

function lit_exposant :	TYPE_LEXEMES;
(* Lit l'exposant d'un r‚el, qui doit ˆtre un entier avec un signe optionnel,
 * renvoie LITERAL_REEL	s'il n'y pas eu	de problŠme, ou	ERREUR sinon.  L'
 * exposant doit ˆtre entre -38	et +38,	mais c'est seulement avec la fonction
 * chaine_a_reel que les v‚rifications se feront.
 *)

begin
	accepte_caractere;	(* saute le 'e'	ou 'E' de l'exposant *)

	if (index <= longueur)
	and ((ligne[index] = '-') or (ligne[index] = '+')) then
		accepte_caractere;

	if (index > longueur) or not est_un_nombre(ligne[index]) then begin
		erreur_lexicale	:= EXPOSANT_MANQUANT;
		lit_exposant :=	ERREUR;
	end else begin
		repeat
			accepte_caractere;
		until (index > longueur) or not	est_un_nombre(ligne[index]);
		lit_exposant :=	LITERAL_REEL;
	end;
end;

begin
	if (ligne[index] = '.')	and (index + 1 <= longueur)
	and est_un_nombre(ligne[index +	1]) then begin
		accepte_caractere;	(* saute le point *)

		while (index <=	longueur) and est_un_nombre(ligne[index]) do
			accepte_caractere;

		if (index <= longueur)
		and ((ligne[index] = 'e') or (ligne[index] = 'E')) then
			lit_reel := lit_exposant
		else
			lit_reel := LITERAL_REEL;
	end else
		lit_reel := LITERAL_ENTIER;
end;

function lit_chaine : TYPE_LEXEMES;
(* Lit une chaine lit‚ral.  La variable lexeme ne contiendra que ce qu'il y a
 * entre guillemet, et les double guillemets de la chaine seront convertis en
 * simple guillemet.  En cas d'erreur, comme une chaine sans ou trop longue,
 * renvoie ERREUR.
 *)

const	LONGUEUR_MAXIMUM	= 255;

var	fin 	: boolean;
	compte	: integer;

begin
	fin := false;
	index := index + 1;
	compte := 0;

	repeat
		if index > longueur then begin
			fin := true;
			erreur_lexicale	:= MANQUE_GUILLEMET;
			lit_chaine := ERREUR;
		end else if ligne[index] = '"' then begin
			if (index + 1 <= longueur)
			and (ligne[index + 1] = '"') then begin
				if compte = LONGUEUR_MAXIMUM then begin
					fin := true;
					erreur_lexicale	:=
						CHAINE_TROP_LONGUE;
					lit_chaine := ERREUR;
				end else begin
					compte := compte + 1;
					accepte_caractere;
					index := index + 1;
				end;
			end else begin
				index := index + 1;
				fin := true;
				lit_chaine := LITERAL_CHAINE;
			end;
		end else begin
			if compte = LONGUEUR_MAXIMUM then begin
				fin := true;
				erreur_lexicale	:= CHAINE_TROP_LONGUE;
				lit_chaine := ERREUR;
			end else begin
				compte := compte + 1;
				accepte_caractere;
			end;
		end;
	until fin = true;
end;

function lit_identificateur : TYPE_LEXEMES;
(* Lit un identificateur et selon son suffixe, ou absence de suffixe, renvoie
 * le type de lexŠme ad‚quat.
 *)

begin
	while (index <= longueur) and est_alphanumerique(ligne[index]) do
		accepte_caractere;

	if index > longueur then
		lit_identificateur := IDENTIFICATEUR_REEL
	else if	ligne[index] = '!' then begin
		accepte_caractere;
		lit_identificateur := IDENTIFICATEUR_REEL;
	end else if ligne[index] = '%' then begin
		accepte_caractere;
		lit_identificateur := IDENTIFICATEUR_ENTIER;
	end else if ligne[index] = '$' then begin
		accepte_caractere;
		lit_identificateur := IDENTIFICATEUR_CHAINE;
	end else
		lit_identificateur := IDENTIFICATEUR_REEL;
end;

function cherche_mot_reserve (s : string) : TYPE_LEXEMES;
(* Fait une recherche binaire sur la table des mots r‚serv‚s.  On appelle ici
 * par le terme g‚n‚rique mot r‚serv‚ toute chaine de caractŠres ayant un
 * sens particulier: op‚rateurs, s‚parateurs, ou mots cl‚s.  Cette fonction
 * renvoie le type du lexŠme trouv‚ si la chaine de caractŠres s se trouve
 * dans la table, ou le pseudo-lexŠme PAS_TROUVE sinon.
 *)

type 	MOT_RESERVE = 	record
				s 	: string;
				t	: TYPE_LEXEMES;
			end;

const   NOMBRE_MOTS_RESERVES = 41;

	(* La table LISTE_MOTS est rang‚e dans l'ordre lexicographique pour
	 * permettre une recherche binaire.  Elle a ‚t‚ construite … l'aide
	 * de la commande sort du systŠme d'exploitation.
	 *)

	LISTE_MOTS : array [1..NOMBRE_MOTS_RESERVES] of MOT_RESERVE =
	(
		(s: '(';		t: SEPARATEUR_PARENTHESE_GAUCHE),
		(s: ')';		t: SEPARATEUR_PARENTHESE_DROITE),
		(s: '*'; 		t: OPERATEUR_MULTIPLICATION),
		(s: '+';		t: OPERATEUR_ADDITION),
		(s: '-';		t: OPERATEUR_SOUSTRACTION),
		(s: '/'; 		t: OPERATEUR_DIVISION),
		(s: '<';		t: OPERATEUR_PLUS_PETIT),
		(s: '<='; 		t: OPERATEUR_PLUS_PETIT_EGAL),
		(s: '<>';		t: OPERATEUR_DIFFERENT),
		(s: '=';		t: OPERATEUR_EGAL),
		(s: '>';		t: OPERATEUR_PLUS_GRAND),
		(s: '>=';		t: OPERATEUR_PLUS_GRAND_EGAL),
		(s: '[';		t: SEPARATEUR_CROCHET_GAUCHE),
		(s: ']';		t: SEPARATEUR_CROCHET_DROIT),
		(s: 'and';		t: OPERATEUR_ET),
		(s: 'else';		t: MOT_CLE_ELSE),
		(s: 'end';		t: MOT_CLE_END),
		(s: 'for';		t: MOT_CLE_FOR),
		(s: 'gosub';		t: MOT_CLE_GOSUB),
		(s: 'goto';		t: MOT_CLE_GOTO),
		(s: 'if';		t: MOT_CLE_IF),
		(s: 'input';		t: MOT_CLE_INPUT),
		(s: 'let';		t: MOT_CLE_LET),
		(s: 'list';		t: COMMANDE_LIST),
		(s: 'load';		t: COMMANDE_LOAD),
		(s: 'mod';		t: OPERATEUR_MODULO),
		(s: 'new';		t: COMMANDE_NEW),
		(s: 'next';		t: MOT_CLE_NEXT),
		(s: 'not';		t: OPERATEUR_NON),
		(s: 'or';		t: OPERATEUR_OU),
		(s: 'print';		t: MOT_CLE_PRINT),
		(s: 'rem';		t: MOT_CLE_REM),
		(s: 'return';		t: MOT_CLE_RETURN),
		(s: 'run';		t: COMMANDE_RUN),
		(s: 'save';		t: COMMANDE_SAVE),
		(s: 'system';		t: COMMANDE_SYSTEM),
		(s: 'then';		t: MOT_CLE_THEN),
		(s: 'to';		t: MOT_CLE_TO),
		(s: 'wend';		t: MOT_CLE_WEND),
		(s: 'while';		t: MOT_CLE_WHILE),
		(s: 'xor'; 		t: OPERATEUR_OU_EXCLUSIF)
	);

var	debut, fin	: integer;
	trouve		: boolean;
	milieu		: integer;

begin
	debut := 1;
	fin := NOMBRE_MOTS_RESERVES;
	trouve := false;

	while (debut <= fin) and (trouve = false) do begin
		milieu := (debut + fin) div 2;
		if LISTE_MOTS[milieu].s = s then
			trouve := true
		else if LISTE_MOTS[milieu].s < s then
			debut := milieu + 1
		else
			fin := milieu - 1;
	end;

	if trouve then
		cherche_mot_reserve := LISTE_MOTS[milieu].t
	else
		cherche_mot_reserve := PAS_TROUVE;
end;

function lit_mot_cle (t : TYPE_LEXEMES) : TYPE_LEXEMES;
(* Si un lexŠme a ‚t‚ identifi‚ comme ‚tant un identificateur, alors il faut
 * v‚rifier que ce lexŠme n'est pas un mot cl‚ ou un op‚rateur, car pour
 * certains ils ob‚issent aux mˆmes rŠgles de construction qu'un
 * identificateur.  La variable t est le type de lexŠme de l'identificateur
 * d‚j… trouv‚, si la recherche s'avŠre infructueuse, alors t est retourn‚,
 * sinon c'est le type du lexŠme trouv‚ dans la table des mots r‚serv‚s.
 *)

var	temp	: TYPE_LEXEMES;

begin
	temp := cherche_mot_reserve(minuscule(lexeme));
	if temp = PAS_TROUVE then
		lit_mot_cle := t
	else
		lit_mot_cle := temp;
end;

function lit_mot_reserve : TYPE_LEXEMES;
(* Si toutes les recherches pr‚c‚dentes s'avŠrent infructueuses alors il s'
 * agit d'un op‚rateur ou d'un s‚parateur.  La rŠgle est de prendre le plus
 * long mot r‚serv‚, par exemple dans le cas de l'op‚rateur relationnel plus
 * petit ou ‚gal <=, lit_mot_reserve trouve bien <= et non < l'op‚rateur plus
 * petit.  Cela ‚tait fait implicitement par lit_mot_cle par le bias de la
 * fonction lit_identificateur.  Si lit_mot_reserve ne trouve rien alors on
 * est face … un lexŠme non reconnu, ce qui est une erreur, sinon le mot
 * r‚serv‚ trouv‚ est renvoy‚.
 *)

const	PLUS_LONG_MOT_RESERVE	= 2;

var	i 	: integer;
	s	: string;
	trouve 	: TYPE_LEXEMES;
	temp	: TYPE_LEXEMES;

begin
	i := 1;
	s := '';
	trouve := PAS_TROUVE;

	while (i <= PLUS_LONG_MOT_RESERVE)
	and (index + i - 1 <= longueur) do begin
		s := s + minuscule(ligne[index + i - 1]);
		temp := cherche_mot_reserve(s);
		if temp <> PAS_TROUVE then begin
			trouve := temp;
			lexeme := s;
		end;
		i := i + 1;
	end;

	if trouve <> PAS_TROUVE then begin
		index := index + length(lexeme);
		lit_mot_reserve := trouve;
	end else begin
		erreur_lexicale := LEXEME_NON_RECONNU;
		lit_mot_reserve := ERREUR;
	end;
end;

var	t	: TYPE_LEXEMES;

begin
	if index = 0 then begin
		writeln('Erreur Interne: ',
			'L''analyseur lexical n''a pas ‚t‚ initialis‚!');
		halt;
	end;

	lexeme := '';
	erreur_lexicale := ANALYSEUR_LEXICAL_OKAY;

	while (index <= longueur) and est_un_espace(ligne[index]) do
		index := index + 1;

	ancien_index := index;

	if (index > longueur) then
		prend_lexeme := FIN_DE_LIGNE
	else if (ligne[index] = '''') then begin
		accepte_caractere;
		prend_lexeme := COMMENTAIRE_APOSTROPHE
	end else if est_un_nombre(ligne[index]) then begin
		lit_entier;
		prend_lexeme := lit_reel;
	end else if ligne[index] = '"' then begin
		prend_lexeme :=	lit_chaine;
	end else if est_une_lettre(ligne[index]) then begin
		t := lit_identificateur;
		prend_lexeme :=	lit_mot_cle(t);
	end else
		prend_lexeme :=	lit_mot_reserve;
end;

procedure remet_lexeme;
(* Remet un lexŠme pr‚cedemment	pris par prend_lexeme.	On ne peut remettre
 * qu'un seul lexŠme pas plus, et prend_lexeme doit avoir ‚t‚ appel‚
 * pr‚cedemment.
 *)

begin
	if ancien_index	= -1 then begin
		writeln('Erreur Interne: ',
			'Appel … remet_lexeme sans appel pr‚alable … ',
			'prend_lexeme!');
		halt;
	end else begin
		index := ancien_index;
		ancien_index :=	-1;
	end;
end;

function lit_index : integer;
(* Lit l'index courant de l'analyseur lexical, si celui-ci n'a pas ‚t‚
 * initialis‚, il est nul.
 *)

begin
	lit_index := index;
end;

procedure explique_erreur_lexicale;
(* S'il y a une erreur lexicale, alors ‚crit … l'‚cran une explication avec
 * la ligne en question, et indique o— est l'erreur.  Cette proc‚dure doit
 * ˆtre appel‚, dans son contexte, … savoir juste aprŠs l'erreur.  S'il n'y a
 * pas eu d'erreur il ne se passe rien.
 *)

const	LISTE_EXPLICATIONS : array [1..4] of string =
	(
		'Nombre r‚el sans exposant!',
		'Chaine sans guillemet de fin!',
		'Chaine trop longue (au plus 255 caractŠres)!',
		'LexŠme non reconnu!'
	);

var	i	: integer;

begin
	if erreur_lexicale <> ANALYSEUR_LEXICAL_OKAY then begin
		write('Erreur Lexicale: ');
		writeln(LISTE_EXPLICATIONS[ord(erreur_lexicale)]);
		writeln(ligne);

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

		writeln('^');
	end;
end;

function nom_lexeme (t : TYPE_LEXEMES) : string;
(* Renvoie le nom du type de lexŠme t. *)

const	NOMBRE_TYPE_LEXEMES 	= 51;

	LISTE_NOMS : array [1..NOMBRE_TYPE_LEXEMES] of string =
	(
		'IDENTIFICATEUR_ENTIER',
		'IDENTIFICATEUR_REEL',
		'IDENTIFICATEUR_CHAINE',

		'LITERAL_ENTIER',
		'LITERAL_REEL',
		'LITERAL_CHAINE',

		'OPERATEUR_MULTIPLICATION',
		'OPERATEUR_DIVISION',
		'OPERATEUR_MODULO',
		'OPERATEUR_ADDITION',
		'OPERATEUR_SOUSTRACTION',

		'OPERATEUR_PLUS_PETIT',
		'OPERATEUR_PLUS_PETIT_EGAL',
		'OPERATEUR_PLUS_GRAND',
		'OPERATEUR_PLUS_GRAND_EGAL',
		'OPERATEUR_EGAL',
		'OPERATEUR_DIFFERENT',

		'OPERATEUR_ET',
		'OPERATEUR_OU',
		'OPERATEUR_OU_EXCLUSIF',
		'OPERATEUR_NON',

		'SEPARATEUR_PARENTHESE_GAUCHE',
		'SEPARATEUR_PARENTHESE_DROITE',
		'SEPARATEUR_CROCHET_GAUCHE',
		'SEPARATEUR_CROCHET_DROIT',

		'COMMENTAIRE_APOSTROPHE',

		'MOT_CLE_IF',
		'MOT_CLE_THEN',
		'MOT_CLE_ELSE',
		'MOT_CLE_GOSUB',
		'MOT_CLE_RETURN',
		'MOT_CLE_WHILE',
		'MOT_CLE_WEND',
		'MOT_CLE_FOR',
		'MOT_CLE_TO',
		'MOT_CLE_NEXT',
		'MOT_CLE_GOTO',
		'MOT_CLE_LET',
		'MOT_CLE_END',
		'MOT_CLE_REM',
		'MOT_CLE_INPUT',
		'MOT_CLE_PRINT',

		'COMMANDE_LIST',
		'COMMANDE_NEW',
		'COMMANDE_RUN',
		'COMMANDE_LOAD',
		'COMMANDE_SAVE',
		'COMMANDE_SYSTEM',

		'FIN_DE_LIGNE',
		'ERREUR',
		'PAS_TROUVE'
	);

begin
	nom_lexeme := LISTE_NOMS[ord(t)	+ 1];
end;

begin
	initialise := false;
end.
