FRMG: une grammaire du français

FRMG est une métagrammaire du français développée par ALPAGE depuis 2004. Elle consiste en une description syntaxique de haut niveau qui permet ensuite de produire une grammaire d'arbres adjoints (TAG) exploitable dans un analyseur syntaxique.

Il existe de nombreux phénomènes syntaxiques, certains complexes et beaucoup rares, voire très rares. Ce wiki se propose d'être un espace de discussion pour collecter et discuter ces phénomènes. Il est ouvert à tous, linguistes ou simples passionnés de la langue française.

L'ambition est ensuite de transcrire, dans la mesure du possible, cette expertise linguistique au sein de la description formelle de FRMG. Actuellement, la ressource est répartie sur environ 360 classes qui, combinées, permettent d'engendrer les arbres élémentaires d'une grammaire d'arbres adjoints (TAG). Ces arbres sont ensuite utilisés pendant l'analyse syntaxique d'une phrase pour produire des graphes de dépendances entre mots. La mise en place d'une plateforme web de documentation, d'aide au développement et d'exploitation est une solution pour répondre au besoin de diffusion et de constitution de cette ressource linguistique complexe.

La liste des classes est ici et celle des arbres .

L'analyseur syntaxique découlant de la grammaire est décrit plus précisément ici et est utilisable en ligne

Tags: 

Présentation des Méta-Grammaires

Le développement manuel de grammaire à large couverture pose d'importants problèmes de maintenance, en particulier dus à la taille des grammaires et à la complexité des structures grammaticales.

Une première solution est d'oublier le coté manuel et de s'orienter vers l'extraction de grammaires stochastiques à partir de treebank (le gros du travail étant reporté sur la constitution du treebank). C'est la tendance actuelle mais conduit à des grammaires qui ne sont pas véritablement compréhensibles par des humains et qui ne peuvent être directement modifiées ou étendues.

Une autre approche, initiée dans les années 90 et début des années 2000, consiste à s'appuyer sur des descriptions modulaires et haut-niveau des phénomènes syntaxiques, sous forme de méta-grammaires. Plutôt que de devoir écrire des structures syntaxiques complètes, qui peuvent déjà mettre en œuvre plusieurs phénomènes syntaxiques (comme un sujet et un objet dans le cadre d'un verbe à la voie active), une méta-grammaire permet de décrire d'une part la notion de sujet (avec ses divers raffinement), la notion d'objet, la notion de verbe à la voie active, ..... Ces divers notions sont exprimées sous forme de contraintes regroupées en classes. Une classe peut hériter de classes parentes, ce qui permet de raffiner progressivement une notion. Les classes sont également combinables, et à partir de certaines de ces classes combinées dont les contraintes accumulées sont satisfiables, il est possible de produire des structures grammaticales complètes pour un formalisme cible donné comme les TAGs ou les LFGs.

Les diverses versions des méta-grammaires diffèrent sur les types de contraintes autorisées, les types d'héritages, les mécanismes de combinaison des classes, et la production des structures grammaticales. Elles partagent cependant beaucoup de points communs.

FRMG s'appuie sur une variante de méta-grammaire développée en interne, orientée pour la production de grammaires TAG. Les classes et contraintes peuvent s'écrire sous le format SMG (Simple Meta-Grammar), qui est celui utilisé sur ce wiki pour donner le source des classes.

Composants d'une méta-grammaire

Une méta-grammaire est organisée en une hiérarchie de classes, les classes servant à exprimer des contraintes sur une phénomène syntaxique (ou une facette de celui-ci).

  1. class adverb {
  2. ...
  3. }
  1. Une classe peut <span style="color:#0000CD;">hériter</span> des propriétés de classes parentes, ce qui permet de raffiner progressivement la description des phénomènes.
  2. <: adverb; %% this class inherits from the adverb class
  3. ...
  4. }
  5. ....
  6. }

Une classe peut aussi requérir une fonctionnalité fournie par une autre classe, au travers d'un mécanisme de consommateur/producteur de ressources.

  1. <: adverb;
  2. - x_modifier; # require the functionality "modifier_of_something"
  3. ....
  4. }
  5. class X_modifier {
  6. + x_modifier; # provide the foncionality "modifier_of_something"
  7. ...
  8. }

Ce mécanisme de gestion de ressources, puissant, vient en complément de l'héritage. En particulier, une ressource peut être consommée plusieurs fois par une classe dans des espaces de noms différents, ce qui n'est pas possible de faire par simple héritage.

  1. %% require agreemnt for the determiner (le|la) and the adjective
  2. - det::agreement; det=det::N;
  3. - adj::agreement; adj=adj::N;
  4. ...
  5. }
  6. class agreement {
  7. %% provide agreement constraint between a node and its father
  8. father(N).bot.gender = node(N).bot.gender;
  9. ....
  10. }

Héritage et ressources forme l'ossature de la méta-grammaire (son organisation en terme de classes). La "chair" est fournie par le contenu des classes, portant sur des nœuds des arbres d'analyse, leurs décorations et des contraintes topologiques entre ces nœuds.

  1. %% declaration of nodes S, v, and Subject, with some decorations
  2. node S: [cat: S, type: std];
  3. node v: [cat: v, type: anchor, id: v];
  4. node Subject: [cat: N2, type: subst, id: subject];
  5. %% The subject precedes the verb
  6. Subject < v;
  7. %% The sentence node dominates the subject node
  8. S >> Subject;
  9. %% the sentence node also dominates the verb node, but indirectly
  10. %% (to allow other nodes in-between)
  11. S >>+ v;
  12. ....
  13. }

À coté des contraintes topologiques (précédence, dominance, égalité), il est également possible d'exprimer des contraintes très riches portant sur les décorations des nœuds, par utilisation de variables ou au travers d'équations entre chemins conduisant d'une source à une valeur. La source d'un chemin est en général un nœud.

  1. ...
  2. %% use of variable $number to force number agreement
  3. node Subject: [cat: N2, type: subst, id: subject, top: [number: $number]];
  4. node v : [cat:v, type: anchor, id: v, top: [number: $number]];
  5. }
  1. ...
  2. %% alternative use of a path equation to force number agreement
  3. node(Subject).top.number = node(v).top.number;
  4. }

La classe elle-même est le support d'une décoration, ancrée sur le mot clé desc, en particulier pour préparer l'hypertag qui peut associé à un arbre, ou pour gérer des traits globaux plutôt que spécifique à un nœud. Ce mot-clé desc peut être la source d'un chemin.

  1. ...
  2. %% a non transitive verb has only one subject argument
  3. desc.ht.arg0.function=value(subject);
  4. desc.ht.arg1.function=value(-);
  5. desc.ht.arg2.function=value(-);
  6. }
  7. %% alternative, using a full feature structure as value
  8. ...
  9. %% a non transitive verb has only one subject argument
  10. desc.ht = value([arg0: [function: subject],
  11. arg1: [function: -],
  12. arg2: [function: -]
  13. ]);
  14. }

Il est également possible d'utiliser une variable (comme $ht) comme source d'un chemin.

  1. desc.ht = $ht;
  2. ...
  3. %% a non transitive verb has only one subject argument
  4. $ht.arg1 = value(subject);
  5. ....
  6. }

Les équations sont aussi exploitables pour exprimer des contraintes sur la présence ou l'absence d'un nœud. Une garde, positive ou négative, sur un nœud est ainsi une formule logique à base d'équations.

  1. ...
  2. %% a subject is present
  3. %% if and only if the verb mood is not imperative or infinitive
  4. Subject =>
  5. node(v).top.mood = value(~imperative|infinitive);
  6. ~ Subject =>
  7. node(v).top.mood = value(imperative|infinitive);
  8. }

Les formules construites sur des équations entre chemins sont aussi utilisables pour exprimer des contraintes complexes, incluant entre autres des disjonctions, sans avoir à multiplier les classes.

  1. class subordonate {
  2. ...
  3. SubS +
  4. node(SubS).top.mode = value(participle|gerundive),
  5. node(SubS).top.inv = value(-),
  6. node(SubS).top.extraction = value(-),
  7. ( node(SubS).top.sat = value(-),
  8. ( node(Foot).cat = value(coo)
  9. |
  10. node(Foot).cat = value(~coo),
  11. node(Foot).top.number = node(SubS).bot.number,
  12. node(Foot).top.person = node(SubS).bot.person,
  13. node(Foot).top.gender = node(SubS).bot.gender
  14. )
  15. |
  16. node(SubS).top.sat = value(ppart)
  17. )
  18. |
  19. node(SubS).top.mode = value(~participle|gerundive),
  20. node(SubS).top.sat = value(-)
  21. ;
  22. }

À coté de ces éléments de base, qui suffisent déjà largement, il existe un mécanisme de raccourcis (macro) sur les valeurs des traits et sur les chemins

  1. %% macro on value, for default agreement
  2. template @defaultagr = [person: 3, number: sg, gender: masc]
  3. %% macro on path
  4. path @function0 = .ht.arg0.function
  5. class csu {
  6. ...
  7. node(CS).bot = value(@defaultagr);
  8. }
  9. ...
  10. desc.@function0 = value(subject);
  11. }

Lors de la phase de mise au point, il est possible de désactiver une classe et ses descendants

disable verb_categorization_passive

Comme toujours, le formalisme offre son lot de petits "trucs", bons à savoir. Ainsi, les nœuds ont une propriété type, avec quelques types spéciaux:

  • alternative: pour un nœud dominant un ensemble de nœuds dont l'un seulement peut être utilisé lors d'une analyse
  • sequence: pour un nœud interne dominant une séquence de fils, mais pour lequel on n'a pas de propriétés linguistiques particulières (pas de catégorie syntaxique par exemple)
  1. class subject {
  2. + subject;
  3. node SubjectAlt: [type: alternative];
  4. SubjectAlt >> CliticSubj; node CliticSubj: [cat: cln, type: coanchor];
  5. SubjectAlt >> NominalSubj; node NominalSubj: [cat: N2, type: subst];
  6. SubjectAlt >> SentSubj; node SentSubj: [cat: S, type: subst];
  7. ...
  8. }

Ces types spéciaux seront en particulier utilisés pour produire des arbres factorisés.

On peut également indiquer qu'un noeud est optionnel (sans passer par une garde)

  1. class pnoun {
  2. ...
  3. %% a proper noun may be preceded by an optional title
  4. node Monsieur : [cat: title, type: coanchor, optional: yes];
  5. }

Il est également possible de rendre répétable un noeud, à la manière de l'opérateur "*" dans les expressions régulières (étoile de Kleene). Ceci est en essentiellement utilisé pour représenter la répétition dans les coordinations.

  1. class simple_coord {
  2. ...
  3. node MiddleCoordSeq: [type: sequence, star: *];
  4. node coord: [cat: coo, type: anchor];
  5. node EndCoord: [cat: $cat];
  6. MiddleCordSeq < coord;
  7. coord < EndCoord;
  8. MiddleCoordSeq >> MiddleCoord;
  9. MiddleCoordSeq >> coma;
  10. MiddleCoord < coma;
  11. node MiddleCoord: [cat: $cat];
  12. node comma: [lex: ",", type: lex];
  13. }

Phase de compilation

Production des arbres TAGs


Références

  1. É. de La Clergerie, « From Metagrammars to Factorized TAG/TIG Parsers », in Proceedings of IWPT'05 (poster), Vancouver, Canada, 2005.
  2. É. Villemonte De La Clergerie, « Building factorized TAGs with meta-grammars », in The 10th International Conference on Tree Adjoining Grammars and Related Formalisms - TAG+10, New Haven, CO, États-Unis, 2010.
  3. J. Le Roux, Crabbé, B., et Parmentier, Y., « A constraint driven metagrammar », in Proceedings of the Eighth International Workshop on Tree Adjoining Grammar and Related Formalisms (TAG+8), Sydney, Australia, 2006.
  4. D. Duchier, Le Roux, J., et Parmentier, Y., « XMG: un Compilateur de Métagrammaire Extensible », in Conference Traitement Automatique des Langues Naturelles (TALN'2005), Dourdan, 2005.
  5. B. Gaiffe, Crabbé, B., et Roussanaly, A., « A New Metagrammar Compiler », in Proc. of TAG+6, Venice, Italy, 2002.
  6. M. - H. Candito, « Organisation modulaire et paramétrable de grammaires électroniques lexicalisées », Université Paris 7, 1999.

Quelques rappels sur les Grammaires d'Arbres Adjoints (TAG)

Pour décrire la grammaire d'une langue sous une forme exploitable par un ordinateur, il est nécessaire d'être extrêmement précis et d'utiliser un formalisme syntaxique adéquat.

Le plus simple et le plus connu de ceux-ci est certainement celui des grammaires hors-contexte (CFG, Context-Free Grammars), largement utilisées pour la description des langages de programmation.

Ainsi, la grammaire jouet suivante permet déjà de traiter une infinité de phrases simples, comme "Jean/np voit/v un/det homme/nc avec/prep un/det télescope/nc". Elle définit 8 productions pour les non-terminaux S (pour Sentence) ainsi que GN (Groupe Nominal), GP (Groupe Prépositionnel), et GV (Groupe Verbal).

  1. S --> GN, GV.
  2. GN --> np.
  3. GN --> det, nc.
  4. GN --> GN, GP.
  5. GP --> prep, GN.
  6. GV --> v.
  7. GV --> v GN.
  8. GV --> GV GP.

Les CFG sont ainsi largement utilisées pour le traitement automatique des langues (TAL), mais essentiellement dans le cadre d'extraction automatique de grammaires à partir de corpus annotés syntaxiquement (treebanks). Elles sont par contre beaucoup moins adaptées pour le développement manuel de grammaires à large couverture. Outre leur manque d'expressivité pour traiter certains phénomènes, elles obligent également à multiplier le nombre de productions.

Au moins deux grandes approches ont été explorées pour promouvoir des formalismes syntaxiques de plus haut niveau, plus puissants (en terme de pouvoir d'expression) et mieux adaptés à l'écriture de larges grammaires (concision, ...).

  • La première approche regroupe les grammaires d'unification comme LFG et HPSG, qui s'appuient sur l'utilisation de décorations au niveau des mots et des non-terminaux (via des structures de traits) pour pouvoir, au travers de l'opération d'unification, propager de l'information au sein de la phrase et gérer, par exemple, des phénomènes d'accord (entre un sujet et son verbe) ou des phénomènes d'extraction (pour une relative). Ainsi, une production gérant l'accord entre un nom et son déterminant, avec décorations, pourrait ressembler à
    1. GN{ nombre => N, genre => G } -->
    2. det{ nombre => N, genre => G},
    3. nc{ nombre => N, genre => G}.
  • La seconde approche remplace la structure plate des productions (avec une simple liste de terminaux et non-terminaux) par des arbres. Ainsi, une représentation pour les verbes ditransitifs comme 'donner' pourrait représenter à

S(GN_subj,(GP(v,GN_obj,GP_objà)))

La seconde approche donne lieu à la notion de TSG (Tree Substitution Grammar) qui, en fait, n'étend pas la puissance expressive des CFG (on peut réécrire les arbres en productions CFG en introduisant nombre de non-terminaux intermédiaires). De plus, ces arbres sont quelque part trop fermés, dans le sens où on a parfois besoin d'introduire des éléments optionnels en leur sein, par exemple un adverbe comme dans "S(GN_subj(il) GV(v(donne) souvent GN(du pain) GP(aux canards)))". Ce constat est à la base de la notion de grammaires d'arbres adjoints (TAG) avec son opération d'adjonction. Celle-ci permet d'ouvrir un nœud d'un arbre en une partie haute (top) et basse (bot) et d'insérer entre ces deux parties le contenu d'un arbre dit auxiliaire. Ainsi, on peut avoir un arbre auxiliaire pour les adverbes qui vient s'insérer (s'adjoindre) au niveau d'un nœud GP.

Les TAG sont plus puissantes (en pouvoir d'expression) que les CFG tout en conservant de bonnes propriétés algorithmiques pour l'analyse. Elles font partie d'un continuum de formalismes dit faiblement dépendant du contexte qui allient à la fois cette puissance descriptive pour des phénomènes linguistiques et de bonnes propriétés algorithmiques.

Quelques références:


Références

Arbres factorisés


Références

  1. É. Villemonte De La Clergerie, « Building factorized TAGs with meta-grammars », in The 10th International Conference on Tree Adjoining Grammars and Related Formalisms - TAG+10, New Haven, CO, États-Unis, 2010.

Installation de FRMG

Crédit : Yoann Dupont

Installation de la chaîne

Prérequis

Configuration minimale recommandée :

  • 2 coeurs
  • 17 Go d'espace libre pour l'installation
  • 4 Go de RAM

L'installation prend 2 à 4 heures, selon la puissance de l'ordinateur et la vitesse de la connexion à Internet.

Étapes

  1. docker
  2. alpi-docker
  3. alternative : installation manuelle

1. Installer Docker

Pour installer Docker, il est recommandé de suivre les instructions de la documentation officielle :

2. Utiliser Docker pour installer FRMG

Récupérez le dossier git frmg-docker et lancez l'installation :

git clone https://gitlab.inria.fr/???
cd frmg-docker/
docker build -t frmg .

Notes :

  • Le dépôt git d'Aleda pèse 4Go, il est donc normal que l'installation prenne du temps à ce moment là.
  • FRMG et LeFFF demandent un certain temps et une certaine quantité de RAM, faites bien attention à avoir environ 4Go de RAM disponible à ce moment.
  • Cette méthode requière un accès au serveur.

3. Installation manuelle

Il est possible d'installer un à un les paquets, à partir d'alpi.

git clone https://gitlab.inria.fr/almanach/alpi.git
cd alpi
./alpi

Une fois l'installation terminée, il faut mettre à jour l'environnement afin d'accéder aux exécutables. En supposant que l'installation utilise le préfixe par défaut :

source ${HOME}/exportbuild/sbin/setenv.sh

Cette commande peut être ajoutée au fichier ".bashrc".

Afin de tester votre installation de FRMG, vous pouvez lancer la commande :

echo "Jean mange une pomme." | frmg_lexer | frmg_parser - -disamb -conll

Installation de l'environnement de développement

Paramètres Emacs

Le thème mg.el permet de colorer la syntaxe SMG.

Paramètres VSCode

Vous pouvez télécharger le module de coloration syntaxique pour VSCode à cette adresse : https://gitlab.inria.fr/mgkit/syntax_hightlighting_smg/-/tree/dev