Vous devez ensuite générer trois packages contenant les classes Java implémentant les composants fondamentaux de l'analyseur.
Le package
lexer associé à l'analyseur lexical contient deux classes :
-
LexerDataTable qui permet de créer la table qui, à chaque règle associe, un automate fini qui reconnais le token.
-
RuleEnum qui est une énumération des règles.
Le package
parser associé à l'analyseur syntaxique, contient cinq classes:
-
NonTerminalEnum qui est une énumération des éléments non-terminaux de la grammaire
-
ProductionEnum qui est une énumération des noms des productions de la grammaire
-
VersionEnum qui est une énumération des versions de la grammaire
-
TerminalEnum qui est une énumération des éléments terminaux
-
ParserDataTable qui est implémente l'automate à pile associé à la grammaire
Le package
tools (avec l'unique classe
ToolsDataTable) permet de faire la correspondance entre les tokens reconnus par le lexeur et les éléments terminaux de la grammaire du parseur.
La génération de ces trois packages peut être réalisée à l'aide d'une tâche
ant.
Dans l'exemple
simple-parser, le fichier
build.xml permet de générer ces packages dédiés à l'analyseur décrit dans
simple-parser.ebnf.
La tâche associée génère trois packages
- fr.umlv.tatoo.tutorial.simpleparser.lexer
- fr.umlv.tatoo.tutorial.simpleparser.parser
- fr.umlv.tatoo.tutorial.simpleparser.tools
Les packages sont placés dans le répertoire de destination
gen-src.
La balise
ebnf du fichier de configuration contient différents attributs:
-
parserType qui définit le type du parser à générer : soit 'slr' (type SLR), soit 'lr' (LR1), soit 'lalr' (LALR).
-
ebnfFile qui indique le fichier EBNF décrivant l'analyseur
-
logFile qui indique le nom du fichier log qui contient différentes informations sur l'analyseur (ex. automate d'items, premiers, suivants)
simple-parser.ebnf
build-simple-parser.xml
Une fois les packages dédiés à l'analyseur générés, il s'agit de créer l'analyseur en tant que tel.
La classe
fr.umlv.tatoo.runtime.tools.builder.Builder dans
tatoo-runtime.jar contient des méthodes simples à cet effet (cf. la javadoc).
Dans les faits, il s'agit de créer un lexeur couplé à un analyseur syntaxique.
La création du lexeur nécessite, au minimum, de:
- un LexerDataTable créé à partir de la méthode statique createTable() de la classe LexerDataTable générée par Tatoo.
- un ParserDataTable créé à partir de la méthode statique createTable() de la classe ParserDataTable générée par Tatoo.
- un ToolsDataTable créé à partir de la méthode statique createTable() de la classe ToolsDataTable générée par Tatoo.
- un Reader lisant le texte en entrée que l'on veut compiler
- un listeneur de type AnalyzerListener<R,B,T,N,P> indiquant les actions à réaliser à chaque étape de l'analyse syntaxique.
(R est le type des règles [en général, RuleEnum],
B est le type des buffers [par exemple, ReaderWrapper],
T est le type des terminaux [TerminalEnum] et
N est le type des productions [ProductionEnum]).
La création de l'analyseur se fait à l'aide de la méthode statique
Builder.analyzer(), comme indiqué ci-dessous :
Builder.analyzer(lexerDataTable,parserDataTable,toolsDataTable)
.reader(reader)
.listener(listener)
.create()
Il s'agit ensuite de récupérer le lexeur (méthode
getLexer)
et de le lancer à l'aide de la méthode
run().
Il existe un listener de débogage qui peut être utilisé en appelant
debugListener() à la place de
listener(listener).
Il est possible de spécifier la stratégie du lexeur en cas d'erreur en appelant la méthode
defaultLexerErrorPolicy() qui prend un
LexerWarningReporter<B> (B type de buffer)(cf. Javadoc).
Builder.analyzer(lexerDataTable,parserDataTable,toolsDataTable)
.reader(reader)
.listener(listener)
.expert()
.defaultLexerErrorPolicy(lexerWarningReporter)
.create()
Ci-dessous nous donnons un exemple d'implantation d'un analyseur qui reconnaît les expressions a
nb
n.
L'AnalyzerListener implanté ne fait rien.