Grammalecte  Check-in [19d5e77970]

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fr_killtricks
Files: files | file ages | folders
SHA3-256: 19d5e77970299b3271e485da42b99dc5f18966a235af25dc8282d49d4c383101
User & Date: olr on 2017-09-12 01:59:52
Other Links: branch diff | manifest | tags
Context
2017-09-12
08:54
merge trunk check-in: c51ddd5524 user: olr tags: fr_killtricks
01:59
merge trunk check-in: 19d5e77970 user: olr tags: fr_killtricks
01:20
[fr] phonet_simil: 3 entrées check-in: b542d84d98 user: olr tags: fr, trunk
2017-06-20
18:41
[fr] màj: conjugaisons, suppression des pronoms et de “ne” (2) check-in: 7c28c4de28 user: olr tags: fr, fr_killtricks
Changes

Modified CHANGELOG.txt from [b2b4236d65] to [bdd168ce5d].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    Dictionary switcher
    Text formatter
    Lexicographer
    French Conjugueur

##  0.4
    Suggestion mechanisms
    Simplier user options writing
    Application Launcher
    Author field edition

##  0.5
    Grammalecte is an autonomous package, free from Hunspell and LibreOffice
    Indexable binary dictionary (DAWG-FSA) generator
    Disambiguator
    Multi-actions rules (bi-passes engine again)
    Simplier options for word boundaries
    Unit tests







|








|

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    Dictionary switcher
    Text formatter
    Lexicographer
    French Conjugueur

##  0.4
    Suggestion mechanisms
    Simpler user options writing
    Application Launcher
    Author field edition

##  0.5
    Grammalecte is an autonomous package, free from Hunspell and LibreOffice
    Indexable binary dictionary (DAWG-FSA) generator
    Disambiguator
    Multi-actions rules (bi-passes engine again)
    Simpler options for word boundaries
    Unit tests

Modified LICENSE.fr.txt from [6c800bc372] to [863120fc46].

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
soit gratuit ou contre un paiement, vous devez accorder aux
Destinataires les mêmes libertés que vous avez reçues. Vous devez aussi
vous assurer qu’eux aussi reçoivent ou peuvent recevoir son code
source. Et vous devez leur montrer les termes de cette licence afin
qu’ils connaissent leurs droits.

Les développeurs qui utilisent la GPL GNU protègent vos droits en deux
étapes : (1) ils affirment leur droits d’auteur (“copyright”) sur le
logiciel, et (2) vous accordent cette Licence qui vous donne la
permission légale de le copier, le distribuer et/ou le modifier.

Pour la protection des développeurs et auteurs, la GPL stipule
clairement qu’il n’y a pas de garantie pour ce logiciel libre. Aux fins
à la fois des utilisateurs et auteurs, la GPL requière que les versions
modifiées soient marquées comme changées, afin que leurs problèmes ne
................................................................................

Certains dispositifs sont conçus pour empêcher l’accès des utilisateurs
à l’installation ou l’exécution de versions modifiées du logiciel à
l’intérieur de ces dispositifs, alors que les fabricants le peuvent.
Ceci est fondamentalement incompatible avec le but de protéger la
liberté des utilisateurs de modifier le logiciel. L’aspect systématique
de tels abus se produit dans le secteur des produits destinés aux
utilisateurs individuels, ce qui est précidément ce qui est le plus
inacceptable. Aussi, nous avons conçu cette version de la GPL pour
prohiber cette pratique pour ces produits. Si de tels problèmes
surviennent dans d’autres domaines, nous nous tenons prêt à étendre
cette restriction à ces domaines dans de futures versions de la GPL,
autant qu’il sera nécessaire pour protéger la liberté des utilisateurs.

Finalement, chaque programme est constamment menacé par les brevets
................................................................................
     Appropriées, votre travail n’a pas à les modifier pour qu’elles
     les affichent. 

Une compilation d’un Travail Couvert avec d’autres travaux séparés et
indépendants, qui ne sont pas par leur nature des extensions du Travail
Couvert, et qui ne sont pas combinés avec lui de façon à former un
programme plus large, dans ou sur un volume de stockage ou un support
de distribution, est appelé un « aggrégat » si la compilation et son
Droit d’Auteur résultant ne sont pas utilisés pour limiter l’accès ou
les droits légaux des utilisateurs de la compilation en deça de ce que
permettent les travaux individuels. L’inclusion d’un Travail Couvert
dans un aggrégat ne cause pas l’application de cette Licence aux
autres parties de l’aggrégat.


Article 6. Acheminement des formes non sources.

Vous pouvez acheminer sous forme de code objet un Travail Couvert
suivant les termes des articles 4 et 5, pourvu que vous acheminiez
également suivant les termes de cette Licence le Source Correspondant
................................................................................
     utilisé pour les échanges de logiciels, pour un prix non supérieur
     au coût raisonnable de la réalisation physique de l’acheminement
     de la source, ou soit (2) un accès permettant de copier le Source
     Correspondant depuis un serveur réseau sans frais.

  c) Acheminer des copies individuelles du code objet avec une copie de
     l’offre écrite de fournir le Source Correspondant. Cette
     alternative est permise seulement occasionellement et non
     commercialement, et seulement si vous avez reçu le code objet avec
     une telle offre, en accord avec l’article 6 alinéa b.

  d) Acheminer le code objet en offrant un accès depuis un emplacement
     désigné (gratuit ou contre facturation) et offrir un accès
     équivalent au Source Correspondant de la même façon via le même
     emplacement et sans facturation supplémentaire. Vous n’avez pas
................................................................................

  e) Acheminer le code objet en utilisant une transmission
     d’égal-à-égal, pourvu que vous informiez les autres participants
     sur où le code objet et le Source Correspondant du travail sont
     offerts sans frais au public général suivant l’article 6 alinéa d.
     Une portion séparable du code objet, dont le code source est exclu
     du Source Correspondant en tant que Bibliothèque Système, n’a pas
     besoin d’être inclu dans l’acheminement du travail sous forme de
     code objet.

Un « Produit Utilisateur » est soit (1) un « Produit de Consommation, »
ce qui signifie toute propriété personnelle tangible normalement
utilisée à des fins personnelles, familiales ou relatives au foyer,
soit (2) toute chose conçue ou vendue pour l’incorporation dans un lieu
d’habitation. Pour déterminer si un produit constitue un Produit de
................................................................................
l’acheminement se produit en tant qu’élément d’une transaction dans
laquelle le droit de possession et d’utilisation du Produit
Utilisateur est transféré au Destinataire définitivement ou pour un
terme fixé (indépendamment de la façon dont la transaction est
caractérisée), le Source Correspondant acheminé selon cet article-ci
doit être accompagné des Informations d’Installation. Mais cette
obligation ne s’applique pas si ni vous ni aucune tierce partie ne
détient la possibilité d’intaller un code objet modifié sur le Produit
Utilisateur (par exemple, le travail a été installé en mémoire morte).

L’obligation de fournir les Informations d’Installation n’inclue pas
celle de continuer à fournir un service de support, une garantie ou des
mises à jour pour un travail qui a été modifié ou installé par le
Destinataire, ou pour le Produit Utilisateur dans lequel il a été
modifié ou installé. L’accès à un réseau peut être rejeté quand la
................................................................................
auprès du public sous forme de code source) et ne doit nécessiter
aucune clé ou mot de passe spécial pour le dépaquetage, la lecture ou
la copie.


Article 7. Termes additionnels.

Les « permissions additionelles » désignent les termes qui
supplémentent ceux de cette Licence en émettant des exceptions à l’une
ou plusieurs de ses conditions. Les permissions additionnelles qui
sont applicables au Programme entier doivent être traitées comme si
elles étaient incluent dans cette Licence, dans les limites de leur
validité suivant la loi applicable. Si des permissions additionnelles
s’appliquent seulement à une partie du Programme, cette partie peut
être utilisée séparément suivant ces permissions, mais le Programme
tout entier reste gouverné par cette Licence sans regard aux
permissions additionelles.

Quand vous acheminez une copie d’un Travail Couvert, vous pouvez à
votre convenance ôter toute permission additionelle de cette copie, ou
de n’importe quelle partie de celui-ci. (Des permissions
additionnelles peuvent être rédigées de façon à requérir leur propre
suppression dans certains cas où vous modifiez le travail.) Vous
pouvez placer les permissions additionnelles sur le matériel acheminé,
ajoutées par vous à un Travail Couvert pour lequel vous avez ou pouvez
donner les permissions de Droit d’Auteur (“copyright”) appropriées.

................................................................................
brevet). « Accorder » une telle licence de brevet à une partie signifie
conclure un tel accord ou engagement à ne pas faire appliquer le brevet
à cette partie.

Si vous acheminez un Travail Couvert, dépendant en connaissance d’une
licence de brevet, et si le Source Correspondant du travail n’est pas
disponible à quiconque copie, sans frais et suivant les termes de cette
Licence, à travers un serveur réseau publiquement acessible ou tout
autre moyen immédiatement accessible, alors vous devez soit (1) rendre
la Source Correspondante ainsi disponible, soit (2) vous engager à vous
priver pour vous-même du bénéfice de la licence de brevet pour ce
travail particulier, soit (3) vous engager, d’une façon consistante
avec les obligations de cette Licence, à étendre la licence de brevet
aux Destinataires de ce travail. « Dépendant en connaissance » signifie
que vous avez effectivement connaissance que, selon la licence de
................................................................................

Article 12. Non abandon de la liberté des autres.

Si des conditions vous sont imposées (que ce soit par décision
judiciaire, par un accord ou autrement) qui contredisent les conditions
de cette Licence, elles ne vous excusent pas des conditions de cette
Licence. Si vous ne pouvez pas acheminer un Travail Couvert de façon à
satisfaire simulténément vos obligations suivant cette Licence et
toutes autres obligations pertinentes, alors en conséquence vous ne
pouvez pas du tout l’acheminer. Par exemple, si vous avez un accord sur
des termes qui vous obligent à collecter pour le réacheminement des
royalties depuis ceux à qui vous acheminez le Programme, la seule façon
qui puisse vous permettre de satisfaire à la fois à ces termes et ceux
de cette Licence sera de vous abstenir entièrement d’acheminer le
Programme.
................................................................................

Si le Programme spécifie qu’un intermédiaire peut décider quelles
versions futures de la Licence Générale Publique GNU peut être
utilisée, la déclaration publique d’acceptation d’une version par cet
intermédiaire vous autorise à choisir cette version pour le Programme.

Des versions ultérieures de la licence peuvent vous donner des
permissions additionelles ou différentes. Cependant aucune obligation
additionelle n’est imposée à l’un des auteurs ou titulaires de Droit
d’Auteur du fait de votre choix de suivre une version ultérieure.


Article 15. Déclaration d’absence de garantie.

IL N’Y A AUCUNE GARANTIE POUR LE PROGRAMME, DANS LES LIMITES PERMISES
PAR LA LOI APPLICABLE. À MOINS QUE CELA NE SOIT ÉTABLI DIFFÉREMMENT PAR







|







 







|







 







|

|

|
|







 







|







 







|







 







|







 







|



|




|


|







 







|







 







|







 







|
|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
soit gratuit ou contre un paiement, vous devez accorder aux
Destinataires les mêmes libertés que vous avez reçues. Vous devez aussi
vous assurer qu’eux aussi reçoivent ou peuvent recevoir son code
source. Et vous devez leur montrer les termes de cette licence afin
qu’ils connaissent leurs droits.

Les développeurs qui utilisent la GPL GNU protègent vos droits en deux
étapes : (1) ils affirment leurs droits d’auteur (“copyright”) sur le
logiciel, et (2) vous accordent cette Licence qui vous donne la
permission légale de le copier, le distribuer et/ou le modifier.

Pour la protection des développeurs et auteurs, la GPL stipule
clairement qu’il n’y a pas de garantie pour ce logiciel libre. Aux fins
à la fois des utilisateurs et auteurs, la GPL requière que les versions
modifiées soient marquées comme changées, afin que leurs problèmes ne
................................................................................

Certains dispositifs sont conçus pour empêcher l’accès des utilisateurs
à l’installation ou l’exécution de versions modifiées du logiciel à
l’intérieur de ces dispositifs, alors que les fabricants le peuvent.
Ceci est fondamentalement incompatible avec le but de protéger la
liberté des utilisateurs de modifier le logiciel. L’aspect systématique
de tels abus se produit dans le secteur des produits destinés aux
utilisateurs individuels, ce qui est précisément ce qui est le plus
inacceptable. Aussi, nous avons conçu cette version de la GPL pour
prohiber cette pratique pour ces produits. Si de tels problèmes
surviennent dans d’autres domaines, nous nous tenons prêt à étendre
cette restriction à ces domaines dans de futures versions de la GPL,
autant qu’il sera nécessaire pour protéger la liberté des utilisateurs.

Finalement, chaque programme est constamment menacé par les brevets
................................................................................
     Appropriées, votre travail n’a pas à les modifier pour qu’elles
     les affichent. 

Une compilation d’un Travail Couvert avec d’autres travaux séparés et
indépendants, qui ne sont pas par leur nature des extensions du Travail
Couvert, et qui ne sont pas combinés avec lui de façon à former un
programme plus large, dans ou sur un volume de stockage ou un support
de distribution, est appelé un « agrégat » si la compilation et son
Droit d’Auteur résultant ne sont pas utilisés pour limiter l’accès ou
les droits légaux des utilisateurs de la compilation en deçà de ce que
permettent les travaux individuels. L’inclusion d’un Travail Couvert
dans un agrégat ne cause pas l’application de cette Licence aux
autres parties de l’agrégat.


Article 6. Acheminement des formes non sources.

Vous pouvez acheminer sous forme de code objet un Travail Couvert
suivant les termes des articles 4 et 5, pourvu que vous acheminiez
également suivant les termes de cette Licence le Source Correspondant
................................................................................
     utilisé pour les échanges de logiciels, pour un prix non supérieur
     au coût raisonnable de la réalisation physique de l’acheminement
     de la source, ou soit (2) un accès permettant de copier le Source
     Correspondant depuis un serveur réseau sans frais.

  c) Acheminer des copies individuelles du code objet avec une copie de
     l’offre écrite de fournir le Source Correspondant. Cette
     alternative est permise seulement occasionnellement et non
     commercialement, et seulement si vous avez reçu le code objet avec
     une telle offre, en accord avec l’article 6 alinéa b.

  d) Acheminer le code objet en offrant un accès depuis un emplacement
     désigné (gratuit ou contre facturation) et offrir un accès
     équivalent au Source Correspondant de la même façon via le même
     emplacement et sans facturation supplémentaire. Vous n’avez pas
................................................................................

  e) Acheminer le code objet en utilisant une transmission
     d’égal-à-égal, pourvu que vous informiez les autres participants
     sur où le code objet et le Source Correspondant du travail sont
     offerts sans frais au public général suivant l’article 6 alinéa d.
     Une portion séparable du code objet, dont le code source est exclu
     du Source Correspondant en tant que Bibliothèque Système, n’a pas
     besoin d’être inclus dans l’acheminement du travail sous forme de
     code objet.

Un « Produit Utilisateur » est soit (1) un « Produit de Consommation, »
ce qui signifie toute propriété personnelle tangible normalement
utilisée à des fins personnelles, familiales ou relatives au foyer,
soit (2) toute chose conçue ou vendue pour l’incorporation dans un lieu
d’habitation. Pour déterminer si un produit constitue un Produit de
................................................................................
l’acheminement se produit en tant qu’élément d’une transaction dans
laquelle le droit de possession et d’utilisation du Produit
Utilisateur est transféré au Destinataire définitivement ou pour un
terme fixé (indépendamment de la façon dont la transaction est
caractérisée), le Source Correspondant acheminé selon cet article-ci
doit être accompagné des Informations d’Installation. Mais cette
obligation ne s’applique pas si ni vous ni aucune tierce partie ne
détient la possibilité d’installer un code objet modifié sur le Produit
Utilisateur (par exemple, le travail a été installé en mémoire morte).

L’obligation de fournir les Informations d’Installation n’inclue pas
celle de continuer à fournir un service de support, une garantie ou des
mises à jour pour un travail qui a été modifié ou installé par le
Destinataire, ou pour le Produit Utilisateur dans lequel il a été
modifié ou installé. L’accès à un réseau peut être rejeté quand la
................................................................................
auprès du public sous forme de code source) et ne doit nécessiter
aucune clé ou mot de passe spécial pour le dépaquetage, la lecture ou
la copie.


Article 7. Termes additionnels.

Les « permissions additionnelles » désignent les termes qui
supplémentent ceux de cette Licence en émettant des exceptions à l’une
ou plusieurs de ses conditions. Les permissions additionnelles qui
sont applicables au Programme entier doivent être traitées comme si
elles étaient incluses dans cette Licence, dans les limites de leur
validité suivant la loi applicable. Si des permissions additionnelles
s’appliquent seulement à une partie du Programme, cette partie peut
être utilisée séparément suivant ces permissions, mais le Programme
tout entier reste gouverné par cette Licence sans regard aux
permissions additionnelles.

Quand vous acheminez une copie d’un Travail Couvert, vous pouvez à
votre convenance ôter toute permission additionnelle de cette copie, ou
de n’importe quelle partie de celui-ci. (Des permissions
additionnelles peuvent être rédigées de façon à requérir leur propre
suppression dans certains cas où vous modifiez le travail.) Vous
pouvez placer les permissions additionnelles sur le matériel acheminé,
ajoutées par vous à un Travail Couvert pour lequel vous avez ou pouvez
donner les permissions de Droit d’Auteur (“copyright”) appropriées.

................................................................................
brevet). « Accorder » une telle licence de brevet à une partie signifie
conclure un tel accord ou engagement à ne pas faire appliquer le brevet
à cette partie.

Si vous acheminez un Travail Couvert, dépendant en connaissance d’une
licence de brevet, et si le Source Correspondant du travail n’est pas
disponible à quiconque copie, sans frais et suivant les termes de cette
Licence, à travers un serveur réseau publiquement accessible ou tout
autre moyen immédiatement accessible, alors vous devez soit (1) rendre
la Source Correspondante ainsi disponible, soit (2) vous engager à vous
priver pour vous-même du bénéfice de la licence de brevet pour ce
travail particulier, soit (3) vous engager, d’une façon consistante
avec les obligations de cette Licence, à étendre la licence de brevet
aux Destinataires de ce travail. « Dépendant en connaissance » signifie
que vous avez effectivement connaissance que, selon la licence de
................................................................................

Article 12. Non abandon de la liberté des autres.

Si des conditions vous sont imposées (que ce soit par décision
judiciaire, par un accord ou autrement) qui contredisent les conditions
de cette Licence, elles ne vous excusent pas des conditions de cette
Licence. Si vous ne pouvez pas acheminer un Travail Couvert de façon à
satisfaire simultanément vos obligations suivant cette Licence et
toutes autres obligations pertinentes, alors en conséquence vous ne
pouvez pas du tout l’acheminer. Par exemple, si vous avez un accord sur
des termes qui vous obligent à collecter pour le réacheminement des
royalties depuis ceux à qui vous acheminez le Programme, la seule façon
qui puisse vous permettre de satisfaire à la fois à ces termes et ceux
de cette Licence sera de vous abstenir entièrement d’acheminer le
Programme.
................................................................................

Si le Programme spécifie qu’un intermédiaire peut décider quelles
versions futures de la Licence Générale Publique GNU peut être
utilisée, la déclaration publique d’acceptation d’une version par cet
intermédiaire vous autorise à choisir cette version pour le Programme.

Des versions ultérieures de la licence peuvent vous donner des
permissions additionnelles ou différentes. Cependant aucune obligation
additionnelle n’est imposée à l’un des auteurs ou titulaires de Droit
d’Auteur du fait de votre choix de suivre une version ultérieure.


Article 15. Déclaration d’absence de garantie.

IL N’Y A AUCUNE GARANTIE POUR LE PROGRAMME, DANS LES LIMITES PERMISES
PAR LA LOI APPLICABLE. À MOINS QUE CELA NE SOIT ÉTABLI DIFFÉREMMENT PAR

Modified THANKS.txt from [8029bfb1ad] to [8dd14e0ca5].

1
2
3
4
5
6
7
8
9
10
11
12
13
...
177
178
179
180
181
182
183
184

# THANKS

## Thanks to all who contributed to the project

László Németh (creator of Lightproof, from which Grammalecte forked),
Dominique Pelé (dominiko),
Jean-Luc T. (Tbj),
Pierre Choffardet (pitpit),


## Thanks to all those who supported us 
 
La Mouette [Association Pour une bureautique libre],
................................................................................
Vincent Meunier,
Willy Mangin,
Yann Asset,
Yann Brelière,
Yannick Geynet,
Yelin

et aux centaines de contributeurs qui ont préféré garder l’anonymat, ainsi qu’à la GPL3 de Richard Matthew Stallman.






|







 







|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
...
177
178
179
180
181
182
183
184
185
# THANKS

## Thanks to all who contributed to the project

László Németh (creator of Lightproof, from which Grammalecte forked),
Dominique Pellé (dominiko),
Jean-Luc T. (Tbj),
Pierre Choffardet (pitpit),


## Thanks to all those who supported us 
 
La Mouette [Association Pour une bureautique libre],
................................................................................
Vincent Meunier,
Willy Mangin,
Yann Asset,
Yann Brelière,
Yannick Geynet,
Yelin

and to hundred of supporters who prefered to keep their anonymity,
and to the GPL3 by Richard Matthew Stallman.

Modified cli.py from [39244ea849] to [ed7458a4d3].

16
17
18
19
20
21
22



23
24
25
26
27
28
29
...
196
197
198
199
200
201
202
203
204
205









206
207
208
209
210
211
212
_EXAMPLE = "Quoi ? Racontes ! Racontes-moi ! Bon sangg, parles ! Oui. Il y a des menteur partout. " \
           "Je suit sidéré par la brutales arrogance de cette homme-là. Quelle salopard ! Un escrocs de la pire espece. " \
           "Quant sera t’il châtiés pour ses mensonge ?             Merde ! J’en aie marre."

_HELP = """
    /help                       /h      show this text
    ?word1 [word2] ...                  words analysis



    /lopt                       /lo     list options
    /+ option1 [option2] ...            activate grammar checking options
    /- option1 [option2] ...            deactivate grammar checking options
    /lrules [pattern]           /lr     list rules
    /--rule1 [rule2] ...                deactivate grammar checking rule
    /++rule1 [rule2] ...                reactivate grammar checking rule
    /quit                       /q      exit
................................................................................
        # pseudo-console
        sInputText = "\n~==========~ Enter your text [/h /q] ~==========~\n"
        sText = _getText(sInputText)
        while True:
            if sText.startswith("?"):
                for sWord in sText[1:].strip().split():
                    if sWord:
                        echo("* {}".format(sWord))
                        for sMorph in oDict.getMorph(sWord):
                            echo("  {:<32} {}".format(sMorph, oLexGraphe.formatTags(sMorph)))









            elif sText.startswith("/+ "):
                gce.setOptions({ opt:True  for opt in sText[3:].strip().split()  if opt in gce.getOptions() })
                echo("done")
            elif sText.startswith("/- "):
                gce.setOptions({ opt:False  for opt in sText[3:].strip().split()  if opt in gce.getOptions() })
                echo("done")
            elif sText.startswith("/-- "):







>
>
>







 







|


>
>
>
>
>
>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
_EXAMPLE = "Quoi ? Racontes ! Racontes-moi ! Bon sangg, parles ! Oui. Il y a des menteur partout. " \
           "Je suit sidéré par la brutales arrogance de cette homme-là. Quelle salopard ! Un escrocs de la pire espece. " \
           "Quant sera t’il châtiés pour ses mensonge ?             Merde ! J’en aie marre."

_HELP = """
    /help                       /h      show this text
    ?word1 [word2] ...                  words analysis
    !word                               suggestion
    >word                               draw path of word in the word graph
    =filter                             show all entries whose morphology fits to filter
    /lopt                       /lo     list options
    /+ option1 [option2] ...            activate grammar checking options
    /- option1 [option2] ...            deactivate grammar checking options
    /lrules [pattern]           /lr     list rules
    /--rule1 [rule2] ...                deactivate grammar checking rule
    /++rule1 [rule2] ...                reactivate grammar checking rule
    /quit                       /q      exit
................................................................................
        # pseudo-console
        sInputText = "\n~==========~ Enter your text [/h /q] ~==========~\n"
        sText = _getText(sInputText)
        while True:
            if sText.startswith("?"):
                for sWord in sText[1:].strip().split():
                    if sWord:
                        echo("* " + sWord)
                        for sMorph in oDict.getMorph(sWord):
                            echo("  {:<32} {}".format(sMorph, oLexGraphe.formatTags(sMorph)))
            elif sText.startswith("!"):
                for sWord in sText[1:].strip().split():
                    if sWord:
                        echo(" | ".join(oDict.suggest(sWord)))
            elif sText.startswith(">"):
                oDict.drawPath(sText[1:].strip())
            elif sText.startswith("="):
                for sRes in oDict.select(sText[1:].strip()):
                    echo(sRes)
            elif sText.startswith("/+ "):
                gce.setOptions({ opt:True  for opt in sText[3:].strip().split()  if opt in gce.getOptions() })
                echo("done")
            elif sText.startswith("/- "):
                gce.setOptions({ opt:False  for opt in sText[3:].strip().split()  if opt in gce.getOptions() })
                echo("done")
            elif sText.startswith("/-- "):

Modified compile_rules.py from [20229cb495] to [7fa2e820bf].

1
2
3
4
5
6
7


8
9
10
11
12
13
14
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
322
323
324
325
326
327
328





329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
...
514
515
516
517
518
519
520

521
522
523
524
525
526
527
...
536
537
538
539
540
541
542



543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678

import re
import sys
import traceback
import copy
import json
from distutils import file_util




dDEF = {}
lFUNCTIONS = []

aRULESET = set()     # set of rule-ids to check if there is several rules with the same id
nRULEWITHOUTNAME = 0
................................................................................
    s = re.sub(r"isEndOfNG\(\s*\)", 'isEndOfNG(dDA, s[m.end():], m.end())', s)              # isEndOfNG(s)
    s = re.sub(r"isNextNotCOD\(\s*\)", 'isNextNotCOD(dDA, s[m.end():], m.end())', s)        # isNextNotCOD(s)
    s = re.sub(r"isNextVerb\(\s*\)", 'isNextVerb(dDA, s[m.end():], m.end())', s)            # isNextVerb(s)
    s = re.sub(r"\bspell *[(]", '_oDict.isValid(', s)
    s = re.sub(r"[\\](\d+)", 'm.group(\\1)', s)
    return s


def py2js (sCode):
    "convert Python code to JavaScript code"
    # Python 2.x unicode strings
    sCode = re.sub('\\b[ur]"', '"', sCode)
    sCode = re.sub("\\b[ur]'", "'", sCode)
    # operators
    sCode = sCode.replace(" and ", " && ")
    sCode = sCode.replace(" or ", " || ")
    sCode = re.sub("\\bnot\\b", "!", sCode)
    sCode = re.sub("(.+) if (.+) else (.+)", "(\\2) ? \\1 : \\3", sCode)
    # boolean
    sCode = sCode.replace("False", "false")
    sCode = sCode.replace("True", "true")
    sCode = sCode.replace("bool", "Boolean")
    # methods
    sCode = sCode.replace(".__len__()", ".length")
    sCode = sCode.replace(".endswith", ".endsWith")
    sCode = sCode.replace(".find", ".indexOf")
    sCode = sCode.replace(".startswith", ".startsWith")
    sCode = sCode.replace(".lower", ".toLowerCase")
    sCode = sCode.replace(".upper", ".toUpperCase")
    sCode = sCode.replace(".isdigit", "._isDigit")
    sCode = sCode.replace(".isupper", "._isUpperCase")
    sCode = sCode.replace(".islower", "._isLowerCase")
    sCode = sCode.replace(".istitle", "._isTitle")
    sCode = sCode.replace(".capitalize", "._toCapitalize")
    sCode = sCode.replace(".strip", "._trim")
    sCode = sCode.replace(".lstrip", "._trimLeft")
    sCode = sCode.replace(".rstrip", "._trimRight")
    sCode = sCode.replace('.replace("."', ".replace(/\./g")
    sCode = sCode.replace('.replace("..."', ".replace(/\.\.\./g")
    sCode = re.sub('.replace\("([^"]+)" ?,', ".replace(/\\1/g,", sCode)
    # regex
    sCode = re.sub('re.search\("([^"]+)", *(m.group\(\\d\))\)', "(\\2.search(/\\1/) >= 0)", sCode)
    sCode = re.sub(".search\\(/\\(\\?i\\)([^/]+)/\\) >= 0\\)", ".search(/\\1/i) >= 0)", sCode)
    sCode = re.sub('(look\\(sx?[][.a-z:()]*), "\\(\\?i\\)([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = re.sub('(look\\(sx?[][.a-z:()]*), "([^"]+)"', "\\1, /\\2/", sCode)
    sCode = re.sub('(look_chk1\\(dDA, sx?[][.a-z:()]*, [0-9a-z.()]+), "\\(\\?i\\)([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = re.sub('(look_chk1\\(dDA, sx?[][.a-z:()]*, [0-9a-z.()]+), "([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = sCode.replace("(?<!-)", "")  # todo
    # slices
    sCode = sCode.replace("[:m.start()]", ".slice(0,m.index)")
    sCode = sCode.replace("[m.end():]", ".slice(m.end[0])")
    sCode = sCode.replace("[m.start():m.end()]", ".slice(m.index, m.end[0])")
    sCode = re.sub("\\[(-?\\d+):(-?\\d+)\\]", ".slice(\\1,\\2)", sCode)
    sCode = re.sub("\\[(-?\\d+):\\]", ".slice(\\1)", sCode)
    sCode = re.sub("\\[:(-?\\d+)\\]", ".slice(0,\\1)", sCode)
    # regex matches
    sCode = sCode.replace(".end()", ".end[0]")
    sCode = sCode.replace(".start()", ".index")
    sCode = sCode.replace("m.group()", "m[0]")
    sCode = re.sub("\\.start\\((\\d+)\\)", ".start[\\1]", sCode)
    sCode = re.sub("m\\.group\\((\\d+)\\)", "m[\\1]", sCode)
    # tuples -> lists
    sCode = re.sub("\((m\.start\[\\d+\], m\[\\d+\])\)", "[\\1]", sCode)
    # regex
    sCode = sCode.replace("\w[\w-]+", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st][a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]+")
    sCode = sCode.replace(r"/\w/", "/[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st]/")
    sCode = sCode.replace(r"[\w-]", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]")
    sCode = sCode.replace(r"[\w,]", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st,]")
    return sCode


def uppercase (s, sLang):
    "(flag i is not enough): converts regex to uppercase regex: 'foo' becomes '[Ff][Oo][Oo]', but 'Bar' becomes 'B[Aa][Rr]'."
    sUp = ""
    nState = 0
    for i in range(0, len(s)):
        c = s[i]
................................................................................
        return None
    sRegex = s[:i].strip()
    s = s[i+4:]
    
    # JS groups positioning codes
    m = re.search("@@\\S+", sRegex)
    if m:
        tGroups = groupsPositioningCodeToList(sRegex[m.start()+2:])
        sRegex = sRegex[:m.start()].strip()
    # JS regex
    m = re.search("<js>.+</js>i?", sRegex)
    if m:
        dJSREGEXES[sLineId] = m.group(0)
        sRegex = sRegex[:m.start()].strip()
    if "<js>" in sRegex or "</js>" in sRegex:
................................................................................
    
    #### ACTION
    sAction = sAction[m.end():].strip()
    cAction = m.group(1)
    if cAction == "-":
        ## error
        iMsg = sAction.find(" # ")





        sMsg = sAction[iMsg+3:].strip()
        sAction = sAction[:iMsg].strip()
        sURL = ""
        mURL = re.search("[|] *(https?://.*)", sMsg)
        if mURL:
            sURL = mURL.group(1).strip()
            sMsg = sMsg[:mURL.start(0)].strip()
        if sMsg[0:1] == "=":
            sMsg = prepareFunction(sMsg[1:])
            lFUNCTIONS.append(("m_"+sIdAction, sMsg))
            for x in re.finditer("group[(](\d+)[)]", sMsg):
                if int(x.group(1)) > nGroup:
                    print("# Error in groups in message at line " + sIdAction + " ("+str(nGroup)+" groups only)")
            sMsg = "=m_"+sIdAction
        else:
            for x in re.finditer(r"\\(\d+)", sMsg):
                if int(x.group(1)) > nGroup:
                    print("# Error in groups in message at line " + sIdAction + " ("+str(nGroup)+" groups only)")
            if re.search("[.]\\w+[(]", sMsg):
                print("# Error in message at line " + sIdAction + ":  This message looks like code. Line should begin with =")
            
    if sAction[0:1] == "=" or cAction == "=":
        if "define" in sAction and not re.search(r"define\(\\\d+ *, *\[.*\] *\)", sAction):
            print("# Error in action at line " + sIdAction + ": second argument for define must be a list of strings")
        sAction = prepareFunction(sAction)
        sAction = sAction.replace("m.group(i[4])", "m.group("+str(iGroup)+")")
        for x in re.finditer("group[(](\d+)[)]", sAction):
            if int(x.group(1)) > nGroup:
                print("# Error in groups in replacement at line " + sIdAction + " ("+str(nGroup)+" groups only)")
    else:
        for x in re.finditer(r"\\(\d+)", sAction):
            if int(x.group(1)) > nGroup:
                print("# Error in groups in replacement at line " + sIdAction + " ("+str(nGroup)+" groups only)")
        if re.search("[.]\\w+[(]", sAction):
            print("# Error in action at line " + sIdAction + ":  This action looks like code. Line should begin with =")

    if cAction == "-":
        ## error detected --> suggestion
        if not sAction:
            print("# Error in action at line " + sIdAction + ":  This action is empty.")
        if sAction[0:1] == "=":
................................................................................
    elif cAction == ">":
        ## no action, break loop if condition is False
        return [sCondition, cAction, ""]
    else:
        print("# Unknown action at line " + sIdAction)
        return None


def regex2js (sRegex):
    "converts Python regex to JS regex and returns JS regex and list of negative lookbefore assertions"
    #   Latin letters: http://unicode-table.com/fr/
    #   0-9  and  _
    #   A-Z
    #   a-z
    #   À-Ö     00C0-00D6   (upper case)
    #   Ø-ß     00D8-00DF   (upper case)
    #   à-ö     00E0-00F6   (lower case)
    #   ø-ÿ     00F8-00FF   (lower case)
    #   Ā-ʯ     0100-02AF   (mixed)
    #   -> a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ
    bCaseInsensitive = False
    if "(?i)" in sRegex:
        sRegex = sRegex.replace("(?i)", "")
        bCaseInsensitive = True
    lNegLookBeforeRegex = []
    if sWORDLIMITLEFT in sRegex:
        sRegex = sRegex.replace(sWORDLIMITLEFT, "")
        lNegLookBeforeRegex = ["[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ.,–-]$"]
    sRegex = sRegex.replace("[\\w", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ")
    sRegex = sRegex.replace("\\w", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ]")
    sRegex = sRegex.replace("[.]", r"\.")
    if not sRegex.startswith("<js>"):
        sRegex = sRegex.replace("/", r"\/")
    m = re.search(r"\(\?<!([^()]+)\)", sRegex)  # Negative lookbefore assertion should always be at the beginning of regex
    if m:
        lNegLookBeforeRegex.append(m.group(1)+"$")
        sRegex = sRegex.replace(m.group(0), "")
    if "(?<" in sRegex:
        print("# Warning. Lookbefore assertion not changed in:\n  ")
        print(sRegex)
    if sRegex.startswith("<js>"):
        sRegex = sRegex.replace('<js>', '/').replace('</js>i', '/ig').replace('</js>', '/g')
    else:
        sRegex = "/" + sRegex + "/g"
    if bCaseInsensitive and not sRegex.endswith("/ig"):
        sRegex = sRegex + "i"
    if not lNegLookBeforeRegex:
        lNegLookBeforeRegex = None
    return (sRegex, lNegLookBeforeRegex)


def pyRuleToJS (lRule):
    lRuleJS = copy.deepcopy(lRule)
    del lRule[-1] # tGroups positioning codes are useless for Python
    # error messages
    for aAction in lRuleJS[6]:
        if aAction[1] == "-":
            aAction[4] = aAction[4].replace("« ", "«&nbsp;").replace(" »", "&nbsp;»")
    # js regexes
    lRuleJS[1], lNegLookBehindRegex = regex2js( dJSREGEXES.get(lRuleJS[3], lRuleJS[1]) )
    lRuleJS.append(lNegLookBehindRegex)
    return lRuleJS


def writeRulesToJSArray (lRules):
    sArray = "[\n"
    for sOption, aRuleGroup in lRules:
        sArray += '  ["' + sOption + '", [\n'  if sOption  else  "  [false, [\n"
        for sRegex, bCaseInsensitive, sLineId, sRuleId, nPriority, lActions, aGroups, aNegLookBehindRegex in aRuleGroup:
            sArray += '    [' + sRegex + ", "
            sArray += "true, " if bCaseInsensitive  else "false, "
            sArray += '"' + sLineId + '", '
            sArray += '"' + sRuleId + '", '
            sArray += str(nPriority) + ", "
            sArray += json.dumps(lActions, ensure_ascii=False) + ", "
            sArray += json.dumps(aGroups, ensure_ascii=False) + ", "
            sArray += json.dumps(aNegLookBehindRegex, ensure_ascii=False) + "],\n"
        sArray += "  ]],\n"
    sArray += "]"
    return sArray


def groupsPositioningCodeToList (sGroupsPositioningCode):
    if not sGroupsPositioningCode:
        return None
    return [ int(sCode)  if sCode.isdigit() or (sCode[0:1] == "-" and sCode[1:].isdigit())  else sCode \
             for sCode in sGroupsPositioningCode.split(",") ]


def _calcRulesStats (lRules):
    d = {'=':0, '~': 0, '-': 0, '>': 0}
    for aRule in lRules:
        for aAction in aRule[6]:
            d[aAction[1]] = d[aAction[1]] + 1
    return (d, len(lRules))
................................................................................
    lFinal.append([sOption, lTemp])
    return lFinal


def prepareOptions (lOptionLines):
    "returns a dictionary with data about options"
    sLang = ""

    lStructOpt = []
    lOpt = []
    dOptLabel = {}
    dOptPriority = {}
    for sLine in lOptionLines:
        sLine = sLine.strip()
        if sLine.startswith("OPTGROUP/"):
................................................................................
        elif sLine.startswith("OPTPRIORITY/"):
            m = re.match("OPTPRIORITY/([a-z0-9]+): *([0-9])$", sLine)
            dOptPriority[m.group(1)] = int(m.group(2))
        elif sLine.startswith("OPTLANG/"):
            m = re.match("OPTLANG/([a-z][a-z](?:_[A-Z][A-Z]|)):(.+)$", sLine)
            sLang = m.group(1)[:2]
            dOptLabel[sLang] = { "__optiontitle__": m.group(2).strip() }



        elif sLine.startswith("OPTLABEL/"):
            m = re.match("OPTLABEL/([a-z0-9]+):(.+)$", sLine)
            dOptLabel[sLang][m.group(1)] = list(map(str.strip, m.group(2).split("|")))  if "|" in m.group(2)  else  [m.group(2).strip(), ""]
        else:
            print("# Error. Wrong option line in:\n  ")
            print(sLine)
    print("  options defined for: " + ", ".join([ t[0] for t in lOpt ]))
    dOptions = { "lStructOpt": lStructOpt, "dOptLabel": dOptLabel }
    dOptions.update({ "dOpt"+k: v  for k, v in lOpt })
    return dOptions, dOptPriority


def printBookmark (nLevel, sComment, nLine):
    print("  {:>6}:  {}".format(nLine, "  " * nLevel + sComment))

................................................................................
            else:
                print("Error in definition: ", end="")
                print(sLine.strip())
        elif sLine.startswith("TEST:"):
            lTest.append("{:<8}".format(i) + "  " + sLine[5:].strip())
        elif sLine.startswith("TODO:"):
            pass
        elif sLine.startswith(("OPTGROUP/", "OPTSOFTWARE:", "OPT/", "OPTLANG/", "OPTLABEL/", "OPTPRIORITY/")):
            lOpt.append(sLine)
        elif re.match("[  \t]*$", sLine):
            pass
        elif sLine.startswith("!!"):
            m = zBookmark.search(sLine)
            nExMk = len(m.group(0))
            if sLine[nExMk:].strip():
................................................................................
            if sLine == "[++]":
                bParagraph = False
            else:
                aRule = createRule(sLine, nLine, sLang, bParagraph, dOptPriority)
                if aRule:
                    if bParagraph:
                        lParagraphRules.append(aRule)
                        lParagraphRulesJS.append(pyRuleToJS(aRule))
                    else:
                        lSentenceRules.append(aRule)
                        lSentenceRulesJS.append(pyRuleToJS(aRule))

    # creating file with all functions callable by rules
    print("  creating callables...")
    sPyCallables = "# generated code, do not edit\n"
    sJSCallables = "// generated code, do not edit\nconst oEvalFunc = {\n"
    for sFuncName, sReturn in lFUNCTIONS:
        cType = sFuncName[0:1]
................................................................................
            sParams = "s, m, dDA"
        else:
            print("# Unknown function type in [" + sFuncName + "]")
            continue
        sPyCallables += "def {} ({}):\n".format(sFuncName, sParams)
        sPyCallables += "    return " + sReturn + "\n"
        sJSCallables += "    {}: function ({})".format(sFuncName, sParams) + " {\n"
        sJSCallables += "        return " + py2js(sReturn) + ";\n"
        sJSCallables += "    },\n"
    sJSCallables += "}\n"

    displayStats(lParagraphRules, lSentenceRules)

    print("Unnamed rules: " + str(nRULEWITHOUTNAME))

    d = { "callables": sPyCallables,
          "callablesJS": sJSCallables,
          "gctests": sGCTests,
          "gctestsJS": sGCTestsJS,
          "paragraph_rules": mergeRulesByOption(lParagraphRules),
          "sentence_rules": mergeRulesByOption(lSentenceRules),
          "paragraph_rules_JS": writeRulesToJSArray(mergeRulesByOption(lParagraphRulesJS)),
          "sentence_rules_JS": writeRulesToJSArray(mergeRulesByOption(lSentenceRulesJS)) }
    d.update(dOptions)

    return d




<


>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|













|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>







 







>
>
>







|







 







|







 







|


|







 







|













|
|



1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
..
56
57
58
59
60
61
62































































63
64
65
66
67
68
69
...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
339
340
341
342
343
344
345

















































































346
347
348
349
350
351
352
...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544

import re
import sys
import traceback

import json
from distutils import file_util

import compile_rules_js_convert as jsconv


dDEF = {}
lFUNCTIONS = []

aRULESET = set()     # set of rule-ids to check if there is several rules with the same id
nRULEWITHOUTNAME = 0
................................................................................
    s = re.sub(r"isEndOfNG\(\s*\)", 'isEndOfNG(dDA, s[m.end():], m.end())', s)              # isEndOfNG(s)
    s = re.sub(r"isNextNotCOD\(\s*\)", 'isNextNotCOD(dDA, s[m.end():], m.end())', s)        # isNextNotCOD(s)
    s = re.sub(r"isNextVerb\(\s*\)", 'isNextVerb(dDA, s[m.end():], m.end())', s)            # isNextVerb(s)
    s = re.sub(r"\bspell *[(]", '_oDict.isValid(', s)
    s = re.sub(r"[\\](\d+)", 'm.group(\\1)', s)
    return s

































































def uppercase (s, sLang):
    "(flag i is not enough): converts regex to uppercase regex: 'foo' becomes '[Ff][Oo][Oo]', but 'Bar' becomes 'B[Aa][Rr]'."
    sUp = ""
    nState = 0
    for i in range(0, len(s)):
        c = s[i]
................................................................................
        return None
    sRegex = s[:i].strip()
    s = s[i+4:]
    
    # JS groups positioning codes
    m = re.search("@@\\S+", sRegex)
    if m:
        tGroups = jsconv.groupsPositioningCodeToList(sRegex[m.start()+2:])
        sRegex = sRegex[:m.start()].strip()
    # JS regex
    m = re.search("<js>.+</js>i?", sRegex)
    if m:
        dJSREGEXES[sLineId] = m.group(0)
        sRegex = sRegex[:m.start()].strip()
    if "<js>" in sRegex or "</js>" in sRegex:
................................................................................
    
    #### ACTION
    sAction = sAction[m.end():].strip()
    cAction = m.group(1)
    if cAction == "-":
        ## error
        iMsg = sAction.find(" # ")
        if iMsg == -1:
            sMsg = "# Error. Error message not found."
            sURL = ""
            print(sMsg + " Action id: " + sIdAction)
        else:
            sMsg = sAction[iMsg+3:].strip()
            sAction = sAction[:iMsg].strip()
            sURL = ""
            mURL = re.search("[|] *(https?://.*)", sMsg)
            if mURL:
                sURL = mURL.group(1).strip()
                sMsg = sMsg[:mURL.start(0)].strip()
            if sMsg[0:1] == "=":
                sMsg = prepareFunction(sMsg[1:])
                lFUNCTIONS.append(("m_"+sIdAction, sMsg))
                for x in re.finditer("group[(](\d+)[)]", sMsg):
                    if int(x.group(1)) > nGroup:
                        print("# Error in groups in message at line " + sIdAction + " ("+str(nGroup)+" groups only)")
                sMsg = "=m_"+sIdAction
            else:
                for x in re.finditer(r"\\(\d+)", sMsg):
                    if int(x.group(1)) > nGroup:
                        print("# Error in groups in message at line " + sIdAction + " ("+str(nGroup)+" groups only)")
                if re.search("[.]\\w+[(]", sMsg):
                    print("# Error in message at line " + sIdAction + ":  This message looks like code. Line should begin with =")
            
    if sAction[0:1] == "=" or cAction == "=":
        if "define" in sAction and not re.search(r"define\(\\\d+ *, *\[.*\] *\)", sAction):
            print("# Error in action at line " + sIdAction + ": second argument for define must be a list of strings")
        sAction = prepareFunction(sAction)
        sAction = sAction.replace("m.group(i[4])", "m.group("+str(iGroup)+")")
        for x in re.finditer("group[(](\d+)[)]", sAction):
            if int(x.group(1)) > nGroup:
                print("# Error in groups in replacement at line " + sIdAction + " ("+str(nGroup)+" groups only)")
    else:
        for x in re.finditer(r"\\(\d+)", sAction):
            if int(x.group(1)) > nGroup:
                print("# Error in groups in replacement at line " + sIdAction + " ("+str(nGroup)+" groups only)")
        if re.search("[.]\\w+[(]|sugg\\w+[(]", sAction):
            print("# Error in action at line " + sIdAction + ":  This action looks like code. Line should begin with =")

    if cAction == "-":
        ## error detected --> suggestion
        if not sAction:
            print("# Error in action at line " + sIdAction + ":  This action is empty.")
        if sAction[0:1] == "=":
................................................................................
    elif cAction == ">":
        ## no action, break loop if condition is False
        return [sCondition, cAction, ""]
    else:
        print("# Unknown action at line " + sIdAction)
        return None



















































































def _calcRulesStats (lRules):
    d = {'=':0, '~': 0, '-': 0, '>': 0}
    for aRule in lRules:
        for aAction in aRule[6]:
            d[aAction[1]] = d[aAction[1]] + 1
    return (d, len(lRules))
................................................................................
    lFinal.append([sOption, lTemp])
    return lFinal


def prepareOptions (lOptionLines):
    "returns a dictionary with data about options"
    sLang = ""
    sDefaultUILang = ""
    lStructOpt = []
    lOpt = []
    dOptLabel = {}
    dOptPriority = {}
    for sLine in lOptionLines:
        sLine = sLine.strip()
        if sLine.startswith("OPTGROUP/"):
................................................................................
        elif sLine.startswith("OPTPRIORITY/"):
            m = re.match("OPTPRIORITY/([a-z0-9]+): *([0-9])$", sLine)
            dOptPriority[m.group(1)] = int(m.group(2))
        elif sLine.startswith("OPTLANG/"):
            m = re.match("OPTLANG/([a-z][a-z](?:_[A-Z][A-Z]|)):(.+)$", sLine)
            sLang = m.group(1)[:2]
            dOptLabel[sLang] = { "__optiontitle__": m.group(2).strip() }
        elif sLine.startswith("OPTDEFAULTUILANG:"):
            m = re.match("OPTDEFAULTUILANG: *([a-z][a-z](?:_[A-Z][A-Z]|))$", sLine)
            sDefaultUILang = m.group(1)[:2]
        elif sLine.startswith("OPTLABEL/"):
            m = re.match("OPTLABEL/([a-z0-9]+):(.+)$", sLine)
            dOptLabel[sLang][m.group(1)] = list(map(str.strip, m.group(2).split("|")))  if "|" in m.group(2)  else  [m.group(2).strip(), ""]
        else:
            print("# Error. Wrong option line in:\n  ")
            print(sLine)
    print("  options defined for: " + ", ".join([ t[0] for t in lOpt ]))
    dOptions = { "lStructOpt": lStructOpt, "dOptLabel": dOptLabel, "sDefaultUILang": sDefaultUILang }
    dOptions.update({ "dOpt"+k: v  for k, v in lOpt })
    return dOptions, dOptPriority


def printBookmark (nLevel, sComment, nLine):
    print("  {:>6}:  {}".format(nLine, "  " * nLevel + sComment))

................................................................................
            else:
                print("Error in definition: ", end="")
                print(sLine.strip())
        elif sLine.startswith("TEST:"):
            lTest.append("{:<8}".format(i) + "  " + sLine[5:].strip())
        elif sLine.startswith("TODO:"):
            pass
        elif sLine.startswith(("OPTGROUP/", "OPTSOFTWARE:", "OPT/", "OPTLANG/", "OPTDEFAULTUILANG:", "OPTLABEL/", "OPTPRIORITY/")):
            lOpt.append(sLine)
        elif re.match("[  \t]*$", sLine):
            pass
        elif sLine.startswith("!!"):
            m = zBookmark.search(sLine)
            nExMk = len(m.group(0))
            if sLine[nExMk:].strip():
................................................................................
            if sLine == "[++]":
                bParagraph = False
            else:
                aRule = createRule(sLine, nLine, sLang, bParagraph, dOptPriority)
                if aRule:
                    if bParagraph:
                        lParagraphRules.append(aRule)
                        lParagraphRulesJS.append(jsconv.pyRuleToJS(aRule, dJSREGEXES, sWORDLIMITLEFT))
                    else:
                        lSentenceRules.append(aRule)
                        lSentenceRulesJS.append(jsconv.pyRuleToJS(aRule, dJSREGEXES, sWORDLIMITLEFT))

    # creating file with all functions callable by rules
    print("  creating callables...")
    sPyCallables = "# generated code, do not edit\n"
    sJSCallables = "// generated code, do not edit\nconst oEvalFunc = {\n"
    for sFuncName, sReturn in lFUNCTIONS:
        cType = sFuncName[0:1]
................................................................................
            sParams = "s, m, dDA"
        else:
            print("# Unknown function type in [" + sFuncName + "]")
            continue
        sPyCallables += "def {} ({}):\n".format(sFuncName, sParams)
        sPyCallables += "    return " + sReturn + "\n"
        sJSCallables += "    {}: function ({})".format(sFuncName, sParams) + " {\n"
        sJSCallables += "        return " + jsconv.py2js(sReturn) + ";\n"
        sJSCallables += "    },\n"
    sJSCallables += "}\n"

    displayStats(lParagraphRules, lSentenceRules)

    print("Unnamed rules: " + str(nRULEWITHOUTNAME))

    d = { "callables": sPyCallables,
          "callablesJS": sJSCallables,
          "gctests": sGCTests,
          "gctestsJS": sGCTestsJS,
          "paragraph_rules": mergeRulesByOption(lParagraphRules),
          "sentence_rules": mergeRulesByOption(lSentenceRules),
          "paragraph_rules_JS": jsconv.writeRulesToJSArray(mergeRulesByOption(lParagraphRulesJS)),
          "sentence_rules_JS": jsconv.writeRulesToJSArray(mergeRulesByOption(lSentenceRulesJS)) }
    d.update(dOptions)

    return d

Added compile_rules_js_convert.py version [e1dbc7ea44].













































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Convert Python code to JavaScript code

import copy
import re
import json


def py2js (sCode):
    "convert Python code to JavaScript code"
    # Python 2.x unicode strings
    sCode = re.sub('\\b[ur]"', '"', sCode)
    sCode = re.sub("\\b[ur]'", "'", sCode)
    # operators
    sCode = sCode.replace(" and ", " && ")
    sCode = sCode.replace(" or ", " || ")
    sCode = re.sub("\\bnot\\b", "!", sCode)
    sCode = re.sub("(.+) if (.+) else (.+)", "(\\2) ? \\1 : \\3", sCode)
    # boolean
    sCode = sCode.replace("False", "false")
    sCode = sCode.replace("True", "true")
    sCode = sCode.replace("bool", "Boolean")
    # methods
    sCode = sCode.replace(".__len__()", ".length")
    sCode = sCode.replace(".endswith", ".endsWith")
    sCode = sCode.replace(".find", ".indexOf")
    sCode = sCode.replace(".startswith", ".startsWith")
    sCode = sCode.replace(".lower", ".toLowerCase")
    sCode = sCode.replace(".upper", ".toUpperCase")
    sCode = sCode.replace(".isdigit", ".gl_isDigit")
    sCode = sCode.replace(".isupper", ".gl_isUpperCase")
    sCode = sCode.replace(".islower", ".gl_isLowerCase")
    sCode = sCode.replace(".istitle", ".gl_isTitle")
    sCode = sCode.replace(".capitalize", ".gl_toCapitalize")
    sCode = sCode.replace(".strip", ".gl_trim")
    sCode = sCode.replace(".lstrip", ".gl_trimLeft")
    sCode = sCode.replace(".rstrip", ".gl_trimRight")
    sCode = sCode.replace('.replace("."', ".replace(/\./g")
    sCode = sCode.replace('.replace("..."', ".replace(/\.\.\./g")
    sCode = re.sub('.replace\("([^"]+)" ?,', ".replace(/\\1/g,", sCode)
    # regex
    sCode = re.sub('re.search\("([^"]+)", *(m.group\(\\d\))\)', "(\\2.search(/\\1/) >= 0)", sCode)
    sCode = re.sub(".search\\(/\\(\\?i\\)([^/]+)/\\) >= 0\\)", ".search(/\\1/i) >= 0)", sCode)
    sCode = re.sub('(look\\(sx?[][.a-z:()]*), "\\(\\?i\\)([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = re.sub('(look\\(sx?[][.a-z:()]*), "([^"]+)"', "\\1, /\\2/", sCode)
    sCode = re.sub('(look_chk1\\(dDA, sx?[][.a-z:()]*, [0-9a-z.()]+), "\\(\\?i\\)([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = re.sub('(look_chk1\\(dDA, sx?[][.a-z:()]*, [0-9a-z.()]+), "([^"]+)"', "\\1, /\\2/i", sCode)
    sCode = sCode.replace("(?<!-)", "")  # todo
    # slices
    sCode = sCode.replace("[:m.start()]", ".slice(0,m.index)")
    sCode = sCode.replace("[m.end():]", ".slice(m.end[0])")
    sCode = sCode.replace("[m.start():m.end()]", ".slice(m.index, m.end[0])")
    sCode = re.sub("\\[(-?\\d+):(-?\\d+)\\]", ".slice(\\1,\\2)", sCode)
    sCode = re.sub("\\[(-?\\d+):\\]", ".slice(\\1)", sCode)
    sCode = re.sub("\\[:(-?\\d+)\\]", ".slice(0,\\1)", sCode)
    # regex matches
    sCode = sCode.replace(".end()", ".end[0]")
    sCode = sCode.replace(".start()", ".index")
    sCode = sCode.replace("m.group()", "m[0]")
    sCode = re.sub("\\.start\\((\\d+)\\)", ".start[\\1]", sCode)
    sCode = re.sub("m\\.group\\((\\d+)\\)", "m[\\1]", sCode)
    # tuples -> lists
    sCode = re.sub("\((m\.start\[\\d+\], m\[\\d+\])\)", "[\\1]", sCode)
    # regex
    sCode = sCode.replace("\w[\w-]+", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st][a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]+")
    sCode = sCode.replace(r"/\w/", "/[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st]/")
    sCode = sCode.replace(r"[\w-]", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]")
    sCode = sCode.replace(r"[\w,]", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st,]")
    return sCode


def regex2js (sRegex, sWORDLIMITLEFT):
    "converts Python regex to JS regex and returns JS regex and list of negative lookbefore assertions"
    #   Latin letters: http://unicode-table.com/fr/
    #   0-9  and  _
    #   A-Z
    #   a-z
    #   À-Ö     00C0-00D6   (upper case)
    #   Ø-ß     00D8-00DF   (upper case)
    #   à-ö     00E0-00F6   (lower case)
    #   ø-ÿ     00F8-00FF   (lower case)
    #   Ā-ʯ     0100-02AF   (mixed)
    #   -> a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ
    bCaseInsensitive = False
    if "(?i)" in sRegex:
        sRegex = sRegex.replace("(?i)", "")
        bCaseInsensitive = True
    lNegLookBeforeRegex = []
    if sWORDLIMITLEFT in sRegex:
        sRegex = sRegex.replace(sWORDLIMITLEFT, "")
        lNegLookBeforeRegex = ["[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ.,–-]$"]
    sRegex = sRegex.replace("[\\w", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ")
    sRegex = sRegex.replace("\\w", "[a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯ]")
    sRegex = sRegex.replace("[.]", r"\.")
    if not sRegex.startswith("<js>"):
        sRegex = sRegex.replace("/", r"\/")
    m = re.search(r"\(\?<!([^()]+)\)", sRegex)  # Negative lookbefore assertion should always be at the beginning of regex
    if m:
        lNegLookBeforeRegex.append(m.group(1)+"$")
        sRegex = sRegex.replace(m.group(0), "")
    if "(?<" in sRegex:
        print("# Warning. Lookbefore assertion not changed in:\n  ")
        print(sRegex)
    if sRegex.startswith("<js>"):
        sRegex = sRegex.replace('<js>', '/').replace('</js>i', '/ig').replace('</js>', '/g')
    else:
        sRegex = "/" + sRegex + "/g"
    if bCaseInsensitive and not sRegex.endswith("/ig"):
        sRegex = sRegex + "i"
    if not lNegLookBeforeRegex:
        lNegLookBeforeRegex = None
    return (sRegex, lNegLookBeforeRegex)


def pyRuleToJS (lRule, dJSREGEXES, sWORDLIMITLEFT):
    lRuleJS = copy.deepcopy(lRule)
    del lRule[-1] # tGroups positioning codes are useless for Python
    # error messages
    for aAction in lRuleJS[6]:
        if aAction[1] == "-":
            aAction[2] = aAction[2].replace(" ", " ") # nbsp --> nnbsp
            aAction[4] = aAction[4].replace("« ", "« ").replace(" »", " »").replace(" :", " :").replace(" :", " :")
    # js regexes
    lRuleJS[1], lNegLookBehindRegex = regex2js(dJSREGEXES.get(lRuleJS[3], lRuleJS[1]), sWORDLIMITLEFT)
    lRuleJS.append(lNegLookBehindRegex)
    return lRuleJS


def writeRulesToJSArray (lRules):
    sArray = "[\n"
    for sOption, aRuleGroup in lRules:
        sArray += '  ["' + sOption + '", [\n'  if sOption  else  "  [false, [\n"
        for sRegex, bCaseInsensitive, sLineId, sRuleId, nPriority, lActions, aGroups, aNegLookBehindRegex in aRuleGroup:
            sArray += '    [' + sRegex + ", "
            sArray += "true, " if bCaseInsensitive  else "false, "
            sArray += '"' + sLineId + '", '
            sArray += '"' + sRuleId + '", '
            sArray += str(nPriority) + ", "
            sArray += json.dumps(lActions, ensure_ascii=False) + ", "
            sArray += json.dumps(aGroups, ensure_ascii=False) + ", "
            sArray += json.dumps(aNegLookBehindRegex, ensure_ascii=False) + "],\n"
        sArray += "  ]],\n"
    sArray += "]"
    return sArray


def groupsPositioningCodeToList (sGroupsPositioningCode):
    if not sGroupsPositioningCode:
        return None
    return [ int(sCode)  if sCode.isdigit() or (sCode[0:1] == "-" and sCode[1:].isdigit())  else sCode \
             for sCode in sGroupsPositioningCode.split(",") ]

Modified doc/build.md from [0d772932a8] to [28ea36b703].

49
50
51
52
53
54
55
56
57
58





59
60
61
62
63
64
65

`-i --install`

> Install the LibreOffice extension.

`-fx --firefox`

> Launch Firefox Nightly.
> Unit tests can be lanched from Firefox, with CTRL+SHIFT+F12.






`-tb --thunderbird`

> Launch Thunderbird.


## Examples ##








|


>
>
>
>
>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

`-i --install`

> Install the LibreOffice extension.

`-fx --firefox`

> Launch Firefox Developper (before Firefox 57).
> Unit tests can be lanched from Firefox, with CTRL+SHIFT+F12.

`-we --webext`

> Launch Firefox Nightly (Firefox 57+).
> Unit tests can be lanched from the menu.

`-tb --thunderbird`

> Launch Thunderbird.


## Examples ##

Modified gc_core/js/helpers.js from [6c4ecd114f] to [7c62a39694].

1
2


3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34




35





36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82



83
84


85
86
87
88


// HELPERS



"use strict";

// In Firefox, there is no console.log in PromiseWorker, but there is worker.log.
// In Thunderbird, you can’t access to console directly. So it’s required to pass a log function.
let funcOutput = null;



function setLogOutput (func) {
    funcOutput = func;
}

function echo (obj) {
    if (funcOutput !== null) {
        funcOutput(obj);
    } else {
        console.log(obj);
    }
    return true;
}

function logerror (e, bStack=false) {
    let sMsg = "\n" + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message;
    if (bStack) {
        sMsg += "\n--- Stack ---\n" + e.stack;
    }
    if (funcOutput !== null) {
        funcOutput(sMsg);
    } else {
        console.error(sMsg);
    }
}











// load ressources in workers (suggested by Mozilla extensions reviewers)
// for more options have a look here: https://gist.github.com/Noitidart/ec1e6b9a593ec7e3efed
// if not in workers, use sdk/data.load() instead
function loadFile (spf) {
    try {
        let xRequest;
        if (typeof XMLHttpRequest !== "undefined") {
            xRequest = new XMLHttpRequest();
        }
        else {
            // JS bullshit again… necessary for Thunderbird
            let { Cc, Ci } = require("chrome");
            xRequest = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
            xRequest.QueryInterface(Ci.nsIXMLHttpRequest);
        }
        xRequest.open('GET', spf, false); // 3rd arg is false for synchronous, sync is acceptable in workers

        xRequest.send();
        return xRequest.responseText;
    }
    catch (e) {
        logerror(e);
        return null
    }
}


    


// conversions
function objectToMap (obj) {
    let m = new Map();
    for (let param in obj) {
        //console.log(param + " " + obj[param]);
        m.set(param, obj[param]);
    }
    return m;
}

function mapToObject (m) {
    let obj = {};
    for (let [k, v] of m) {
        obj[k] = v;
    }
    return obj;
}





exports.echo = echo;
exports.logerror = logerror;


exports.objectToMap = objectToMap;
exports.mapToObject = mapToObject;
exports.setLogOutput = setLogOutput;
exports.loadFile = loadFile;



>
>







>
>
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

>
>
>
>
|
>
>
>
>
>
|
|
|
<
|
|
|
|
<
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|

<
<
<
<
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
>

>
>
>
|
|
>
>
|
|
<
<
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72




73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


101

// HELPERS
/*jslint esversion: 6*/
/*global console,require,exports,XMLHttpRequest*/

"use strict";

// In Firefox, there is no console.log in PromiseWorker, but there is worker.log.
// In Thunderbird, you can’t access to console directly. So it’s required to pass a log function.
let funcOutput = null;

var helpers = {

    setLogOutput: function (func) {
        funcOutput = func;
    },

    echo: function (obj) {
        if (funcOutput !== null) {
            funcOutput(obj);
        } else {
            console.log(obj);
        }
        return true;
    },

    logerror: function (e, bStack=false) {
        let sMsg = "\n" + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message;
        if (bStack) {
            sMsg += "\n--- Stack ---\n" + e.stack;
        }
        if (funcOutput !== null) {
            funcOutput(sMsg);
        } else {
            console.error(sMsg);
        }
    },

    inspect: function (o) {
        let sMsg = "__inspect__: " + typeof o;
        for (let sParam in o) {
            sMsg += "\n" + sParam + ": " + o.sParam;
        }
        sMsg += "\n" + JSON.stringify(o) + "\n__end__";
        this.echo(sMsg);
    },

    loadFile: function (spf) {
        // load ressources in workers (suggested by Mozilla extensions reviewers)
        // for more options have a look here: https://gist.github.com/Noitidart/ec1e6b9a593ec7e3efed
        // if not in workers, use sdk/data.load() instead

        try {
            let xRequest;
            if (typeof XMLHttpRequest !== "undefined") {
                xRequest = new XMLHttpRequest();

            } else {
                // JS bullshit again… necessary for Thunderbird
                let { Cc, Ci } = require("chrome");
                xRequest = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
                xRequest.QueryInterface(Ci.nsIXMLHttpRequest);
            }
            xRequest.open('GET', spf, false); // 3rd arg is false for synchronous, sync is acceptable in workers
            xRequest.overrideMimeType('text/json');
            xRequest.send();
            return xRequest.responseText;
        }
        catch (e) {
            this.logerror(e);
            return null;
        }
    },





    // conversions
    objectToMap: function (obj) {
        let m = new Map();
        for (let param in obj) {
            //console.log(param + " " + obj[param]);
            m.set(param, obj[param]);
        }
        return m;
    },

    mapToObject: function (m) {
        let obj = {};
        for (let [k, v] of m) {
            obj[k] = v;
        }
        return obj;
    }
};


if (typeof(exports) !== 'undefined') {
    exports.setLogOutput = helpers.setLogOutput;
    exports.echo = helpers.echo;
    exports.logerror = helpers.logerror;
    exports.inspect = helpers.inspect;
    exports.loadFile = helpers.loadFile;
    exports.objectToMap = helpers.objectToMap;
    exports.mapToObject = helpers.mapToObject;


}

Modified gc_core/js/ibdawg.js from [2d42754063] to [4cc6e3ad82].

1


2
3
4


5
6

7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291

//// IBDAWG



"use strict";



const st = require("resource://grammalecte/str_transform.js");
const helpers = require("resource://grammalecte/helpers.js");



// String
// Don’t remove. Necessary in TB.
${string}



class IBDAWG {
    // INDEXABLE BINARY DIRECT ACYCLIC WORD GRAPH

    constructor (sDicName) {
        try {

            const dict = JSON.parse(helpers.loadFile("resource://grammalecte/_dictionaries/"+sDicName));
            Object.assign(this, dict);
            //const dict = require("resource://grammalecte/"+sLang+"/dictionary.js");
            //Object.assign(this, dict.dictionary);
        }
        catch (e) {
            throw Error("# Error. File not found or not loadable.\n" + e.message + "\n");
        }
        /*
            Properties:
            sName, nVersion, sHeader, lArcVal, nArcVal, byDic, sLang, nChar, nBytesArc, nBytesNodeAddress,
................................................................................
            throw RangeError("# Error. Unknown dictionary version: " + this.nVersion);
        }

        this.dChar = helpers.objectToMap(this.dChar);
        //this.byDic = new Uint8Array(this.byDic);  // not quicker, even slower

        if (this.cStemming == "S") {
            this.funcStemming = st.getStemFromSuffixCode;
        } else if (this.cStemming == "A") {
            this.funcStemming = st.getStemFromAffixCode;
        } else {
            this.funcStemming = st.noStemming;
        }

        // Configuring DAWG functions according to nVersion
        switch (this.nVersion) {
            case 1:
                this.morph = this._morph1;
                this.stem = this._stem1;
................................................................................
                break;
            default:
                throw ValueError("# Error: unknown code: " + this.nVersion);
        }
        //console.log(this.getInfo());
        this.bOptNumSigle = true;
        this.bOptNumAtLast = false;
    };

    getInfo () {
        return  `  Language: ${this.sLang}      Version: ${this.nVersion}      Stemming: ${this.cStemming}FX\n` +
                `  Arcs values:  ${this.nArcVal} = ${this.nChar} characters,  ${this.nAff} affixes,  ${this.nTag} tags\n` +
                `  Dictionary: ${this.nEntries} entries,    ${this.nNode} nodes,   ${this.nArc} arcs\n` +
                `  Address size: ${this.nBytesNodeAddress} bytes,  Arc size: ${this.nBytesArc} bytes\n`;
    };

    isValidToken (sToken) {
        // checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)
        if (this.isValid(sToken)) {
            return true;
        }
        if (sToken.includes("-")) {
            if (sToken._count("-") > 4) {
                return true;
            }
            return sToken.split("-").every(sWord  =>  this.isValid(sWord)); 
        }
        return false;
    };

    isValid (sWord) {
        // checks if sWord is valid (different casing tested if the first letter is a capital)
        if (!sWord) {
            return null;
        }
        if (sWord.includes("’")) { // ugly hack
            sWord = sWord.replace("’", "'");
        }
        if (this.lookup(sWord)) {
            return true;
        }
        if (sWord.charAt(0)._isUpperCase()) {
            if (sWord.length > 1) {
                if (sWord._isTitle()) {
                    return !!this.lookup(sWord.toLowerCase());
                }
                if (sWord._isUpperCase()) {
                    if (this.bOptNumSigle) {
                        return true;
                    }
                    return !!(this.lookup(sWord.toLowerCase()) || this.lookup(sWord._toCapitalize()));
                }
                return !!this.lookup(sWord.slice(0, 1).toLowerCase() + sWord.slice(1));
            } else {
                return !!this.lookup(sWord.toLowerCase());
            }
        }
        return false;
    };

    _convBytesToInteger (aBytes) {
        // Byte order = Big Endian (bigger first)
        let nVal = 0;
        let nWeight = (aBytes.length - 1) * 8;
        for (let n of aBytes) {
            nVal += n << nWeight;
            nWeight = nWeight - 8;
        }
        return nVal;
    };

    lookup (sWord) {
        // returns true if sWord in dictionary (strict verification)
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
                return false;
................................................................................
            }
            iAddr = this._lookupArcNode(this.dChar.get(c), iAddr);
            if (iAddr === null) {
                return false;
            }
        }
        return Boolean(this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask);
    };

    getMorph (sWord) {
        // retrieves morphologies list, different casing allowed
        let l = this.morph(sWord);
        if (sWord[0]._isUpperCase()) {
            l = l.concat(this.morph(sWord.toLowerCase()));
            if (sWord._isUpperCase() && sWord.length > 1) {
                l = l.concat(this.morph(sWord._toCapitalize()));
            }
        }
        return l;
    };

    // morph (sWord) {
    //     is defined in constructor
    // };
    
    // VERSION 1
    _morph1 (sWord) {
        // returns morphologies of sWord
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
................................................................................
                    }
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
            return l;
        }
        return [];
    };

    _stem1 (sWord) {
        // returns stems list of sWord
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
                return [];
................................................................................
                    l.push(this.funcStemming(sWord, this.lArcVal[nArc]));
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
            return l;
        }
        return [];
    };

    _lookupArcNode1 (nVal, iAddr) {
        // looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None
        while (true) {
            let iEndArcAddr = iAddr+this.nBytesArc;
            let nRawArc = this._convBytesToInteger(this.byDic.slice(iAddr, iEndArcAddr));
            if (nVal == (nRawArc & this._arcMask)) {
................................................................................
                // value not found
                if (nRawArc & this._lastArcMask) {
                    return null;
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
        }
    };

    // VERSION 2
    _morph2 (sWord) {
        // to do
    };

    _stem2 (sWord) {
        // to do
    };

    _lookupArcNode2 (nVal, iAddr) {
        // to do
    };


    // VERSION 3
    _morph3 (sWord) {
        // to do
    };

    _stem3 (sWord) {
        // to do
    };

    _lookupArcNode3 (nVal, iAddr) {
        // to do
    };
}



exports.IBDAWG = IBDAWG;


>
>



>
>
|
|
>











|

>
|

<
<







 







|

|

|







 







|






|







|





|












|

|


|



|







|










|







 







|




|

|
|



|



|







 







|







 







|







 







|




|



|



|





|



|



|



>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
..
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
//// IBDAWG
/*jslint esversion: 6*/
/*global console,require,exports*/

"use strict";


if (typeof(require) !== 'undefined') {
    var str_transform = require("resource://grammalecte/str_transform.js");
    var helpers = require("resource://grammalecte/helpers.js");
}


// String
// Don’t remove. Necessary in TB.
${string}



class IBDAWG {
    // INDEXABLE BINARY DIRECT ACYCLIC WORD GRAPH

    constructor (sDicName, sPath="") {
        try {
            let sURL = (sPath !== "") ? sPath + "/" + sDicName : "resource://grammalecte/_dictionaries/"+sDicName;
            const dict = JSON.parse(helpers.loadFile(sURL));
            Object.assign(this, dict);


        }
        catch (e) {
            throw Error("# Error. File not found or not loadable.\n" + e.message + "\n");
        }
        /*
            Properties:
            sName, nVersion, sHeader, lArcVal, nArcVal, byDic, sLang, nChar, nBytesArc, nBytesNodeAddress,
................................................................................
            throw RangeError("# Error. Unknown dictionary version: " + this.nVersion);
        }

        this.dChar = helpers.objectToMap(this.dChar);
        //this.byDic = new Uint8Array(this.byDic);  // not quicker, even slower

        if (this.cStemming == "S") {
            this.funcStemming = str_transform.getStemFromSuffixCode;
        } else if (this.cStemming == "A") {
            this.funcStemming = str_transform.getStemFromAffixCode;
        } else {
            this.funcStemming = str_transform.noStemming;
        }

        // Configuring DAWG functions according to nVersion
        switch (this.nVersion) {
            case 1:
                this.morph = this._morph1;
                this.stem = this._stem1;
................................................................................
                break;
            default:
                throw ValueError("# Error: unknown code: " + this.nVersion);
        }
        //console.log(this.getInfo());
        this.bOptNumSigle = true;
        this.bOptNumAtLast = false;
    }

    getInfo () {
        return  `  Language: ${this.sLang}      Version: ${this.nVersion}      Stemming: ${this.cStemming}FX\n` +
                `  Arcs values:  ${this.nArcVal} = ${this.nChar} characters,  ${this.nAff} affixes,  ${this.nTag} tags\n` +
                `  Dictionary: ${this.nEntries} entries,    ${this.nNode} nodes,   ${this.nArc} arcs\n` +
                `  Address size: ${this.nBytesNodeAddress} bytes,  Arc size: ${this.nBytesArc} bytes\n`;
    }

    isValidToken (sToken) {
        // checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)
        if (this.isValid(sToken)) {
            return true;
        }
        if (sToken.includes("-")) {
            if (sToken.gl_count("-") > 4) {
                return true;
            }
            return sToken.split("-").every(sWord  =>  this.isValid(sWord)); 
        }
        return false;
    }

    isValid (sWord) {
        // checks if sWord is valid (different casing tested if the first letter is a capital)
        if (!sWord) {
            return null;
        }
        if (sWord.includes("’")) { // ugly hack
            sWord = sWord.replace("’", "'");
        }
        if (this.lookup(sWord)) {
            return true;
        }
        if (sWord.charAt(0).gl_isUpperCase()) {
            if (sWord.length > 1) {
                if (sWord.gl_isTitle()) {
                    return !!this.lookup(sWord.toLowerCase());
                }
                if (sWord.gl_isUpperCase()) {
                    if (this.bOptNumSigle) {
                        return true;
                    }
                    return !!(this.lookup(sWord.toLowerCase()) || this.lookup(sWord.gl_toCapitalize()));
                }
                return !!this.lookup(sWord.slice(0, 1).toLowerCase() + sWord.slice(1));
            } else {
                return !!this.lookup(sWord.toLowerCase());
            }
        }
        return false;
    }

    _convBytesToInteger (aBytes) {
        // Byte order = Big Endian (bigger first)
        let nVal = 0;
        let nWeight = (aBytes.length - 1) * 8;
        for (let n of aBytes) {
            nVal += n << nWeight;
            nWeight = nWeight - 8;
        }
        return nVal;
    }

    lookup (sWord) {
        // returns true if sWord in dictionary (strict verification)
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
                return false;
................................................................................
            }
            iAddr = this._lookupArcNode(this.dChar.get(c), iAddr);
            if (iAddr === null) {
                return false;
            }
        }
        return Boolean(this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask);
    }

    getMorph (sWord) {
        // retrieves morphologies list, different casing allowed
        let l = this.morph(sWord);
        if (sWord[0].gl_isUpperCase()) {
            l = l.concat(this.morph(sWord.toLowerCase()));
            if (sWord.gl_isUpperCase() && sWord.length > 1) {
                l = l.concat(this.morph(sWord.gl_toCapitalize()));
            }
        }
        return l;
    }

    // morph (sWord) {
    //     is defined in constructor
    // }
    
    // VERSION 1
    _morph1 (sWord) {
        // returns morphologies of sWord
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
................................................................................
                    }
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
            return l;
        }
        return [];
    }

    _stem1 (sWord) {
        // returns stems list of sWord
        let iAddr = 0;
        for (let c of sWord) {
            if (!this.dChar.has(c)) {
                return [];
................................................................................
                    l.push(this.funcStemming(sWord, this.lArcVal[nArc]));
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
            return l;
        }
        return [];
    }

    _lookupArcNode1 (nVal, iAddr) {
        // looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None
        while (true) {
            let iEndArcAddr = iAddr+this.nBytesArc;
            let nRawArc = this._convBytesToInteger(this.byDic.slice(iAddr, iEndArcAddr));
            if (nVal == (nRawArc & this._arcMask)) {
................................................................................
                // value not found
                if (nRawArc & this._lastArcMask) {
                    return null;
                }
                iAddr = iEndArcAddr + this.nBytesNodeAddress;
            }
        }
    }

    // VERSION 2
    _morph2 (sWord) {
        // to do
    }

    _stem2 (sWord) {
        // to do
    }

    _lookupArcNode2 (nVal, iAddr) {
        // to do
    }


    // VERSION 3
    _morph3 (sWord) {
        // to do
    }

    _stem3 (sWord) {
        // to do
    }

    _lookupArcNode3 (nVal, iAddr) {
        // to do
    }
}


if (typeof(exports) !== 'undefined') {
    exports.IBDAWG = IBDAWG;
}

Modified gc_core/js/jsex_map.js from [181b814a6e] to [3dc39be41a].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

// Map


if (Map.prototype.__grammalecte__ === undefined) {
    Map.prototype._shallowCopy = function () {
        let oNewMap = new Map();
        for (let [key, val] of this.entries()) {
            oNewMap.set(key, val);
        }
        return oNewMap;
    }

    Map.prototype._get = function (key, defaultValue) {
        let res = this.get(key);
        if (res !== undefined) {
            return res;
        }
        return defaultValue;
    }

    Map.prototype._toString = function () {
        // Default .toString() gives nothing useful
        let sRes = "{ ";
        for (let [k, v] of this.entries()) {
            sRes += (typeof k === "string") ? '"' + k + '": ' : k.toString() + ": ";
            sRes += (typeof v === "string") ? '"' + v + '", ' : v.toString() + ", ";
        }
        sRes = sRes.slice(0, -2) + " }"
        return sRes;
    }

    Map.prototype._update = function (dDict) {
        for (let [k, v] of dDict.entries()) {
            this.set(k, v);
        }
    }

    Map.prototype._updateOnlyExistingKeys = function (dDict) {
        for (let [k, v] of dDict.entries()) {
            if (this.has(k)){
                this.set(k, v);
            }
        }
    }

    Map.prototype.__grammalecte__ = true;
}


>

|
|





|

|





|

|






|

|

|



|

|





|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// Map
/*jslint esversion: 6*/

if (Map.prototype.grammalecte === undefined) {
    Map.prototype.gl_shallowCopy = function () {
        let oNewMap = new Map();
        for (let [key, val] of this.entries()) {
            oNewMap.set(key, val);
        }
        return oNewMap;
    };

    Map.prototype.gl_get = function (key, defaultValue) {
        let res = this.get(key);
        if (res !== undefined) {
            return res;
        }
        return defaultValue;
    };

    Map.prototype.gl_toString = function () {
        // Default .toString() gives nothing useful
        let sRes = "{ ";
        for (let [k, v] of this.entries()) {
            sRes += (typeof k === "string") ? '"' + k + '": ' : k.toString() + ": ";
            sRes += (typeof v === "string") ? '"' + v + '", ' : v.toString() + ", ";
        }
        sRes = sRes.slice(0, -2) + " }";
        return sRes;
    };

    Map.prototype.gl_update = function (dDict) {
        for (let [k, v] of dDict.entries()) {
            this.set(k, v);
        }
    };

    Map.prototype.gl_updateOnlyExistingKeys = function (dDict) {
        for (let [k, v] of dDict.entries()) {
            if (this.has(k)){
                this.set(k, v);
            }
        }
    };

    Map.prototype.grammalecte = true;
}

Modified gc_core/js/jsex_regex.js from [de380ed036] to [0c1a934c00].

1
2

3
4
5
6
7
8
9
10
11
12
..
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75








76
77
78
79
80

// regex


if (RegExp.prototype.__grammalecte__ === undefined) {
    RegExp.prototype._exec2 = function (sText, aGroupsPos, aNegLookBefore=null) {
        let m;
        while ((m = this.exec(sText)) !== null) {
            // we have to iterate over sText here too
            // because first match doesn’t imply it’s a valid match according to negative lookbefore assertions,
            // and even if first match is finally invalid, it doesn’t mean the following eligible matchs would be invalid too.
            if (aNegLookBefore !== null) {
                // check negative look before assertions
................................................................................
            return null;
        }

        let codePos;
        let iPos = 0;
        m.start = [m.index];
        m.end = [this.lastIndex];

        if (m.length > 1) {
            // there is subgroup(s)
            if (aGroupsPos !== null) {
                // aGroupsPos is defined
                for (let i = 1; i <= m.length-1; i++) {
                    codePos = aGroupsPos[i-1];
                    if (typeof codePos === "number") {
                        // position as a number
                        m.start.push(m.index + codePos);
                        m.end.push(m.index + codePos + m[i].length);
                    } else if (codePos === "$") {
                        // at the end of the pattern
                        m.start.push(this.lastIndex - m[i].length);
                        m.end.push(this.lastIndex);
                    } else if (codePos === "w") {
                        // word in the middle of the pattern
                        iPos = m[0].search("[ ~’,()«»“”]"+m[i]+"[ ,’~()«»“”]") + 1 + m.index
                        m.start.push(iPos);
                        m.end.push(iPos + m[i].length)
                    } else if (codePos === "*") {
                        // anywhere
                        iPos = m[0].indexOf(m[i]) + m.index;
                        m.start.push(iPos);
                        m.end.push(iPos + m[i].length)
                    } else if (codePos === "**") {
                        // anywhere after previous group
                        iPos = m[0].indexOf(m[i], m.end[i-1]-m.index) + m.index;
                        m.start.push(iPos);
                        m.end.push(iPos + m[i].length)
                    } else if (codePos.startsWith(">")) {
                        // >x:_
                        // todo: look in substring x
                        iPos = m[0].indexOf(m[i]) + m.index;
                        m.start.push(iPos);
                        m.end.push(iPos + m[i].length);
                    } else {
                        console.error("# Error: unknown positioning code in regex [" + this.source + "], for group[" + i.toString() +"], code: [" + codePos + "]");
                    }
                }
            } else {
                // no aGroupsPos
                for (let subm of m.slice(1)) {
                    iPos = m[0].indexOf(subm) + m.index;
                    m.start.push(iPos);
                    m.end.push(iPos + subm.length);
                }
            }
        }








        return m;
    }

    RegExp.prototype.__grammalecte__ = true;
}


>

|
|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>

|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
..
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

// regex
/*jslint esversion: 6*/

if (RegExp.prototype.grammalecte === undefined) {
    RegExp.prototype.gl_exec2 = function (sText, aGroupsPos, aNegLookBefore=null) {
        let m;
        while ((m = this.exec(sText)) !== null) {
            // we have to iterate over sText here too
            // because first match doesn’t imply it’s a valid match according to negative lookbefore assertions,
            // and even if first match is finally invalid, it doesn’t mean the following eligible matchs would be invalid too.
            if (aNegLookBefore !== null) {
                // check negative look before assertions
................................................................................
            return null;
        }

        let codePos;
        let iPos = 0;
        m.start = [m.index];
        m.end = [this.lastIndex];
        try {
            if (m.length > 1) {
                // there is subgroup(s)
                if (aGroupsPos !== null) {
                    // aGroupsPos is defined
                    for (let i = 1; i <= m.length-1; i++) {
                        codePos = aGroupsPos[i-1];
                        if (typeof codePos === "number") {
                            // position as a number
                            m.start.push(m.index + codePos);
                            m.end.push(m.index + codePos + m[i].length);
                        } else if (codePos === "$") {
                            // at the end of the pattern
                            m.start.push(this.lastIndex - m[i].length);
                            m.end.push(this.lastIndex);
                        } else if (codePos === "w") {
                            // word in the middle of the pattern
                            iPos = m[0].search("[ ’,()«»“”]"+m[i]+"[ ,’()«»“”]") + 1 + m.index;
                            m.start.push(iPos);
                            m.end.push(iPos + m[i].length);
                        } else if (codePos === "*") {
                            // anywhere
                            iPos = m[0].indexOf(m[i]) + m.index;
                            m.start.push(iPos);
                            m.end.push(iPos + m[i].length);
                        } else if (codePos === "**") {
                            // anywhere after previous group
                            iPos = m[0].indexOf(m[i], m.end[i-1]-m.index) + m.index;
                            m.start.push(iPos);
                            m.end.push(iPos + m[i].length);
                        } else if (codePos.startsWith(">")) {
                            // >x:_
                            // todo: look in substring x
                            iPos = m[0].indexOf(m[i]) + m.index;
                            m.start.push(iPos);
                            m.end.push(iPos + m[i].length);
                        } else {
                            console.error("# Error: unknown positioning code in regex [" + this.source + "], for group[" + i.toString() +"], code: [" + codePos + "]");
                        }
                    }
                } else {
                    // no aGroupsPos
                    for (let subm of m.slice(1)) {
                        iPos = m[0].indexOf(subm) + m.index;
                        m.start.push(iPos);
                        m.end.push(iPos + subm.length);
                    }
                }
            }
        }
        catch (e) {
            if (typeof(helpers) !== "undefined") {
                helpers.logerror(e);
            } else {
                console.error(e);
            }
        }
        return m;
    };

    RegExp.prototype.grammalecte = true;
}

Modified gc_core/js/jsex_string.js from [adf06fbda5] to [34840fe9fe].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

// String


if (String.prototype.__grammalecte__ === undefined) {
    String.prototype._count = function (sSearch, bOverlapping) {
        // http://jsperf.com/string-ocurrence-split-vs-match/8
        if (sSearch.length <= 0) {
            return this.length + 1;
        }
        let nOccur = 0;
        let iPos = 0;
        let nStep = (bOverlapping) ? 1 : sSearch.length;
        while ((iPos = this.indexOf(sSearch, iPos)) >= 0) {
            nOccur++;
            iPos += nStep;
        }
        return nOccur;
    }
    String.prototype._isDigit = function () {
        return (this.search(/^[0-9⁰¹²³⁴⁵⁶⁷⁸⁹]+$/) !== -1);
    }
    String.prototype._isLowerCase = function () {
        return (this.search(/^[a-zà-öø-ÿ0-9-]+$/) !== -1);
    }
    String.prototype._isUpperCase = function () {
        return (this.search(/^[A-ZÀ-ÖØ-ߌ0-9-]+$/) !== -1);
    }
    String.prototype._isTitle = function () {
        return (this.search(/^[A-ZÀ-ÖØ-ߌ][a-zà-öø-ÿ'’-]+$/) !== -1);
    }
    String.prototype._toCapitalize = function () {
        return this.slice(0,1).toUpperCase() + this.slice(1).toLowerCase();
    }
    String.prototype._expand = function (oMatch) {
        let sNew = this;
        for (let i = 0; i < oMatch.length ; i++) {
            let z = new RegExp("\\\\"+parseInt(i), "g");
            sNew = sNew.replace(z, oMatch[i]);
        }
        return sNew;
    }
    String.prototype._trimRight = function (sChars) {
        let z = new RegExp("["+sChars+"]+$");
        return this.replace(z, "");
    }
    String.prototype._trimLeft = function (sChars) {
        let z = new RegExp("^["+sChars+"]+");
        return this.replace(z, "");
    }
    String.prototype._trim = function (sChars) {
        let z1 = new RegExp("^["+sChars+"]+");
        let z2 = new RegExp("["+sChars+"]+$");
        return this.replace(z1, "").replace(z2, "");
    }

    String.prototype.__grammalecte__ = true;
}


>

|
|












|
|

|
|

|
|

|
|

|
|

|
|






|
|


|
|


|
|



|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

// String
/*jslint esversion: 6*/

if (String.prototype.grammalecte === undefined) {
    String.prototype.gl_count = function (sSearch, bOverlapping) {
        // http://jsperf.com/string-ocurrence-split-vs-match/8
        if (sSearch.length <= 0) {
            return this.length + 1;
        }
        let nOccur = 0;
        let iPos = 0;
        let nStep = (bOverlapping) ? 1 : sSearch.length;
        while ((iPos = this.indexOf(sSearch, iPos)) >= 0) {
            nOccur++;
            iPos += nStep;
        }
        return nOccur;
    };
    String.prototype.gl_isDigit = function () {
        return (this.search(/^[0-9⁰¹²³⁴⁵⁶⁷⁸⁹]+$/) !== -1);
    };
    String.prototype.gl_isLowerCase = function () {
        return (this.search(/^[a-zà-öø-ÿ0-9-]+$/) !== -1);
    };
    String.prototype.gl_isUpperCase = function () {
        return (this.search(/^[A-ZÀ-ÖØ-ߌ0-9-]+$/) !== -1);
    };
    String.prototype.gl_isTitle = function () {
        return (this.search(/^[A-ZÀ-ÖØ-ߌ][a-zà-öø-ÿ'’-]+$/) !== -1);
    };
    String.prototype.gl_toCapitalize = function () {
        return this.slice(0,1).toUpperCase() + this.slice(1).toLowerCase();
    };
    String.prototype.gl_expand = function (oMatch) {
        let sNew = this;
        for (let i = 0; i < oMatch.length ; i++) {
            let z = new RegExp("\\\\"+parseInt(i), "g");
            sNew = sNew.replace(z, oMatch[i]);
        }
        return sNew;
    };
    String.prototype.gl_trimRight = function (sChars) {
        let z = new RegExp("["+sChars+"]+$");
        return this.replace(z, "");
    };
    String.prototype.gl_trimLeft = function (sChars) {
        let z = new RegExp("^["+sChars+"]+");
        return this.replace(z, "");
    };
    String.prototype.gl_trim = function (sChars) {
        let z1 = new RegExp("^["+sChars+"]+");
        let z2 = new RegExp("["+sChars+"]+$");
        return this.replace(z1, "").replace(z2, "");
    };

    String.prototype.grammalecte = true;
}

Modified gc_core/js/lang_core/gc_engine.js from [908b008d84] to [a71cf52ea3].

1




2
3
4
5
6















7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489


490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
...
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606

607
608
609

610















611
612
613
614
615
616
617
618
619
620

// Grammar checker engine





${string}
${regex}
${map}

















function capitalizeArray (aArray) {
    // can’t map on user defined function??
    let aNew = [];
    for (let i = 0; i < aArray.length; i = i + 1) {
        aNew[i] = aArray[i]._toCapitalize();
    }
    return aNew;
}

const ibdawg = require("resource://grammalecte/ibdawg.js");
const helpers = require("resource://grammalecte/helpers.js");
const gc_options = require("resource://grammalecte/${lang}/gc_options.js");
const cr = require("resource://grammalecte/${lang}/cregex.js");
const text = require("resource://grammalecte/text.js");
const echo = require("resource://grammalecte/helpers.js").echo;

const lang = "${lang}";
const locales = ${loc};
const pkg = "${implname}";
const name = "${name}";
const version = "${version}";
const author = "${author}";

// commons regexes
const _zEndOfSentence = new RegExp ('([.?!:;…][ .?!… »”")]*|.$)', "g");
const _zBeginOfParagraph = new RegExp ("^[-  –—.,;?!…]*", "ig");
const _zEndOfParagraph = new RegExp ("[-  .,;?!…–—]*$", "ig");

// grammar rules and dictionary
//const _rules = require("./gc_rules.js");
const _rules = require("resource://grammalecte/${lang}/gc_rules.js");
let _dOptions = gc_options.dOpt._shallowCopy();     // duplication necessary, to be able to reset to default
let _aIgnoredRules = new Set();
let _oDict = null;
let _dAnalyses = new Map();                        // cache for data from dictionary


///// Parsing

function parse (sText, sCountry="${country_default}", bDebug=false, bContext=false) {
    // analyses the paragraph sText and returns list of errors
    let dErrors;
    let errs;
    let sAlt = sText;
    let dDA = new Map();        // Disamnbiguator
    let dPriority = new Map();  // Key = position; value = priority
    let sNew = "";

    // parse paragraph
    try {
        [sNew, dErrors] = _proofread(sText, sAlt, 0, true, dDA, dPriority, sCountry, bDebug, bContext);
        if (sNew) {
            sText = sNew;
        }
    }
    catch (e) {
        helpers.logerror(e);
    }

    // cleanup
    if (sText.includes(" ")) {
        sText = sText.replace(/ /g, ' '); // nbsp
    }
    if (sText.includes(" ")) {
        sText = sText.replace(/ /g, ' '); // snbsp
    }
    if (sText.includes("'")) {
        sText = sText.replace(/'/g, "’");
    }
    if (sText.includes("‑")) {
        sText = sText.replace(/‑/g, "-"); // nobreakdash
    }

    // parse sentence
    for (let [iStart, iEnd] of _getSentenceBoundaries(sText)) {
        if (4 < (iEnd - iStart) < 2000) {
            dDA.clear();
            //echo(sText.slice(iStart, iEnd));
            try {
                [_, errs] = _proofread(sText.slice(iStart, iEnd), sAlt.slice(iStart, iEnd), iStart, false, dDA, dPriority, sCountry, bDebug, bContext);
                dErrors._update(errs);
            }
            catch (e) {
                helpers.logerror(e);
            }
        }
    }
    return Array.from(dErrors.values());
}

function* _getSentenceBoundaries (sText) {
    let mBeginOfSentence = _zBeginOfParagraph.exec(sText)
    let iStart = _zBeginOfParagraph.lastIndex;
    let m;
    while ((m = _zEndOfSentence.exec(sText)) !== null) {
        yield [iStart, _zEndOfSentence.lastIndex];
        iStart = _zEndOfSentence.lastIndex;
    }
}

function _proofread (s, sx, nOffset, bParagraph, dDA, dPriority, sCountry, bDebug, bContext) {
    let dErrs = new Map();
    let bChange = false;
    let bIdRule = option('idrule');
    let m;
    let bCondMemo;
    let nErrorStart;

    for (let [sOption, lRuleGroup] of _getRules(bParagraph)) {
        if (!sOption || option(sOption)) {
            for (let [zRegex, bUppercase, sLineId, sRuleId, nPriority, lActions, lGroups, lNegLookBefore] of lRuleGroup) {
                if (!_aIgnoredRules.has(sRuleId)) {
                    while ((m = zRegex._exec2(s, lGroups, lNegLookBefore)) !== null) {
                        bCondMemo = null;
                        /*if (bDebug) {
                            echo(">>>> Rule # " + sLineId + " - Text: " + s + " opt: "+ sOption);
                        }*/
                        for (let [sFuncCond, cActionType, sWhat, ...eAct] of lActions) {
                        // action in lActions: [ condition, action type, replacement/suggestion/action[, iGroup[, message, URL]] ]
                            try {
                                //echo(oEvalFunc[sFuncCond]);
                                bCondMemo = (!sFuncCond || oEvalFunc[sFuncCond](s, sx, m, dDA, sCountry, bCondMemo))
                                if (bCondMemo) {
                                    switch (cActionType) {
                                        case "-":
                                            // grammar error
                                            //echo("-> error detected in " + sLineId + "\nzRegex: " + zRegex.source);
                                            nErrorStart = nOffset + m.start[eAct[0]];
                                            if (!dErrs.has(nErrorStart) || nPriority > dPriority.get(nErrorStart)) {
                                                dErrs.set(nErrorStart, _createError(s, sx, sWhat, nOffset, m, eAct[0], sLineId, sRuleId, bUppercase, eAct[1], eAct[2], bIdRule, sOption, bContext));
                                                dPriority.set(nErrorStart, nPriority);
                                            }
                                            break;
                                        case "~":
                                            // text processor
                                            //echo("-> text processor by " + sLineId + "\nzRegex: " + zRegex.source);
                                            s = _rewrite(s, sWhat, eAct[0], m, bUppercase);
                                            bChange = true;
                                            if (bDebug) {
                                                echo("~ " + s + "  -- " + m[eAct[0]] + "  # " + sLineId);
                                            }
                                            break;
                                        case "=":
                                            // disambiguation
                                            //echo("-> disambiguation by " + sLineId + "\nzRegex: " + zRegex.source);
                                            oEvalFunc[sWhat](s, m, dDA);
                                            if (bDebug) {
                                                echo("= " + m[0] + "  # " + sLineId + "\nDA: " + dDA._toString());
                                            }
                                            break;
                                        case ">":
                                            // we do nothing, this test is just a condition to apply all following actions
                                            break;
                                        default:
                                            echo("# error: unknown action at " + sLineId);
                                    }
                                } else {
                                    if (cActionType == ">") {
                                        break;
                                    }
                                }
                            }
                            catch (e) {
                                echo(s);
                                echo("# line id: " + sLineId + "\n# rule id: " + sRuleId);
                                helpers.logerror(e);
                            }
                        }
                    }
                }
            }
        }
    }
    if (bChange) {
        return [s, dErrs];
    }
    return [false, dErrs];
}

function _createError (s, sx, sRepl, nOffset, m, iGroup, sLineId, sRuleId, bUppercase, sMsg, sURL, bIdRule, sOption, bContext) {
    let oErr = {};
    oErr["nStart"] = nOffset + m.start[iGroup];
    oErr["nEnd"] = nOffset + m.end[iGroup];
    oErr["sLineId"] = sLineId;
    oErr["sRuleId"] = sRuleId;
    oErr["sType"] = (sOption) ? sOption : "notype";
    // suggestions
    if (sRepl[0] === "=") {
        let sugg = oEvalFunc[sRepl.slice(1)](s, m);
        if (sugg) {
            if (bUppercase && m[iGroup].slice(0,1)._isUpperCase()) {
                oErr["aSuggestions"] = capitalizeArray(sugg.split("|"));
            } else {
                oErr["aSuggestions"] = sugg.split("|");
            }
        } else {
            oErr["aSuggestions"] = [];
        }
    } else if (sRepl == "_") {
        oErr["aSuggestions"] = [];
    } else {
        if (bUppercase && m[iGroup].slice(0,1)._isUpperCase()) {
            oErr["aSuggestions"] = capitalizeArray(sRepl._expand(m).split("|"));
        } else {
            oErr["aSuggestions"] = sRepl._expand(m).split("|");
        }
    }
    // Message
    if (sMsg[0] === "=") {
        sMessage = oEvalFunc[sMsg.slice(1)](s, m)
    } else {
        sMessage = sMsg._expand(m);
    }
    if (bIdRule) {
        sMessage += "  #" + sLineId + " #" + sRuleId;
    }
    oErr["sMessage"] = sMessage;
    // URL
    oErr["URL"] = sURL || "";
    // Context
    if (bContext) {
        oErr["sUnderlined"] = sx.slice(m.start[iGroup], m.end[iGroup]);
        oErr["sBefore"] = sx.slice(Math.max(0, m.start[iGroup]-80), m.start[iGroup]);
        oErr["sAfter"] = sx.slice(m.end[iGroup], m.end[iGroup]+80);
    }
    return oErr;
}

function _rewrite (s, sRepl, iGroup, m, bUppercase) {
    // text processor: write sRepl in s at iGroup position"
    let ln = m.end[iGroup] - m.start[iGroup];
    let sNew = "";
    if (sRepl === "*") {
        sNew = " ".repeat(ln);
    } else if (sRepl === ">" || sRepl === "_" || sRepl === "~") {
        sNew = sRepl + " ".repeat(ln-1);
    } else if (sRepl === "@") {
        sNew = "@".repeat(ln);
    } else if (sRepl.slice(0,1) === "=") {
        sNew = oEvalFunc[sRepl.slice(1)](s, m);
        sNew = sNew + " ".repeat(ln-sNew.length);
        if (bUppercase && m[iGroup].slice(0,1)._isUpperCase()) {
            sNew = sNew._toCapitalize();
        }
    } else {
        sNew = sRepl._expand(m);
        sNew = sNew + " ".repeat(ln-sNew.length);
    }
    //echo("\n"+s+"\nstart: "+m.start[iGroup]+" end:"+m.end[iGroup])
    return s.slice(0, m.start[iGroup]) + sNew + s.slice(m.end[iGroup]);
}

function ignoreRule (sRuleId) {
    _aIgnoredRules.add(sRuleId);
}

function resetIgnoreRules () {
    _aIgnoredRules.clear();
}

function reactivateRule (sRuleId) {
    _aIgnoredRules.delete(sRuleId);
}

function listRules (sFilter=null) {
    // generator: returns tuple (sOption, sLineId, sRuleId)
    try {
        for ([sOption, lRuleGroup] of _getRules(true)) {
            for ([_, _, sLineId, sRuleId, _, _] of lRuleGroup) {
                if (!sFilter || sRuleId.test(sFilter)) {
                    yield [sOption, sLineId, sRuleId];
                }
            }
        }
        for ([sOption, lRuleGroup] of _getRules(false)) {
            for ([_, _, sLineId, sRuleId, _, _] of lRuleGroup) {
                if (!sFilter || sRuleId.test(sFilter)) {
                    yield [sOption, sLineId, sRuleId];
                }
            }
        }
    }
    catch (e) {
        helpers.logerror(e);
    }
}


//////// init

function load () {
    try {
        _oDict = new ibdawg.IBDAWG("${js_binary_dic}");
    }
    catch (e) {
        helpers.logerror(e);
    }
}

function setOption (sOpt, bVal) {
    if (_dOptions.has(sOpt)) {
        _dOptions.set(sOpt, bVal);
    }
}

function setOptions (dOpt) {
    _dOptions._updateOnlyExistingKeys(dOpt);
}

function getOptions () {
    return _dOptions;
}

function getDefaultOptions () {
    return gc_options.dOpt._shallowCopy();
}

function resetOptions () {
    _dOptions = gc_options.dOpt._shallowCopy();
}

function getDictionary () {
    return _oDict;
}

function _getRules (bParagraph) {
    if (!bParagraph) {
        return _rules.lSentenceRules;
    }
    return _rules.lParagraphRules;
}



//////// common functions

function option (sOpt) {
    // return true if option sOpt is active
    return _dOptions.get(sOpt);
}

function displayInfo (dDA, aWord) {
    // for debugging: info of word
    if (!aWord) {
        echo("> nothing to find");







        return true;
    }
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        echo("> not in FSA");
        return true;
    }
    if (dDA.has(aWord[0])) {
        echo("DA: " + dDA.get(aWord[0]));
    }
    echo("FSA: " + _dAnalyses.get(aWord[1]));
    return true;
}

function _storeMorphFromFSA (sWord) {
    // retrieves morphologies list from _oDict -> _dAnalyses
    //echo("register: "+sWord + " " + _oDict.getMorph(sWord).toString())
    _dAnalyses.set(sWord, _oDict.getMorph(sWord));
    return !!_dAnalyses.get(sWord);
}

function morph (dDA, aWord, sPattern, bStrict=true, bNoWord=false) {
    // analyse a tuple (position, word), return true if sPattern in morphologies (disambiguation on)
    if (!aWord) {
        //echo("morph: noword, returns " + bNoWord);
        return bNoWord;
    }
    //echo("aWord: "+aWord.toString());
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        return false;
    }
    let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
    //echo("lMorph: "+lMorph.toString());
    if (lMorph.length === 0) {
        return false;
    }
    //echo("***");
    if (bStrict) {
        return lMorph.every(s  =>  (s.search(sPattern) !== -1));
    }
    return lMorph.some(s  =>  (s.search(sPattern) !== -1));
}

function morphex (dDA, aWord, sPattern, sNegPattern, bNoWord=false) {
    // analyse a tuple (position, word), returns true if not sNegPattern in word morphologies and sPattern in word morphologies (disambiguation on)
    if (!aWord) {
        //echo("morph: noword, returns " + bNoWord);
        return bNoWord;
    }
    //echo("aWord: "+aWord.toString());
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        return false;
    }
    let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
    //echo("lMorph: "+lMorph.toString());
    if (lMorph.length === 0) {
        return false;
    }
    //echo("***");
    // check negative condition
    if (lMorph.some(s  =>  (s.search(sNegPattern) !== -1))) {
        return false;
    }
    // search sPattern
    return lMorph.some(s  =>  (s.search(sPattern) !== -1));
}
................................................................................
    // returns a list of sWord's stems
    if (!sWord) {
        return [];
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return [];
    }
    return [ for (s of _dAnalyses.get(sWord))  s.slice(1, s.indexOf(" ")) ];
}


//// functions to get text outside pattern scope

// warning: check compile_rules.py to understand how it works

function nextword (s, iStart, n) {
    // get the nth word of the input string or empty string
    let z = new RegExp("^( +[a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+){" + (n-1).toString() + "} +([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+)", "i");
    let m = z.exec(s.slice(iStart));
    if (!m) {
        return null;
    }
    return [iStart + RegExp.lastIndex - m[2].length, m[2]];
}

function prevword (s, iEnd, n) {
    // get the (-)nth word of the input string or empty string
    let z = new RegExp("([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+) +([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+ +){" + (n-1).toString() + "}$", "i");
    let m = z.exec(s.slice(0, iEnd));
    if (!m) {
        return null;
    }
    return [m.index, m[1]];
}

const _zNextWord = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_][a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_-]*)", "i");
const _zPrevWord = new RegExp ("([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_][a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_-]*) +$", "i");

function nextword1 (s, iStart) {
    // get next word (optimization)

    let m = _zNextWord.exec(s.slice(iStart));
    if (!m) {
        return null;
    }
    return [iStart + RegExp.lastIndex - m[1].length, m[1]];
}



function prevword1 (s, iEnd) {
    // get previous word (optimization)
    //echo("prev1, s:"+s);
    //echo("prev1, s.slice(0, iEnd):"+s.slice(0, iEnd));
    let m = _zPrevWord.exec(s.slice(0, iEnd));
    //echo("prev1, m:"+m);
    if (!m) {
        return null;
    }
    //echo("prev1: " + m.index + " " + m[1]);
    return [m.index, m[1]];
}

function look (s, zPattern, zNegPattern=null) {
    // seek zPattern in s (before/after/fulltext), if antipattern zNegPattern not in s
    try {
        if (zNegPattern && zNegPattern.test(s)) {
................................................................................
        helpers.logerror(e);
    }
    return false;
}

function look_chk1 (dDA, s, nOffset, zPattern, sPatternGroup1, sNegPatternGroup1=null) {
    // returns True if s has pattern zPattern and m.group(1) has pattern sPatternGroup1
    let m = zPattern._exec2(s, null);
    if (!m) {
        return false;
    }
    try {
        let sWord = m[1];
        let nPos = m.start[1] + nOffset;
        if (sNegPatternGroup1) {
................................................................................
    }
    if (dDA.has(nPos)) {
        return true;
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return true;
    }
    //echo("morph: "+_dAnalyses.get(sWord).toString());
    if (_dAnalyses.get(sWord).length === 1) {
        return true;
    }
    let lSelect = [ for (sMorph of _dAnalyses.get(sWord))  if (sMorph.search(sPattern) !== -1)  sMorph ];
    //echo("lSelect: "+lSelect.toString());
    if (lSelect.length > 0) {
        if (lSelect.length != _dAnalyses.get(sWord).length) {
            dDA.set(nPos, lSelect);
        }
    } else if (lDefault) {
        dDA.set(nPos, lDefaul);
    }
................................................................................
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return true;
    }
    if (_dAnalyses.get(sWord).length === 1) {
        return true;
    }
    let lSelect = [ for (sMorph of _dAnalyses.get(sWord))  if (sMorph.search(sPattern) === -1)  sMorph ];
    //echo("lSelect: "+lSelect.toString());
    if (lSelect.length > 0) {
        if (lSelect.length != _dAnalyses.get(sWord).length) {
            dDA.set(nPos, lSelect);
        }
    } else if (lDefault) {
        dDA.set(nPos, lDefault);
    }
................................................................................
    return true;
}

function define (dDA, nPos, lMorph) {
    dDA.set(nPos, lMorph);
    return true;
}


//////// GRAMMAR CHECKER PLUGINS

${pluginsJS}


${callablesJS}





exports.load = load;
exports.parse = parse;
exports.lang = lang;

exports.version = version;















exports.getDictionary = getDictionary;
exports.setOption = setOption;
exports.setOptions = setOptions;
exports.getOptions = getOptions;
exports.getDefaultOptions = getDefaultOptions;
exports.resetOptions = resetOptions;
exports.ignoreRule = ignoreRule;
exports.reactivateRule = reactivateRule;
exports.resetIgnoreRules = resetIgnoreRules;
exports.listRules = listRules;


>
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>



|



|

|





|







|


|




|



|









|


|




|



|







 







|









|




|




|







<
<
<


>




|

>
>



<
<

<



<







 







|







 







<



|
<







 







|
<







 







>










<
>
|
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
<
<
<
<
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504



505
506
507
508
509
510
511
512
513
514
515
516
517
518


519

520
521
522

523
524
525
526
527
528
529
...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
...
566
567
568
569
570
571
572

573
574
575
576

577
578
579
580
581
582
583
...
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652




653
// Grammar checker engine
/*jslint esversion: 6*/
/*global console,require,exports*/

"use strict";

${string}
${regex}
${map}


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
    var gc_options = require("resource://grammalecte/${lang}/gc_options.js");
    var gc_rules = require("resource://grammalecte/${lang}/gc_rules.js");
    var cregex = require("resource://grammalecte/${lang}/cregex.js");
    var text = require("resource://grammalecte/text.js");
    var echo = helpers.echo;
}
else if (typeof(console) !== "undefined") {
    var echo = function (o) { console.log(o); return true; };
}
else {
    var echo = function () { return true; }
}

function capitalizeArray (aArray) {
    // can’t map on user defined function??
    let aNew = [];
    for (let i = 0; i < aArray.length; i = i + 1) {
        aNew[i] = aArray[i].gl_toCapitalize();
    }
    return aNew;
}


// data
let _sAppContext = "";                                  // what software is running
let _dOptions = null;
let _aIgnoredRules = new Set();
let _oDict = null;
let _dAnalyses = new Map();                             // cache for data from dictionary


var gc_engine = {

    //// Informations

    lang: "${lang}",
    locales: ${loc},
    pkg: "${implname}",
    name: "${name}",
    version: "${version}",
    author: "${author}",

    //// Parsing

    parse: function (sText, sCountry="${country_default}", bDebug=false, bContext=false) {
        // analyses the paragraph sText and returns list of errors
        let dErrors;
        let errs;
        let sAlt = sText;
        let dDA = new Map();        // Disamnbiguator
        let dPriority = new Map();  // Key = position; value = priority
        let sNew = "";

        // parse paragraph
        try {
            [sNew, dErrors] = this._proofread(sText, sAlt, 0, true, dDA, dPriority, sCountry, bDebug, bContext);
            if (sNew) {
                sText = sNew;
            }
        }
        catch (e) {
            helpers.logerror(e);
        }

        // cleanup
        if (sText.includes(" ")) {
            sText = sText.replace(/ /g, ' '); // nbsp
        }
        if (sText.includes(" ")) {
            sText = sText.replace(/ /g, ' '); // snbsp
        }
        if (sText.includes("'")) {
            sText = sText.replace(/'/g, "’");
        }
        if (sText.includes("‑")) {
            sText = sText.replace(/‑/g, "-"); // nobreakdash
        }

        // parse sentence
        for (let [iStart, iEnd] of this._getSentenceBoundaries(sText)) {
            if (4 < (iEnd - iStart) < 2000) {
                dDA.clear();
                //helpers.echo(sText.slice(iStart, iEnd));
                try {
                    [, errs] = this._proofread(sText.slice(iStart, iEnd), sAlt.slice(iStart, iEnd), iStart, false, dDA, dPriority, sCountry, bDebug, bContext);
                    dErrors.gl_update(errs);
                }
                catch (e) {
                    helpers.logerror(e);
                }
            }
        }
        return Array.from(dErrors.values());
    },

    _zEndOfSentence: new RegExp ('([.?!:;…][ .?!… »”")]*|.$)', "g"),
    _zBeginOfParagraph: new RegExp ("^[-  –—.,;?!…]*", "ig"),
    _zEndOfParagraph: new RegExp ("[-  .,;?!…–—]*$", "ig"),

    _getSentenceBoundaries: function* (sText) {
        let mBeginOfSentence = this._zBeginOfParagraph.exec(sText);
        let iStart = this._zBeginOfParagraph.lastIndex;
        let m;
        while ((m = this._zEndOfSentence.exec(sText)) !== null) {
            yield [iStart, this._zEndOfSentence.lastIndex];
            iStart = this._zEndOfSentence.lastIndex;
        }
    },

    _proofread: function (s, sx, nOffset, bParagraph, dDA, dPriority, sCountry, bDebug, bContext) {
        let dErrs = new Map();
        let bChange = false;
        let bIdRule = option('idrule');
        let m;
        let bCondMemo;
        let nErrorStart;

        for (let [sOption, lRuleGroup] of this._getRules(bParagraph)) {
            if (!sOption || option(sOption)) {
                for (let [zRegex, bUppercase, sLineId, sRuleId, nPriority, lActions, lGroups, lNegLookBefore] of lRuleGroup) {
                    if (!_aIgnoredRules.has(sRuleId)) {
                        while ((m = zRegex.gl_exec2(s, lGroups, lNegLookBefore)) !== null) {
                            bCondMemo = null;
                            /*if (bDebug) {
                                helpers.echo(">>>> Rule # " + sLineId + " - Text: " + s + " opt: "+ sOption);
                            }*/
                            for (let [sFuncCond, cActionType, sWhat, ...eAct] of lActions) {
                            // action in lActions: [ condition, action type, replacement/suggestion/action[, iGroup[, message, URL]] ]
                                try {
                                    //helpers.echo(oEvalFunc[sFuncCond]);
                                    bCondMemo = (!sFuncCond || oEvalFunc[sFuncCond](s, sx, m, dDA, sCountry, bCondMemo));
                                    if (bCondMemo) {
                                        switch (cActionType) {
                                            case "-":
                                                // grammar error
                                                //helpers.echo("-> error detected in " + sLineId + "\nzRegex: " + zRegex.source);
                                                nErrorStart = nOffset + m.start[eAct[0]];
                                                if (!dErrs.has(nErrorStart) || nPriority > dPriority.get(nErrorStart)) {
                                                    dErrs.set(nErrorStart, this._createError(s, sx, sWhat, nOffset, m, eAct[0], sLineId, sRuleId, bUppercase, eAct[1], eAct[2], bIdRule, sOption, bContext));
                                                    dPriority.set(nErrorStart, nPriority);
                                                }
                                                break;
                                            case "~":
                                                // text processor
                                                //helpers.echo("-> text processor by " + sLineId + "\nzRegex: " + zRegex.source);
                                                s = this._rewrite(s, sWhat, eAct[0], m, bUppercase);
                                                bChange = true;
                                                if (bDebug) {
                                                    helpers.echo("~ " + s + "  -- " + m[eAct[0]] + "  # " + sLineId);
                                                }
                                                break;
                                            case "=":
                                                // disambiguation
                                                //helpers.echo("-> disambiguation by " + sLineId + "\nzRegex: " + zRegex.source);
                                                oEvalFunc[sWhat](s, m, dDA);
                                                if (bDebug) {
                                                    helpers.echo("= " + m[0] + "  # " + sLineId + "\nDA: " + dDA.gl_toString());
                                                }
                                                break;
                                            case ">":
                                                // we do nothing, this test is just a condition to apply all following actions
                                                break;
                                            default:
                                                helpers.echo("# error: unknown action at " + sLineId);
                                        }
                                    } else {
                                        if (cActionType == ">") {
                                            break;
                                        }
                                    }
                                }
                                catch (e) {
                                    helpers.echo(s);
                                    helpers.echo("# line id: " + sLineId + "\n# rule id: " + sRuleId);
                                    helpers.logerror(e);
                                }
                            }
                        }
                    }
                }
            }
        }
        if (bChange) {
            return [s, dErrs];
        }
        return [false, dErrs];
    },

    _createError: function (s, sx, sRepl, nOffset, m, iGroup, sLineId, sRuleId, bUppercase, sMsg, sURL, bIdRule, sOption, bContext) {
        let oErr = {};
        oErr["nStart"] = nOffset + m.start[iGroup];
        oErr["nEnd"] = nOffset + m.end[iGroup];
        oErr["sLineId"] = sLineId;
        oErr["sRuleId"] = sRuleId;
        oErr["sType"] = (sOption) ? sOption : "notype";
        // suggestions
        if (sRepl.slice(0,1) === "=") {
            let sugg = oEvalFunc[sRepl.slice(1)](s, m);
            if (sugg) {
                if (bUppercase && m[iGroup].slice(0,1).gl_isUpperCase()) {
                    oErr["aSuggestions"] = capitalizeArray(sugg.split("|"));
                } else {
                    oErr["aSuggestions"] = sugg.split("|");
                }
            } else {
                oErr["aSuggestions"] = [];
            }
        } else if (sRepl == "_") {
            oErr["aSuggestions"] = [];
        } else {
            if (bUppercase && m[iGroup].slice(0,1).gl_isUpperCase()) {
                oErr["aSuggestions"] = capitalizeArray(sRepl.gl_expand(m).split("|"));
            } else {
                oErr["aSuggestions"] = sRepl.gl_expand(m).split("|");
            }
        }
        // Message
        let sMessage = "";
        if (sMsg.slice(0,1) === "=") {
            sMessage = oEvalFunc[sMsg.slice(1)](s, m);
        } else {
            sMessage = sMsg.gl_expand(m);
        }
        if (bIdRule) {
            sMessage += " ##" + sLineId + " #" + sRuleId;
        }
        oErr["sMessage"] = sMessage;
        // URL
        oErr["URL"] = sURL || "";
        // Context
        if (bContext) {
            oErr["sUnderlined"] = sx.slice(m.start[iGroup], m.end[iGroup]);
            oErr["sBefore"] = sx.slice(Math.max(0, m.start[iGroup]-80), m.start[iGroup]);
            oErr["sAfter"] = sx.slice(m.end[iGroup], m.end[iGroup]+80);
        }
        return oErr;
    },

    _rewrite: function (s, sRepl, iGroup, m, bUppercase) {
        // text processor: write sRepl in s at iGroup position"
        let ln = m.end[iGroup] - m.start[iGroup];
        let sNew = "";
        if (sRepl === "*") {
            sNew = " ".repeat(ln);
        } else if (sRepl === ">" || sRepl === "_" || sRepl === "~") {
            sNew = sRepl + " ".repeat(ln-1);
        } else if (sRepl === "@") {
            sNew = "@".repeat(ln);
        } else if (sRepl.slice(0,1) === "=") {
            sNew = oEvalFunc[sRepl.slice(1)](s, m);
            sNew = sNew + " ".repeat(ln-sNew.length);
            if (bUppercase && m[iGroup].slice(0,1).gl_isUpperCase()) {
                sNew = sNew.gl_toCapitalize();
            }
        } else {
            sNew = sRepl.gl_expand(m);
            sNew = sNew + " ".repeat(ln-sNew.length);
        }
        //helpers.echo("\n"+s+"\nstart: "+m.start[iGroup]+" end:"+m.end[iGroup])
        return s.slice(0, m.start[iGroup]) + sNew + s.slice(m.end[iGroup]);
    },

    // Actions on rules

    ignoreRule: function (sRuleId) {
        _aIgnoredRules.add(sRuleId);
    },

    resetIgnoreRules: function () {
        _aIgnoredRules.clear();
    },

    reactivateRule: function (sRuleId) {
        _aIgnoredRules.delete(sRuleId);
    },

    listRules: function* (sFilter=null) {
        // generator: returns tuple (sOption, sLineId, sRuleId)
        try {
            for (let [sOption, lRuleGroup] of this._getRules(true)) {
                for (let [,, sLineId, sRuleId,,] of lRuleGroup) {
                    if (!sFilter || sRuleId.test(sFilter)) {
                        yield [sOption, sLineId, sRuleId];
                    }
                }
            }
            for (let [sOption, lRuleGroup] of this._getRules(false)) {
                for (let [,, sLineId, sRuleId,,] of lRuleGroup) {
                    if (!sFilter || sRuleId.test(sFilter)) {
                        yield [sOption, sLineId, sRuleId];
                    }
                }
            }
        }
        catch (e) {
            helpers.logerror(e);
        }
    },

    _getRules: function (bParagraph) {
        if (!bParagraph) {
            return gc_rules.lSentenceRules;
        }
        return gc_rules.lParagraphRules;
    },

    //// Initialization

    load: function (sContext="JavaScript", sPath="") {
        try {
            if (typeof(require) !== 'undefined') {
                var ibdawg = require("resource://grammalecte/ibdawg.js");
                _oDict = new ibdawg.IBDAWG("${dic_name}.json");
            } else {
                _oDict = new IBDAWG("${dic_name}.json", sPath);
            }
            _sAppContext = sContext;
            _dOptions = gc_options.getOptions(sContext).gl_shallowCopy();     // duplication necessary, to be able to reset to default
        }
        catch (e) {
            helpers.logerror(e);
        }
    },

    getDictionary: function () {
        return _oDict;
    },

    //// Options

    setOption: function (sOpt, bVal) {
        if (_dOptions.has(sOpt)) {
            _dOptions.set(sOpt, bVal);
        }
    },

    setOptions: function (dOpt) {
        _dOptions.gl_updateOnlyExistingKeys(dOpt);
    },

    getOptions: function () {
        return _dOptions;
    },

    getDefaultOptions: function () {
        return gc_options.getOptions(_sAppContext).gl_shallowCopy();
    },

    resetOptions: function () {
        _dOptions = gc_options.getOptions(_sAppContext).gl_shallowCopy();
    }
};


//////// Common functions

function option (sOpt) {
    // return true if option sOpt is active
    return _dOptions.get(sOpt);
}

function displayInfo (dDA, aWord) {
    // for debugging: info of word
    if (!aWord) {
        helpers.echo("> nothing to find");
        return true;
    }
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        helpers.echo("> not in FSA");
        return true;
    }
    if (dDA.has(aWord[0])) {
        helpers.echo("DA: " + dDA.get(aWord[0]));
    }
    helpers.echo("FSA: " + _dAnalyses.get(aWord[1]));
    return true;
}

function _storeMorphFromFSA (sWord) {
    // retrieves morphologies list from _oDict -> _dAnalyses
    //helpers.echo("register: "+sWord + " " + _oDict.getMorph(sWord).toString())
    _dAnalyses.set(sWord, _oDict.getMorph(sWord));
    return !!_dAnalyses.get(sWord);
}

function morph (dDA, aWord, sPattern, bStrict=true, bNoWord=false) {
    // analyse a tuple (position, word), return true if sPattern in morphologies (disambiguation on)
    if (!aWord) {
        //helpers.echo("morph: noword, returns " + bNoWord);
        return bNoWord;
    }
    //helpers.echo("aWord: "+aWord.toString());
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        return false;
    }
    let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
    //helpers.echo("lMorph: "+lMorph.toString());
    if (lMorph.length === 0) {
        return false;
    }
    //helpers.echo("***");
    if (bStrict) {
        return lMorph.every(s  =>  (s.search(sPattern) !== -1));
    }
    return lMorph.some(s  =>  (s.search(sPattern) !== -1));
}

function morphex (dDA, aWord, sPattern, sNegPattern, bNoWord=false) {
    // analyse a tuple (position, word), returns true if not sNegPattern in word morphologies and sPattern in word morphologies (disambiguation on)
    if (!aWord) {
        //helpers.echo("morph: noword, returns " + bNoWord);
        return bNoWord;
    }
    //helpers.echo("aWord: "+aWord.toString());
    if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
        return false;
    }
    let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
    //helpers.echo("lMorph: "+lMorph.toString());
    if (lMorph.length === 0) {
        return false;
    }
    //helpers.echo("***");
    // check negative condition
    if (lMorph.some(s  =>  (s.search(sNegPattern) !== -1))) {
        return false;
    }
    // search sPattern
    return lMorph.some(s  =>  (s.search(sPattern) !== -1));
}
................................................................................
    // returns a list of sWord's stems
    if (!sWord) {
        return [];
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return [];
    }
    return _dAnalyses.get(sWord).map( s => s.slice(1, s.indexOf(" ")) );
}


//// functions to get text outside pattern scope

// warning: check compile_rules.py to understand how it works

function nextword (s, iStart, n) {
    // get the nth word of the input string or empty string
    let z = new RegExp("^(?: +[a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+){" + (n-1).toString() + "} +([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+)", "ig");
    let m = z.exec(s.slice(iStart));
    if (!m) {
        return null;
    }
    return [iStart + z.lastIndex - m[1].length, m[1]];
}

function prevword (s, iEnd, n) {
    // get the (-)nth word of the input string or empty string
    let z = new RegExp("([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+) +(?:[a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st%_-]+ +){" + (n-1).toString() + "}$", "i");
    let m = z.exec(s.slice(0, iEnd));
    if (!m) {
        return null;
    }
    return [m.index, m[1]];
}




function nextword1 (s, iStart) {
    // get next word (optimization)
    let _zNextWord = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_][a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_-]*)", "ig");
    let m = _zNextWord.exec(s.slice(iStart));
    if (!m) {
        return null;
    }
    return [iStart + _zNextWord.lastIndex - m[1].length, m[1]];
}

const _zPrevWord = new RegExp ("([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_][a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_-]*) +$", "i");

function prevword1 (s, iEnd) {
    // get previous word (optimization)


    let m = _zPrevWord.exec(s.slice(0, iEnd));

    if (!m) {
        return null;
    }

    return [m.index, m[1]];
}

function look (s, zPattern, zNegPattern=null) {
    // seek zPattern in s (before/after/fulltext), if antipattern zNegPattern not in s
    try {
        if (zNegPattern && zNegPattern.test(s)) {
................................................................................
        helpers.logerror(e);
    }
    return false;
}

function look_chk1 (dDA, s, nOffset, zPattern, sPatternGroup1, sNegPatternGroup1=null) {
    // returns True if s has pattern zPattern and m.group(1) has pattern sPatternGroup1
    let m = zPattern.gl_exec2(s, null);
    if (!m) {
        return false;
    }
    try {
        let sWord = m[1];
        let nPos = m.start[1] + nOffset;
        if (sNegPatternGroup1) {
................................................................................
    }
    if (dDA.has(nPos)) {
        return true;
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return true;
    }

    if (_dAnalyses.get(sWord).length === 1) {
        return true;
    }
    let lSelect = _dAnalyses.get(sWord).filter( sMorph => sMorph.search(sPattern) !== -1 );

    if (lSelect.length > 0) {
        if (lSelect.length != _dAnalyses.get(sWord).length) {
            dDA.set(nPos, lSelect);
        }
    } else if (lDefault) {
        dDA.set(nPos, lDefaul);
    }
................................................................................
    }
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return true;
    }
    if (_dAnalyses.get(sWord).length === 1) {
        return true;
    }
    let lSelect = _dAnalyses.get(sWord).filter( sMorph => sMorph.search(sPattern) === -1 );

    if (lSelect.length > 0) {
        if (lSelect.length != _dAnalyses.get(sWord).length) {
            dDA.set(nPos, lSelect);
        }
    } else if (lDefault) {
        dDA.set(nPos, lDefault);
    }
................................................................................
    return true;
}

function define (dDA, nPos, lMorph) {
    dDA.set(nPos, lMorph);
    return true;
}


//////// GRAMMAR CHECKER PLUGINS

${pluginsJS}


${callablesJS}




if (typeof(exports) !== 'undefined') {
    exports.lang = gc_engine.lang;
    exports.locales = gc_engine.locales;
    exports.pkg = gc_engine.pkg;
    exports.name = gc_engine.name;
    exports.version = gc_engine.version;
    exports.author = gc_engine.author;
    exports.parse = gc_engine.parse;
    exports._zEndOfSentence = gc_engine._zEndOfSentence;
    exports._zBeginOfParagraph = gc_engine._zBeginOfParagraph;
    exports._zEndOfParagraph = gc_engine._zEndOfParagraph;
    exports._getSentenceBoundaries = gc_engine._getSentenceBoundaries;
    exports._proofread = gc_engine._proofread;
    exports._createError = gc_engine._createError;
    exports._rewrite = gc_engine._rewrite;
    exports.ignoreRule = gc_engine.ignoreRule;
    exports.resetIgnoreRules = gc_engine.resetIgnoreRules;
    exports.reactivateRule = gc_engine.reactivateRule;
    exports.listRules = gc_engine.listRules;
    exports._getRules = gc_engine._getRules;
    exports.load = gc_engine.load;
    exports.getDictionary = gc_engine.getDictionary;
    exports.setOption = gc_engine.setOption;
    exports.setOptions = gc_engine.setOptions;
    exports.getOptions = gc_engine.getOptions;
    exports.getDefaultOptions = gc_engine.getDefaultOptions;
    exports.resetOptions = gc_engine.resetOptions;




}

Modified gc_core/js/lang_core/gc_options.js from [3105c2862f] to [f47ea826e5].

1


2
3
4









5
6

7



8
9
10




11
12
13

// Options for Grammalecte



${map}










const lStructOpt = ${lStructOpt};


const dOpt = new Map (${dOptJavaScript});




const dOptLabel = ${dOptLabel};





exports.lStructOpt = lStructOpt;
exports.dOpt = dOpt;
exports.dOptLabel = dOptLabel;


>
>



>
>
>
>
>
>
>
>
>
|

>
|
>
>
>

|
|
>
>
>
>
|
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Options for Grammalecte
/*jslint esversion: 6*/
/*global exports*/

${map}


var gc_options = {
    getOptions: function (sContext="JavaScript") {
        if (this.dOpt.hasOwnProperty(sContext)) {
            return this.dOpt[sContext];
        }
        return this.dOpt["JavaScript"];
    },

    lStructOpt: ${lStructOpt},

    dOpt: {
        "JavaScript": new Map (${dOptJavaScript}),
        "Firefox": new Map (${dOptFirefox}),
        "Thunderbird": new Map (${dOptThunderbird}),
    },

    dOptLabel: ${dOptLabel}
}


if (typeof(exports) !== 'undefined') {
	exports.getOptions = gc_options.getOptions;
	exports.lStructOpt = gc_options.lStructOpt;
    exports.dOpt = gc_options.dOpt;
	exports.dOptLabel = gc_options.dOptLabel;
}

Modified gc_core/js/lang_core/gc_rules.js from [c85bd666a1] to [cdb121423e].

1



2
3
4
5
6

7
8
9
10
11


12
13

// Grammar checker rules



"use strict";

${string}
${regex}


const lParagraphRules = ${paragraph_rules_JS};

const lSentenceRules = ${sentence_rules_JS};




exports.lParagraphRules = lParagraphRules;
exports.lSentenceRules = lSentenceRules;


>
>
>





>
|

|
|

>
>
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Grammar checker rules
/*jslint esversion: 6*/
/*global exports*/

"use strict";

${string}
${regex}

var gc_rules = {
    lParagraphRules: ${paragraph_rules_JS},

    lSentenceRules: ${sentence_rules_JS}
}


if (typeof(exports) !== 'undefined') {
    exports.lParagraphRules = gc_rules.lParagraphRules;
    exports.lSentenceRules = gc_rules.lSentenceRules;
}

Modified gc_core/js/str_transform.js from [572c35f46a] to [6745507121].

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54

55
56

57
58

//// STRING TRANSFORMATION


var dSimilarChars = new Map ([
    ["a", "aàâáä"],
    ["à", "aàâáä"],
    ["â", "aàâáä"],
    ["á", "aàâáä"],
    ["ä", "aàâáä"],
    ["c", "cç"],
    ["ç", "cç"],
    ["e", "eéêèë"],
    ["é", "eéêèë"],
    ["ê", "eéêèë"],
    ["è", "eéêèë"],
    ["ë", "eéêèë"],
    ["i", "iîïíì"],
    ["î", "iîïíì"],
    ["ï", "iîïíì"],
    ["í", "iîïíì"],
    ["ì", "iîïíì"],
    ["o", "oôóòö"],
    ["ô", "oôóòö"],
    ["ó", "oôóòö"],
    ["ò", "oôóòö"],
    ["ö", "oôóòö"],
    ["u", "uûùüú"],
    ["û", "uûùüú"],
    ["ù", "uûùüú"],
    ["ü", "uûùüú"],
    ["ú", "uûùüú"]
]);

// Note: 48 is the ASCII code for "0"



// Suffix only
function getStemFromSuffixCode (sFlex, sSfxCode) {
    if (sSfxCode == "0") {
        return sFlex;
    }
    return sSfxCode[0] == '0' ? sFlex + sSfxCode.slice(1) : sFlex.slice(0, -(sSfxCode.charCodeAt(0)-48)) + sSfxCode.slice(1);
}


// Prefix and suffix
function getStemFromAffixCode (sFlex, sAffCode) {
    if (sAffCode == "0") {
        return sFlex;
    }
    if (!sAffCode.includes("/")) {
        return "# error #";
    }
    var [sPfxCode, sSfxCode] = sAffCode.split('/');
    sFlex = sPfxCode.slice(1) + sFlex.slice(sPfxCode.charCodeAt(0)-48);
    return sSfxCode[0] == '0' ? sFlex + sSfxCode.slice(1) : sFlex.slice(0, -(sSfxCode.charCodeAt(0)-48)) + sSfxCode.slice(1);
}




exports.getStemFromSuffixCode = getStemFromSuffixCode;
exports.getStemFromAffixCode = getStemFromAffixCode;


>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


>
>
|
<
|
|
|
|
|
|
>
|
<
|
|
|
|
|
|
|
|
|
|
>


>
|
|
>
1
2
3






























4
5
6
7
8

9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//// STRING TRANSFORMATION
/*jslint esversion: 6*/































// Note: 48 is the ASCII code for "0"

var str_transform = {
    getStemFromSuffixCode: function (sFlex, sSfxCode) {
        // Suffix only

        if (sSfxCode == "0") {
            return sFlex;
        }
        return sSfxCode[0] == '0' ? sFlex + sSfxCode.slice(1) : sFlex.slice(0, -(sSfxCode.charCodeAt(0)-48)) + sSfxCode.slice(1);
    },
    
    getStemFromAffixCode: function (sFlex, sAffCode) {
        // Prefix and suffix

        if (sAffCode == "0") {
            return sFlex;
        }
        if (!sAffCode.includes("/")) {
            return "# error #";
        }
        let [sPfxCode, sSfxCode] = sAffCode.split('/');
        sFlex = sPfxCode.slice(1) + sFlex.slice(sPfxCode.charCodeAt(0)-48);
        return sSfxCode[0] == '0' ? sFlex + sSfxCode.slice(1) : sFlex.slice(0, -(sSfxCode.charCodeAt(0)-48)) + sSfxCode.slice(1);
    }
};


if (typeof(exports) !== 'undefined') {
    exports.getStemFromSuffixCode = str_transform.getStemFromSuffixCode;
    exports.getStemFromAffixCode = str_transform.getStemFromAffixCode;
}

Modified gc_core/js/tests.js from [24427fff6b] to [4504bb3576].

1


2
3
4
5

6

7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
139
140
141
142
143
144
145
146
147
148
149


150

// JavaScript



"use strict";



const helpers = require("resource://grammalecte/helpers.js");



class TestGrammarChecking {

    constructor (gce) {
        this.gce = gce;

        this._aRuleTested = new Set();
    };


    * testParse (bDebug=false) {
        const t0 = Date.now();
        const aData = JSON.parse(helpers.loadFile("resource://grammalecte/"+this.gce.lang+"/tests_data.json")).aData;
        //const aData = require("resource://grammalecte/"+this.gce.lang+"/tests_data.js").aData;
        let nInvalid = 0
        let nTotal = 0
        let sErrorText;
        let sSugg;
        let sExpectedErrors;
        let sTextToCheck;
        let sFoundErrors;
        let sListErr;
        let sLineNum;
................................................................................
                    if (sExpectedErrors !== sFoundErrors) {
                        yield "\n" + i.toString() +
                              "\n# Line num: " + sLineNum +
                              "\n> to check: " + sTextToCheck +
                              "\n  expected: " + sExpectedErrors +
                              "\n  found:    " + sFoundErrors +
                              "\n  errors:   \n" + sListErr;
                        nInvalid = nInvalid + 1
                    }
                    nTotal = nTotal + 1;
                }
                i = i + 1;
                if (i % 1000 === 0) {
                    yield i.toString();
                }
................................................................................
        }
        catch (e) {
            helpers.logerror(e);
        }

        if (bShowUntested) {
            i = 0;
            for (let [sOpt, sLineId, sRuleId] of gce.listRules()) {
                if (!this._aRuleTested.has(sLineId) && !/^[0-9]+[sp]$|^[pd]_/.test(sRuleId)) {
                    sUntestedRules += sRuleId + ", ";
                    i += 1;
                }
            }
            if (i > 0) {
                yield sUntestedRules + "\n[" + i.toString() + " untested rules]";
            }
        }

        const t1 = Date.now();
        yield "Tests parse finished in " + ((t1-t0)/1000).toString()
            + " s\nTotal errors: " + nInvalid.toString() + " / " + nTotal.toString();
    };

    _getExpectedErrors (sLine) {
        try {
            let sRes = " ".repeat(sLine.length);
            let z = /\{\{.+?\}\}/g;
            let m;
            let i = 0;
................................................................................
            }
            return sRes;
        }
        catch (e) {
            helpers.logerror(e);
        }
        return " ".repeat(sLine.length);
    };

    _getFoundErrors (sLine, bDebug, sOption) {
        try {
            let aErrs = [];
            if (sOption) {
                gce.setOption(sOption, true);
                aErrs = this.gce.parse(sLine, "FR", bDebug);
                gce.setOption(sOption, false);
            } else {
                aErrs = this.gce.parse(sLine, "FR", bDebug);
            }
            let sRes = " ".repeat(sLine.length);
            let sListErr = "";
            for (let dErr of aErrs) {
                sRes = sRes.slice(0, dErr["nStart"]) + "~".repeat(dErr["nEnd"] - dErr["nStart"]) + sRes.slice(dErr["nEnd"]);
................................................................................
            }
            return [sRes, sListErr];
        }
        catch (e) {
            helpers.logerror(e);
        }
        return [" ".repeat(sLine.length), ""];
    };

}



exports.TestGrammarChecking = TestGrammarChecking;


>
>




>
|
>




|

>

<
>



|
|
|
|







 







|







 







|













|







 







|





|

|







 







|



>
>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// JavaScript
/*jslint esversion: 6*/
/*global console,require,exports*/

"use strict";


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
}


class TestGrammarChecking {

    constructor (gce, spfTests="") {
        this.gce = gce;
        this.spfTests = spfTests;
        this._aRuleTested = new Set();

    }

    * testParse (bDebug=false) {
        const t0 = Date.now();
        let sURL = (this.spfTests !== "") ? this.spfTests : "resource://grammalecte/"+this.gce.lang+"/tests_data.json";
        const aData = JSON.parse(helpers.loadFile(sURL)).aData;
        let nInvalid = 0;
        let nTotal = 0;
        let sErrorText;
        let sSugg;
        let sExpectedErrors;
        let sTextToCheck;
        let sFoundErrors;
        let sListErr;
        let sLineNum;
................................................................................
                    if (sExpectedErrors !== sFoundErrors) {
                        yield "\n" + i.toString() +
                              "\n# Line num: " + sLineNum +
                              "\n> to check: " + sTextToCheck +
                              "\n  expected: " + sExpectedErrors +
                              "\n  found:    " + sFoundErrors +
                              "\n  errors:   \n" + sListErr;
                        nInvalid = nInvalid + 1;
                    }
                    nTotal = nTotal + 1;
                }
                i = i + 1;
                if (i % 1000 === 0) {
                    yield i.toString();
                }
................................................................................
        }
        catch (e) {
            helpers.logerror(e);
        }

        if (bShowUntested) {
            i = 0;
            for (let [sOpt, sLineId, sRuleId] of this.gce.listRules()) {
                if (!this._aRuleTested.has(sLineId) && !/^[0-9]+[sp]$|^[pd]_/.test(sRuleId)) {
                    sUntestedRules += sRuleId + ", ";
                    i += 1;
                }
            }
            if (i > 0) {
                yield sUntestedRules + "\n[" + i.toString() + " untested rules]";
            }
        }

        const t1 = Date.now();
        yield "Tests parse finished in " + ((t1-t0)/1000).toString()
            + " s\nTotal errors: " + nInvalid.toString() + " / " + nTotal.toString();
    }

    _getExpectedErrors (sLine) {
        try {
            let sRes = " ".repeat(sLine.length);
            let z = /\{\{.+?\}\}/g;
            let m;
            let i = 0;
................................................................................
            }
            return sRes;
        }
        catch (e) {
            helpers.logerror(e);
        }
        return " ".repeat(sLine.length);
    }

    _getFoundErrors (sLine, bDebug, sOption) {
        try {
            let aErrs = [];
            if (sOption) {
                this.gce.setOption(sOption, true);
                aErrs = this.gce.parse(sLine, "FR", bDebug);
                this.gce.setOption(sOption, false);
            } else {
                aErrs = this.gce.parse(sLine, "FR", bDebug);
            }
            let sRes = " ".repeat(sLine.length);
            let sListErr = "";
            for (let dErr of aErrs) {
                sRes = sRes.slice(0, dErr["nStart"]) + "~".repeat(dErr["nEnd"] - dErr["nStart"]) + sRes.slice(dErr["nEnd"]);
................................................................................
            }
            return [sRes, sListErr];
        }
        catch (e) {
            helpers.logerror(e);
        }
        return [" ".repeat(sLine.length), ""];
    }

}


if (typeof(exports) !== 'undefined') {
    exports.TestGrammarChecking = TestGrammarChecking;
}

Modified gc_core/js/text.js from [f8cb0efb57] to [9bf91b3594].

1


2
3
4


5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176

177

// JavaScript



"use strict";



const helpers = require("resource://grammalecte/helpers.js");




function* getParagraph (sText) {
    // generator: returns paragraphs of text
    let iStart = 0;
    let iEnd = 0;
    sText = sText.replace("\r", "");
    while ((iEnd = sText.indexOf("\n", iStart)) !== -1) {
        yield sText.slice(iStart, iEnd);
        iStart = iEnd + 1;
    }
    yield sText.slice(iStart);
}

function* wrap (sText, nWidth=80) {
    // generator: returns text line by line
    while (sText) {
        if (sText.length >= nWidth) {
            let nEnd = sText.lastIndexOf(" ", nWidth) + 1;
            if (nEnd > 0) {
                yield sText.slice(0, nEnd);
                sText = sText.slice(nEnd);
            } else {
                yield sText.slice(0, nWidth);
                sText = sText.slice(nWidth);
            }
        } else {
            break;
        }
    }
    yield sText;
}

function getReadableError (oErr) {
    // Returns an error oErr as a readable error
    try {
        let s = "\n* " + oErr['nStart'] + ":" + oErr['nEnd'] + "  # " + oErr['sRuleId']+":\n";

        s += "  " + oErr["sMessage"];
        if (oErr["aSuggestions"].length > 0) {
            s += "\n  > Suggestions : " + oErr["aSuggestions"].join(" | ");
        }
        if (oErr["URL"] !== "") {
            s += "\n  > URL: " + oErr["URL"];
        }
        return s;
    }
    catch (e) {
        helpers.logerror(e);
        return "\n# Error. Data: " + oErr.toString();
    }
}

function addHtmlEntities (sParagraph) {
    if (sParagraph.includes("&")) {
        sParagraph = sParagraph.replace(/&/g, "&amp;");
    }
    if (sParagraph.includes("<")) {
        sParagraph = sParagraph.replace(/</g, "&lt;").replace(/>/g, "&gt;");
    }
    return sParagraph;
}

function createHTMLBlock (sParagraph, iParagraph) {
    let sClassName = (sParagraph.includes('<u id="err')) ? " softred" : "";
    return '<p id="paragr'+iParagraph.toString()+'" class="paragraph' + sClassName + '" lang="fr" spellcheck="false">' + sParagraph + '</p>\n'
           + '<div class="actions"><div id="end'+iParagraph.toString()+'" class="button red">×</div>'
           + '<div id="edit'+iParagraph.toString()+'" class="button">Éditer</div>'
           + '<div id="check'+iParagraph.toString()+'" class="button green">Réanalyser</div>&nbsp;</div>\n';
}

function tagParagraph (sParagraph, iParagraph, aGrammErr, aSpellErr, bDebug=false) {
    // Returns a text with with underlined errors and messages in tooltip
    try {
        if (aGrammErr.length === 0  &&  aSpellErr.length === 0) {
            return sParagraph;
        }
        aGrammErr.push(...aSpellErr);
        aGrammErr.sort(function (a, b) {
            if (a["nStart"] < b["nStart"])
                return 1;
            if (a["nStart"] > b["nStart"])
                return -1;
            return 0;
        });

        let nErr = aGrammErr.length - 1; // we count errors to give them an identifier
        let nStartLastErr = sParagraph.length;
        for (let oErr of aGrammErr) {
            let sErrId = iParagraph.toString() + "_" + nErr.toString();
            let nStart = oErr["nStart"];
            let nEnd = oErr["nEnd"];
            if (nEnd <= nStartLastErr) {
                oErr["sId"] = sErrId;
                if (oErr['sType'] !== 'WORD') {
                    // Grammar Error
                    sParagraph = sParagraph.slice(0, nStart)
                               + '<u id="err' + sErrId + '" class="error '+oErr['sType']+'" href="#" onclick="return false;">'
                               + sParagraph.slice(nStart, nEnd)
                               + '<span id="tooltip' + sErrId + '" class="tooltip" contenteditable="false">'
                               + getGrammarErrorHTML(oErr, bDebug) + '</span>'
                               + "</u><!-- err_end -->" + sParagraph.slice(nEnd);
                } else {
                    // Spelling error
                    sParagraph = sParagraph.slice(0, nStart)
                               + '<u id="err' + sErrId + '" class="error spell" href="#" onclick="return false;">'
                               + sParagraph.slice(nStart, nEnd)
                               + '<span id="tooltip' + sErrId + '" class="tooltip" contenteditable="false">'
                               + getSpellingErrorHTML(oErr) + '</span>'
                               + "</u><!-- err_end -->" + sParagraph.slice(nEnd);
                }
                nStartLastErr = nStart;
            }
            nErr -= 1;
        }
        return sParagraph;
    }
    catch (e) {
        helpers.logerror(e);
        return "# Error.";
    }
}

function getGrammarErrorHTML (oErr, bDebug=false) {
    // Returns an error oErr as a readable error in HTML
    try {
        let sErr = '';
        if (bDebug) {
            sErr += '<em class="debug">'
              + '<i id="data'+oErr['sId']+'" class="data" hidden>'
              + oErr['nStart'] + ":" + oErr['nEnd'] + ' · #' + oErr['sRuleId'] + " </i>+</em>";
        }
        sErr += oErr["sMessage"];
        sErr += ' <a id="ignore'+oErr['sId']+'" class="ignore" href="#" onclick="return false;">IGNORER</a>';
        if (oErr["URL"] !== "") {
            sErr += ' <a href="' + oErr["URL"] + '" onclick="return false;">Infos…</a>';
        }
        if (oErr["aSuggestions"].length > 0) {
            sErr += '<br/><s>Suggestions :</s><br/>';
            let iSugg = 0;
            for (let sSugg of oErr["aSuggestions"]) {
                sErr += '<a id="sugg' + oErr['sId'] + "-" + iSugg + '" class="sugg" href="#" onclick="return false;">' + sSugg + '</a> ';
                iSugg += 1;
            }
        }
        return sErr;
    }
    catch (e) {
        helpers.logerror(e);
        return '# Error. Data: ' + oErr.toString();
    }
}

function getSpellingErrorHTML (oErr) {
    // Returns an error oErr as a readable error in HTML
    try {
        let sErr = 'Mot inconnu du dictionnaire.';
        sErr += ' <a id="ignore' + oErr['sId'] + '" class="ignore" href="#" onclick="return false;">IGNORER</a>';
        sErr += '<br/><s>Suggestions :</s><br/>';
        return sErr;
    }
    catch (e) {
        helpers.logerror(e);
        return '# Error. Data: ' + oErr.toString();
    }
}



exports.getParagraph = getParagraph;
exports.addHtmlEntities = addHtmlEntities;
exports.createHTMLBlock = createHTMLBlock;
exports.tagParagraph = tagParagraph;

exports.getReadableError = getReadableError;


>
>



>
>
|
|

>
>
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
<
<
>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63




64


65

66










































































































67
68



69
70
71
// JavaScript
/*jslint esversion: 6*/
/*global require,exports*/

"use strict";


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
}


var text = {
    getParagraph: function* (sText) {
        // generator: returns paragraphs of text
        let iStart = 0;
        let iEnd = 0;
        sText = sText.replace("\r\n", "\n").replace("\r", "\n");
        while ((iEnd = sText.indexOf("\n", iStart)) !== -1) {
            yield sText.slice(iStart, iEnd);
            iStart = iEnd + 1;
        }
        yield sText.slice(iStart);
    },

    wrap: function* (sText, nWidth=80) {
        // generator: returns text line by line
        while (sText) {
            if (sText.length >= nWidth) {
                let nEnd = sText.lastIndexOf(" ", nWidth) + 1;
                if (nEnd > 0) {
                    yield sText.slice(0, nEnd);
                    sText = sText.slice(nEnd);
                } else {
                    yield sText.slice(0, nWidth);
                    sText = sText.slice(nWidth);
                }
            } else {
                break;
            }
        }
        yield sText;
    },

    getReadableError: function (oErr) {
        // Returns an error oErr as a readable error
        try {
            let sResult = "\n* " + oErr['nStart'] + ":" + oErr['nEnd'] 
                        + "  # " + oErr['sLineId'] + "  # " + oErr['sRuleId'] + ":\n";
            sResult += "  " + oErr["sMessage"];
            if (oErr["aSuggestions"].length > 0) {
                sResult += "\n  > Suggestions : " + oErr["aSuggestions"].join(" | ");
            }
            if (oErr["URL"] !== "") {
                sResult += "\n  > URL: " + oErr["URL"];
            }
            return sResult;
        }
        catch (e) {
            helpers.logerror(e);
            return "\n# Error. Data: " + oErr.toString();
        }
    }




};















































































































if (typeof(exports) !== 'undefined') {
    exports.getParagraph = text.getParagraph;



    exports.wrap = text.wrap;
    exports.getReadableError = text.getReadableError;
}

Modified gc_core/js/tokenizer.js from [d06151ccd7] to [81088a0177].

1
2


3
4
5


6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59





60

61
62
63
64
65
66
67
68
69
70
71
72
73





74







75

// JavaScript
// Very simple tokenizer



"use strict";



const helpers = require("resource://grammalecte/helpers.js");



const aPatterns = {
    // All regexps must start with ^.
    "default":
        [
            [/^[   \t]+/, 'SPACE'],
            [/^[,.;:!?…«»“”"()/·]+/, 'SEPARATOR'],
            [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'],
            [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'],
            [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'],
            [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'],
            [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'],
            [/^\d\d?h\d\d\b/, 'HOUR'],
            [/^-?\d+(?:[.,]\d+|)/, 'NUM'],
            [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD']
        ],
    "fr":
        [
            [/^[   \t]+/, 'SPACE'],
            [/^[,.;:!?…«»“”"()/·]+/, 'SEPARATOR'],
            [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'],
            [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'],
            [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'],
            [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'],
            [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'],
            [/^(?:l|d|n|m|t|s|j|c|ç|lorsqu|puisqu|jusqu|quoiqu|qu)['’`]/i, 'ELPFX'],
            [/^\d\d?[hm]\d\d\b/, 'HOUR'],
            [/^\d+(?:er|nd|e|de|ième|ème|eme)\b/, 'ORDINAL'],
            [/^-?\d+(?:[.,]\d+|)/, 'NUM'],
            [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD']
        ]
}


class Tokenizer {

    constructor (sLang) {
        this.sLang = sLang;
        if (!aPatterns.hasOwnProperty(sLang)) {
            this.sLang = "default";
        }
        this.aRules = aPatterns[sLang];
    };


    * genTokens (sText) {
        let m;
        let i = 0;
        while (sText) {
            let nCut = 1;
            for (let [zRegex, sType] of this.aRules) {
                try {
                    if ((m = zRegex.exec(sText)) !== null) {





                        yield { "sType": sType, "sValue": m[0], "nStart": i, "nEnd": i + m[0].length }

                        nCut = m[0].length;
                        break;
                    }
                }
                catch (e) {
                    helpers.logerror(e);
                }
            }
            i += nCut;
            sText = sText.slice(nCut);
        }
    }
}













exports.Tokenizer = Tokenizer;



>
>



>
>
|
|

>
|




|












|







|



|






|


|
<
>









>
>
>
>
>
|
>












|
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// JavaScript
// Very simple tokenizer
/*jslint esversion: 6*/
/*global require,exports*/

"use strict";


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
}


const aTkzPatterns = {
    // All regexps must start with ^.
    "default":
        [
            [/^[   \t]+/, 'SPACE'],
            [/^[,.;:!?…«»“”‘’"(){}\[\]/·–—]+/, 'SEPARATOR'],
            [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'],
            [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'],
            [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'],
            [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'],
            [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'],
            [/^\d\d?h\d\d\b/, 'HOUR'],
            [/^-?\d+(?:[.,]\d+|)/, 'NUM'],
            [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD']
        ],
    "fr":
        [
            [/^[   \t]+/, 'SPACE'],
            [/^[,.;:!?…«»“”‘’"(){}\[\]/·–—]+/, 'SEPARATOR'],
            [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'],
            [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'],
            [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'],
            [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'],
            [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'],
            [/^(?:l|d|n|m|t|s|j|c|ç|lorsqu|puisqu|jusqu|quoiqu|qu)['’`]/i, 'ELPFX'],
            [/^\d\d?[hm]\d\d\b/, 'HOUR'],
            [/^\d+(?:er|nd|e|de|ième|ème|eme)s?\b/, 'ORDINAL'],
            [/^-?\d+(?:[.,]\d+|)/, 'NUM'],
            [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD']
        ]
};


class Tokenizer {

    constructor (sLang) {
        this.sLang = sLang;
        if (!aTkzPatterns.hasOwnProperty(sLang)) {
            this.sLang = "default";
        }
        this.aRules = aTkzPatterns[this.sLang];

    }

    * genTokens (sText) {
        let m;
        let i = 0;
        while (sText) {
            let nCut = 1;
            for (let [zRegex, sType] of this.aRules) {
                try {
                    if ((m = zRegex.exec(sText)) !== null) {
                        if (sType == 'SEPARATOR') {
                            for (let c of m[0]) {
                                yield { "sType": sType, "sValue": c, "nStart": i, "nEnd": i + m[0].length }    
                            }
                        } else {
                            yield { "sType": sType, "sValue": m[0], "nStart": i, "nEnd": i + m[0].length }    
                        }
                        nCut = m[0].length;
                        break;
                    }
                }
                catch (e) {
                    helpers.logerror(e);
                }
            }
            i += nCut;
            sText = sText.slice(nCut);
        }
    }

    getSpellingErrors (sText, oDict) {
        let aSpellErr = [];
        for (let oToken of this.genTokens(sText)) {
            if (oToken.sType === 'WORD' && !oDict.isValidToken(oToken.sValue)) {
                aSpellErr.push(oToken);
            }
        }
        return aSpellErr;
    }
}


if (typeof(exports) !== 'undefined') {
    exports.Tokenizer = Tokenizer;
}

Added gc_core/py/char_player.py version [845d36e2d1].





































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# list of similar chars
# useful for suggestion mechanism


def distanceBetweenWords (s1, s2):
    "distance of Damerau-Levenshtein between <s1> and <s2>"
    # https://fr.wikipedia.org/wiki/Distance_de_Damerau-Levenshtein
    d = {}
    nLen1 = len(s1)
    nLen2 = len(s2)
    for i in range(-1, nLen1+1):
        d[i, -1] = i + 1
    for j in range(-1, nLen2+1):
        d[-1, j] = j + 1
    for i in range(nLen1):
        for j in range(nLen2):
            nCost = 0  if s1[i] == s2[j]  else 1
            d[i, j] = min(
                d[i-1, j]   + 1,        # Deletion
                d[i,   j-1] + 1,        # Insertion
                d[i-1, j-1] + nCost,    # Substitution
            )
            if i and j and s1[i] == s2[j-1] and s1[i-1] == s2[j]:
                d[i, j] = min(d[i, j], d[i-2, j-2] + nCost)     # Transposition
    return d[nLen1-1, nLen2-1]


# Method: Remove Useless Chars

_dVovels = {
    'a': '',  'e': '',  'i': '',  'o': '',  'u': '',  'y': '',
    'à': '',  'é': '',  'î': '',  'ô': '',  'û': '',  'ÿ': '',
    'â': '',  'è': '',  'ï': '',  'ö': '',  'ù': '',  'ŷ': '',
    'ä': '',  'ê': '',  'í': '',  'ó': '',  'ü': '',  'ý': '',
    'á': '',  'ë': '',  'ì': '',  'ò': '',  'ú': '',  'ỳ': '',
    'ā': '',  'ē': '',  'ī': '',  'ō': '',  'ū': '',  'ȳ': '',
    'h': '',  'œ': '',  'æ': ''
 }

_xTransVovels = str.maketrans(_dVovels)


aVovels = frozenset(_dVovels.keys())


def clearWord (sWord):
    "remove vovels and h"
    return sWord[0:1].replace("h", "") + sWord[1:].translate(_xTransVovels)


# Similar chars

d1to1 = {
    "1": "li",
    "2": "z",
    "3": "e",
    "4": "aà",
    "5": "sg",
    "6": "bdg",
    "7": "lt",
    "8": "b",
    "9": "gbd",
    "0": "o",

    "a": "aàâáäæ",
    "à": "aàâáäæ",
    "â": "aàâáäæ",
    "á": "aàâáäæ",
    "ä": "aàâáäæ",

    "æ": "æéa",

    "c": "cçskqśŝ",
    "ç": "cçskqśŝ",

    "e": "eéèêëœ",
    "é": "eéèêëœ",
    "ê": "eéèêëœ",
    "è": "eéèêëœ",
    "ë": "eéèêëœ",

    "g": "gj",
    
    "i": "iîïyíìÿ",
    "î": "iîïyíìÿ",
    "ï": "iîïyíìÿ",
    "í": "iîïyíìÿ",
    "ì": "iîïyíìÿ",

    "j": "jg",

    "k": "kcq",

    "n": "nñ",

    "o": "oôóòöœ",
    "ô": "oôóòöœ",
    "ó": "oôóòöœ",
    "ò": "oôóòöœ",
    "ö": "oôóòöœ",

    "œ": "œoôeéèêë",

    "q": "qck",

    "s": "sśŝcç",
    "ś": "sśŝcç",
    "ŝ": "sśŝcç",

    "u": "uûùüú",
    "û": "uûùüú",
    "ù": "uûùüú",
    "ü": "uûùüú",
    "ú": "uûùüú",

    "v": "vw",

    "w": "wv",

    "x": "xck",

    "y": "yÿiîŷýỳ",
    "ÿ": "yÿiîŷýỳ",
    "ŷ": "yÿiîŷýỳ",
    "ý": "yÿiîŷýỳ",
    "ỳ": "yÿiîŷýỳ",

    "z": "zs",
}

d1toX = {
    "æ": ("ae",),
    "b": ("bb",),
    "c": ("cc", "ss", "qu", "ch"),
    "ç": ("ss", "cc", "qh", "ch"),
    "d": ("dd",),
    "f": ("ff", "ph"),
    "g": ("gu", "ge", "gg", "gh"),
    "i": ("ii",),
    "j": ("jj", "dj"),
    "k": ("qu", "ck", "ch", "cu", "kk", "kh"),
    "l": ("ll",),
    "m": ("mm", "mn"),
    "n": ("nn", "nm", "mn"),
    "o": ("au", "eau", "aut"),
    "œ": ("oe", "eu"),
    "p": ("pp", "ph"),
    "q": ("qu", "ch", "cq", "ck", "kk"),
    "r": ("rr",),
    "s": ("ss", "sh"),
    "t": ("tt", "th"),
    "x": ("cc", "ct", "xx"),
    "z": ("ss", "zh")
}

d2toX = {
    "an": ("en",),
    "en": ("an",),
    "ai": ("ei", "é", "è", "ê", "ë"),
    "ei": ("ai", "é", "è", "ê", "ë"),
    "ch": ("sh", "c", "ss"),
    "ct": ("x", "cc"),
    "oa": ("oi",),
    "oi": ("oa", "oie"),
    "qu": ("q", "cq", "ck", "c", "k"),
    "ss": ("c", "ç"),
}


# End of word

dFinal1 = {
    "a": ("as", "at", "ant", "ah"),
    "c": ("ch",),
    "e": ("et", "er", "ets", "ée", "ez", "ai", "ais", "ait", "ent", "eh"),
    "é": ("et", "er", "ets", "ée", "ez", "ai", "ais", "ait"),
    "è": ("et", "er", "ets", "ée", "ez", "ai", "ais", "ait"),
    "ê": ("et", "er", "ets", "ée", "ez", "ai", "ais", "ait"),
    "ë": ("et", "er", "ets", "ée", "ez", "ai", "ais", "ait"),
    "g": ("gh",),
    "i": ("is", "it", "ie", "in"),
    "n": ("nt", "nd", "ns", "nh"),
    "o": ("aut", "ot", "os"),
    "ô": ("aut", "ot", "os"),
    "ö": ("aut", "ot", "os"),
    "p": ("ph",),
    "s": ("sh",),
    "t": ("th",),
    "u": ("ut", "us", "uh"),
}

dFinal2 = {
    "ai": ("aient", "ais", "et"),
    "an": ("ant", "ent"),
    "en": ("ent", "ant"),
    "ei": ("ait", "ais"),
    "on": ("ons", "ont"),
    "oi": ("ois", "oit", "oix"),
}


# Préfixes

aPfx1 = frozenset([
    "anti", "archi", "contre", "hyper", "mé", "méta", "im", "in", "ir", "par", "proto",
    "pseudo", "pré", "re", "ré", "sans", "sous", "supra", "sur", "ultra"
])
aPfx2 = frozenset([
    "belgo", "franco", "génito", "gynéco", "médico", "russo"
])

Modified gc_core/py/dawg.py from [a9c487538f] to [eb4c8506bd].

12
13
14
15
16
17
18





























































19
20
21
22
23
24
25
..
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203








204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
...
479
480
481
482
483
484
485
486



487
488
489
490
491
492
493
...
682
683
684
685
686
687
688



























import sys
import os
import collections

from . import str_transform as st
from .progressbar import ProgressBar































































class DAWG:
    """DIRECT ACYCLIC WORD GRAPH"""
    # This code is inspired from Steve Hanov’s DAWG, 2011. (http://stevehanov.ca/blog/index.php?id=115)
    # We store suffix/affix codes and tags within the graph after the “real” word.
    # A word is a list of numbers [ c1, c2, c3 . . . cN, iAffix, iTags]
    # Each arc is an index in self.lArcVal, where are stored characters, suffix/affix codes for stemming and tags.
................................................................................
        if cStemming == "A":
            funcStemmingGen = st.defineAffixCode
        elif cStemming == "S":
            funcStemmingGen = st.defineSuffixCode
        elif cStemming == "N":
            funcStemmingGen = st.noStemming
        else:
            print("# Error code: {}".format(cStemming))
            exit()

        lEntry = []
        lChar = ['']; dChar = {}; nChar = 1; dCharOccur = {}
        lAff  = [];   dAff  = {}; nAff  = 0; dAffOccur = {}
        lTag  = [];   dTag  = {}; nTag  = 0; dTagOccur = {}
        nErr = 0
        
        # read lexicon

        with open(spfSrc, 'r', encoding='utf-8') as hSrc:
            print(" > Reading lexicon: " + spfSrc + " ...")
            for line in hSrc:
                line = line.strip()
                if not (line.startswith('#') or line == ''):
                    try:
                        flex, stem, tag = line.split("\t")
                    except:
                        nErr += 1
                        continue
                    # chars
                    for c in flex:
                        if c not in dChar:
                            dChar[c] = nChar
                            lChar.append(c)
                            nChar += 1
                        dCharOccur[c] = dCharOccur.get(c, 0) + 1
                    # affixes to find stem from flexion
                    aff = funcStemmingGen(flex, stem)
                    if aff not in dAff:
                        dAff[aff] = nAff
                        lAff.append(aff)
                        nAff += 1
                    dAffOccur[aff] = dCharOccur.get(aff, 0) + 1
                    # tags
                    if tag not in dTag:
                        dTag[tag] = nTag
                        lTag.append(tag)
                        nTag += 1
                    dTagOccur[tag] = dTagOccur.get(tag, 0) + 1
                    lEntry.append((flex, dAff[aff], dTag[tag]))
            hSrc.close()
        if nErr:
            print(" # Lines ignored: {:>10}".format(nErr))
        if not(lEntry):
            print(" # Empty lexicon")
            exit()
        
        # Preparing DAWG
        print(" > Preparing list of words")
        lVal = lChar + lAff + lTag
        lWord = [ [dChar[c] for c in sFlex] + [iAff+nChar] + [iTag+nChar+nAff]  for sFlex, iAff, iTag in lEntry ]
        lEntry = None
        
................................................................................
        #    for iKey, nOcc in sorted(dValOccur.items(), key=lambda t: t[1], reverse=True):
        #        hFreqDst.write("{}: {}\n".format(lVal[iKey], nOcc))
        #    hFreqDst.close()
        
        self.sFile = spfSrc
        self.sLang = sLangName
        self.nEntry = len(lWord)
        self.previousWord = []
        DawgNode.resetNextId()
        self.root = DawgNode()
        self.uncheckedNodes = []  # list of nodes that have not been checked for duplication.
        self.minimizedNodes = {}  # list of unique nodes that have been checked for duplication.
        self.sortedNodes = []     # version 2 and 3
        self.nNode = 0
        self.nArc = 0
        self.dChar = dChar
        self.nChar = len(dChar)
        self.nAff = nAff
        self.lArcVal = lVal
        self.nArcVal = len(lVal)
        self.nTag = self.nArcVal - self.nChar - nAff
        self.cStemming = cStemming.upper()
        if cStemming == "A":
            self.funcStemming = st.getStemFromAffixCode
        elif cStemming == "S":    
            self.funcStemming = st.getStemFromSuffixCode
        else:
            self.funcStemming = st.noStemming
        
        # build
        lWord.sort()
        oProgBar = ProgressBar(0, len(lWord))
        for word in lWord:
            self.insert(word)
            oProgBar.increment(1)
        oProgBar.done()
        self.finish()
        self.countNodes()
        self.countArcs()
        self.sortNodes()
        self.sortNodeArcs(dValOccur)

        self.displayInfo()

    # BUILD DAWG
    def insert (self, word):
        if word < self.previousWord:
            sys.exit("# Error: Words must be inserted in alphabetical order.")
        
        # find common prefix between word and previous word
        commonPrefix = 0
        for i in range(min(len(word), len(self.previousWord))):
            if word[i] != self.previousWord[i]:
                break
            commonPrefix += 1

        # Check the uncheckedNodes for redundant nodes, proceeding from last
        # one down to the common prefix size. Then truncate the list at that point.
        self._minimize(commonPrefix)

        # add the suffix, starting from the correct node mid-way through the graph
        if len(self.uncheckedNodes) == 0:
            oNode = self.root
        else:
            oNode = self.uncheckedNodes[-1][2]

        iChar = commonPrefix
        for c in word[commonPrefix:]:
            oNextNode = DawgNode()
            oNode.arcs[c] = oNextNode
            self.uncheckedNodes.append((oNode, c, oNextNode))
            if iChar == (len(word) - 2): 
                oNode.final = True
            iChar += 1
            oNode = oNextNode
        oNode.final = True
        self.previousWord = word

    def finish (self):
        "minimize unchecked nodes"
        self._minimize(0)

    def _minimize (self, downTo):
        # proceed from the leaf up to a certain point
        for i in range( len(self.uncheckedNodes)-1, downTo-1, -1 ):
            (parent, char, child) = self.uncheckedNodes[i]
            if child in self.minimizedNodes:
                # replace the child with the previously encountered one
                parent.arcs[char] = self.minimizedNodes[child]
            else:
                # add the state to the minimized nodes.
                self.minimizedNodes[child] = child
            self.uncheckedNodes.pop()

    def countNodes (self):
        self.nNode = len(self.minimizedNodes)

    def countArcs (self):
        self.nArc = 0
        for node in self.minimizedNodes:
            self.nArc += len(node.arcs)
    
    def sortNodeArcs (self, dValOccur):
        print(" > Sort node arcs")
        self.root.sortArcs(dValOccur)
        for oNode in self.minimizedNodes:
            oNode.sortArcs(dValOccur)
    








    def sortNodes (self):
        print(" > Sort nodes")
        for oNode in self.root.arcs.values():
            self._parseNodes(oNode)
    
    def _parseNodes (self, oNode):
        # Warning: recursive method
        if oNode.pos > 0:
            return
        oNode.setPos()
        self.sortedNodes.append(oNode)
        for oNextNode in oNode.arcs.values():
             self._parseNodes(oNextNode)
        
    def lookup (self, sWord):
        oNode = self.root
        for c in sWord:
            if self.dChar.get(c, '') not in oNode.arcs:
                return False
            oNode = oNode.arcs[self.dChar[c]]
        return oNode.final

    def morph (self, sWord):
        oNode = self.root
        for c in sWord:
            if self.dChar.get(c, '') not in oNode.arcs:
                return ''
            oNode = oNode.arcs[self.dChar[c]]
        if oNode.final:
            s = "* "
            for arc in oNode.arcs:
................................................................................
        print(" * {:<12} {:>16,}".format("Arc values:", self.nArcVal))
        print(" * {:<12} {:>16,}".format("Nodes:", self.nNode))
        print(" * {:<12} {:>16,}".format("Arcs:", self.nArc))
        print(" * {:<12} {:>16}".format("Stemming:", self.cStemming + "FX"))

    def getArcStats (self):
        d = {}
        for oNode in self.minimizedNodes:
            n = len(oNode.arcs)
            d[n] = d.get(n, 0) + 1
        s = " * Nodes:\n"
        for n in d:
            s = s + " {:>9} nodes have {:>3} arcs\n".format(d[n], n)
        return s

................................................................................
                hDst.write(" {:>6}. {}\n".format(i, s))
            hDst.close()

    # BINARY CONVERSION
    def createBinary (self, sPathFile, nMethod, bDebug=False):
        print(" > Write DAWG as an indexable binary dictionary [method: %d]" % nMethod)
        if nMethod == 1:
            self.nBytesArc = ( ( (self.nArcVal).bit_length() + 2 ) // 8 ) + 1   # We add 2 bits. See DawgNode.convToBytes1()
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress1()
        elif nMethod == 2:
            self.nBytesArc = ( ( (self.nArcVal).bit_length() + 3 ) // 8 ) + 1   # We add 3 bits. See DawgNode.convToBytes2()
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress2()
        elif nMethod == 3:
            self.nBytesArc = ( ( (self.nArcVal).bit_length() + 3 ) // 8 ) + 1   # We add 3 bits. See DawgNode.convToBytes3()
            self.nBytesOffset = 1
            self.nMaxOffset = (2 ** (self.nBytesOffset * 8)) - 1
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress3()
        else:
            print(" # Error: unknown compression method")
        print("   Arc values (chars, affixes and tags): {}  ->  {} bytes".format( self.nArcVal, len("\t".join(self.lArcVal).encode("utf-8")) ))
................................................................................
        "how many bytes needed to store all nodes/arcs in the binary dictionary"
        self.nBytesNodeAddress = 1
        while ((self.nBytesArc + self.nBytesNodeAddress) * self.nArc) > (2 ** (self.nBytesNodeAddress * 8)):
            self.nBytesNodeAddress += 1

    def _calcNodesAddress1 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        iAddr = len(self.root.arcs) * nBytesNode
        for oNode in self.minimizedNodes:
            oNode.addr = iAddr
            iAddr += max(len(oNode.arcs), 1) * nBytesNode

    def _calcNodesAddress2 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        iAddr = len(self.root.arcs) * nBytesNode
        for oNode in self.sortedNodes:
            oNode.addr = iAddr
            iAddr += max(len(oNode.arcs), 1) * nBytesNode
            for oNextNode in oNode.arcs.values():
                if (oNode.pos + 1) == oNextNode.pos:
                    iAddr -= self.nBytesNodeAddress
                    #break

    def _calcNodesAddress3 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        # theorical nodes size if only addresses and no offset
        self.root.size = len(self.root.arcs) * nBytesNode
        for oNode in self.sortedNodes:
            oNode.size = max(len(oNode.arcs), 1) * nBytesNode
        # rewind and calculate dropdown from the end, several times
        nDiff = self.nBytesNodeAddress - self.nBytesOffset
        bEnd = False
        while not bEnd:
            bEnd = True
            # recalculate addresses
            iAddr = self.root.size
            for oNode in self.sortedNodes:
                oNode.addr = iAddr
                iAddr += oNode.size
            # rewind and calculate dropdown from the end, several times
            for i in range(self.nNode-1, -1, -1):
                nSize = max(len(self.sortedNodes[i].arcs), 1) * nBytesNode
                for oNextNode in self.sortedNodes[i].arcs.values():
                    if 1 < (oNextNode.addr - self.sortedNodes[i].addr) < self.nMaxOffset:
                        nSize -= nDiff
                if self.sortedNodes[i].size != nSize:
                    self.sortedNodes[i].size = nSize
                    bEnd = False

    def _writeBinary (self, sPathFile, nMethod):
        """
        Format of the binary indexable dictionary:
        Each section is separated with 4 bytes of \0
        
................................................................................
                                                           self.nEntry, self.nNode, self.nArc, self.nAff, self.cStemming).encode("utf-8"))
            hDst.write(b"\0\0\0\0")
            # lArcVal
            hDst.write("\t".join(self.lArcVal).encode("utf-8"))
            hDst.write(b"\0\0\0\0")
            # DAWG: nodes / arcs
            if nMethod == 1:
                hDst.write(self.root.convToBytes1(self.nBytesArc, self.nBytesNodeAddress))
                for oNode in self.minimizedNodes:
                    hDst.write(oNode.convToBytes1(self.nBytesArc, self.nBytesNodeAddress))
            elif nMethod == 2:
                hDst.write(self.root.convToBytes2(self.nBytesArc, self.nBytesNodeAddress))
                for oNode in self.sortedNodes:
                    hDst.write(oNode.convToBytes2(self.nBytesArc, self.nBytesNodeAddress))
            elif nMethod == 3:
                hDst.write(self.root.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
                for oNode in self.sortedNodes:
                    hDst.write(oNode.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
            hDst.close()

    def _writeNodes (self, sPathFile, nMethod):
        "for debugging only"
        print(" > Write nodes")
        with open(sPathFile+".nodes."+str(nMethod)+".txt", 'w', encoding='utf-8', newline="\n") as hDst:
            if nMethod == 1:
                hDst.write(self.root.getTxtRepr1(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
                #hDst.write( ''.join( [ "%02X " %  z  for z in self.root.convToBytes1(self.nBytesArc, self.nBytesNodeAddress) ] ).strip() )
                for oNode in self.minimizedNodes:
                    hDst.write(oNode.getTxtRepr1(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
            if nMethod == 2:
                hDst.write(self.root.getTxtRepr2(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
                for oNode in self.sortedNodes:
                    hDst.write(oNode.getTxtRepr2(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
            if nMethod == 3:
                hDst.write(self.root.getTxtRepr3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset, self.lArcVal)+"\n")
                #hDst.write( ''.join( [ "%02X " %  z  for z in self.root.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset) ] ).strip() )
                for oNode in self.sortedNodes:
                    hDst.write(oNode.getTxtRepr3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset, self.lArcVal)+"\n")
            hDst.close()
    
    def writeResults (self, sPathFile):
        bFileExits = os.path.isfile("_lexicons.res.txt")
        with open("_lexicons.res.txt", "a", encoding='utf-8', newline="\n") as hDst:
            sFormat1 = "{:<12} {:>12} {:>5} {:>8} {:>8} {:>6} {:>8} {:>9} {:>9} {:>15} {:>12} {:>12}\n"
................................................................................

    def __eq__ (self, other):
        # Used as a key in a python dictionary.
        # Nodes are equivalent if they have identical arcs, and each identical arc leads to identical states.
        return self.__str__() == other.__str__()

    def sortArcs (self, dValOccur):
        self.arcs = collections.OrderedDict(sorted(self.arcs.items(), key=lambda t: dValOccur[t[0]], reverse=True))




    # VERSION 1 =====================================================================================================
    def convToBytes1 (self, nBytesArc, nBytesNodeAddress):
        """
        Node scheme:
        - Arc length is defined by nBytesArc
        - Address length is defined by nBytesNodeAddress
................................................................................
                val = val | nFinalArcMask
            if 1 < (self.arcs[arc].addr - self.addr) < nMaxOffset and self.i != 0:
                val = val | nNextNodeMask
                s += "  {:<20}  {:0>16}  i{:_>10}   +{:_>10}\n".format(lVal[arc], bin(val)[2:], self.arcs[arc].i, self.arcs[arc].addr - self.addr)
            else:
                s += "  {:<20}  {:0>16}  i{:_>10}   #{:_>10}\n".format(lVal[arc], bin(val)[2:], self.arcs[arc].i, self.arcs[arc].addr)
        return s


































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<








>
|
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
|
|
<







 







|

|
|
|
|








|

|

|






|
|







>



|
|



|
|
|

|

|

|


|
|

|

|
|


|
|




|







|
|
|

|


|
|


|



|
|



|
|


>
>
>
>
>
>
>
>


|







|




|







|







 







|







 







|



|



|







 







|
|





|
|










|
|







|
|




|
|
|

|
|







 







|
|


|
|


|
|








|
|
|


|
|


|
|
|







 







|
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109









110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130



131
132

133
134
135
136
137
138
139
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
...
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
import sys
import os
import collections

from . import str_transform as st
from .progressbar import ProgressBar



def readFile (spf):
    print(" < Read lexicon: " + spf)
    if os.path.isfile(spf):
        with open(spf, "r", encoding="utf-8") as hSrc:
            for sLine in hSrc:
                sLine = sLine.strip()
                if sLine and not sLine.startswith("#"):
                    yield sLine
    else:
        raise OSError("# Error. File not found or not loadable: " + spf)


def getElemsFromFile (spf):
    "returns tuple of (flexion, stem, tags) from lexicon file"
    nErr = 0
    if not spf.endswith(".clex"):
        for sLine in readFile(spf):
            try:
                sFlex, sStem, sTag = sLine.split("\t")
                yield (sFlex, sStem, sTag)
            except:
                nErr += 1
    else:
        sTag = "_" # neutral tag
        sTag2 = ""
        for sLine in readFile(spf):
            if sLine.startswith("[") and sLine.endswith("]"):
                # tag line
                if "-->" in sLine:
                    try:
                        sTag, sSfxCode, sTag2 = sLine[1:-1].split(" --> ")
                    except:
                        nErr += 1
                        continue
                    sTag = sTag.strip()
                    sSfxCode = sSfxCode.strip()
                    sTag2 = sTag2.strip()
                else:
                    sTag = sLine[1:-1]
                    sTag2 = ""
            else:
                # entry line
                if "\t" in sLine:
                    if sLine.count("\t") > 1:
                        nErr += 1
                        continue
                    sFlex, sStem = sLine.split("\t")
                else:
                    sFlex = sStem = sLine
                #print(sFlex, sStem, sTag)
                yield (sFlex, sStem, sTag)
                if sTag2:
                    sFlex2 = st.changeWordWithSuffixCode(sFlex, sSfxCode)
                    #print(sFlex2, sStem, sTag2)
                    yield (sFlex2, sStem, sTag2)
    if nErr:
        print(" # Lines ignored: {:>10}".format(nErr))



class DAWG:
    """DIRECT ACYCLIC WORD GRAPH"""
    # This code is inspired from Steve Hanov’s DAWG, 2011. (http://stevehanov.ca/blog/index.php?id=115)
    # We store suffix/affix codes and tags within the graph after the “real” word.
    # A word is a list of numbers [ c1, c2, c3 . . . cN, iAffix, iTags]
    # Each arc is an index in self.lArcVal, where are stored characters, suffix/affix codes for stemming and tags.
................................................................................
        if cStemming == "A":
            funcStemmingGen = st.defineAffixCode
        elif cStemming == "S":
            funcStemmingGen = st.defineSuffixCode
        elif cStemming == "N":
            funcStemmingGen = st.noStemming
        else:
            raise ValueError("# Error. Unknown stemming code: {}".format(cStemming))


        lEntry = []
        lChar = ['']; dChar = {}; nChar = 1; dCharOccur = {}
        lAff  = [];   dAff  = {}; nAff  = 0; dAffOccur = {}
        lTag  = [];   dTag  = {}; nTag  = 0; dTagOccur = {}
        nErr = 0
        
        # read lexicon
        for sFlex, sStem, sTag in getElemsFromFile(spfSrc):
            addWordToCharDict(sFlex)









            # chars
            for c in sFlex:
                if c not in dChar:
                    dChar[c] = nChar
                    lChar.append(c)
                    nChar += 1
                dCharOccur[c] = dCharOccur.get(c, 0) + 1
            # affixes to find stem from flexion
            aff = funcStemmingGen(sFlex, sStem)
            if aff not in dAff:
                dAff[aff] = nAff
                lAff.append(aff)
                nAff += 1
            dAffOccur[aff] = dCharOccur.get(aff, 0) + 1
            # tags
            if sTag not in dTag:
                dTag[sTag] = nTag
                lTag.append(sTag)
                nTag += 1
            dTagOccur[sTag] = dTagOccur.get(sTag, 0) + 1
            lEntry.append((sFlex, dAff[aff], dTag[sTag]))



        if not lEntry:
            raise ValueError("# Error. Empty lexicon")

        
        # Preparing DAWG
        print(" > Preparing list of words")
        lVal = lChar + lAff + lTag
        lWord = [ [dChar[c] for c in sFlex] + [iAff+nChar] + [iTag+nChar+nAff]  for sFlex, iAff, iTag in lEntry ]
        lEntry = None
        
................................................................................
        #    for iKey, nOcc in sorted(dValOccur.items(), key=lambda t: t[1], reverse=True):
        #        hFreqDst.write("{}: {}\n".format(lVal[iKey], nOcc))
        #    hFreqDst.close()
        
        self.sFile = spfSrc
        self.sLang = sLangName
        self.nEntry = len(lWord)
        self.aPreviousEntry = []
        DawgNode.resetNextId()
        self.oRoot = DawgNode()
        self.lUncheckedNodes = []  # list of nodes that have not been checked for duplication.
        self.lMinimizedNodes = {}  # list of unique nodes that have been checked for duplication.
        self.lSortedNodes = []     # version 2 and 3
        self.nNode = 0
        self.nArc = 0
        self.dChar = dChar
        self.nChar = len(dChar)
        self.nAff = nAff
        self.lArcVal = lVal
        self.nArcVal = len(lVal)
        self.nTag = self.nArcVal - self.nChar - nAff
        self.cStemming = cStemming
        if cStemming == "A":
            self.funcStemming = st.changeWordWithAffixCode
        elif cStemming == "S":    
            self.funcStemming = st.changeWordWithSuffixCode
        else:
            self.funcStemming = st.noStemming
        
        # build
        lWord.sort()
        oProgBar = ProgressBar(0, len(lWord))
        for aEntry in lWord:
            self.insert(aEntry)
            oProgBar.increment(1)
        oProgBar.done()
        self.finish()
        self.countNodes()
        self.countArcs()
        self.sortNodes()
        self.sortNodeArcs(dValOccur)
        #self.sortNodeArcs2 (self.oRoot, "")
        self.displayInfo()

    # BUILD DAWG
    def insert (self, aEntry):
        if aEntry < self.aPreviousEntry:
            sys.exit("# Error: Words must be inserted in alphabetical order.")
        
        # find common prefix between word and previous word
        nCommonPrefix = 0
        for i in range(min(len(aEntry), len(self.aPreviousEntry))):
            if aEntry[i] != self.aPreviousEntry[i]:
                break
            nCommonPrefix += 1

        # Check the lUncheckedNodes for redundant nodes, proceeding from last
        # one down to the common prefix size. Then truncate the list at that point.
        self._minimize(nCommonPrefix)

        # add the suffix, starting from the correct node mid-way through the graph
        if len(self.lUncheckedNodes) == 0:
            oNode = self.oRoot
        else:
            oNode = self.lUncheckedNodes[-1][2]

        iChar = nCommonPrefix
        for c in aEntry[nCommonPrefix:]:
            oNextNode = DawgNode()
            oNode.arcs[c] = oNextNode
            self.lUncheckedNodes.append((oNode, c, oNextNode))
            if iChar == (len(aEntry) - 2): 
                oNode.final = True
            iChar += 1
            oNode = oNextNode
        oNode.final = True
        self.aPreviousEntry = aEntry

    def finish (self):
        "minimize unchecked nodes"
        self._minimize(0)

    def _minimize (self, downTo):
        # proceed from the leaf up to a certain point
        for i in range( len(self.lUncheckedNodes)-1, downTo-1, -1 ):
            oNode, char, oChildNode = self.lUncheckedNodes[i]
            if oChildNode in self.lMinimizedNodes:
                # replace the child with the previously encountered one
                oNode.arcs[char] = self.lMinimizedNodes[oChildNode]
            else:
                # add the state to the minimized nodes.
                self.lMinimizedNodes[oChildNode] = oChildNode
            self.lUncheckedNodes.pop()

    def countNodes (self):
        self.nNode = len(self.lMinimizedNodes)

    def countArcs (self):
        self.nArc = 0
        for oNode in self.lMinimizedNodes:
            self.nArc += len(oNode.arcs)
    
    def sortNodeArcs (self, dValOccur):
        print(" > Sort node arcs")
        self.oRoot.sortArcs(dValOccur)
        for oNode in self.lMinimizedNodes:
            oNode.sortArcs(dValOccur)
    
    def sortNodeArcs2 (self, oNode, cPrevious=""):
        # recursive function
        dCharOccur = getCharOrderAfterChar(cPrevious)
        if dCharOccur:
            oNode.sortArcs2(dCharOccur, self.lArcVal)
        for nArcVal, oNextNode in oNode.arcs.items():
            self.sortNodeArcs2(oNextNode, self.lArcVal[nArcVal])

    def sortNodes (self):
        print(" > Sort nodes")
        for oNode in self.oRoot.arcs.values():
            self._parseNodes(oNode)
    
    def _parseNodes (self, oNode):
        # Warning: recursive method
        if oNode.pos > 0:
            return
        oNode.setPos()
        self.lSortedNodes.append(oNode)
        for oNextNode in oNode.arcs.values():
             self._parseNodes(oNextNode)
        
    def lookup (self, sWord):
        oNode = self.oRoot
        for c in sWord:
            if self.dChar.get(c, '') not in oNode.arcs:
                return False
            oNode = oNode.arcs[self.dChar[c]]
        return oNode.final

    def morph (self, sWord):
        oNode = self.oRoot
        for c in sWord:
            if self.dChar.get(c, '') not in oNode.arcs:
                return ''
            oNode = oNode.arcs[self.dChar[c]]
        if oNode.final:
            s = "* "
            for arc in oNode.arcs:
................................................................................
        print(" * {:<12} {:>16,}".format("Arc values:", self.nArcVal))
        print(" * {:<12} {:>16,}".format("Nodes:", self.nNode))
        print(" * {:<12} {:>16,}".format("Arcs:", self.nArc))
        print(" * {:<12} {:>16}".format("Stemming:", self.cStemming + "FX"))

    def getArcStats (self):
        d = {}
        for oNode in self.lMinimizedNodes:
            n = len(oNode.arcs)
            d[n] = d.get(n, 0) + 1
        s = " * Nodes:\n"
        for n in d:
            s = s + " {:>9} nodes have {:>3} arcs\n".format(d[n], n)
        return s

................................................................................
                hDst.write(" {:>6}. {}\n".format(i, s))
            hDst.close()

    # BINARY CONVERSION
    def createBinary (self, sPathFile, nMethod, bDebug=False):
        print(" > Write DAWG as an indexable binary dictionary [method: %d]" % nMethod)
        if nMethod == 1:
            self.nBytesArc = ( (self.nArcVal.bit_length() + 2) // 8 ) + 1   # We add 2 bits. See DawgNode.convToBytes1()
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress1()
        elif nMethod == 2:
            self.nBytesArc = ( (self.nArcVal.bit_length() + 3) // 8 ) + 1   # We add 3 bits. See DawgNode.convToBytes2()
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress2()
        elif nMethod == 3:
            self.nBytesArc = ( (self.nArcVal.bit_length() + 3) // 8 ) + 1   # We add 3 bits. See DawgNode.convToBytes3()
            self.nBytesOffset = 1
            self.nMaxOffset = (2 ** (self.nBytesOffset * 8)) - 1
            self._calcNumBytesNodeAddress()
            self._calcNodesAddress3()
        else:
            print(" # Error: unknown compression method")
        print("   Arc values (chars, affixes and tags): {}  ->  {} bytes".format( self.nArcVal, len("\t".join(self.lArcVal).encode("utf-8")) ))
................................................................................
        "how many bytes needed to store all nodes/arcs in the binary dictionary"
        self.nBytesNodeAddress = 1
        while ((self.nBytesArc + self.nBytesNodeAddress) * self.nArc) > (2 ** (self.nBytesNodeAddress * 8)):
            self.nBytesNodeAddress += 1

    def _calcNodesAddress1 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        iAddr = len(self.oRoot.arcs) * nBytesNode
        for oNode in self.lMinimizedNodes:
            oNode.addr = iAddr
            iAddr += max(len(oNode.arcs), 1) * nBytesNode

    def _calcNodesAddress2 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        iAddr = len(self.oRoot.arcs) * nBytesNode
        for oNode in self.lSortedNodes:
            oNode.addr = iAddr
            iAddr += max(len(oNode.arcs), 1) * nBytesNode
            for oNextNode in oNode.arcs.values():
                if (oNode.pos + 1) == oNextNode.pos:
                    iAddr -= self.nBytesNodeAddress
                    #break

    def _calcNodesAddress3 (self):
        nBytesNode = self.nBytesArc + self.nBytesNodeAddress
        # theorical nodes size if only addresses and no offset
        self.oRoot.size = len(self.oRoot.arcs) * nBytesNode
        for oNode in self.lSortedNodes:
            oNode.size = max(len(oNode.arcs), 1) * nBytesNode
        # rewind and calculate dropdown from the end, several times
        nDiff = self.nBytesNodeAddress - self.nBytesOffset
        bEnd = False
        while not bEnd:
            bEnd = True
            # recalculate addresses
            iAddr = self.oRoot.size
            for oNode in self.lSortedNodes:
                oNode.addr = iAddr
                iAddr += oNode.size
            # rewind and calculate dropdown from the end, several times
            for i in range(self.nNode-1, -1, -1):
                nSize = max(len(self.lSortedNodes[i].arcs), 1) * nBytesNode
                for oNextNode in self.lSortedNodes[i].arcs.values():
                    if 1 < (oNextNode.addr - self.lSortedNodes[i].addr) < self.nMaxOffset:
                        nSize -= nDiff
                if self.lSortedNodes[i].size != nSize:
                    self.lSortedNodes[i].size = nSize
                    bEnd = False

    def _writeBinary (self, sPathFile, nMethod):
        """
        Format of the binary indexable dictionary:
        Each section is separated with 4 bytes of \0
        
................................................................................
                                                           self.nEntry, self.nNode, self.nArc, self.nAff, self.cStemming).encode("utf-8"))
            hDst.write(b"\0\0\0\0")
            # lArcVal
            hDst.write("\t".join(self.lArcVal).encode("utf-8"))
            hDst.write(b"\0\0\0\0")
            # DAWG: nodes / arcs
            if nMethod == 1:
                hDst.write(self.oRoot.convToBytes1(self.nBytesArc, self.nBytesNodeAddress))
                for oNode in self.lMinimizedNodes:
                    hDst.write(oNode.convToBytes1(self.nBytesArc, self.nBytesNodeAddress))
            elif nMethod == 2:
                hDst.write(self.oRoot.convToBytes2(self.nBytesArc, self.nBytesNodeAddress))
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.convToBytes2(self.nBytesArc, self.nBytesNodeAddress))
            elif nMethod == 3:
                hDst.write(self.oRoot.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
            hDst.close()

    def _writeNodes (self, sPathFile, nMethod):
        "for debugging only"
        print(" > Write nodes")
        with open(sPathFile+".nodes."+str(nMethod)+".txt", 'w', encoding='utf-8', newline="\n") as hDst:
            if nMethod == 1:
                hDst.write(self.oRoot.getTxtRepr1(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
                #hDst.write( ''.join( [ "%02X " %  z  for z in self.oRoot.convToBytes1(self.nBytesArc, self.nBytesNodeAddress) ] ).strip() )
                for oNode in self.lMinimizedNodes:
                    hDst.write(oNode.getTxtRepr1(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
            if nMethod == 2:
                hDst.write(self.oRoot.getTxtRepr2(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.getTxtRepr2(self.nBytesArc, self.nBytesNodeAddress, self.lArcVal)+"\n")
            if nMethod == 3:
                hDst.write(self.oRoot.getTxtRepr3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset, self.lArcVal)+"\n")
                #hDst.write( ''.join( [ "%02X " %  z  for z in self.oRoot.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset) ] ).strip() )
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.getTxtRepr3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset, self.lArcVal)+"\n")
            hDst.close()
    
    def writeResults (self, sPathFile):
        bFileExits = os.path.isfile("_lexicons.res.txt")
        with open("_lexicons.res.txt", "a", encoding='utf-8', newline="\n") as hDst:
            sFormat1 = "{:<12} {:>12} {:>5} {:>8} {:>8} {:>6} {:>8} {:>9} {:>9} {:>15} {:>12} {:>12}\n"
................................................................................

    def __eq__ (self, other):
        # Used as a key in a python dictionary.
        # Nodes are equivalent if they have identical arcs, and each identical arc leads to identical states.
        return self.__str__() == other.__str__()

    def sortArcs (self, dValOccur):
        self.arcs = collections.OrderedDict(sorted(self.arcs.items(), key=lambda t: dValOccur.get(t[0], 0), reverse=True))

    def sortArcs2 (self, dValOccur, lArcVal):
        self.arcs = collections.OrderedDict(sorted(self.arcs.items(), key=lambda t: dValOccur.get(lArcVal[t[0]], 0), reverse=True))

    # VERSION 1 =====================================================================================================
    def convToBytes1 (self, nBytesArc, nBytesNodeAddress):
        """
        Node scheme:
        - Arc length is defined by nBytesArc
        - Address length is defined by nBytesNodeAddress
................................................................................
                val = val | nFinalArcMask
            if 1 < (self.arcs[arc].addr - self.addr) < nMaxOffset and self.i != 0:
                val = val | nNextNodeMask
                s += "  {:<20}  {:0>16}  i{:_>10}   +{:_>10}\n".format(lVal[arc], bin(val)[2:], self.arcs[arc].i, self.arcs[arc].addr - self.addr)
            else:
                s += "  {:<20}  {:0>16}  i{:_>10}   #{:_>10}\n".format(lVal[arc], bin(val)[2:], self.arcs[arc].i, self.arcs[arc].addr)
        return s



# Another attempt to sort node arcs

_dCharOrder = {
    # key: previous char, value: dictionary of chars {c: nValue}
    "": {}
}


def addWordToCharDict (sWord):
    cPrevious = ""
    for cChar in sWord:
        if cPrevious not in _dCharOrder:
            _dCharOrder[cPrevious] = {}
        _dCharOrder[cPrevious][cChar] = _dCharOrder[cPrevious].get(cChar, 0) + 1
        cPrevious = cChar


def getCharOrderAfterChar (cChar):
    return _dCharOrder.get(cChar, None)


def displayCharOrder ():
    for key, value in _dCharOrder.items():
        print("[" + key + "]: ", ", ".join([ c+":"+str(n)  for c, n  in  sorted(value.items(), key=lambda t: t[1], reverse=True) ]))

Modified gc_core/py/ibdawg.py from [9ce1ce821d] to [9237f7174c].

1
2
3
4
5
6


7
8

9
10




11
12
13
14
15
16
17
..
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73

74
75
76
77

78
79
80
81
82
83
84
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169





















170
171

172


173
174


175
176
177
178







179
180



















181
182
183
184
185



186
187
188



















189





190







191
192
193
194
195
196
197












198



199










200
201
202
203












204
205
206
207
208
209
210
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272










273
274
275
276
277
278
279
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
#!python3
# -*- coding: UTF-8 -*-

import os
import traceback
import pkgutil



from . import str_transform as st

from .echo import echo






class IBDAWG:
    """INDEXABLE BINARY DIRECT ACYCLIC WORD GRAPH"""

    def __init__ (self, sDicName):
        self.by = pkgutil.get_data(__package__, "_dictionaries/" + sDicName)
        if not self.by:
................................................................................
        self.nBytesNodeAddress = int(l[3])
        self.nEntries = int(l[4])
        self.nNode = int(l[5])
        self.nArc = int(l[6])
        self.nAff = int(l[7])
        self.cStemming = l[8]
        if self.cStemming == "S":
            self.funcStemming = st.getStemFromSuffixCode
        elif self.cStemming == "A":
            self.funcStemming = st.getStemFromAffixCode
        else:
            self.funcStemming = st.noStemming
        self.nTag = self.nArcVal - self.nChar - self.nAff

        self.dChar = {}
        for i in range(1, self.nChar):
            self.dChar[self.lArcVal[i]] = i

            
        self._arcMask = (2 ** ((self.nBytesArc * 8) - 3)) - 1
        self._finalNodeMask = 1 << ((self.nBytesArc * 8) - 1)
        self._lastArcMask = 1 << ((self.nBytesArc * 8) - 2)
        self._addrBitMask = 1 << ((self.nBytesArc * 8) - 3)  # version 2

        self.nBytesOffset = 1 # version 3

        # Configuring DAWG functions according to nVersion
        if self.nVersion == 1:
            self.morph = self._morph1
            self.stem = self._stem1
            self._lookupArcNode = self._lookupArcNode1

            self._writeNodes = self._writeNodes1
        elif self.nVersion == 2:
            self.morph = self._morph2
            self.stem = self._stem2
            self._lookupArcNode = self._lookupArcNode2

            self._writeNodes = self._writeNodes2
        elif self.nVersion == 3:
            self.morph = self._morph3
            self.stem = self._stem3

            self._lookupArcNode = self._lookupArcNode3
            self._writeNodes = self._writeNodes3
        else:
            raise ValueError("  # Error: unknown code: {}".format(self.nVersion))

        self.bOptNumSigle = False
        self.bOptNumAtLast = False
................................................................................
                            "_addrBitMask": self._addrBitMask,
                            "nBytesOffset": self.nBytesOffset
                        }, ensure_ascii=False))
            if bInJSModule:
                hDst.write(";\n\nexports.dictionary = dictionary;\n")

    def isValidToken (self, sToken):
        "checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)"
        if self.isValid(sToken):
            return True
        if "-" in sToken:
            if sToken.count("-") > 4:
                return True
            return all(self.isValid(sWord)  for sWord in sToken.split("-"))
        return False

    def isValid (self, sWord):
        "checks if sWord is valid (different casing tested if the first letter is a capital)"
        if not sWord:
            return None
        if "’" in sWord: # ugly hack
            sWord = sWord.replace("’", "'")
        if self.lookup(sWord):
            return True
        if sWord[0:1].isupper():
            if len(sWord) > 1:
                if sWord.istitle():
                    return bool(self.lookup(sWord.lower()))
                if sWord.isupper():
                    if self.bOptNumSigle:
                        return True
                    return bool(self.lookup(sWord.lower()) or self.lookup(sWord.capitalize()))
                return bool(self.lookup(sWord[:1].lower() + sWord[1:]))
            else:
                return bool(self.lookup(sWord.lower()))
        return False

    def lookup (self, sWord):
        "returns True if sWord in dictionary (strict verification)"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return False
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return False
        return int.from_bytes(self.byDic[iAddr:iAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask

    def getSugg (self, sWord, iAddr=0, sNewWord=""):
        "not finished"
        # RECURSIVE FUNCTION





















        if not sWord:
            if int.from_bytes(self.byDic[iAddr:iAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask:

                return [sNewWord]


            return []
        lSugg = []


        lArc = self._getSimilarArcs(sWord[0:1], iAddr)
        if lArc:
            for t in lArc:
                lSugg.extend(self._lookupAndSuggest(sWord[1:], t[1], sNewWord+t[0]))







        else:
            pass



















        return lSugg

    def _getSimilarArcs (self, cChar, iAddr):
        lArc = []
        for c in st.dSimilarChars.get(cChar, cChar):



            jAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if jAddr:
                lArc.append((c, iAddr))



















        return lArc













    def getMorph (self, sWord):
        "retrieves morphologies list, different casing allowed"
        l = self.morph(sWord)
        if sWord[0:1].isupper():
            l.extend(self.morph(sWord.lower()))
            if sWord.isupper() and len(sWord) > 1:
                l.extend(self.morph(sWord.capitalize()))












        return l














    # def morph (self, sWord):
    #     is defined in __init__

    # VERSION 1












    def _morph1 (self, sWord):
        "returns morphologies of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress
                iAddr = iEndArcAddr+self.nBytesNodeAddress
            return l
        return []

    def _stem1 (self, sWord):
        "returns stems list of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                    # This value is not a char, this is a stemming code 
                    l.append(self.funcStemming(sWord, self.lArcVal[nArc]))
                iAddr = iEndArcAddr+self.nBytesNodeAddress
            return l
        return []

    def _lookupArcNode1 (self, nVal, iAddr):
        "looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None"
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                # we return the address of the next node
                return int.from_bytes(self.byDic[iEndArcAddr:iEndArcAddr+self.nBytesNodeAddress], byteorder='big')
            else:
                # value not found
                if (nRawArc & self._lastArcMask):
                    return None
                iAddr = iEndArcAddr+self.nBytesNodeAddress











    def _writeNodes1 (self, spfDest):
        "for debugging only"
        print(" > Write binary nodes")
        with codecs.open(spfDest, 'w', 'utf-8', newline="\n") as hDst:
            iAddr = 0
            hDst.write("i{:_>10} -- #{:_>10}\n".format("0", iAddr))
            while iAddr < len(self.byDic):
................................................................................
                iAddr = iEndArcAddr+self.nBytesNodeAddress
                if (nRawArc & self._lastArcMask) and iAddr < len(self.byDic):
                    hDst.write("\ni{:_>10} -- #{:_>10}\n".format("?", iAddr))
            hDst.close()

    # VERSION 2
    def _morph2 (self, sWord):
        "returns morphologies of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress  if not (nRawArc2 & self._addrBitMask) else iEndArcAddr2
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr
            return l
        return []

    def _stem2 (self, sWord):
        "returns stems list of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                            nRawArc = int.from_bytes(self.byDic[iAddr2:iAddr2+self.nBytesArc], byteorder='big')
                            iAddr2 += self.nBytesArc + self.nBytesNodeAddress
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr
            return l
        return []

    def _lookupArcNode2 (self, nVal, iAddr):
        "looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None"
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                if not (nRawArc & self._addrBitMask):
                    # we return the address of the next node
................................................................................
                    iAddr = iEndArcAddr
                if (nRawArc & self._lastArcMask):
                    hDst.write("\ni{:_>10} -- #{:_>10}\n".format("?", iAddr))
            hDst.close()

    # VERSION 3
    def _morph3 (self, sWord):
        "returns morphologies of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress  if not (nRawArc2 & self._addrBitMask) else iEndArcAddr2+self.nBytesOffset
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr+self.nBytesOffset
            return l
        return []

    def _stem3 (self, sWord):
        "returns stems list of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                    # This value is not a char, this is a stemming code 
                    l.append(self.funcStemming(sWord, self.lArcVal[nArc]))
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr+self.nBytesOffset
            return l
        return []

    def _lookupArcNode3 (self, nVal, iAddr):
        "looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None"
        iAddrNode = iAddr
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                if not (nRawArc & self._addrBitMask):

<




>
>


>


>
>
>
>







 







|

|



>



>













>





>




>







 







|









|









|



|
|

|



|







|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
|
>
>
|
<
>
>
|
<
<
<
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


<
<
>
>
>
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
>
|
<
<
<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>

>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|













>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|







 







|







 







|







 







|







1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211



212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280






281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
#!python3


import os
import traceback
import pkgutil
import re
from itertools import chain

from . import str_transform as st
from . import char_player as cp
from .echo import echo


def show (nDeep, sText):
    print(nDeep * "  " + sText)


class IBDAWG:
    """INDEXABLE BINARY DIRECT ACYCLIC WORD GRAPH"""

    def __init__ (self, sDicName):
        self.by = pkgutil.get_data(__package__, "_dictionaries/" + sDicName)
        if not self.by:
................................................................................
        self.nBytesNodeAddress = int(l[3])
        self.nEntries = int(l[4])
        self.nNode = int(l[5])
        self.nArc = int(l[6])
        self.nAff = int(l[7])
        self.cStemming = l[8]
        if self.cStemming == "S":
            self.funcStemming = st.changeWordWithSuffixCode
        elif self.cStemming == "A":
            self.funcStemming = st.changeWordWithAffixCode
        else:
            self.funcStemming = st.noStemming
        self.nTag = self.nArcVal - self.nChar - self.nAff
        # <dChar> to get the value of an arc, <dCharVal> to get the char of an arc with its value
        self.dChar = {}
        for i in range(1, self.nChar):
            self.dChar[self.lArcVal[i]] = i
        self.dCharVal = { v: k  for k, v in self.dChar.items() }
            
        self._arcMask = (2 ** ((self.nBytesArc * 8) - 3)) - 1
        self._finalNodeMask = 1 << ((self.nBytesArc * 8) - 1)
        self._lastArcMask = 1 << ((self.nBytesArc * 8) - 2)
        self._addrBitMask = 1 << ((self.nBytesArc * 8) - 3)  # version 2

        self.nBytesOffset = 1 # version 3

        # Configuring DAWG functions according to nVersion
        if self.nVersion == 1:
            self.morph = self._morph1
            self.stem = self._stem1
            self._lookupArcNode = self._lookupArcNode1
            self._getArcs = self._getArcs1
            self._writeNodes = self._writeNodes1
        elif self.nVersion == 2:
            self.morph = self._morph2
            self.stem = self._stem2
            self._lookupArcNode = self._lookupArcNode2
            self._getArcs = self._getArcs2
            self._writeNodes = self._writeNodes2
        elif self.nVersion == 3:
            self.morph = self._morph3
            self.stem = self._stem3
            self._getArcs = self._getArcs3
            self._lookupArcNode = self._lookupArcNode3
            self._writeNodes = self._writeNodes3
        else:
            raise ValueError("  # Error: unknown code: {}".format(self.nVersion))

        self.bOptNumSigle = False
        self.bOptNumAtLast = False
................................................................................
                            "_addrBitMask": self._addrBitMask,
                            "nBytesOffset": self.nBytesOffset
                        }, ensure_ascii=False))
            if bInJSModule:
                hDst.write(";\n\nexports.dictionary = dictionary;\n")

    def isValidToken (self, sToken):
        "checks if <sToken> is valid (if there is hyphens in <sToken>, <sToken> is split, each part is checked)"
        if self.isValid(sToken):
            return True
        if "-" in sToken:
            if sToken.count("-") > 4:
                return True
            return all(self.isValid(sWord)  for sWord in sToken.split("-"))
        return False

    def isValid (self, sWord):
        "checks if <sWord> is valid (different casing tested if the first letter is a capital)"
        if not sWord:
            return None
        if "’" in sWord: # ugly hack
            sWord = sWord.replace("’", "'")
        if self.lookup(sWord):
            return True
        if sWord[0:1].isupper():
            if len(sWord) > 1:
                if sWord.istitle():
                    return self.lookup(sWord.lower())
                if sWord.isupper():
                    if self.bOptNumSigle:
                        return True
                    return self.lookup(sWord.lower()) or self.lookup(sWord.capitalize())
                return self.lookup(sWord[:1].lower() + sWord[1:])
            else:
                return self.lookup(sWord.lower())
        return False

    def lookup (self, sWord):
        "returns True if <sWord> in dictionary (strict verification)"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return False
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return False
        return bool(int.from_bytes(self.byDic[iAddr:iAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask)

    def getMorph (self, sWord):
        "retrieves morphologies list, different casing allowed"
        l = self.morph(sWord)
        if sWord[0:1].isupper():
            l.extend(self.morph(sWord.lower()))
            if sWord.isupper() and len(sWord) > 1:
                l.extend(self.morph(sWord.capitalize()))
        return l

    def suggest (self, sWord, nMaxSugg=10):
        "returns a set of suggestions for <sWord>"
        # first, we check for similar words
        #return self._suggestWithCrushedUselessChars(cp.clearWord(sWord))
        aSugg = self._suggest(sWord)
        if not aSugg:
            aSugg.update(self._suggest(sWord[1:]))
            if not aSugg:
                aSugg.update(self._suggestWithCrushedUselessChars(cp.clearWord(sWord)))
        return sorted(aSugg, key=lambda sSugg: cp.distanceBetweenWords(sWord, sSugg))

    def _suggest (self, sRemain, nDeep=0, iAddr=0, sNewWord="", bAvoidLoop=False):
        "returns a set of suggestions"
        # recursive function
        aSugg = set()
        if not sRemain:
            if int.from_bytes(self.byDic[iAddr:iAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask:
                #show(nDeep, "___" + sNewWord + "___")
                aSugg.add(sNewWord)
            for sTail in self._getTails(iAddr):
                aSugg.add(sNewWord+sTail)
            return aSugg

        #show(nDeep, "<" + sRemain + ">  ===>  " + sNewWord)
        cCurrent = sRemain[0:1]
        for cChar, jAddr in self._getSimilarArcs(cCurrent, iAddr):



            #show(nDeep, cChar)
            aSugg.update(self._suggest(sRemain[1:], nDeep+1, jAddr, sNewWord+cChar))
        if not bAvoidLoop: # avoid infinite loop
            #show(nDeep, ":no loop:")
            if cCurrent == sRemain[1:2]:
                # same char, we remove 1 char without adding 1 to <sNewWord>
                aSugg.update(self._suggest(sRemain[1:], nDeep+1, iAddr, sNewWord))
            else:

                # switching chars
                aSugg.update(self._suggest(sRemain[1:2]+sRemain[0:1]+sRemain[2:], nDeep+1, iAddr, sNewWord, True))
            for sRepl in cp.d1toX.get(cCurrent, ()):
                #show(nDeep, sRepl)
                aSugg.update(self._suggest(sRepl + sRemain[1:], nDeep+1, iAddr, sNewWord, True))
            for sRepl in cp.d2toX.get(sRemain[0:2], ()):
                #show(nDeep, sRepl)
                aSugg.update(self._suggest(sRepl + sRemain[2:], nDeep+1, iAddr, sNewWord, True))
            if len(sRemain) == 2:
                for sRepl in cp.dFinal2.get(sRemain, ()):
                    #show(nDeep, sRepl)
                    aSugg.update(self._suggest(sRepl, nDeep+1, iAddr, sNewWord, True))
            elif len(sRemain) == 1:
                #show(nDeep, ":end of word:")
                # end of word
                aSugg.update(self._suggest("", nDeep+1, iAddr, sNewWord, True)) # remove last char and go on
                for sRepl in cp.dFinal1.get(sRemain, ()):
                    #show(nDeep, sRepl)
                    aSugg.update(self._suggest(sRepl, nDeep+1, iAddr, sNewWord, True))
        return aSugg

    def _getSimilarArcs (self, cChar, iAddr):


        "generator: yield similar char of <cChar> and address of the following node"
        for c in cp.d1to1.get(cChar, [cChar]):
            if c in self.dChar:
                jAddr = self._lookupArcNode(self.dChar[c], iAddr)
                if jAddr:

                    yield (c, jAddr)

    def _getTails (self, iAddr, sTail="", n=2):
        "return a list of suffixes ending at a distance of <n> from <iAddr>"
        aTails = set()
        for nVal, jAddr in self._getArcs(iAddr):
            if nVal < self.nChar:
                if int.from_bytes(self.byDic[jAddr:jAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask:
                    aTails.add(sTail + self.dCharVal[nVal])
                if n and not aTails:
                    aTails.update(self._getTails(jAddr, sTail+self.dCharVal[nVal], n-1))
        return aTails

    def _suggestWithCrushedUselessChars (self, sWord, nDeep=0, iAddr=0, sNewWord="", bAvoidLoop=False):
        aSugg = set()
        if not sWord:
            if int.from_bytes(self.byDic[iAddr:iAddr+self.nBytesArc], byteorder='big') & self._finalNodeMask:
                show(nDeep, "!!! " + sNewWord + " !!!")
                aSugg.add(sNewWord)
            return aSugg
        cCurrent = sWord[0:1]
        for cChar, jAddr in self._getSimilarArcsAndCrushedChars(cCurrent, iAddr):
            show(nDeep, cChar)
            aSugg.update(self._suggestWithCrushedUselessChars(sWord[1:], nDeep+1, jAddr, sNewWord+cChar))
        return aSugg

    def _getSimilarArcsAndCrushedChars (self, cChar, iAddr):
        "generator: yield similar char of <cChar> and address of the following node"
        for nVal, jAddr in self._getArcs(iAddr):
            if self.dCharVal.get(nVal, None) in cp.aVovels:
                yield (self.dCharVal[nVal], jAddr)
        yield from self._getSimilarArcs(cChar, iAddr)

    def drawPath (self, sWord, iAddr=0):






        cChar = sWord[0:1]  if sWord  else " "
        iPos = -1
        n = 0
        print(cChar + ": ", end="")
        for nVal, jAddr in self._getArcs(iAddr):
            if nVal in self.dCharVal:
                print(self.dCharVal[nVal], end="")
                if self.dCharVal[nVal] == sWord[0:1]:
                    iNextNodeAddr = jAddr
                    iPos = n
                n += 1
        if not sWord:
            return
        if iPos >= 0:
            print("\n   "+ " " * iPos + "|")
            self.drawPath(sWord[1:], iNextNodeAddr)

    def select (self, sPattern=""):
        "generator: returns all entries which morphology fits <sPattern>"
        zPattern = None
        try:
            zPattern = re.compile(sPattern)
        except:
            print("# Error in regex pattern")
            traceback.print_exc()
        yield from self._select1(zPattern, 0, "")

    # def morph (self, sWord):
    #     is defined in __init__

    # VERSION 1
    def _select1 (self, zPattern, iAddr, sWord):
        # recursive generator
        for nVal, jAddr in self._getArcs1(iAddr):
            if nVal < self.nChar:
                # simple character
                yield from self._select1(zPattern, jAddr, sWord + self.lArcVal[nVal])
            else:
                sEntry = sWord + "\t" + self.funcStemming(sWord, self.lArcVal[nVal])
                for nMorphVal, _ in self._getArcs1(jAddr):
                    if not zPattern or zPattern.search(self.lArcVal[nMorphVal]):
                        yield sEntry + "\t" + self.lArcVal[nMorphVal]

    def _morph1 (self, sWord):
        "returns morphologies of sWord"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress
                iAddr = iEndArcAddr+self.nBytesNodeAddress
            return l
        return []

    def _stem1 (self, sWord):
        "returns stems list of <sWord>"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                    # This value is not a char, this is a stemming code 
                    l.append(self.funcStemming(sWord, self.lArcVal[nArc]))
                iAddr = iEndArcAddr+self.nBytesNodeAddress
            return l
        return []

    def _lookupArcNode1 (self, nVal, iAddr):
        "looks if <nVal> is an arc at the node at <iAddr>, if yes, returns address of next node else None"
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                # we return the address of the next node
                return int.from_bytes(self.byDic[iEndArcAddr:iEndArcAddr+self.nBytesNodeAddress], byteorder='big')
            else:
                # value not found
                if (nRawArc & self._lastArcMask):
                    return None
                iAddr = iEndArcAddr+self.nBytesNodeAddress

    def _getArcs1 (self, iAddr):
        "generator: return all arcs at <iAddr> as tuples of (nVal, iAddr)"
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            yield (nRawArc & self._arcMask, int.from_bytes(self.byDic[iEndArcAddr:iEndArcAddr+self.nBytesNodeAddress], byteorder='big'))
            if (nRawArc & self._lastArcMask):
                break
            iAddr = iEndArcAddr+self.nBytesNodeAddress

    def _writeNodes1 (self, spfDest):
        "for debugging only"
        print(" > Write binary nodes")
        with codecs.open(spfDest, 'w', 'utf-8', newline="\n") as hDst:
            iAddr = 0
            hDst.write("i{:_>10} -- #{:_>10}\n".format("0", iAddr))
            while iAddr < len(self.byDic):
................................................................................
                iAddr = iEndArcAddr+self.nBytesNodeAddress
                if (nRawArc & self._lastArcMask) and iAddr < len(self.byDic):
                    hDst.write("\ni{:_>10} -- #{:_>10}\n".format("?", iAddr))
            hDst.close()

    # VERSION 2
    def _morph2 (self, sWord):
        "returns morphologies of <sWord>"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress  if not (nRawArc2 & self._addrBitMask) else iEndArcAddr2
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr
            return l
        return []

    def _stem2 (self, sWord):
        "returns stems list of <sWord>"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                            nRawArc = int.from_bytes(self.byDic[iAddr2:iAddr2+self.nBytesArc], byteorder='big')
                            iAddr2 += self.nBytesArc + self.nBytesNodeAddress
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr
            return l
        return []

    def _lookupArcNode2 (self, nVal, iAddr):
        "looks if <nVal> is an arc at the node at <iAddr>, if yes, returns address of next node else None"
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                if not (nRawArc & self._addrBitMask):
                    # we return the address of the next node
................................................................................
                    iAddr = iEndArcAddr
                if (nRawArc & self._lastArcMask):
                    hDst.write("\ni{:_>10} -- #{:_>10}\n".format("?", iAddr))
            hDst.close()

    # VERSION 3
    def _morph3 (self, sWord):
        "returns morphologies of <sWord>"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                        l.append(sStem + " " + self.lArcVal[nRawArc2 & self._arcMask])
                        iAddr2 = iEndArcAddr2+self.nBytesNodeAddress  if not (nRawArc2 & self._addrBitMask) else iEndArcAddr2+self.nBytesOffset
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr+self.nBytesOffset
            return l
        return []

    def _stem3 (self, sWord):
        "returns stems list of <sWord>"
        iAddr = 0
        for c in sWord:
            if c not in self.dChar:
                return []
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr == None:
                return []
................................................................................
                    # This value is not a char, this is a stemming code 
                    l.append(self.funcStemming(sWord, self.lArcVal[nArc]))
                iAddr = iEndArcAddr+self.nBytesNodeAddress  if not (nRawArc & self._addrBitMask)  else iEndArcAddr+self.nBytesOffset
            return l
        return []

    def _lookupArcNode3 (self, nVal, iAddr):
        "looks if <nVal> is an arc at the node at <iAddr>, if yes, returns address of next node else None"
        iAddrNode = iAddr
        while True:
            iEndArcAddr = iAddr+self.nBytesArc
            nRawArc = int.from_bytes(self.byDic[iAddr:iEndArcAddr], byteorder='big')
            if nVal == (nRawArc & self._arcMask):
                # the value we are looking for 
                if not (nRawArc & self._addrBitMask):

Added gc_core/py/keyboard_chars_proximity.py version [8f397a7bbf].

























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# Keyboard chars proximity


def getKeyboardMap (sKeyboard):
    return _dKeyboardMap.get(sKeyboard.lower(), {})


def getKeyboardList ():
    return _dKeyboardMap.keys()


_dKeyboardMap = {
    # keyboards by alphabetical order
    # bépo, colemak and dvorak users are assumed to do less typing errors.
    "azerty": {
        # fr
        # line 1
        "é": "az",
        "è": "yu",
        "ç": "àio",
        "à": "op",
        # line 2
        "a": "zéq",
        "z": "aesq",
        "e": "zrds",
        "r": "etfd",
        "t": "rygf",
        "y": "tuhg",
        "u": "yijh",
        "i": "uokj",
        "o": "iplk",
        "p": "oml",
        # line 3
        "q": "sawz",
        "s": "qdzwxe",
        "d": "sfexcr",
        "f": "dgrcvt",
        "g": "fhtvby",
        "h": "gjybnu",
        "j": "hkuni",
        "k": "jlio",
        "l": "kmop",
        "m": "lùp",
        "ù": "m",
        # line 4
        "w": "xqs",
        "x": "wcsd",
        "c": "xvdf",
        "v": "cbfg",
        "b": "vngh",
        "n": "bhj",
    },
    "bépo": {
        # fr
        # line 2
        "b": "éa",
        "é": "bpu",
        "p": "éoi",
        "o": "pèe",
        "è": "o",
        "v": "dt",
        "d": "vls",
        "l": "djr",
        "j": "lzn",
        "z": "jmw",
        # line 3
        "a": "ubà",
        "u": "aiéy",
        "i": "uepx",
        "e": "io",
        "c": "t",
        "t": "csvq",
        "s": "trdg",
        "r": "snlh",
        "n": "rmjf",
        "m": "nzç",
        # line 4
        "à": "yêa",
        "y": "àxu",
        "x": "ywi",
        "w": "z",
        "k": "c",
        "q": "gt",
        "g": "qhs",
        "h": "gfr",
        "f": "hçn",
        "ç": "fm",
    },
    "colemak": {
        # en, us, intl
        # line 2
        "q": "wa",
        "w": "qfr",
        "f": "wps",
        "p": "fgt",
        "g": "pjd",
        "j": "glh",
        "l": "jun",
        "u": "lye",
        "y": "ui",
        # line 3
        "a": "rqz",
        "r": "aswx",
        "s": "rtfc",
        "t": "sdpv",
        "d": "thgb",
        "h": "dnjk",
        "n": "helm",
        "e": "niu",
        "i": "eoy",
        "o": "i",
        # line 4
        "z": "xa",
        "x": "zcr",
        "c": "xvs",
        "v": "cbt",
        "b": "vkd",
        "k": "bmh",
        "m": "kn",
    },
    "dvorak": {
        # en, us, intl
        # line 2
        "p": "yu",
        "y": "pfi",
        "f": "ygd",
        "g": "fch",
        "c": "grt",
        "r": "cln",
        "l": "rs",
        # line 3
        "a": "o",
        "o": "aeq",
        "e": "ouj",
        "u": "eipk",
        "i": "udyx",
        "d": "ihfb",
        "h": "dtgm",
        "t": "hncw",
        "n": "tsrv",
        "s": "nlz",
        # line 4
        "q": "jo",
        "j": "qke",
        "k": "jxu",
        "x": "kbi",
        "b": "xmd",
        "m": "bwh",
        "w": "mvt",
        "v": "wzn",
        "z": "vs",
    },
    "qwerty": {
        # en, us, intl
        # line 2
        "q": "wa",
        "w": "qeas",
        "e": "wrds",
        "r": "etfd",
        "t": "rygf",
        "y": "tuhg",
        "u": "yijh",
        "i": "uokj",
        "o": "iplk",
        "p": "ol",
        # line 3
        "a": "sqzw",
        "s": "adwzxe",
        "d": "sfexcr",
        "f": "dgrcvt",
        "g": "fhtvby",
        "h": "gjybnu",
        "j": "hkunmi",
        "k": "jlimo",
        "l": "kop",
        # line 4
        "z": "xas",
        "x": "zcsd",
        "c": "xvdf",
        "v": "cbfg",
        "b": "vngh",
        "n": "bmhj",
        "m": "njk",
    },
    "qwertz": {
        # ge, au
        # line 2
        "q": "wa",
        "w": "qeas",
        "e": "wrds",
        "r": "etfd",
        "t": "rzgf",
        "z": "tuhg",
        "u": "zijh",
        "i": "uokj",
        "o": "iplk",
        "p": "oüöl",
        "ü": "päö",
        # line 3
        "a": "sqyw",
        "s": "adwyxe",
        "d": "sfexcr",
        "f": "dgrcvt",
        "g": "fhtvbz",
        "h": "gjzbnu",
        "j": "hkunmi",
        "k": "jlimo",
        "l": "köop",
        "ö": "läpü",
        "ä": "öü",
        # line 4
        "y": "xas",
        "x": "ycsd",
        "c": "xvdf",
        "v": "cbfg",
        "b": "vngh",
        "n": "bmhj",
        "m": "njk",
    }
}

Modified gc_core/py/lang_core/gc_engine.py from [dfad6de958] to [f3dfb392d0].

24
25
26
27
28
29
30
31



32
33
34
35
36
37
38
39
40
41
42
43
...
281
282
283
284
285
286
287
288
289


290
291


292
293
294
295
296
297
298
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
lang = "${lang}"
locales = ${loc}
pkg = "${implname}"
name = "${name}"
version = "${version}"
author = "${author}"

# grammar rules and dictionary



_rules = None
_dOptions = dict(gc_options.dOpt)       # duplication necessary, to be able to reset to default
_aIgnoredRules = set()
_oDict = None
_dAnalyses = {}                         # cache for data from dictionary



#### Parsing

def parse (sText, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False):
    "analyses the paragraph sText and returns list of errors"
................................................................................
    from com.sun.star.beans import PropertyValue
    #import lightproof_handler_${implname} as opt
    _createError = _createWriterError
except ImportError:
    _createError = _createDictError


def load ():
    global _oDict


    try:
        _oDict = IBDAWG("${py_binary_dic}")


    except:
        traceback.print_exc()


def setOption (sOpt, bVal):
    if sOpt in _dOptions:
        _dOptions[sOpt] = bVal
................................................................................


def getOptions ():
    return _dOptions


def getDefaultOptions ():
    return dict(gc_options.dOpt)


def getOptionsLabels (sLang):
    return gc_options.getUI(sLang)


def displayOptions (sLang):
................................................................................
    echo("List of options")
    echo("\n".join( [ k+":\t"+str(v)+"\t"+gc_options.getUI(sLang).get(k, ("?", ""))[0]  for k, v  in sorted(_dOptions.items()) ] ))
    echo("")


def resetOptions ():
    global _dOptions
    _dOptions = dict(gc_options.dOpt)


def getDictionary ():
    return _oDict


def _getRules (bParagraph):
................................................................................

## functions to get text outside pattern scope

# warning: check compile_rules.py to understand how it works

def nextword (s, iStart, n):
    "get the nth word of the input string or empty string"
    m = re.match("( +[\\w%-]+){" + str(n-1) + "} +([\\w%-]+)", s[iStart:])
    if not m:
        return None
    return (iStart+m.start(2), m.group(2))


def prevword (s, iEnd, n):
    "get the (-)nth word of the input string or empty string"
    m = re.search("([\\w%-]+) +([\\w%-]+ +){" + str(n-1) + "}$", s[:iEnd])
    if not m:
        return None
    return (m.start(1), m.group(1))


def nextword1 (s, iStart):
    "get next word (optimization)"







|
>
>
>
|
<


|







 







|

>
>

|
>
>







 







|







 







|







 







|


|




|







24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
lang = "${lang}"
locales = ${loc}
pkg = "${implname}"
name = "${name}"
version = "${version}"
author = "${author}"

_rules = None                               # module gc_rules

# data
_sAppContext = ""                           # what software is running
_dOptions = None

_aIgnoredRules = set()
_oDict = None
_dAnalyses = {}                             # cache for data from dictionary



#### Parsing

def parse (sText, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False):
    "analyses the paragraph sText and returns list of errors"
................................................................................
    from com.sun.star.beans import PropertyValue
    #import lightproof_handler_${implname} as opt
    _createError = _createWriterError
except ImportError:
    _createError = _createDictError


def load (sContext="Python"):
    global _oDict
    global _sAppContext
    global _dOptions
    try:
        _oDict = IBDAWG("${dic_name}.bdic")
        _sAppContext = sContext
        _dOptions = dict(gc_options.getOptions(sContext))   # duplication necessary, to be able to reset to default
    except:
        traceback.print_exc()


def setOption (sOpt, bVal):
    if sOpt in _dOptions:
        _dOptions[sOpt] = bVal
................................................................................


def getOptions ():
    return _dOptions


def getDefaultOptions ():
    return dict(gc_options.getOptions(_sAppContext))


def getOptionsLabels (sLang):
    return gc_options.getUI(sLang)


def displayOptions (sLang):
................................................................................
    echo("List of options")
    echo("\n".join( [ k+":\t"+str(v)+"\t"+gc_options.getUI(sLang).get(k, ("?", ""))[0]  for k, v  in sorted(_dOptions.items()) ] ))
    echo("")


def resetOptions ():
    global _dOptions
    _dOptions = dict(gc_options.getOptions(_sAppContext))


def getDictionary ():
    return _oDict


def _getRules (bParagraph):
................................................................................

## functions to get text outside pattern scope

# warning: check compile_rules.py to understand how it works

def nextword (s, iStart, n):
    "get the nth word of the input string or empty string"
    m = re.match("(?: +[\\w%-]+){" + str(n-1) + "} +([\\w%-]+)", s[iStart:])
    if not m:
        return None
    return (iStart+m.start(1), m.group(1))


def prevword (s, iEnd, n):
    "get the (-)nth word of the input string or empty string"
    m = re.search("([\\w%-]+) +(?:[\\w%-]+ +){" + str(n-1) + "}$", s[:iEnd])
    if not m:
        return None
    return (m.start(1), m.group(1))


def nextword1 (s, iStart):
    "get next word (optimization)"

Modified gc_core/py/lang_core/gc_options.py from [383a99acb3] to [871c8d4b8f].

1
2
3
4
5
6







7
8
9


10


11


12
# generated code, do not edit

def getUI (sLang):
    if sLang in _dOptLabel:
        return _dOptLabel[sLang]
    return _dOptLabel["fr"]








lStructOpt = ${lStructOpt}



dOpt = ${dOptPython}





_dOptLabel = ${dOptLabel}






>
>
>
>
>
>
>



>
>
|
>
>
|
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# generated code, do not edit

def getUI (sLang):
    if sLang in _dOptLabel:
        return _dOptLabel[sLang]
    return _dOptLabel["fr"]


def getOptions (sContext="Python"):
    if sContext in dOpt:
        return dOpt[sContext]
    return dOpt["Python"]


lStructOpt = ${lStructOpt}


dOpt = {
    "Python": ${dOptPython},
    "Server": ${dOptServer},
    "Writer": ${dOptWriter}
}


_dOptLabel = ${dOptLabel}

Modified gc_core/py/oxt/Grammalecte.py from [f962117745] to [0f730fb3f5].

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
        self.locales = []
        for i in gce.locales:
            l = gce.locales[i]
            self.locales.append(Locale(l[0], l[1], l[2]))
        self.locales = tuple(self.locales)
        xCurCtx = uno.getComponentContext()
        # init
        gce.load()
        # GC options
        # opt_handler.load(xCurCtx)
        dOpt = Options.load(xCurCtx)
        gce.setOptions(dOpt)
        # store for results of big paragraphs
        self.dResult = {}
        self.nMaxRes = 1500







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
        self.locales = []
        for i in gce.locales:
            l = gce.locales[i]
            self.locales.append(Locale(l[0], l[1], l[2]))
        self.locales = tuple(self.locales)
        xCurCtx = uno.getComponentContext()
        # init
        gce.load("Writer")
        # GC options
        # opt_handler.load(xCurCtx)
        dOpt = Options.load(xCurCtx)
        gce.setOptions(dOpt)
        # store for results of big paragraphs
        self.dResult = {}
        self.nMaxRes = 1500

Modified gc_core/py/oxt/Options.py from [f3a8765730] to [e0f5ecd431].

137
138
139
140
141
142
143

144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
                self.xContainer.endExecute()
            else:
                print("Wrong command: " + xActionEvent.ActionCommand)
        except:
            traceback.print_exc()

    def _setDefault (self):

        for w in self.lxOptions:
            w.State = gce.gc_options.dOpt.get(w.Name, False)

    def load (self, sLang):
        try:
            xChild = self.xNode.getByName(sLang)

            for sKey in gce.gc_options.dOpt:
                sValue = xChild.getPropertyValue(sKey)
                if sValue == '':
                    if gce.gc_options.dOpt[sKey]:
                        sValue = 1
                    else:
                        sValue = 0
                options[sKey] = bool(int(sValue))
        except:
            traceback.print_exc()








>

|




>
|


|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
                self.xContainer.endExecute()
            else:
                print("Wrong command: " + xActionEvent.ActionCommand)
        except:
            traceback.print_exc()

    def _setDefault (self):
        dOpt = gce.gc_options.getOptions("Writer")
        for w in self.lxOptions:
            w.State = dOpt.get(w.Name, False)

    def load (self, sLang):
        try:
            xChild = self.xNode.getByName(sLang)
            dOpt = gce.gc_options.getOptions("Writer")
            for sKey in dOpt:
                sValue = xChild.getPropertyValue(sKey)
                if sValue == '':
                    if dOpt[sKey]:
                        sValue = 1
                    else:
                        sValue = 0
                options[sKey] = bool(int(sValue))
        except:
            traceback.print_exc()

Added gc_core/py/spellchecker.py version [c6b35d80ee].













































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Spellchecker
# Wrapper for the IBDAWG class.
# Useful to check several dictionaries at once.

from . import ibdawg


dDictionaries = {
    "fr": "French.bdic",
    "en": "English.bdic"
}


class Spellchecker ():

    def __init__ (self, sLangCode):
        self.sLangCode = sLangCode
        self.oMainDic = None
        if sLangCode in dDictionaries:
            self.oMainDic = ibdawg.IBDAWG(dDictionaries[sLangCode])
        self.lOtherDic = []
        return bool(self.oMainDic)


    def setMainDictionary (self, sDicName):
        try:
            self.oMainDic = ibdawg.IBDAWG(sDicName)
            return True
        except:
            print("Error: <" + sDicName + "> not set as main dictionary.")
            return False

    def addDictionary (self, sDicName):
        try:
            self.lOtherDic.append(ibdawg.IBDAWG(sDicName))
            return True
        except:
            print("Error: <" + sDicName + "> not added to the list.")
            return False

    # Return codes:
    #   0: invalid
    #   1: correct in main dictionary
    #   2+: correct in foreign dictionaries


    # check in the main dictionary only

    def isValidToken (self, sToken):
        "(in main dictionary) checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)"
        if self.oMainDic.isValidToken(sToken):
            return 1
        return 0

    def isValid (self, sWord):
        "(in main dictionary) checks if sWord is valid (different casing tested if the first letter is a capital)"
        if self.oMainDic.isValid(sWord):
            return 1
        return 0

    def lookup (self, sWord):
        "(in main dictionary) checks if sWord is in dictionary as is (strict verification)"
        if self.oMainDic.lookup(sWord):
            return 1
        return 0


    # check in all dictionaries

    def isValidTokenAll (self, sToken):
        "(in all dictionaries) checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)"
        if self.oMainDic.isValidToken(sToken):
            return 1
        for i, oDic in enumerate(self.lOtherDic, 2):
            if oDic.isValidToken(sToken):
                return i
        return 0

    def isValidAll (self, sWord):
        "(in all dictionaries) checks if sWord is valid (different casing tested if the first letter is a capital)"
        if self.oMainDic.isValid(sToken):
            return 1
        for i, oDic in enumerate(self.lOtherDic, 2):
            if oDic.isValid(sToken):
                return i
        return 0

    def lookupAll (self, sWord):
        "(in all dictionaries) checks if sWord is in dictionary as is (strict verification)"
        if self.oMainDic.lookup(sToken):
            return 1
        for i, oDic in enumerate(self.lOtherDic, 2):
            if oDic.lookup(sToken):
                return i
        return 0


    # check in dictionaries up to level n

    def isValidTokenLevel (self, sToken, nLevel):
        "(in dictionaries up to level n) checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)"
        if self.oMainDic.isValidToken(sToken):
            return 1
        if nLevel >= 2:
            for i, oDic in enumerate(self.lOtherDic, 2):
                if oDic.isValidToken(sToken):
                    return i
                if i == nLevel:
                    break
        return 0

    def isValidLevel (self, sWord, nLevel):
        "(in dictionaries up to level n) checks if sWord is valid (different casing tested if the first letter is a capital)"
        if self.oMainDic.isValid(sToken):
            return 1
        if nLevel >= 2:
            for i, oDic in enumerate(self.lOtherDic, 2):
                if oDic.isValid(sToken):
                    return i
                if i == nLevel:
                    break
        return 0

    def lookupLevel (self, sWord, nLevel):
        "(in dictionaries up to level n) checks if sWord is in dictionary as is (strict verification)"
        if self.oMainDic.lookup(sToken):
            return 1
        if nLevel >= 2:
            for i, oDic in enumerate(self.lOtherDic, 2):
                if oDic.lookup(sToken):
                    return i
                if i == nLevel:
                    break
        return 0

Modified gc_core/py/str_transform.py from [e86906e5ce] to [23bc31f0e4].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!python3
# -*- coding: UTF-8 -*-


dSimilarChars = {
    "a": "aàâáä",
    "à": "aàâáä",
    "â": "aàâáä",
    "á": "aàâáä",
    "ä": "aàâáä",
    "c": "cç",
    "ç": "cç",
    "e": "eéêèë",
    "é": "eéêèë",
    "ê": "eéêèë",
    "è": "eéêèë",
    "ë": "eéêèë",
    "i": "iîïíì",
    "î": "iîïíì",
    "ï": "iîïíì",
    "í": "iîïíì",
    "ì": "iîïíì",
    "o": "oôóòö",
    "ô": "oôóòö",
    "ó": "oôóòö",
    "ò": "oôóòö",
    "ö": "oôóòö",
    "u": "uûùüú",
    "û": "uûùüú",
    "ù": "uûùüú",
    "ü": "uûùüú",
    "ú": "uûùüú",
}

## No stemming

def noStemming (sFlex, sStem):
    return sStem

def rebuildWord (sFlex, cmd1, cmd2):
................................................................................
    jSfx = 0
    for i in range(min(len(sFlex), len(sStem))):
        if sFlex[i] != sStem[i]:
            break
        jSfx += 1
    return chr(len(sFlex)-jSfx+48) + sStem[jSfx:]  

def getStemFromSuffixCode (sFlex, sSfxCode):
    if sSfxCode == "0":
        return sFlex
    return sFlex[:-(ord(sSfxCode[0])-48)] + sSfxCode[1:]  if sSfxCode[0] != '0'  else sFlex + sSfxCode[1:]


# Prefix and suffix
def defineAffixCode (sFlex, sStem):
    """ Returns a string defining how to get stem from flexion. Examples:
            "0" if stem = flexion
            "stem" if no common substring
................................................................................
                if M[x][y] > longest:
                    longest = M[x][y]
                    x_longest = x
            else:
                M[x][y] = 0
    return s1[x_longest-longest : x_longest]

def getStemFromAffixCode (sFlex, sAffCode):
    if sAffCode == "0":
        return sFlex
    if '/' not in sAffCode:
        return "# error #"
    sPfxCode, sSfxCode = sAffCode.split('/')
    sFlex = sPfxCode[1:] + sFlex[(ord(sPfxCode[0])-48):] 
    return sFlex[:-(ord(sSfxCode[0])-48)] + sSfxCode[1:]  if sSfxCode[0] != '0'  else sFlex + sSfxCode[1:]


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|

|
|







 







|

|



|
|

1
































2
3
4
5
6
7
8
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!python3

































## No stemming

def noStemming (sFlex, sStem):
    return sStem

def rebuildWord (sFlex, cmd1, cmd2):
................................................................................
    jSfx = 0
    for i in range(min(len(sFlex), len(sStem))):
        if sFlex[i] != sStem[i]:
            break
        jSfx += 1
    return chr(len(sFlex)-jSfx+48) + sStem[jSfx:]  

def changeWordWithSuffixCode (sWord, sSfxCode):
    if sSfxCode == "0":
        return sWord
    return sWord[:-(ord(sSfxCode[0])-48)] + sSfxCode[1:]  if sSfxCode[0] != '0'  else sWord + sSfxCode[1:]


# Prefix and suffix
def defineAffixCode (sFlex, sStem):
    """ Returns a string defining how to get stem from flexion. Examples:
            "0" if stem = flexion
            "stem" if no common substring
................................................................................
                if M[x][y] > longest:
                    longest = M[x][y]
                    x_longest = x
            else:
                M[x][y] = 0
    return s1[x_longest-longest : x_longest]

def changeWordWithAffixCode (sWord, sAffCode):
    if sAffCode == "0":
        return sWord
    if '/' not in sAffCode:
        return "# error #"
    sPfxCode, sSfxCode = sAffCode.split('/')
    sWord = sPfxCode[1:] + sWord[(ord(sPfxCode[0])-48):] 
    return sWord[:-(ord(sSfxCode[0])-48)] + sSfxCode[1:]  if sSfxCode[0] != '0'  else sWord + sSfxCode[1:]

Modified gc_core/py/text.py from [e964ece40d] to [72d4931466].

3
4
5
6
7
8
9

10
11
12
13
14
15
16
import textwrap
from itertools import chain


def getParagraph (sText):
    "generator: returns paragraphs of text"
    iStart = 0

    iEnd = sText.find("\n", iStart)
    while iEnd != -1:
        yield sText[iStart:iEnd]
        iStart = iEnd + 1
        iEnd = sText.find("\n", iStart)
    yield sText[iStart:]








>







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import textwrap
from itertools import chain


def getParagraph (sText):
    "generator: returns paragraphs of text"
    iStart = 0
    sText = sText.replace("\r\n", "\n").replace("\r", "\n")
    iEnd = sText.find("\n", iStart)
    while iEnd != -1:
        yield sText[iStart:iEnd]
        iStart = iEnd + 1
        iEnd = sText.find("\n", iStart)
    yield sText[iStart:]

Modified gc_lang/fr/build.py from [9b9cd2c271] to [677a5b04fd].

6
7
8
9
10
11
12

13
14
























15
16
17
18
19
20
21
..
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

import helpers


def build (sLang, dVars, spLangPack):
    "complementary build launched from make.py"
    createFirefoxExtension(sLang, dVars)

    createThunderbirdExtension(sLang, dVars, spLangPack)


























def createFirefoxExtension (sLang, dVars):
    "create extension for Firefox"
    print("Building extension for Firefox")
    helpers.createCleanFolder("_build/xpi/"+sLang)
    dir_util.copy_tree("gc_lang/"+sLang+"/xpi/", "_build/xpi/"+sLang)
    dir_util.copy_tree("grammalecte-js", "_build/xpi/"+sLang+"/grammalecte")
................................................................................
        for lLineOpt in lOpt:
            for sOpt in lLineOpt:
                sHTML += '  <p><input type="checkbox" id="option_'+sOpt+'" /><label id="option_label_'+sOpt+'" for="option_'+sOpt+'" data-l10n-id="option_'+sOpt+'"></label></p>\n'
        sHTML += '</div>\n'
    # Creating translation data
    dProperties = {}
    for sLang in dVars['dOptLabel'].keys():
        dProperties[sLang] = "\n".join( [ "option_" + sOpt + " = " + dVars['dOptLabel'][sLang][sOpt][0].replace(" [!]", " [!]")  for sOpt in dVars['dOptLabel'][sLang] ] )
    return sHTML, dProperties


def createThunderbirdExtension (sLang, dVars, spLangPack):
    "create extension for Thunderbird"
    print("Building extension for Thunderbird")
    sExtensionName = dVars['tb_identifier'] + "-v" + dVars['version'] + '.xpi'
    spfZip = "_build/" + sExtensionName
    hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED)
    _copyGrammalecteJSPackageInZipFile(hZip, spLangPack, dVars['js_binary_dic'])
    for spf in ["LICENSE.txt", "LICENSE.fr.txt"]:
        hZip.write(spf)
    dVars = _createOptionsForThunderbird(dVars)
    helpers.addFolderToZipAndFileFile(hZip, "gc_lang/"+sLang+"/tb", "", dVars, True)
    hZip.write("gc_lang/"+sLang+"/xpi/gce_worker.js", "worker/gce_worker.js")
    spDict = "gc_lang/"+sLang+"/xpi/data/dictionaries"
    for sp in os.listdir(spDict):







>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|









|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

import helpers


def build (sLang, dVars, spLangPack):
    "complementary build launched from make.py"
    createFirefoxExtension(sLang, dVars)
    createWebExtension(sLang, dVars)
    createThunderbirdExtension(sLang, dVars, spLangPack)


def createWebExtension (sLang, dVars):
    "create Web-extension"
    print("Building WebExtension")
    helpers.createCleanFolder("_build/webext/"+sLang)
    dir_util.copy_tree("gc_lang/"+sLang+"/webext/", "_build/webext/"+sLang)
    dir_util.copy_tree("grammalecte-js", "_build/webext/"+sLang+"/grammalecte")
    dVars['webextOptionsHTML'] = _createOptionsForWebExtension(dVars)
    helpers.copyAndFileTemplate("_build/webext/"+sLang+"/panel/main.html", "_build/webext/"+sLang+"/panel/main.html", dVars)
    with helpers.cd("_build/webext/"+sLang):
        os.system("web-ext build")


def _createOptionsForWebExtension (dVars):
    sHTML = ""
    sLang = dVars['sDefaultUILang']
    for sSection, lOpt in dVars['lStructOpt']:
        sHTML += f'\n<div id="subsection_{sSection}" class="opt_subsection">\n  <h2 data-l10n-id="option_{sSection}">{dVars["dOptLabel"][sLang][sSection][0]}</h2>\n'
        for lLineOpt in lOpt:
            for sOpt in lLineOpt:
                sHTML += f'  <p><input type="checkbox" id="option_{sOpt}" data-option="{sOpt}"/><label id="option_label_{sOpt}" for="option_{sOpt}" data-l10n-id="option_{sOpt}">{dVars["dOptLabel"][sLang][sOpt][0]}</label></p>\n'
        sHTML += '</div>\n'
    return sHTML


def createFirefoxExtension (sLang, dVars):
    "create extension for Firefox"
    print("Building extension for Firefox")
    helpers.createCleanFolder("_build/xpi/"+sLang)
    dir_util.copy_tree("gc_lang/"+sLang+"/xpi/", "_build/xpi/"+sLang)
    dir_util.copy_tree("grammalecte-js", "_build/xpi/"+sLang+"/grammalecte")
................................................................................
        for lLineOpt in lOpt:
            for sOpt in lLineOpt:
                sHTML += '  <p><input type="checkbox" id="option_'+sOpt+'" /><label id="option_label_'+sOpt+'" for="option_'+sOpt+'" data-l10n-id="option_'+sOpt+'"></label></p>\n'
        sHTML += '</div>\n'
    # Creating translation data
    dProperties = {}
    for sLang in dVars['dOptLabel'].keys():
        dProperties[sLang] = "\n".join( [ "option_" + sOpt + " = " + dVars['dOptLabel'][sLang][sOpt][0].replace(" [!]", "[!]")  for sOpt in dVars['dOptLabel'][sLang] ] )
    return sHTML, dProperties


def createThunderbirdExtension (sLang, dVars, spLangPack):
    "create extension for Thunderbird"
    print("Building extension for Thunderbird")
    sExtensionName = dVars['tb_identifier'] + "-v" + dVars['version'] + '.xpi'
    spfZip = "_build/" + sExtensionName
    hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED)
    _copyGrammalecteJSPackageInZipFile(hZip, spLangPack, dVars['dic_name']+".json")
    for spf in ["LICENSE.txt", "LICENSE.fr.txt"]:
        hZip.write(spf)
    dVars = _createOptionsForThunderbird(dVars)
    helpers.addFolderToZipAndFileFile(hZip, "gc_lang/"+sLang+"/tb", "", dVars, True)
    hZip.write("gc_lang/"+sLang+"/xpi/gce_worker.js", "worker/gce_worker.js")
    spDict = "gc_lang/"+sLang+"/xpi/data/dictionaries"
    for sp in os.listdir(spDict):

Modified gc_lang/fr/build_data.py from [9294fbef92] to [3f80b32195].

7
8
9
10
11
12
13

14
15
16
17
18
19
20
...
265
266
267
268
269
270
271
272







273
274
275
276
277
278
279

import json
import os

import grammalecte.ibdawg as ibdawg
from grammalecte.echo import echo
from grammalecte.str_transform import defineSuffixCode



class cd:
    """Context manager for changing the current working directory"""
    def __init__ (self, newPath):
        self.newPath = os.path.expanduser(newPath)

................................................................................
        return

    with open(sp+"/data/phonet_simil.txt", 'r', encoding='utf-8') as hSrc:
        # set of homophonic words
        lSet = []
        for sLine in hSrc.readlines():
            if not sLine.startswith("#") and sLine.strip():
                lSet.append(sorted(sLine.strip().split()))







        # dictionary of words
        dWord = {}
        for i, aSet in enumerate(lSet):
            for sWord in aSet:
                if oDict.lookup(sWord):
                    dWord[sWord] = i  # warning, what if word in several sets?
                else:







>







 







|
>
>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

import json
import os

import grammalecte.ibdawg as ibdawg
from grammalecte.echo import echo
from grammalecte.str_transform import defineSuffixCode
import grammalecte.fr.conj as conj


class cd:
    """Context manager for changing the current working directory"""
    def __init__ (self, newPath):
        self.newPath = os.path.expanduser(newPath)

................................................................................
        return

    with open(sp+"/data/phonet_simil.txt", 'r', encoding='utf-8') as hSrc:
        # set of homophonic words
        lSet = []
        for sLine in hSrc.readlines():
            if not sLine.startswith("#") and sLine.strip():
                lWord = sLine.strip().split()
                aMore = set()
                for sWord in lWord:
                    if sWord.endswith("er") and conj.isVerb(sWord):
                        aMore = aMore.union(conj.getConjSimilInfiV1(sWord))
                lWord.extend(list(aMore))
                lSet.append(sorted(set(lWord)))
                #print(lWord)
        # dictionary of words
        dWord = {}
        for i, aSet in enumerate(lSet):
            for sWord in aSet:
                if oDict.lookup(sWord):
                    dWord[sWord] = i  # warning, what if word in several sets?
                else:

Modified gc_lang/fr/config.ini from [678ba4887a] to [61af539d3c].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33






34
35
36
37
38
39
40
..
50
51
52
53
54
55
56

57

58
59
60
61
62
63
64
..
71
72
73
74
75
76
77

78
79
80
81
82
[args]
lang = fr
lang_name = French
locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_MC fr_BF fr_CI fr_SN fr_ML fr_NE fr_TG fr_BJ
country_default = FR
name = Grammalecte
implname = grammalecte

version = 0.5.17
author = Olivier R.
provider = Dicollecte
link = http://grammalecte.net
description = Correcteur grammatical pour le français.
extras = README_fr.txt
logo = logo.png

# lexicon source
lexicon_src = lexicons/French.lex
# binary dictionary name
py_binary_dic = French.bdic
js_binary_dic = French.json
# Finite state automaton compression: 1, 2 (experimental) or 3 (experimental)
fsa_method = 1
# stemming method: S for suffixes only, A for prefixes and suffixes
stemming_method = S

# LibreOffice
unopkg = C:/Program Files/LibreOffice 5/program/unopkg.com
oxt_version = 6.1
oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR

# Firefox
fx_identifier = French-GC@grammalecte.net
fx_name = Grammalecte [fr]







# Thunderbird
tb_identifier = French-GC-TB@grammalecte.net
tb_name = Grammalecte [fr]
tb_debug_extension_path = _build/tb-debug.profile/extensions/French-GC-TB@grammalecte.net
# Set Thunderbird folder in your PATH variable
# Create a local profile:
................................................................................
[oxt]
# the following files must be in your project folder, files will be copied into the zip archive
rules.grx = fr-rules.txt
oxt/addons.xcu = addons.xcu
oxt/package-description.txt = package-description.txt
# images
oxt/_img/logo100.png = img/logo100.png

oxt/_img/LaMouette_small.png = img/LaMouette_small.png

oxt/_img/grammalecte_16.bmp = img/grammalecte_16.bmp
oxt/_img/french_flag_16.bmp = img/french_flag_16.bmp
# AppLauncher
oxt/AppLauncher.py = AppLauncher.py
oxt/helpers.py = pythonpath/helpers.py
# About
oxt/About/About.py = pythonpath/About.py
................................................................................
# ContextMenu
oxt/ContextMenu/ContextMenu.py = ContextMenu.py
oxt/ContextMenu/jobs.xcu = config/jobs.xcu
# TextFormatter
oxt/TextFormatter/TextFormatter.py = pythonpath/TextFormatter.py
oxt/TextFormatter/tf_strings.py = pythonpath/tf_strings.py
oxt/TextFormatter/tf_options.py = pythonpath/tf_options.py

# Conjugueur
oxt/Conjugueur/Conjugueur.py = pythonpath/Conjugueur.py
# Modify author
oxt/ChangeAuthor/Author.py = pythonpath/Author.py
oxt/ChangeAuthor/ca_strings.py = pythonpath/ca_strings.py







>
|










|
<







|





>
>
>
>
>
>







 







>

>







 







>





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
79
80
81
82
83
84
85
86
87
88
89
90
91
[args]
lang = fr
lang_name = French
locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_MC fr_BF fr_CI fr_SN fr_ML fr_NE fr_TG fr_BJ
country_default = FR
name = Grammalecte
implname = grammalecte
# always use 3 numbers for version: x.y.z
version = 0.6.0b
author = Olivier R.
provider = Dicollecte
link = http://grammalecte.net
description = Correcteur grammatical pour le français.
extras = README_fr.txt
logo = logo.png

# lexicon source
lexicon_src = lexicons/French.lex
# binary dictionary name
dic_name = French

# Finite state automaton compression: 1, 2 (experimental) or 3 (experimental)
fsa_method = 1
# stemming method: S for suffixes only, A for prefixes and suffixes
stemming_method = S

# LibreOffice
unopkg = C:/Program Files/LibreOffice 5/program/unopkg.com
oxt_version = 6.2
oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR

# Firefox
fx_identifier = French-GC@grammalecte.net
fx_name = Grammalecte [fr]

win_fx_dev_path = C:\Program Files\Firefox Developer Edition\firefox.exe
win_fx_nightly_path = C:\Program Files (x86)\Nightly\firefox.exe
linux_fx_dev_path = /usr/bin/firefox
linux_fx_nightly_path = /usr/bin/firefox


# Thunderbird
tb_identifier = French-GC-TB@grammalecte.net
tb_name = Grammalecte [fr]
tb_debug_extension_path = _build/tb-debug.profile/extensions/French-GC-TB@grammalecte.net
# Set Thunderbird folder in your PATH variable
# Create a local profile:
................................................................................
[oxt]
# the following files must be in your project folder, files will be copied into the zip archive
rules.grx = fr-rules.txt
oxt/addons.xcu = addons.xcu
oxt/package-description.txt = package-description.txt
# images
oxt/_img/logo100.png = img/logo100.png
oxt/_img/logo120_text.png = img/logo120_text.png
oxt/_img/LaMouette_small.png = img/LaMouette_small.png
oxt/_img/Algoo_logo.png = img/Algoo_logo.png
oxt/_img/grammalecte_16.bmp = img/grammalecte_16.bmp
oxt/_img/french_flag_16.bmp = img/french_flag_16.bmp
# AppLauncher
oxt/AppLauncher.py = AppLauncher.py
oxt/helpers.py = pythonpath/helpers.py
# About
oxt/About/About.py = pythonpath/About.py
................................................................................
# ContextMenu
oxt/ContextMenu/ContextMenu.py = ContextMenu.py
oxt/ContextMenu/jobs.xcu = config/jobs.xcu
# TextFormatter
oxt/TextFormatter/TextFormatter.py = pythonpath/TextFormatter.py
oxt/TextFormatter/tf_strings.py = pythonpath/tf_strings.py
oxt/TextFormatter/tf_options.py = pythonpath/tf_options.py
oxt/TextFormatter/tf_tabrep.py = pythonpath/tf_tabrep.py
# Conjugueur
oxt/Conjugueur/Conjugueur.py = pythonpath/Conjugueur.py
# Modify author
oxt/ChangeAuthor/Author.py = pythonpath/Author.py
oxt/ChangeAuthor/ca_strings.py = pythonpath/ca_strings.py

Modified gc_lang/fr/data/dictConj.txt from [3497ce77d3] to [1288011f2c].

142838
142839
142840
142841
142842
142843
142844






















































142845
142846
142847
142848
142849
142850
142851
......
322851
322852
322853
322854
322855
322856
322857






















































322858
322859
322860
322861
322862
322863
322864
......
385898
385899
385900
385901
385902
385903
385904



















































385905
385906
385907
385908
385909
385910
385911
......
421221
421222
421223
421224
421225
421226
421227






















































421228
421229
421230
421231
421232
421233
421234
_	impe 1pl	désindexons
_	impe 2pl	désindexez
_	ppas mas sg	désindexé
_	ppas mas pl	désindexés
_	ppas fem sg	désindexée
_	ppas fem pl	désindexées
$






















































désindustrialiser	1__t_q_zz
_	infi	désindustrialiser
_	ppre	désindustrialisant
_	ipre 1sg	désindustrialise
_	ipre 3sg	désindustrialise
_	spre 1sg	désindustrialise
_	spre 3sg	désindustrialise
................................................................................
_	impe 1pl	protestons
_	impe 2pl	protestez
_	ppas mas sg	protesté
_	ppas mas pl	protestés
_	ppas fem sg	protestée
_	ppas fem pl	protestées
$






















































prouter	1_i____zz
_	infi	prouter
_	ppre	proutant
_	ipre 1sg	proute
_	ipre 3sg	proute
_	spre 1sg	proute
_	spre 3sg	proute
................................................................................
_	impe 1pl	scriptons
_	impe 2pl	scriptez
_	ppas mas sg	scripté
_	ppas mas pl	scriptés
_	ppas fem sg	scriptée
_	ppas fem pl	scriptées
$



















































scruter	1__t___zz
_	infi	scruter
_	ppre	scrutant
_	ipre 1sg	scrute
_	ipre 3sg	scrute
_	spre 1sg	scrute
_	spre 3sg	scrute
................................................................................
_	impe 1pl	transvidons
_	impe 2pl	transvidez
_	ppas mas sg	transvidé
_	ppas mas pl	transvidés
_	ppas fem sg	transvidée
_	ppas fem pl	transvidées
$






















































traquer	1__t___zz
_	infi	traquer
_	ppre	traquant
_	ipre 1sg	traque
_	ipre 3sg	traque
_	spre 1sg	traque
_	spre 3sg	traque







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







142838
142839
142840
142841
142842
142843
142844
142845
142846
142847
142848
142849
142850
142851
142852
142853
142854
142855
142856
142857
142858
142859
142860
142861
142862
142863
142864
142865
142866
142867
142868
142869
142870
142871
142872
142873
142874
142875
142876
142877
142878
142879
142880
142881
142882
142883
142884
142885
142886
142887
142888
142889
142890
142891
142892
142893
142894
142895
142896
142897
142898
142899
142900
142901
142902
142903
142904
142905
......
322905
322906
322907
322908
322909
322910
322911
322912
322913
322914
322915
322916
322917
322918
322919
322920
322921
322922
322923
322924
322925
322926
322927
322928
322929
322930
322931
322932
322933
322934
322935
322936
322937
322938
322939
322940
322941
322942
322943
322944
322945
322946
322947
322948
322949
322950
322951
322952
322953
322954
322955
322956
322957
322958
322959
322960
322961
322962
322963
322964
322965
322966
322967
322968
322969
322970
322971
322972
......
386006
386007
386008
386009
386010
386011
386012
386013
386014
386015
386016
386017
386018
386019
386020
386021
386022
386023
386024
386025
386026
386027
386028
386029
386030
386031
386032
386033
386034
386035
386036
386037
386038
386039
386040
386041
386042
386043
386044
386045
386046
386047
386048
386049
386050
386051
386052
386053
386054
386055
386056
386057
386058
386059
386060
386061
386062
386063
386064
386065
386066
386067
386068
386069
386070
......
421380
421381
421382
421383
421384
421385
421386
421387
421388
421389
421390
421391
421392
421393
421394
421395
421396
421397
421398
421399
421400
421401
421402
421403
421404
421405
421406
421407
421408
421409
421410
421411
421412
421413
421414
421415
421416
421417
421418
421419
421420
421421
421422
421423
421424
421425
421426
421427
421428
421429
421430
421431
421432
421433
421434
421435
421436
421437
421438
421439
421440
421441
421442
421443
421444
421445
421446
421447
_	impe 1pl	désindexons
_	impe 2pl	désindexez
_	ppas mas sg	désindexé
_	ppas mas pl	désindexés
_	ppas fem sg	désindexée
_	ppas fem pl	désindexées
$
désindividualiser	1_it_q__a
_	infi	désindividualiser
_	ppre	désindividualisant
_	ipre 1sg	désindividualise
_	ipre 3sg	désindividualise
_	spre 1sg	désindividualise
_	spre 3sg	désindividualise
_	ipre 1isg	désindividualisè
_	ipre 2sg	désindividualises
_	spre 2sg	désindividualises
_	ipre 1pl	désindividualisons
_	ipre 2pl	désindividualisez
_	ipre 3pl	désindividualisent
_	spre 3pl	désindividualisent
_	iimp 1sg	désindividualisais
_	iimp 2sg	désindividualisais
_	iimp 3sg	désindividualisait
_	iimp 1pl	désindividualisions
_	spre 1pl	désindividualisions
_	iimp 2pl	désindividualisiez
_	spre 2pl	désindividualisiez
_	iimp 3pl	désindividualisaient
_	ipsi 1sg	désindividualisai
_	ipsi 2sg	désindividualisas
_	ipsi 3sg	désindividualisa
_	ipsi 1pl	désindividualisâmes
_	ipsi 2pl	désindividualisâtes
_	ipsi 3pl	désindividualisèrent
_	ifut 1sg	désindividualiserai
_	ifut 2sg	désindividualiseras
_	ifut 3sg	désindividualisera
_	ifut 1pl	désindividualiserons
_	ifut 2pl	désindividualiserez
_	ifut 3pl	désindividualiseront
_	cond 1sg	désindividualiserais
_	cond 2sg	désindividualiserais
_	cond 3sg	désindividualiserait
_	cond 1pl	désindividualiserions
_	cond 2pl	désindividualiseriez
_	cond 3pl	désindividualiseraient
_	simp 1sg	désindividualisasse
_	simp 2sg	désindividualisasses
_	simp 3sg	désindividualisât
_	simp 1pl	désindividualisassions
_	simp 2pl	désindividualisassiez
_	simp 3pl	désindividualisassent
_	impe 2sg	désindividualise
_	impe 1pl	désindividualisons
_	impe 2pl	désindividualisez
_	ppas mas sg	désindividualisé
_	ppas mas pl	désindividualisés
_	ppas fem sg	désindividualisée
_	ppas fem pl	désindividualisées
$
désindustrialiser	1__t_q_zz
_	infi	désindustrialiser
_	ppre	désindustrialisant
_	ipre 1sg	désindustrialise
_	ipre 3sg	désindustrialise
_	spre 1sg	désindustrialise
_	spre 3sg	désindustrialise
................................................................................
_	impe 1pl	protestons
_	impe 2pl	protestez
_	ppas mas sg	protesté
_	ppas mas pl	protestés
_	ppas fem sg	protestée
_	ppas fem pl	protestées
$
prototyper	1_it____a
_	infi	prototyper
_	ppre	prototypant
_	ipre 1sg	prototype
_	ipre 3sg	prototype
_	spre 1sg	prototype
_	spre 3sg	prototype
_	ipre 1isg	prototypè
_	ipre 2sg	prototypes
_	spre 2sg	prototypes
_	ipre 1pl	prototypons
_	ipre 2pl	prototypez
_	ipre 3pl	prototypent
_	spre 3pl	prototypent
_	iimp 1sg	prototypais
_	iimp 2sg	prototypais
_	iimp 3sg	prototypait
_	iimp 1pl	prototypions
_	spre 1pl	prototypions
_	iimp 2pl	prototypiez
_	spre 2pl	prototypiez
_	iimp 3pl	prototypaient
_	ipsi 1sg	prototypai
_	ipsi 2sg	prototypas
_	ipsi 3sg	prototypa
_	ipsi 1pl	prototypâmes
_	ipsi 2pl	prototypâtes
_	ipsi 3pl	prototypèrent
_	ifut 1sg	prototyperai
_	ifut 2sg	prototyperas
_	ifut 3sg	prototypera
_	ifut 1pl	prototyperons
_	ifut 2pl	prototyperez
_	ifut 3pl	prototyperont
_	cond 1sg	prototyperais
_	cond 2sg	prototyperais
_	cond 3sg	prototyperait
_	cond 1pl	prototyperions
_	cond 2pl	prototyperiez
_	cond 3pl	prototyperaient
_	simp 1sg	prototypasse
_	simp 2sg	prototypasses
_	simp 3sg	prototypât
_	simp 1pl	prototypassions
_	simp 2pl	prototypassiez
_	simp 3pl	prototypassent
_	impe 2sg	prototype
_	impe 1pl	prototypons
_	impe 2pl	prototypez
_	ppas mas sg	prototypé
_	ppas mas pl	prototypés
_	ppas fem sg	prototypée
_	ppas fem pl	prototypées
$
prouter	1_i____zz
_	infi	prouter
_	ppre	proutant
_	ipre 1sg	proute
_	ipre 3sg	proute
_	spre 1sg	proute
_	spre 3sg	proute
................................................................................
_	impe 1pl	scriptons
_	impe 2pl	scriptez
_	ppas mas sg	scripté
_	ppas mas pl	scriptés
_	ppas fem sg	scriptée
_	ppas fem pl	scriptées
$
scroller	1_i_____a
_	infi	scroller
_	ppre	scrollant
_	ipre 1sg	scrolle
_	ipre 3sg	scrolle
_	spre 1sg	scrolle
_	spre 3sg	scrolle
_	ipre 1isg	scrollè
_	ipre 2sg	scrolles
_	spre 2sg	scrolles
_	ipre 1pl	scrollons
_	ipre 2pl	scrollez
_	ipre 3pl	scrollent
_	spre 3pl	scrollent
_	iimp 1sg	scrollais
_	iimp 2sg	scrollais
_	iimp 3sg	scrollait
_	iimp 1pl	scrollions
_	spre 1pl	scrollions
_	iimp 2pl	scrolliez
_	spre 2pl	scrolliez
_	iimp 3pl	scrollaient
_	ipsi 1sg	scrollai
_	ipsi 2sg	scrollas
_	ipsi 3sg	scrolla
_	ipsi 1pl	scrollâmes
_	ipsi 2pl	scrollâtes
_	ipsi 3pl	scrollèrent
_	ifut 1sg	scrollerai
_	ifut 2sg	scrolleras
_	ifut 3sg	scrollera
_	ifut 1pl	scrollerons
_	ifut 2pl	scrollerez
_	ifut 3pl	scrolleront
_	cond 1sg	scrollerais
_	cond 2sg	scrollerais
_	cond 3sg	scrollerait
_	cond 1pl	scrollerions
_	cond 2pl	scrolleriez
_	cond 3pl	scrolleraient
_	simp 1sg	scrollasse
_	simp 2sg	scrollasses
_	simp 3sg	scrollât
_	simp 1pl	scrollassions
_	simp 2pl	scrollassiez
_	simp 3pl	scrollassent
_	impe 2sg	scrolle
_	impe 1pl	scrollons
_	impe 2pl	scrollez
_	ppas epi inv	scrollé
$
scruter	1__t___zz
_	infi	scruter
_	ppre	scrutant
_	ipre 1sg	scrute
_	ipre 3sg	scrute
_	spre 1sg	scrute
_	spre 3sg	scrute
................................................................................
_	impe 1pl	transvidons
_	impe 2pl	transvidez
_	ppas mas sg	transvidé
_	ppas mas pl	transvidés
_	ppas fem sg	transvidée
_	ppas fem pl	transvidées
$
trapper	1_it____a
_	infi	trapper
_	ppre	trappant
_	ipre 1sg	trappe
_	ipre 3sg	trappe
_	spre 1sg	trappe
_	spre 3sg	trappe
_	ipre 1isg	trappè
_	ipre 2sg	trappes
_	spre 2sg	trappes
_	ipre 1pl	trappons
_	ipre 2pl	trappez
_	ipre 3pl	trappent
_	spre 3pl	trappent
_	iimp 1sg	trappais
_	iimp 2sg	trappais
_	iimp 3sg	trappait
_	iimp 1pl	trappions
_	spre 1pl	trappions
_	iimp 2pl	trappiez
_	spre 2pl	trappiez
_	iimp 3pl	trappaient
_	ipsi 1sg	trappai
_	ipsi 2sg	trappas
_	ipsi 3sg	trappa
_	ipsi 1pl	trappâmes
_	ipsi 2pl	trappâtes
_	ipsi 3pl	trappèrent
_	ifut 1sg	trapperai
_	ifut 2sg	trapperas
_	ifut 3sg	trappera
_	ifut 1pl	trapperons
_	ifut 2pl	trapperez
_	ifut 3pl	trapperont
_	cond 1sg	trapperais
_	cond 2sg	trapperais
_	cond 3sg	trapperait
_	cond 1pl	trapperions
_	cond 2pl	trapperiez
_	cond 3pl	trapperaient
_	simp 1sg	trappasse
_	simp 2sg	trappasses
_	simp 3sg	trappât
_	simp 1pl	trappassions
_	simp 2pl	trappassiez
_	simp 3pl	trappassent
_	impe 2sg	trappe
_	impe 1pl	trappons
_	impe 2pl	trappez
_	ppas mas sg	trappé
_	ppas mas pl	trappés
_	ppas fem sg	trappée
_	ppas fem pl	trappées
$
traquer	1__t___zz
_	infi	traquer
_	ppre	traquant
_	ipre 1sg	traque
_	ipre 3sg	traque
_	spre 1sg	traque
_	spre 3sg	traque

Modified gc_lang/fr/data/dictDecl.txt from [ebca45ebbc] to [250741fc7c].

3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
....
3240
3241
3242
3243
3244
3245
3246




3247
3248
3249
3250
3251
3252
3253
....
6154
6155
6156
6157
6158
6159
6160




6161
6162
6163
6164
6165
6166
6167
....
8533
8534
8535
8536
8537
8538
8539




8540
8541
8542
8543
8544
8545
8546
.....
11777
11778
11779
11780
11781
11782
11783




11784
11785
11786
11787
11788
11789
11790
.....
13041
13042
13043
13044
13045
13046
13047








13048
13049
13050
13051
13052
13053
13054
.....
27018
27019
27020
27021
27022
27023
27024





27025
27026
27027
27028
27029
27030
27031
.....
35413
35414
35415
35416
35417
35418
35419




35420
35421
35422
35423
35424
35425
35426
.....
36629
36630
36631
36632
36633
36634
36635
36636
36637
36638
36639
36640
36641
36642
36643
36644
.....
36646
36647
36648
36649
36650
36651
36652






36653
36654
36655
36656
36657
36658
36659
36660
36661
36662
.....
38073
38074
38075
38076
38077
38078
38079




38080
38081
38082
38083
38084
38085
38086
.....
41724
41725
41726
41727
41728
41729
41730




41731
41732
41733
41734
41735
41736
41737
.....
58779
58780
58781
58782
58783
58784
58785




58786
58787
58788
58789
58790
58791
58792
.....
64250
64251
64252
64253
64254
64255
64256




64257
64258
64259
64260
64261
64262
64263
.....
68224
68225
68226
68227
68228
68229
68230
68231
68232
68233
68234
68235
68236
68237
68238
68239
.....
69403
69404
69405
69406
69407
69408
69409




69410
69411
69412
69413
69414
69415
69416
.....
71700
71701
71702
71703
71704
71705
71706






71707
71708
71709
71710
71711
71712
71713
.....
72745
72746
72747
72748
72749
72750
72751
72752
72753
72754
72755
72756
72757
72758
72759
72760
72761
72762
.....
73562
73563
73564
73565
73566
73567
73568




73569
73570
73571
73572
73573
73574
73575
.....
76205
76206
76207
76208
76209
76210
76211




76212
76213
76214
76215
76216
76217
76218
.....
84897
84898
84899
84900
84901
84902
84903




84904
84905
84906
84907
84908
84909
84910
.....
90701
90702
90703
90704
90705
90706
90707








90708
90709
90710
90711
90712
90713
90714
.....
90846
90847
90848
90849
90850
90851
90852






90853
90854
90855
90856
90857
90858
90859
.....
92962
92963
92964
92965
92966
92967
92968




92969
92970
92971
92972
92973
92974
92975
.....
93687
93688
93689
93690
93691
93692
93693








93694
93695
93696
93697
93698
93699
93700
.....
97824
97825
97826
97827
97828
97829
97830




97831
97832
97833
97834
97835
97836
97837
......
101000
101001
101002
101003
101004
101005
101006




101007
101008
101009
101010
101011
101012
101013
......
113518
113519
113520
113521
113522
113523
113524




113525
113526
113527
113528
113529
113530
113531
......
118115
118116
118117
118118
118119
118120
118121






118122
118123
118124
118125
118126
118127
118128
......
120044
120045
120046
120047
120048
120049
120050










120051
120052
120053
120054
120055
120056
120057
......
122402
122403
122404
122405
122406
122407
122408




122409
122410
122411
122412
122413
122414
122415
......
133612
133613
133614
133615
133616
133617
133618




133619
133620
133621
133622
133623
133624
133625
......
134673
134674
134675
134676
134677
134678
134679




134680
134681
134682
134683
134684
134685
134686
......
158049
158050
158051
158052
158053
158054
158055




158056
158057
158058
158059
158060
158061
158062
......
167051
167052
167053
167054
167055
167056
167057
167058
167059
167060
167061
167062
167063
167064
167065
167066
167067
167068
167069
167070
167071
167072
......
183952
183953
183954
183955
183956
183957
183958




183959
183960
183961
183962
183963
183964
183965
......
184786
184787
184788
184789
184790
184791
184792




184793
184794
184795
184796
184797
184798
184799
......
185290
185291
185292
185293
185294
185295
185296




185297
185298
185299
185300
185301
185302
185303
......
186847
186848
186849
186850
186851
186852
186853




186854
186855
186856
186857
186858
186859
186860
......
187938
187939
187940
187941
187942
187943
187944




187945
187946
187947
187948
187949
187950
187951
......
189481
189482
189483
189484
189485
189486
189487
189488


189489
189490
189491
189492
189493
189494
189495
189496
189497
189498
189499
189500
189501
189502
......
196542
196543
196544
196545
196546
196547
196548




196549
196550
196551
196552
196553
196554
196555
......
214603
214604
214605
214606
214607
214608
214609




214610
214611
214612
214613
214614
214615
214616
......
231023
231024
231025
231026
231027
231028
231029





231030
231031
231032
231033
231034
231035
231036
......
231716
231717
231718
231719
231720
231721
231722






231723
231724
231725
231726
231727
231728
231729
......
249640
249641
249642
249643
249644
249645
249646




249647
249648
249649
249650
249651
249652
249653
_	adj mas sg	additif
_	adj mas pl	additifs
$
additivité	S*()
_	nom fem sg	additivité
_	nom fem pl	additivités
$
addon	S*()
_	nom mas sg	addon
_	nom mas pl	addons
$
adducteur	S*()
_	nom mas sg	adducteur
_	nom mas pl	adducteurs
$
adduction	S*()
_	nom fem sg	adduction
................................................................................
_	nom mas sg	adduit
_	nom mas pl	adduits
$
adèle	S*()
_	nom fem sg	adèle
_	nom fem pl	adèles
$




adelphophagie	S*()
_	nom fem sg	adelphophagie
_	nom fem pl	adelphophagies
$
adénine	S*()
_	nom fem sg	adénine
_	nom fem pl	adénines
................................................................................
_	adj epi sg	aimable
_	adj epi pl	aimables
$
aimant	S*()
_	nom mas sg	aimant
_	nom mas pl	aimants
$




aimantation	S*()
_	nom fem sg	aimantation
_	nom fem pl	aimantations
$
aimante	F*()
_	adj fem sg	aimante
_	adj fem pl	aimantes
................................................................................
_	adj mas sg	amazonien
_	adj mas pl	amazoniens
$
amazonite	S*()
_	nom fem sg	amazonite
_	nom fem pl	amazonites
$




ambassade	S*()
_	nom fem sg	ambassade
_	nom fem pl	ambassades
$
ambassadrice	F*()
_	nom adj fem sg	ambassadrice
_	nom adj fem pl	ambassadrices
................................................................................
$
annulatrice	F*()
_	nom adj fem sg	annulatrice
_	nom adj fem pl	annulatrices
_	nom adj mas sg	annulateur
_	nom adj mas pl	annulateurs
$




anoblissante	F*()
_	adj fem sg	anoblissante
_	adj fem pl	anoblissantes
_	adj mas sg	anoblissant
_	adj mas pl	anoblissants
$
anoblissement	S*()
................................................................................
_	nom mas sg	antiestrogène
_	nom mas pl	antiestrogènes
$
antiétatique	S*()
_	adj epi sg	antiétatique
_	adj epi pl	antiétatiques
$








antifading	S*()
_	nom mas sg	antifading
_	nom mas pl	antifadings
$
antifascisme	S*()
_	nom mas sg	antifascisme
_	nom mas pl	antifascismes
................................................................................
_	nom fem sg	bernicle
_	nom fem pl	bernicles
$
bernique	S.()
_	nom fem sg	bernique
_	nom fem pl	berniques
$





berrichonne	F.()
_	nom adj fem sg	berrichonne
_	nom adj fem pl	berrichonnes
_	nom adj mas sg	berrichon
_	nom adj mas pl	berrichons
$
bersaglier	S.()
................................................................................
_	nom mas sg	building
_	nom mas pl	buildings
$
buire	S.()
_	nom fem sg	buire
_	nom fem pl	buires
$




buisson	S.()
_	nom mas sg	buisson
_	nom mas pl	buissons
$
buissonnante	F.()
_	adj fem sg	buissonnante
_	adj fem pl	buissonnantes
................................................................................
_	nom mas pl	cadreurs
$
cadriciel	S.()
_	nom mas sg	cadriciel
_	nom mas pl	cadriciels
$
caduc	S.()
_	adj epi sg	caduc
_	adj epi pl	caducs
$
caducée	S.()
_	nom mas sg	caducée
_	nom mas pl	caducées
$
caducifoliée	F.()
_	adj fem sg	caducifoliée
................................................................................
_	adj mas sg	caducifolié
_	adj mas pl	caducifoliés
$
caducité	S.()
_	nom fem sg	caducité
_	nom fem pl	caducités
$






caduque	S.()
_	adj epi sg	caduque
_	adj epi pl	caduques
$
cæcale	W.()
_	adj fem sg	cæcale
_	adj fem pl	cæcales
_	adj mas sg	cæcal
_	adj mas pl	cæcaux
$
................................................................................
_	nom adj fem pl	camuses
_	nom adj mas inv	camus
$
canada	S.()
_	nom fem sg	canada
_	nom fem pl	canadas
$




canadianisme	S.()
_	nom mas sg	canadianisme
_	nom mas pl	canadianismes
$
canadienne	F.()
_	nom adj fem sg	canadienne
_	nom adj fem pl	canadiennes
................................................................................
$
caudale	W.()
_	adj fem sg	caudale
_	adj fem pl	caudales
_	adj mas sg	caudal
_	adj mas pl	caudaux
$




caudataire	S.()
_	adj epi sg	caudataire
_	adj epi pl	caudataires
$
caudataire	S.()
_	nom mas sg	caudataire
_	nom mas pl	caudataires
................................................................................
_	nom mas sg	corselet
_	nom mas pl	corselets
$
corset	S.()
_	nom mas sg	corset
_	nom mas pl	corsets
$




corseterie	S.()
_	nom fem sg	corseterie
_	nom fem pl	corseteries
$
corsetière	F.()
_	nom adj fem sg	corsetière
_	nom adj fem pl	corsetières
................................................................................
_	nom mas sg	czar
_	nom mas pl	czars
$
czimbalum	S.()
_	nom mas sg	czimbalum
_	nom mas pl	czimbalums
$




dacryoadénite	S.()
_	nom fem sg	dacryoadénite
_	nom fem pl	dacryoadénites
$
dacryocystite	S.()
_	nom fem sg	dacryocystite
_	nom fem pl	dacryocystites
................................................................................
délitescente	F.()
_	adj fem sg	délitescente
_	adj fem pl	délitescentes
_	adj mas sg	délitescent
_	adj mas pl	délitescents
$
délivrable	S.()
_	nom mas sg	délivrable
_	nom mas pl	délivrables
$
délivrance	S.()
_	nom fem sg	délivrance
_	nom fem pl	délivrances
$
délivreur	S.()
_	nom mas sg	délivreur
................................................................................
$
dénominative	F.()
_	nom adj fem sg	dénominative
_	nom adj fem pl	dénominatives
_	nom adj mas sg	dénominatif
_	nom adj mas pl	dénominatifs
$




dénonciation	S.()
_	nom fem sg	dénonciation
_	nom fem pl	dénonciations
$
dénonciatrice	F.()
_	nom adj fem sg	dénonciatrice
_	nom adj fem pl	dénonciatrices
................................................................................
_	nom fem sg	désirabilité
_	nom fem pl	désirabilités
$
désirable	S.()
_	adj epi sg	désirable
_	adj epi pl	désirables
$






désireuse	W.()
_	adj fem sg	désireuse
_	adj fem pl	désireuses
_	adj mas inv	désireux
$
désistement	S.()
_	nom mas sg	désistement
................................................................................
_	nom mas pl	déverbatifs
$
dévergondage	S.()
_	nom mas sg	dévergondage
_	nom mas pl	dévergondages
$
dévergondée	F.()
_	nom adj fem sg	dévergondée
_	nom adj fem pl	dévergondées
_	nom adj mas sg	dévergondé
_	nom adj mas pl	dévergondés
$
déverminage	S.()
_	nom mas sg	déverminage
_	nom mas pl	déverminages
$
dévernissage	S.()
_	nom mas sg	dévernissage
................................................................................
_	nom mas sg	diascordium
_	nom mas pl	diascordiums
$
diaspora	S.()
_	nom fem sg	diaspora
_	nom fem pl	diasporas
$




diastase	S.()
_	nom fem sg	diastase
_	nom fem pl	diastases
$
diastasique	S.()
_	adj epi sg	diastasique
_	adj epi pl	diastasiques
................................................................................
_	adj epi sg	diversiforme
_	adj epi pl	diversiformes
$
diversion	S.()
_	nom fem sg	diversion
_	nom fem pl	diversions
$




diversité	S.()
_	nom fem sg	diversité
_	nom fem pl	diversités
$
diverticule	S.()
_	nom mas sg	diverticule
_	nom mas pl	diverticules
................................................................................
_	adj epi sg	endogène
_	adj epi pl	endogènes
$
endogénéité	S*()
_	nom fem sg	endogénéité
_	nom fem pl	endogénéités
$




endolocalisation	S*()
_	nom fem sg	endolocalisation
_	nom fem pl	endolocalisations
$
endolorissement	S*()
_	nom mas sg	endolorissement
_	nom mas pl	endolorissements
................................................................................
_	nom mas sg	ethnarque
_	nom mas pl	ethnarques
$
ethnicisation	S*()
_	nom fem sg	ethnicisation
_	nom fem pl	ethnicisations
$








ethnicité	S*()
_	nom fem sg	ethnicité
_	nom fem pl	ethnicités
$
ethnico-religieuse	W*()
_	adj fem sg	ethnico-religieuse
_	adj fem pl	ethnico-religieuses
................................................................................
_	nom fem sg	ethnopsychiatrie
_	nom fem pl	ethnopsychiatries
$
ethnopsychologie	S*()
_	nom fem sg	ethnopsychologie
_	nom fem pl	ethnopsychologies
$






ethnoreligieuse	W*()
_	adj fem sg	ethnoreligieuse
_	adj fem pl	ethnoreligieuses
_	adj mas inv	ethnoreligieux
$
éthographie	S*()
_	nom fem sg	éthographie
................................................................................
_	adj epi sg	exogène
_	adj epi pl	exogènes
$
exogénéité	S*()
_	nom fem sg	exogénéité
_	nom fem pl	exogénéités
$




exomphale	S*()
_	nom fem sg	exomphale
_	nom fem pl	exomphales
$
exon	S*()
_	nom mas sg	exon
_	nom mas pl	exons
................................................................................
_	nom fem sg	extensivité
_	nom fem pl	extensivités
$
extensomètre	S*()
_	nom mas sg	extensomètre
_	nom mas pl	extensomètres
$








exténuante	F*()
_	adj fem sg	exténuante
_	adj fem pl	exténuantes
_	adj mas sg	exténuant
_	adj mas pl	exténuants
$
exténuation	S*()
................................................................................
_	nom mas sg	filoutage
_	nom mas pl	filoutages
$
filouterie	S.()
_	nom fem sg	filouterie
_	nom fem pl	filouteries
$




filtrable	S.()
_	adj epi sg	filtrable
_	adj epi pl	filtrables
$
filtrage	S.()
_	nom mas sg	filtrage
_	nom mas pl	filtrages
................................................................................
_	nom adj epi sg	foutraque
_	nom adj epi pl	foutraques
$
foutre	S.()
_	nom mas sg	foutre
_	nom mas pl	foutres
$




foutriquet	S.()
_	nom mas sg	foutriquet
_	nom mas pl	foutriquets
$
foutue	F.()
_	adj fem sg	foutue
_	adj fem pl	foutues
................................................................................
_	nom mas sg	harakiri
_	nom mas pl	harakiris
$
hara-kiri	S.()
_	nom mas sg	hara-kiri
_	nom mas pl	hara-kiris
$




harangue	S.()
_	nom fem sg	harangue
_	nom fem pl	harangues
$
harangueuse	F.()
_	nom fem sg	harangueuse
_	nom fem pl	harangueuses
................................................................................
_	nom fem sg	huée
_	nom fem pl	huées
$
huerta	S.()
_	nom fem sg	huerta
_	nom fem pl	huertas
$






huguenote	F.()
_	nom adj fem sg	huguenote
_	nom adj fem pl	huguenotes
_	nom adj mas sg	huguenot
_	nom adj mas pl	huguenots
$
huilage	S*()
................................................................................
_	nom fem sg	hyperventilation
_	nom fem pl	hyperventilations
$
hypervigilance	S*()
_	nom fem sg	hypervigilance
_	nom fem pl	hypervigilances
$










hyperviscosité	S*()
_	nom fem sg	hyperviscosité
_	nom fem pl	hyperviscosités
$
hyperviseur	S*()
_	nom mas sg	hyperviseur
_	nom mas pl	hyperviseurs
................................................................................
_	adj mas sg	impartial
_	adj mas pl	impartiaux
$
impartialité	S*()
_	nom fem sg	impartialité
_	nom fem pl	impartialités
$




impasse	S*()
_	nom fem sg	impasse
_	nom fem pl	impasses
$
impassibilité	S*()
_	nom fem sg	impassibilité
_	nom fem pl	impassibilités
................................................................................
_	nom adj epi sg	jihadiste
_	nom adj epi pl	jihadistes
$
jingle	S.()
_	nom mas sg	jingle
_	nom mas pl	jingles
$




jiujitsu	S.()
_	nom mas sg	jiujitsu
_	nom mas pl	jiujitsus
$
joaillère	F.()
_	nom adj fem sg	joaillère
_	nom adj fem pl	joaillères
................................................................................
_	nom adj epi sg	kachoube
_	nom adj epi pl	kachoubes
$
kaddish	S.()
_	nom mas sg	kaddish
_	nom mas pl	kaddishs
$




kafir	S.()
_	nom adj epi sg	kafir
_	nom adj epi pl	kafirs
$
kafkaïenne	F.()
_	adj fem sg	kafkaïenne
_	adj fem pl	kafkaïennes
................................................................................
_	adj mas sg	multidirectionnel
_	adj mas pl	multidirectionnels
$
multidisciplinaire	S.()
_	adj epi sg	multidisciplinaire
_	adj epi pl	multidisciplinaires
$




multiethnique	S.()
_	adj epi sg	multiethnique
_	adj epi pl	multiethniques
$
multi-ethnique	S.()
_	adj epi sg	multi-ethnique
_	adj epi pl	multi-ethniques
................................................................................
_	nom mas sg	oligodendrogliome
_	nom mas pl	oligodendrogliomes
$
oligoélément	S*()
_	nom mas sg	oligoélément
_	nom mas pl	oligoéléments
$
oligoélément	S*()
_	nom mas sg	oligoélément
_	nom mas pl	oligoéléments
$
oligo-élément	S*()
_	nom mas sg	oligo-élément
_	nom mas pl	oligo-éléments
$
oligo-élément	S*()
_	nom mas sg	oligo-élément
_	nom mas pl	oligo-éléments
$
oligogalacturonate	S*()
_	nom mas sg	oligogalacturonate
_	nom mas pl	oligogalacturonates
................................................................................
_	nom mas sg	placage
_	nom mas pl	placages
$
placard	S.()
_	nom mas sg	placard
_	nom mas pl	placards
$




placardisation	S.()
_	nom fem sg	placardisation
_	nom fem pl	placardisations
$
place	S.()
_	nom fem sg	place
_	nom fem pl	places
................................................................................
_	adj epi sg	plausible
_	adj epi pl	plausibles
$
playback	S.()
_	nom mas sg	playback
_	nom mas pl	playbacks
$




playboy	S.()
_	nom mas sg	playboy
_	nom mas pl	playboys
$
play-boy	S.()
_	nom mas sg	play-boy
_	nom mas pl	play-boys
................................................................................
_	adj fem pl	plucheuses
_	adj mas inv	plucheux
$
plugin	S.()
_	nom mas sg	plugin
_	nom mas pl	plugins
$




pluie	S.()
_	nom fem sg	pluie
_	nom fem pl	pluies
$
plumage	S.()
_	nom mas sg	plumage
_	nom mas pl	plumages
................................................................................
_	adj epi sg	polychrome
_	adj epi pl	polychromes
$
polychromie	S.()
_	nom fem sg	polychromie
_	nom fem pl	polychromies
$




polycistronique	S.()
_	adj epi sg	polycistronique
_	adj epi pl	polycistroniques
$
polyclinique	S.()
_	nom fem sg	polyclinique
_	nom fem pl	polycliniques
................................................................................
_	nom fem sg	popote
_	nom fem pl	popotes
$
popotin	S.()
_	nom mas sg	popotin
_	nom mas pl	popotins
$




populace	S.()
_	nom fem sg	populace
_	nom fem pl	populaces
$
populacière	F.()
_	adj fem sg	populacière
_	adj fem pl	populacières
................................................................................
_	nom mas sg	poulbot
_	nom mas pl	poulbots
$
poule	S.()
_	nom fem sg	poule
_	nom fem pl	poules
$
poulet	S.()


_	nom mas sg	poulet
_	nom mas pl	poulets
$
poulette	S.()
_	nom fem sg	poulette
_	nom fem pl	poulettes
$
pouliage	S.()
_	nom mas sg	pouliage
_	nom mas pl	pouliages
$
pouliche	S.()
_	nom fem sg	pouliche
_	nom fem pl	pouliches
................................................................................
_	adj fem pl	pustuleuses
_	adj mas inv	pustuleux
$
putain	S.()
_	nom fem sg	putain
_	nom fem pl	putains
$




putassière	F.()
_	adj fem sg	putassière
_	adj fem pl	putassières
_	adj mas sg	putassier
_	adj mas pl	putassiers
$
putative	F.()
................................................................................
_	nom fem sg	scélératesse
_	nom fem pl	scélératesses
$
scellage	S.()
_	nom mas sg	scellage
_	nom mas pl	scellages
$




scellement	S.()
_	nom mas sg	scellement
_	nom mas pl	scellements
$
scénarimage	S.()
_	nom mas sg	scénarimage
_	nom mas pl	scénarimages
................................................................................
_	nom fem sg	syringe
_	nom fem pl	syringes
$
syringomyélie	S.()
_	nom fem sg	syringomyélie
_	nom fem pl	syringomyélies
$





syrphe	S.()
_	nom mas sg	syrphe
_	nom mas pl	syrphes
$
sysadmin	S.()
_	nom epi sg	sysadmin
_	nom epi pl	sysadmins
................................................................................
$
talibane	F.()
_	nom adj fem sg	talibane
_	nom adj fem pl	talibanes
_	nom adj mas sg	taliban
_	nom adj mas pl	talibans
$






talion	S.()
_	nom mas sg	talion
_	nom mas pl	talions
$
talisman	S.()
_	nom mas sg	talisman
_	nom mas pl	talismans
................................................................................
_	nom mas sg	vibrion
_	nom mas pl	vibrions
$
vibrisse	S.()
_	nom fem sg	vibrisse
_	nom fem pl	vibrisses
$




vibromasseur	S.()
_	nom mas sg	vibromasseur
_	nom mas pl	vibromasseurs
$
vicaire	S.()
_	nom mas sg	vicaire
_	nom mas pl	vicaires







|
|
|







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>
>
>







 







>
>
>
>







 







|
|







 







>
>
>
>
>
>

|
|







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







|
|







 







>
>
>
>







 







>
>
>
>
>
>







 







|
|
|
|







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







<
<
<
<
<
<
<
<







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







|
>
>



<
<
<
<







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>
>







 







>
>
>
>
>
>







 







>
>
>
>







3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
....
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
....
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
....
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
.....
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
.....
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
.....
27042
27043
27044
27045
27046
27047
27048
27049
27050
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
.....
35442
35443
35444
35445
35446
35447
35448
35449
35450
35451
35452
35453
35454
35455
35456
35457
35458
35459
.....
36662
36663
36664
36665
36666
36667
36668
36669
36670
36671
36672
36673
36674
36675
36676
36677
.....
36679
36680
36681
36682
36683
36684
36685
36686
36687
36688
36689
36690
36691
36692
36693
36694
36695
36696
36697
36698
36699
36700
36701
.....
38112
38113
38114
38115
38116
38117
38118
38119
38120
38121
38122
38123
38124
38125
38126
38127
38128
38129
.....
41767
41768
41769
41770
41771
41772
41773
41774
41775
41776
41777
41778
41779
41780
41781
41782
41783
41784
.....
58826
58827
58828
58829
58830
58831
58832
58833
58834
58835
58836
58837
58838
58839
58840
58841
58842
58843
.....
64301
64302
64303
64304
64305
64306
64307
64308
64309
64310
64311
64312
64313
64314
64315
64316
64317
64318
.....
68279
68280
68281
68282
68283
68284
68285
68286
68287
68288
68289
68290
68291
68292
68293
68294
.....
69458
69459
69460
69461
69462
69463
69464
69465
69466
69467
69468
69469
69470
69471
69472
69473
69474
69475
.....
71759
71760
71761
71762
71763
71764
71765
71766
71767
71768
71769
71770
71771
71772
71773
71774
71775
71776
71777
71778
.....
72810
72811
72812
72813
72814
72815
72816
72817
72818
72819
72820
72821
72822
72823
72824
72825
72826
72827
.....
73627
73628
73629
73630
73631
73632
73633
73634
73635
73636
73637
73638
73639
73640
73641
73642
73643
73644
.....
76274
76275
76276
76277
76278
76279
76280
76281
76282
76283
76284
76285
76286
76287
76288
76289
76290
76291
.....
84970
84971
84972
84973
84974
84975
84976
84977
84978
84979
84980
84981
84982
84983
84984
84985
84986
84987
.....
90778
90779
90780
90781
90782
90783
90784
90785
90786
90787
90788
90789
90790
90791
90792
90793
90794
90795
90796
90797
90798
90799
.....
90931
90932
90933
90934
90935
90936
90937
90938
90939
90940
90941
90942
90943
90944
90945
90946
90947
90948
90949
90950
.....
93053
93054
93055
93056
93057
93058
93059
93060
93061
93062
93063
93064
93065
93066
93067
93068
93069
93070
.....
93782
93783
93784
93785
93786
93787
93788
93789
93790
93791
93792
93793
93794
93795
93796
93797
93798
93799
93800
93801
93802
93803
.....
97927
97928
97929
97930
97931
97932
97933
97934
97935
97936
97937
97938
97939
97940
97941
97942
97943
97944
......
101107
101108
101109
101110
101111
101112
101113
101114
101115
101116
101117
101118
101119
101120
101121
101122
101123
101124
......
113629
113630
113631
113632
113633
113634
113635
113636
113637
113638
113639
113640
113641
113642
113643
113644
113645
113646
......
118230
118231
118232
118233
118234
118235
118236
118237
118238
118239
118240
118241
118242
118243
118244
118245
118246
118247
118248
118249
......
120165
120166
120167
120168
120169
120170
120171
120172
120173
120174
120175
120176
120177
120178
120179
120180
120181
120182
120183
120184
120185
120186
120187
120188
......
122533
122534
122535
122536
122537
122538
122539
122540
122541
122542
122543
122544
122545
122546
122547
122548
122549
122550
......
133747
133748
133749
133750
133751
133752
133753
133754
133755
133756
133757
133758
133759
133760
133761
133762
133763
133764
......
134812
134813
134814
134815
134816
134817
134818
134819
134820
134821
134822
134823
134824
134825
134826
134827
134828
134829
......
158192
158193
158194
158195
158196
158197
158198
158199
158200
158201
158202
158203
158204
158205
158206
158207
158208
158209
......
167198
167199
167200
167201
167202
167203
167204








167205
167206
167207
167208
167209
167210
167211
......
184091
184092
184093
184094
184095
184096
184097
184098
184099
184100
184101
184102
184103
184104
184105
184106
184107
184108
......
184929
184930
184931
184932
184933
184934
184935
184936
184937
184938
184939
184940
184941
184942
184943
184944
184945
184946
......
185437
185438
185439
185440
185441
185442
185443
185444
185445
185446
185447
185448
185449
185450
185451
185452
185453
185454
......
186998
186999
187000
187001
187002
187003
187004
187005
187006
187007
187008
187009
187010
187011
187012
187013
187014
187015
......
188093
188094
188095
188096
188097
188098
188099
188100
188101
188102
188103
188104
188105
188106
188107
188108
188109
188110
......
189640
189641
189642
189643
189644
189645
189646
189647
189648
189649
189650
189651
189652




189653
189654
189655
189656
189657
189658
189659
......
196699
196700
196701
196702
196703
196704
196705
196706
196707
196708
196709
196710
196711
196712
196713
196714
196715
196716
......
214764
214765
214766
214767
214768
214769
214770
214771
214772
214773
214774
214775
214776
214777
214778
214779
214780
214781
......
231188
231189
231190
231191
231192
231193
231194
231195
231196
231197
231198
231199
231200
231201
231202
231203
231204
231205
231206
......
231886
231887
231888
231889
231890
231891
231892
231893
231894
231895
231896
231897
231898
231899
231900
231901
231902
231903
231904
231905
......
249816
249817
249818
249819
249820
249821
249822
249823
249824
249825
249826
249827
249828
249829
249830
249831
249832
249833
_	adj mas sg	additif
_	adj mas pl	additifs
$
additivité	S*()
_	nom fem sg	additivité
_	nom fem pl	additivités
$
add-on	S*()
_	nom mas sg	add-on
_	nom mas pl	add-ons
$
adducteur	S*()
_	nom mas sg	adducteur
_	nom mas pl	adducteurs
$
adduction	S*()
_	nom fem sg	adduction
................................................................................
_	nom mas sg	adduit
_	nom mas pl	adduits
$
adèle	S*()
_	nom fem sg	adèle
_	nom fem pl	adèles
$
adelphe	S*()
_	nom adj epi sg	adelphe
_	nom adj epi pl	adelphes
$
adelphophagie	S*()
_	nom fem sg	adelphophagie
_	nom fem pl	adelphophagies
$
adénine	S*()
_	nom fem sg	adénine
_	nom fem pl	adénines
................................................................................
_	adj epi sg	aimable
_	adj epi pl	aimables
$
aimant	S*()
_	nom mas sg	aimant
_	nom mas pl	aimants
$
aimantable	S*()
_	adj epi sg	aimantable
_	adj epi pl	aimantables
$
aimantation	S*()
_	nom fem sg	aimantation
_	nom fem pl	aimantations
$
aimante	F*()
_	adj fem sg	aimante
_	adj fem pl	aimantes
................................................................................
_	adj mas sg	amazonien
_	adj mas pl	amazoniens
$
amazonite	S*()
_	nom fem sg	amazonite
_	nom fem pl	amazonites
$
ambage	S*()
_	nom fem sg	ambage
_	nom fem pl	ambages
$
ambassade	S*()
_	nom fem sg	ambassade
_	nom fem pl	ambassades
$
ambassadrice	F*()
_	nom adj fem sg	ambassadrice
_	nom adj fem pl	ambassadrices
................................................................................
$
annulatrice	F*()
_	nom adj fem sg	annulatrice
_	nom adj fem pl	annulatrices
_	nom adj mas sg	annulateur
_	nom adj mas pl	annulateurs
$
annulement	S*()
_	nom mas sg	annulement
_	nom mas pl	annulements
$
anoblissante	F*()
_	adj fem sg	anoblissante
_	adj fem pl	anoblissantes
_	adj mas sg	anoblissant
_	adj mas pl	anoblissants
$
anoblissement	S*()
................................................................................
_	nom mas sg	antiestrogène
_	nom mas pl	antiestrogènes
$
antiétatique	S*()
_	adj epi sg	antiétatique
_	adj epi pl	antiétatiques
$
antiétatisme	S*()
_	nom mas sg	antiétatisme
_	nom mas pl	antiétatismes
$
antifa	S*()
_	nom adj epi sg	antifa
_	nom adj epi pl	antifas
$
antifading	S*()
_	nom mas sg	antifading
_	nom mas pl	antifadings
$
antifascisme	S*()
_	nom mas sg	antifascisme
_	nom mas pl	antifascismes
................................................................................
_	nom fem sg	bernicle
_	nom fem pl	bernicles
$
bernique	S.()
_	nom fem sg	bernique
_	nom fem pl	berniques
$
bernoise	F.()
_	nom adj fem sg	bernoise
_	nom adj fem pl	bernoises
_	nom adj mas inv	bernois
$
berrichonne	F.()
_	nom adj fem sg	berrichonne
_	nom adj fem pl	berrichonnes
_	nom adj mas sg	berrichon
_	nom adj mas pl	berrichons
$
bersaglier	S.()
................................................................................
_	nom mas sg	building
_	nom mas pl	buildings
$
buire	S.()
_	nom fem sg	buire
_	nom fem pl	buires
$
buissaie	S.()
_	nom fem sg	buissaie
_	nom fem pl	buissaies
$
buisson	S.()
_	nom mas sg	buisson
_	nom mas pl	buissons
$
buissonnante	F.()
_	adj fem sg	buissonnante
_	adj fem pl	buissonnantes
................................................................................
_	nom mas pl	cadreurs
$
cadriciel	S.()
_	nom mas sg	cadriciel
_	nom mas pl	cadriciels
$
caduc	S.()
_	adj mas sg	caduc
_	adj mas pl	caducs
$
caducée	S.()
_	nom mas sg	caducée
_	nom mas pl	caducées
$
caducifoliée	F.()
_	adj fem sg	caducifoliée
................................................................................
_	adj mas sg	caducifolié
_	adj mas pl	caducifoliés
$
caducité	S.()
_	nom fem sg	caducité
_	nom fem pl	caducités
$
caduque	F.()
_	adj fem sg	caduque
_	adj fem pl	caduques
_	adj mas sg	caduc
_	adj mas pl	caducs
$
caduque	S.()
_	nom fem sg	caduque
_	nom fem pl	caduques
$
cæcale	W.()
_	adj fem sg	cæcale
_	adj fem pl	cæcales
_	adj mas sg	cæcal
_	adj mas pl	cæcaux
$
................................................................................
_	nom adj fem pl	camuses
_	nom adj mas inv	camus
$
canada	S.()
_	nom fem sg	canada
_	nom fem pl	canadas
$
canadair	S.()
_	nom mas sg	canadair
_	nom mas pl	canadairs
$
canadianisme	S.()
_	nom mas sg	canadianisme
_	nom mas pl	canadianismes
$
canadienne	F.()
_	nom adj fem sg	canadienne
_	nom adj fem pl	canadiennes
................................................................................
$
caudale	W.()
_	adj fem sg	caudale
_	adj fem pl	caudales
_	adj mas sg	caudal
_	adj mas pl	caudaux
$
caudalie	S.()
_	nom fem sg	caudalie
_	nom fem pl	caudalies
$
caudataire	S.()
_	adj epi sg	caudataire
_	adj epi pl	caudataires
$
caudataire	S.()
_	nom mas sg	caudataire
_	nom mas pl	caudataires
................................................................................
_	nom mas sg	corselet
_	nom mas pl	corselets
$
corset	S.()
_	nom mas sg	corset
_	nom mas pl	corsets
$
corsetage	S.()
_	nom mas sg	corsetage
_	nom mas pl	corsetages
$
corseterie	S.()
_	nom fem sg	corseterie
_	nom fem pl	corseteries
$
corsetière	F.()
_	nom adj fem sg	corsetière
_	nom adj fem pl	corsetières
................................................................................
_	nom mas sg	czar
_	nom mas pl	czars
$
czimbalum	S.()
_	nom mas sg	czimbalum
_	nom mas pl	czimbalums
$
daba	S.()
_	nom fem sg	daba
_	nom fem pl	dabas
$
dacryoadénite	S.()
_	nom fem sg	dacryoadénite
_	nom fem pl	dacryoadénites
$
dacryocystite	S.()
_	nom fem sg	dacryocystite
_	nom fem pl	dacryocystites
................................................................................
délitescente	F.()
_	adj fem sg	délitescente
_	adj fem pl	délitescentes
_	adj mas sg	délitescent
_	adj mas pl	délitescents
$
délivrable	S.()
_	adj epi sg	délivrable
_	adj epi pl	délivrables
$
délivrance	S.()
_	nom fem sg	délivrance
_	nom fem pl	délivrances
$
délivreur	S.()
_	nom mas sg	délivreur
................................................................................
$
dénominative	F.()
_	nom adj fem sg	dénominative
_	nom adj fem pl	dénominatives
_	nom adj mas sg	dénominatif
_	nom adj mas pl	dénominatifs
$
dénommable	S.()
_	adj epi sg	dénommable
_	adj epi pl	dénommables
$
dénonciation	S.()
_	nom fem sg	dénonciation
_	nom fem pl	dénonciations
$
dénonciatrice	F.()
_	nom adj fem sg	dénonciatrice
_	nom adj fem pl	dénonciatrices
................................................................................
_	nom fem sg	désirabilité
_	nom fem pl	désirabilités
$
désirable	S.()
_	adj epi sg	désirable
_	adj epi pl	désirables
$
désirante	F.()
_	adj fem sg	désirante
_	adj fem pl	désirantes
_	adj mas sg	désirant
_	adj mas pl	désirants
$
désireuse	W.()
_	adj fem sg	désireuse
_	adj fem pl	désireuses
_	adj mas inv	désireux
$
désistement	S.()
_	nom mas sg	désistement
................................................................................
_	nom mas pl	déverbatifs
$
dévergondage	S.()
_	nom mas sg	dévergondage
_	nom mas pl	dévergondages
$
dévergondée	F.()
_	nom fem sg	dévergondée
_	nom fem pl	dévergondées
_	nom mas sg	dévergondé
_	nom mas pl	dévergondés
$
déverminage	S.()
_	nom mas sg	déverminage
_	nom mas pl	déverminages
$
dévernissage	S.()
_	nom mas sg	dévernissage
................................................................................
_	nom mas sg	diascordium
_	nom mas pl	diascordiums
$
diaspora	S.()
_	nom fem sg	diaspora
_	nom fem pl	diasporas
$
diasporique	S.()
_	adj epi sg	diasporique
_	adj epi pl	diasporiques
$
diastase	S.()
_	nom fem sg	diastase
_	nom fem pl	diastases
$
diastasique	S.()
_	adj epi sg	diastasique
_	adj epi pl	diastasiques
................................................................................
_	adj epi sg	diversiforme
_	adj epi pl	diversiformes
$
diversion	S.()
_	nom fem sg	diversion
_	nom fem pl	diversions
$
diversitaire	S.()
_	adj epi sg	diversitaire
_	adj epi pl	diversitaires
$
diversité	S.()
_	nom fem sg	diversité
_	nom fem pl	diversités
$
diverticule	S.()
_	nom mas sg	diverticule
_	nom mas pl	diverticules
................................................................................
_	adj epi sg	endogène
_	adj epi pl	endogènes
$
endogénéité	S*()
_	nom fem sg	endogénéité
_	nom fem pl	endogénéités
$
endogroupe	S*()
_	nom mas sg	endogroupe
_	nom mas pl	endogroupes
$
endolocalisation	S*()
_	nom fem sg	endolocalisation
_	nom fem pl	endolocalisations
$
endolorissement	S*()
_	nom mas sg	endolorissement
_	nom mas pl	endolorissements
................................................................................
_	nom mas sg	ethnarque
_	nom mas pl	ethnarques
$
ethnicisation	S*()
_	nom fem sg	ethnicisation
_	nom fem pl	ethnicisations
$
ethnicisme	S*()
_	nom mas sg	ethnicisme
_	nom mas pl	ethnicismes
$
ethniciste	S*()
_	nom adj epi sg	ethniciste
_	nom adj epi pl	ethnicistes
$
ethnicité	S*()
_	nom fem sg	ethnicité
_	nom fem pl	ethnicités
$
ethnico-religieuse	W*()
_	adj fem sg	ethnico-religieuse
_	adj fem pl	ethnico-religieuses
................................................................................
_	nom fem sg	ethnopsychiatrie
_	nom fem pl	ethnopsychiatries
$
ethnopsychologie	S*()
_	nom fem sg	ethnopsychologie
_	nom fem pl	ethnopsychologies
$
ethno-raciale	W*()
_	adj fem sg	ethno-raciale
_	adj fem pl	ethno-raciales
_	adj mas sg	ethno-racial
_	adj mas pl	ethno-raciaux
$
ethnoreligieuse	W*()
_	adj fem sg	ethnoreligieuse
_	adj fem pl	ethnoreligieuses
_	adj mas inv	ethnoreligieux
$
éthographie	S*()
_	nom fem sg	éthographie
................................................................................
_	adj epi sg	exogène
_	adj epi pl	exogènes
$
exogénéité	S*()
_	nom fem sg	exogénéité
_	nom fem pl	exogénéités
$
exogroupe	S*()
_	nom mas sg	exogroupe
_	nom mas pl	exogroupes
$
exomphale	S*()
_	nom fem sg	exomphale
_	nom fem pl	exomphales
$
exon	S*()
_	nom mas sg	exon
_	nom mas pl	exons
................................................................................
_	nom fem sg	extensivité
_	nom fem pl	extensivités
$
extensomètre	S*()
_	nom mas sg	extensomètre
_	nom mas pl	extensomètres
$
extensométrie	S*()
_	nom fem sg	extensométrie
_	nom fem pl	extensométries
$
extensométrique	S*()
_	adj epi sg	extensométrique
_	adj epi pl	extensométriques
$
exténuante	F*()
_	adj fem sg	exténuante
_	adj fem pl	exténuantes
_	adj mas sg	exténuant
_	adj mas pl	exténuants
$
exténuation	S*()
................................................................................
_	nom mas sg	filoutage
_	nom mas pl	filoutages
$
filouterie	S.()
_	nom fem sg	filouterie
_	nom fem pl	filouteries
$
filsdeputerie	S.()
_	nom fem sg	filsdeputerie
_	nom fem pl	filsdeputeries
$
filtrable	S.()
_	adj epi sg	filtrable
_	adj epi pl	filtrables
$
filtrage	S.()
_	nom mas sg	filtrage
_	nom mas pl	filtrages
................................................................................
_	nom adj epi sg	foutraque
_	nom adj epi pl	foutraques
$
foutre	S.()
_	nom mas sg	foutre
_	nom mas pl	foutres
$
foutrerie	S.()
_	nom fem sg	foutrerie
_	nom fem pl	foutreries
$
foutriquet	S.()
_	nom mas sg	foutriquet
_	nom mas pl	foutriquets
$
foutue	F.()
_	adj fem sg	foutue
_	adj fem pl	foutues
................................................................................
_	nom mas sg	harakiri
_	nom mas pl	harakiris
$
hara-kiri	S.()
_	nom mas sg	hara-kiri
_	nom mas pl	hara-kiris
$
haram	S.()
_	adj epi sg	haram
_	adj epi pl	harams
$
harangue	S.()
_	nom fem sg	harangue
_	nom fem pl	harangues
$
harangueuse	F.()
_	nom fem sg	harangueuse
_	nom fem pl	harangueuses
................................................................................
_	nom fem sg	huée
_	nom fem pl	huées
$
huerta	S.()
_	nom fem sg	huerta
_	nom fem pl	huertas
$
hugolienne	F*()
_	adj fem sg	hugolienne
_	adj fem pl	hugoliennes
_	adj mas sg	hugolien
_	adj mas pl	hugoliens
$
huguenote	F.()
_	nom adj fem sg	huguenote
_	nom adj fem pl	huguenotes
_	nom adj mas sg	huguenot
_	nom adj mas pl	huguenots
$
huilage	S*()
................................................................................
_	nom fem sg	hyperventilation
_	nom fem pl	hyperventilations
$
hypervigilance	S*()
_	nom fem sg	hypervigilance
_	nom fem pl	hypervigilances
$
hyperviolence	S*()
_	nom fem sg	hyperviolence
_	nom fem pl	hyperviolences
$
hyperviolente	F*()
_	adj fem sg	hyperviolente
_	adj fem pl	hyperviolentes
_	adj mas sg	hyperviolent
_	adj mas pl	hyperviolents
$
hyperviscosité	S*()
_	nom fem sg	hyperviscosité
_	nom fem pl	hyperviscosités
$
hyperviseur	S*()
_	nom mas sg	hyperviseur
_	nom mas pl	hyperviseurs
................................................................................
_	adj mas sg	impartial
_	adj mas pl	impartiaux
$
impartialité	S*()
_	nom fem sg	impartialité
_	nom fem pl	impartialités
$
impassable	S*()
_	adj epi sg	impassable
_	adj epi pl	impassables
$
impasse	S*()
_	nom fem sg	impasse
_	nom fem pl	impasses
$
impassibilité	S*()
_	nom fem sg	impassibilité
_	nom fem pl	impassibilités
................................................................................
_	nom adj epi sg	jihadiste
_	nom adj epi pl	jihadistes
$
jingle	S.()
_	nom mas sg	jingle
_	nom mas pl	jingles
$
jinn	S.()
_	nom mas sg	jinn
_	nom mas pl	jinns
$
jiujitsu	S.()
_	nom mas sg	jiujitsu
_	nom mas pl	jiujitsus
$
joaillère	F.()
_	nom adj fem sg	joaillère
_	nom adj fem pl	joaillères
................................................................................
_	nom adj epi sg	kachoube
_	nom adj epi pl	kachoubes
$
kaddish	S.()
_	nom mas sg	kaddish
_	nom mas pl	kaddishs
$
kadi	S.()
_	nom mas sg	kadi
_	nom mas pl	kadis
$
kafir	S.()
_	nom adj epi sg	kafir
_	nom adj epi pl	kafirs
$
kafkaïenne	F.()
_	adj fem sg	kafkaïenne
_	adj fem pl	kafkaïennes
................................................................................
_	adj mas sg	multidirectionnel
_	adj mas pl	multidirectionnels
$
multidisciplinaire	S.()
_	adj epi sg	multidisciplinaire
_	adj epi pl	multidisciplinaires
$
multidisciplinarité	S.()
_	nom fem sg	multidisciplinarité
_	nom fem pl	multidisciplinarités
$
multiethnique	S.()
_	adj epi sg	multiethnique
_	adj epi pl	multiethniques
$
multi-ethnique	S.()
_	adj epi sg	multi-ethnique
_	adj epi pl	multi-ethniques
................................................................................
_	nom mas sg	oligodendrogliome
_	nom mas pl	oligodendrogliomes
$
oligoélément	S*()
_	nom mas sg	oligoélément
_	nom mas pl	oligoéléments
$








oligo-élément	S*()
_	nom mas sg	oligo-élément
_	nom mas pl	oligo-éléments
$
oligogalacturonate	S*()
_	nom mas sg	oligogalacturonate
_	nom mas pl	oligogalacturonates
................................................................................
_	nom mas sg	placage
_	nom mas pl	placages
$
placard	S.()
_	nom mas sg	placard
_	nom mas pl	placards
$
placardage	S.()
_	nom mas sg	placardage
_	nom mas pl	placardages
$
placardisation	S.()
_	nom fem sg	placardisation
_	nom fem pl	placardisations
$
place	S.()
_	nom fem sg	place
_	nom fem pl	places
................................................................................
_	adj epi sg	plausible
_	adj epi pl	plausibles
$
playback	S.()
_	nom mas sg	playback
_	nom mas pl	playbacks
$
play-back	S.()
_	nom mas sg	play-back
_	nom mas pl	play-backs
$
playboy	S.()
_	nom mas sg	playboy
_	nom mas pl	playboys
$
play-boy	S.()
_	nom mas sg	play-boy
_	nom mas pl	play-boys
................................................................................
_	adj fem pl	plucheuses
_	adj mas inv	plucheux
$
plugin	S.()
_	nom mas sg	plugin
_	nom mas pl	plugins
$
plug-in	S.()
_	nom mas sg	plug-in
_	nom mas pl	plug-ins
$
pluie	S.()
_	nom fem sg	pluie
_	nom fem pl	pluies
$
plumage	S.()
_	nom mas sg	plumage
_	nom mas pl	plumages
................................................................................
_	adj epi sg	polychrome
_	adj epi pl	polychromes
$
polychromie	S.()
_	nom fem sg	polychromie
_	nom fem pl	polychromies
$
polychromique	S.()
_	adj epi sg	polychromique
_	adj epi pl	polychromiques
$
polycistronique	S.()
_	adj epi sg	polycistronique
_	adj epi pl	polycistroniques
$
polyclinique	S.()
_	nom fem sg	polyclinique
_	nom fem pl	polycliniques
................................................................................
_	nom fem sg	popote
_	nom fem pl	popotes
$
popotin	S.()
_	nom mas sg	popotin
_	nom mas pl	popotins
$
popstar	S.()
_	nom fem sg	popstar
_	nom fem pl	popstars
$
populace	S.()
_	nom fem sg	populace
_	nom fem pl	populaces
$
populacière	F.()
_	adj fem sg	populacière
_	adj fem pl	populacières
................................................................................
_	nom mas sg	poulbot
_	nom mas pl	poulbots
$
poule	S.()
_	nom fem sg	poule
_	nom fem pl	poules
$
poulette	F.()
_	nom fem sg	poulette
_	nom fem pl	poulettes
_	nom mas sg	poulet
_	nom mas pl	poulets
$




pouliage	S.()
_	nom mas sg	pouliage
_	nom mas pl	pouliages
$
pouliche	S.()
_	nom fem sg	pouliche
_	nom fem pl	pouliches
................................................................................
_	adj fem pl	pustuleuses
_	adj mas inv	pustuleux
$
putain	S.()
_	nom fem sg	putain
_	nom fem pl	putains
$
putasserie	S.()
_	nom fem sg	putasserie
_	nom fem pl	putasseries
$
putassière	F.()
_	adj fem sg	putassière
_	adj fem pl	putassières
_	adj mas sg	putassier
_	adj mas pl	putassiers
$
putative	F.()
................................................................................
_	nom fem sg	scélératesse
_	nom fem pl	scélératesses
$
scellage	S.()
_	nom mas sg	scellage
_	nom mas pl	scellages
$
scellé	S.()
_	nom mas sg	scellé
_	nom mas pl	scellés
$
scellement	S.()
_	nom mas sg	scellement
_	nom mas pl	scellements
$
scénarimage	S.()
_	nom mas sg	scénarimage
_	nom mas pl	scénarimages
................................................................................
_	nom fem sg	syringe
_	nom fem pl	syringes
$
syringomyélie	S.()
_	nom fem sg	syringomyélie
_	nom fem pl	syringomyélies
$
syro-libanaise	F.()
_	nom adj fem sg	syro-libanaise
_	nom adj fem pl	syro-libanaises
_	nom adj mas inv	syro-libanais
$
syrphe	S.()
_	nom mas sg	syrphe
_	nom mas pl	syrphes
$
sysadmin	S.()
_	nom epi sg	sysadmin
_	nom epi pl	sysadmins
................................................................................
$
talibane	F.()
_	nom adj fem sg	talibane
_	nom adj fem pl	talibanes
_	nom adj mas sg	taliban
_	nom adj mas pl	talibans
$
talibée	F.()
_	nom fem sg	talibée
_	nom fem pl	talibées
_	nom mas sg	talibé
_	nom mas pl	talibés
$
talion	S.()
_	nom mas sg	talion
_	nom mas pl	talions
$
talisman	S.()
_	nom mas sg	talisman
_	nom mas pl	talismans
................................................................................
_	nom mas sg	vibrion
_	nom mas pl	vibrions
$
vibrisse	S.()
_	nom fem sg	vibrisse
_	nom fem pl	vibrisses
$
vibro	S.()
_	nom mas sg	vibro
_	nom mas pl	vibros
$
vibromasseur	S.()
_	nom mas sg	vibromasseur
_	nom mas pl	vibromasseurs
$
vicaire	S.()
_	nom mas sg	vicaire
_	nom mas pl	vicaires

Modified gc_lang/fr/data/phonet_simil.txt from [8905288c4c] to [acd30a4cca].

1
2









3
4

5



6




7

8



9
10
11
12



13




14

15

16

17
18


19


20
21
22
23
24
25
26
27
28
29
30
31



32
33
34

35

36

37
38
39

40


41
42
43


44
45



46





47
48
49



50

51
52
53
54
55
56
57
58
59

60






61
62
63

64
65
66
67
68

69

70
71

72


73
74



75
76
77
78

79
80
81

82

83



84
85

86

87
88

89

90

91
92
93
94





95
96
97
98
99

100
101

102
103
104
105
106



107
108
109



110
111

112
113
114
115

116
117
118
119
120
121




122
123
124
125

126
127

128
129





130
131

132





133
134
135

136


137
138

139
140

141

142

143
144

145
146

147

148


149


150

151

152
153



154
155
156



157
158
159

160
161
162
163

164
165
166
167
168

169
170
171




172

173
174
175

176
177
178
179
180

181
182
183
184
185


186
187


188

189
190
191
192

193

194
195


196
197

198
199
200

201
202
203
204

205
206



207
208
209
210
211
212
213

214
215
216



217
218
219


220

221
222
223
224
225
226
227
228
229
230




231
232
233
234

235
236

237

238

239
240
241
242
243
244

245
246
247

248

249
250


251

252
253


254
255
256
257

258
259

260

261
262


263

264
265

266
267
268
269
270
271
272
273

274
275

276

277
278


279





280
281

282
283
284





285

286

287
288
289
290
291
292
293

294
295
296
297
298

299
300


301


302

303
304
305
306
307

308
309


310

311


312
313
314
315
316
317
318
319
320
321
322
323
324

325
326
327



328
329
330
331

332
333
334
335




336

337
338
339
340


341
342
343


344
345

346

347
348
349
350
351
352

353
354
355
356
357
358


359


360
361
362
363
364
365
366
367
368
369

370
371
372
373

374


375


376
377

378


379
380

381
382
383
384
385


386



387
388
389



390





391

392
393
394


395
396
397


398
399
400
401


402
403
404







405


406
407

408
409
410

411
412
413
414
415
416
417
418
419

420

421
422
423
424
425





426


427

428
429




430
431



432

433
434



435
436
437
438
439


440


441
442
443
444
445




446
447

448
449
450
451
452

453
454


455

456
457

458
459
460
461
462
463
464

465
466
467

468
469
470


471
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492

493
494




















































































































495
496
497
498
499
500
# Homophonies










a as à ha ah
abaisse abaisses abaissent abbesse abbesses

abord abord abhorre abhorres abhorrent



accueil accueils accueille accueilles accueillent




acre acres âcre âcres

adhérant adhérent adhérents



ai ait aie aies aient ais hé eh es haie haies hais est et
air airs aire aires ère ères hère hères erre erres errent ers haire haires
ail aille ailles aillent aïe
aile ailes elle elles



aller allers allée allées allé allés allez allais allait allaient




amen amène amènes amènent

an ans en

antre antres entre entres entrent

appareil appareils appareille appareilles appareillent
appel appels appelle appelles appellent


appui appuis appuie appuies appuient


archée archées archer archers archet archets
arête arêtes arrête arrêtes arrêtent
assassinat assassinats assassina assassinas assassinât
assignat assignats assigna assignas assignât
assimilat assimilats assimila assimilas assimilât
atèle atèles attelle attelles attellent
attentat attentats attenta attentas attentât
attribut attributs attribue attribues attribuent
au aux ô eau eaux haut hauts
auteur auteurs auteure auteures hauteur hauteurs
avait avais avaient avez avé
aval avals avale avales avalent



bail baille bailles baillent bâille bâilles bâillent bâillent baye bayes bayent
bâillon bâillons baillons bayons
bal bals balle balles

balai balais balaie balaies balaient ballet ballets

bar bars barre barres barrent bard bards

bas bât bâts bah
bassinet bassinets bassiner bassinais bassinait bassinaient bassinez
basilic basilics basilique basiliques

beau beaux baux


beur beurs beurre beurre beurrent
bit bits bite bites bitent bitte bittes bittent
bloc blocs bloque bloques bloquent


bois boit
boîte boîtes boite boite boitent



boss bosse bosses bossent





bourg bourgs bourre bourres bourrent
bous boue boues bout bouts
box boxe boxes boxent



bric brick bricks brique briques briquent

bure bures burent
but buts bute butes butent butte buttes buttent bûtes
cal cals cale cales calent
calcul calculs calcule calcules calculent
camouflet camouflets camoufler camouflais camouflaient camouflez
camp camps quand quant khan khans
cap caps cape capes
cache caches cachent cash
cachet cachets cacher cachais cachait cachaient cachez

cadran cadrans cadrant






caret carets carré carrés carrais carrait carraient carrez
carné carnée carnés carnées carnet carnets
carte cartes cartent kart karts

ce se
céleri céleris sellerie selleries
celle celles sel sels selle selles sellent cèle cèles cèlent scelle scelles scellent
cendre cendres sandre sandres
cène saine saines scène scènes senne sennes sen Seine

centon centons santon santons sentons

cerf cerfs serre serres serrent sers sert serf serfs
ces ses sais sait

cet cette sept set sets


chant chants champ champs
chaud chauds chaux show shows chaut



chic chics chique chiques chiquent
choc chocs choque choques choquent
choix choie choies choient
choral chorals chorale chorales corral corrals

ci si scie scies scient six sis
cilice cilices silice silices
cire cires cirent sire sires cirre cirres cirrhe cirrhes

cite cites citent site sites scythe scythes

clair clairs claire claires clerc clercs



clic clics clique cliques cliquent
cliquet cliquets cliquer cliquais cliquait cliquaient cliquez

coffret coffrets coffrer coffrais coffrait coffraient coffrez

coïncidant coïncident coïncidents
col cols colle colles collent khôl khôls

collet collets coller collais collait collaient collez

combinat combinats combina combinas combinât

comité comités commiter commitais commitait commitaient commitez
commis commit commits commite commites commitent
communicant communicants communiquant
complet complets complais complait complaît





connexion connexions connections
conseil conseils conseille conseilles conseillent
conseiller conseillers conseiller conseillais conseillait conseillaient conseillez
consonne consonnes consone consones consonent
contact contacts contacte contactes contactent

conte contes content compte comptes comptent comte comtes
continu continus continue continues continuent

convaincant convaincants convainquant
convergeant convergent convergents
convoi convois convoie convoies convoient
cool cools coule coules coulent
coq coqs coque coques coke cokes



cote cotes cotent côte côtes cotte cottes
coter coté cotais cotait cotaient côté côtés
cou cous coût coûts coup coups coud couds



couplet couplets coupler couplais couplait couplaient couplez
cour cours court courts coure coures courent courre

crachat crachats cracha crachas crachât
crack cracks craque craques craquent krak kraks crac
créer créé créés créée créées crée crées créent créais créait créaient créez
crème crèmes chrême chrêmes

creuset creusets creuser creusais creusait creusaient creusez
cri cris crie cries crient
cric crics crique criques criquent
criquet criquets criquer criquais criquait criquaient criquez
crochet crochets crocher crochais crochait crochaient crochez
crois croit croient croîs croît croix




cuir cuirs cuire
cumul cumuls cumule cumules cumulent
cumulet cumulets cumuler cumulais cumulait cumulaient cumulez
cygne cygnes signe signes signent

dans dent dents
danse danses dansent dense denses

dé dés dès dais des
deal deals deale deales dealent





défi défis défie défies défient
dégel dégels dégèle dégèles dégèlent

délégant délégants déléguant





dépens dépends dépend
desceller déceler desseller
désir désirs désire désires désirent

détail détails détaille détailles détaillent


diagnostic diagnostics diagnostique diagnostiques diagnostiquent
différant différent différents

dîne dînes dînent dyne dynes
dis dit dît dix

discussion discussions discutions

divergeant divergent divergents

doigt doigts dois doit
don dons dont

doublet doublets doubler doublais doublait doublaient doublez
du dû dus due dues

dialysat dialysats dialysa dialysas dialysât

éclair éclairs éclaire éclaires éclairent


égal égale égales


éjaculat éjaculats éjacula éjaculas éjaculât

élisais élisait élisaient élisez Élysée Élysées

emploi emplois emploie emploies emploient
empreinte empreintes emprunte empruntes empruntent



ennui ennuis ennuie ennuies ennuient
entretien entretiens entretient
entrée entrées entrer entrais entrait entrez entraient



envoi envois envoie envoies envoient
envol envols envole envoles envolent
épais épée épées

équivalant équivalent équivalents
errâmes Éram
essai essais essaie essaies essaient essaye essayes essayent
essor essors essore essores essorent

étai étais était étaient été étés
étain étains éteint éteins
étal étals étale étales étalent
étang étangs étant étends étend
être êtres hêtre hêtres

eusse eusses eussent us
éveil éveils éveille éveilles éveillent
excellant excellent excellents




exsudat exsudats exsuda exsudas exsudât

extravagant extravagants extravaguant
fabriquant fabricant fabricants
face faces fasse fasses fassent fasce fasces

faire fer fers ferre ferres ferrent
faisan faisans faisant
fait faits fée fées
far fard fards phare phares
fatigant fatigants fatiguant

fausse fausses faussent fosses fosses
fausset faussets fossé fossés fausser faussais faussait faussaient faussez
faux faut
faîte faîtes fait faits faite faites fête fêtes fêtent
fèces fesse fesses fessent


feuillet feuillets feuillée feuillées
fi fis fit fît


fief fiefs fieffe fieffes fieffent

fil fils file files filent
filet filets filer filais filait filaient filez
film films filme filmes filment
filtrat filtrats filtra filtras filtrât

fin fins faim faims feins feint

flair flairs flaire flaires flairent
flan flan flanc flancs


flic flics flique fliques fliquent
flou flous floue floues flouent

foi fois foie foies
font fonts fond fonds
forçat forçats força forças forçât

foret forets forer forais forait foraient forêt forêts
format formats forma formas formât
fort forts for fore fores forent fors
fou fous fout

four fours fourre fourres fourrent
fumée fumées fumet fumets fumer fumais fumait fumaient fumez



fus fut fût
futé futés futée futées futaie futaies
gal gals gale gales galle galles
gang gangs gangue gangues
garantie garanties garantis garantit
gaule gaules goal goals
gai gais gaie gaies gay gays gué gués guet guets

gaz gaze gazes gazent
gel gels gèle gèles gèlent
gène gènes gêne gênes gênent



golf golfs golfe golfes golfent
gosse gosses gausse gausses gaussent gauss Gauss
goulet goulets goulée goulées


gré grès

guère guerre guerres
hâle hâles halle halles hall halls
haltère haltères altère altères altèrent
harde hardes arde ardes ardent
hausse hausses haussent os
haute hautes hôte hôtes hotte hotte ôte ôtes ôtent
héro héros héraut hérauts
heur heure heures heurt heurts
hochet hochets hocher hochais hochait hochaient hochez
homme hommes ohm ohms heaume heaumes




hydrolysat hydrolysats hydrolysa hydrolysas hydrolysât
hyène hyènes yen yens
i y
il ils île îles

incarnat incarnats incarna incarnas incarnât
indic indics indique indiques indiquent

infiltrat infiltrats infiltra infiltras infiltrât

institut instituts institue institues instituent

internat internats interna internas internât
intriguant intrigant intrigants
jar jars jard jards jarre jarres
jardinet jardinets jardiner jardinais jardinait jardinaient jardinez
jet jets jette jettes jettent
jeune jeunes jeûne jeûnes jeûnent

joue joues jouent joug jougs
jouer jouais jouait jouaient jouet jouets jouez
kermès kermesse kermesses

la là las

lac lacs laque laques laquent
lacet lacets lacer laçais laçait laçaient lacez lasser lassais lassait lassaient lassez


laîche laîches laiche laîches lèche lèches lèchent

legs lègue lègues lèguent
les laid laids lait laits laie laies lai


levée levées lever levers levais levait levaient levez
lieu lieux lieue lieues
lice lices lisse lisses lissent lys
lis lit lits lie lies lient

lire lires lyre lyres
livret livrets livrer livrais livrait livraient livrez

loch lochs loque loques

loir loirs Loir Loire
loup loups loue loues louent


luth luths luttes luttes luttent lut lute lutes lutent

lyophilisat lyophilisats lyophilisa lyophilisas lyophilisât
ma mas mât mâts

macro macros maquereau maquereaux
magazine magazines magasine magasines magasinent
mai mais mes met mets
main mains maint maints
maintien maintiens maintient
maire maires mer mers mère mères
maison maisons méson mésons
maître maîtres mètre mètres mettre

mal mâle mâles malle malles
mante mantes mente mentes mentent menthe menthes

marais marée marées marrais marrait marraient

marché marchés marcher marchais marchait marchez marchaient
mare mares marre marres marrent marc marcs


mark marks marque marques marquent





mec mecs Mecque
mél mêle mêles mêlent

mess messe messes
meurs meurt mœurs
mi mie mies mis mit mît





mir mirs mire mires mirent myrrhe myrrhes

mite mites mythe mythes

mol mols mole moles molle molles môle môles
mon mont monts
monitorat monitorats monitora monitoras monitorât
mort morts mors mords mord maure maures
mot mots maux
moi mois
mou mous moult moût moûts mouds moud moue moues

mur murs mûr mûrs mûre mûres mure mures murent
muret murets murer murais murait muraient murez
mu mus mû mue mues muent
nais nait nez
navigant navigants naviguant

négligeant négligent négligents
ni nid nids nie nies nient


noix noie noies noient


notre nôtre nôtres

nous noue noues nouent
nui nuis nuit nuits
octroi octrois octroie octroies octroient
œil œils œille œilles œillent
œillet œillets œiller

on ont
or ors hors


ou où houx houe houes hou

oubli oublis oublie oublies oublient


pain pains pin pins peins peint
pair pairs paire paires père pères perds perd pers
paix pet pets paie paies paient
pal pals pale pales pâle pâles
palier paliers pallier palliais palliait palliez palliaient
pan pans pend pends
panse panses pansent pense penses pensent
pansé pansés pansée pansées pensé pensés pensée pensées penser pensais pensait pensaient pensez pansais pensez pansait pansaient
par part parts par pare pares parent pars
parait paraît parais parer parez
parant parent parents
parc parcs parque parques parquent Parque Parques
parquet parquets parquer parquais parquait parquaient parquez

pari paris parie paries parient Paris
parquet parquets parquer parquais parquait parquaient parquez
parti partis partit partie parties



pause pauses pose poses posent
peau peaux pot pots Po Pau
pêche pêches pèche pèches pèchent
péché péchés pêcher pêchers péchais péchait péchaient pêchais pêchait pêchaient

peine peines peinent penne pennes pêne pênes
pèle pèles pèlent pelle pelles pellent
pellet pellets peler pelait pelais pelaient peller pellait pellais pellaient
pensionnat pensionnats pensionna pensionnas pensionnât




peu peux peut

pic pics pique piques piquent
pinson pinsons pinçons
piquer piquais piquait piquaient piqué piqués piquée piquées piquet piquets
pissat pissats pissa pissas pissât


plagiat plagiats plagia plagias plagiât
plaid plaids plaide plaides plaident
plain plains plaint plaints plein pleins


plais plaît plaie plaies
plan plans plant plants

pli plis plie plies plient

police polices policent polisse polisses polissent
poêle poêles poil poils
poignée poignées poignet poignets
poids pois poix pouah
point points poing poings
polissoir polissoirs polissoire polissoires

porc porcs port ports pore pores
pool pools poule poules
post poste postes postent
pou poux pouls
pouf poufs pouffe pouffes pouffent
pouce pouces pousse pousses poussent


précédant précédent précédents


prêt prêts près pré prés
primat primats prima primas primât
prix pris prit prît prie pries prient
profil profils profile profiles profilent
pronostic pronostics pronostique pronostiques pronostiquent
provoc provocs provoque provoques provoquent
provocant provocants provoquant
pu pue pues pus put
puce puces pucent pusse pusses pussent
puis puits

quadruplet quadruplets quadrupler quadruplais quadruplait quadruplaient quadruplez
quintuplet quintuplets quintupler quintuplais quintuplait quintuplaient quintuplez
rappel rappels rappelle rappelles rappellent
racket rackets raquette raquettes rackette rackettes rackettent

raffinat raffinats raffina raffinas raffinât


rail rails raille railles raillent raye rayes rayent


RAM rame rames rament
rauque rauques roc rocs roque roques roquent

recel recels recèle recèles recèlent


recueil recueils recueille recueilles recueillent
recul reculs recule recules reculent

régal régals régale régale régalent
reine reines renne rennes rêne rênes
relai relais relaye relayes relayent
remblai remblais remblaie remblaies remblaient
renvoi renvois renvoie renvoies renvoient


ressenti ressentis ressentit



restaurant restaurants restaurent
résultat résultats résulta résultât
réveil réveils réveille réveilles réveillent



ris rit rient rie ries riz





roue roues rouent roux

sac sacs saque saques saquent
sachet sachets sachez
sacret sacrets sacré sacrés sacrée sacrées sacrer sacrais sacrait sacraient sacrez


salariat salariats salaria salarias salariât
sale sales salent salles salles
salut saluts salue salues saluent


sang sangs sans cent cents sens sent cens
saoul saouls saoule saoules saoulent soûl soûls soûle soûles soûlent soul souls soule soules soulent
saké sakés saquer saquais saquait saquaient saquez
satire satires satyre satyres


saut sauts sot sots sceau sceaux seau seaux
saute sautes sautent sotte sottes
savon savons







sein seins saint saints sain sains ceins ceint ceints


ses ces sais sait
shoot shoots shoote shootes shootent

sifflet sifflets siffler sifflais sifflait sifflaient sifflez
signal signale signales signalent
signet signets signer signais signait signaient signez

soi soie soies soit sois soient
sol sols sole soles saule saules
somme sommes somment
sommeil sommeils sommeille sommeilles sommeillent
sommet sommets sommer sommais sommait sommaient sommez
son sons sont
sonnet sonnets sonner sonnais sonnait sonnaient sonnez
sors sort sorts
sortie sorties sortis sortit

souci soucis soucie soucies soucient

soupir soupirs soupire soupires soupirent
soutien soutiens soutient
soufflet soufflets soufflé soufflés souffler soufflais soufflait soufflaient soufflez
soufre soufres souffre souffres souffrent
souk souks souque souques souquent





stress stresse stresses stressent


substitut substituts substitue substitues substituent

sui suis suit suie suies
su sus sue sues suent




survie survies survis survit
survol survols survole survoles survolent



ta tas

taie taies tes thé thés
tain teint teints thym thyms tin tins tint teins



tant temps tends tend
tante tantes tente tentes tentent
tapir tapirs tapirent
tapis tapit tapît
tare tares tard


teinte teintes teintent tinte tintes tintent


test tests teste testes testent
tête têtes tète tètes tètent
tic tics tique tiques tiquent
tir tirs tire tires tirent
tien tiens tient




toc toque toques toquent
toi toit toits

ton tons thon thons tond tonds
tort torts tore tores taure taures tord tords tors
tournoi tournois tournoie tournoies tournoient
tout toux
tous tousse tousses toussent

trafic trafics trafique trafiques trafiquent
tram trams trame trames trament


travail travaille travailles travaillent

treuil treuils treuille treuilles treuillent
tri tris trie tries trient

triplet triplets tripler triplais triplait triplaient triplez
troc trocs troque troques troquent
troquet troquets troquer troquais troquait troquaient troquez
troll trolls trolle trolles trollent
troller trolley trolleys trollais trollait trollaient trollez
trou trous troue troues trouent
truc trucs truque truques truquent

tu tus tue tues tuent
tutorat tutorats tutora tutoras tutorât
usa usas USA

vacant vacants vaquant
vais vé vés
vain vains vin vins vint vingt vaincs vainc


val vals valent
valet valets valais valait valaient valez vallée vallées

vaux vaut vau veau veaux vos
vent vents vend vends van vans
ver vers verre verres vert verts vair
verrat verrats verra verras
verset versets verser versais versait versaient versez
veule veules veulent
veux veut vœu vœux
vil vils vile viles ville villes
vie vies vis vit
vis vice vices visse visses vissent
viol viols viole violes violent
violant violent violents
violat violats viola violas violât
violet violets violer violais violait violaient violez violé violés violée violées

voix voie voies voient vois voit
voir voire
vol vols vole voles volent
volet volets voler volais volait volaient volez
vomi vomis vomit
vous voue voues vouent

zigzagant zigzagants zigzaguant





















































































































# Construire des liens avec les mots préfixés par une graphie élidée?
# laide laides l’aide l’aides l’aident
# l’ire lire lires lyre lyres
# l’or lors
# dard d’art d’arts
# 


>
>
>
>
>
>
>
>
>


>

>
>
>

>
>
>
>

>

>
>
>
|

|
|
>
>
>
|
>
>
>
>

>

>

>


>
>

>
>










|

>
>
>



>

>

>

|

>

>
>



>
>


>
>
>

>
>
>
>
>



>
>
>

>




|

<

|
>

>
>
>
>
>
>



>





>

>

|
>

>
>


>
>
>




>



>

>

>
>
>

|
>
|
>


>
|
>

>
|



>
>
>
>
>


|


>


>





>
>
>

|
|
>
>
>
|

>

|
|

>
|


|
|
|
>
>
>
>


|

>


>


>
>
>
>
>
|

>

>
>
>
>
>



>

>
>

|
>


>

>

>


>
|
|
>

>

>
>
|
>
>

>

>


>
>
>


|
>
>
>



>




>
|




>



>
>
>
>

>

|

>





>

|



>
>

<
>
>

>
|
|


>

>


>
>


>



>
|



>

<
>
>
>
|






>



>
>
>



>
>

>


<





|

>
>
>
>


|

>


>

>

>



|
|

>

|

>

>

|
>
>

>

<
>
>
|



>

|
>

>


>
>

>


>








>


>

>
|

>
>

>
>
>
>
>


>



>
>
>
>
>

>

>







>

|

|

>


>
>
|
>
>

>





>


>
>

>

>
>




|
|

|

|


|
>

|
|
>
>
>



|
>


|

>
>
>
>

>


|

>
>



>
>
|

>

>


|

|

>






>
>

>
>










>
|
|


>

>
>

>
>


>

>
>


>


|


>
>

>
>
>



>
>
>

>
>
>
>
>

>


|
>
>



>
>


|

>
>



>
>
>
>
>
>
>
|
>
>


>
|

|
>




|

|


>

>


|


>
>
>
>
>

>
>

>

<
>
>
>
>


>
>
>

>
|

>
>
>
|




>
>

>
>



<

>
>
>
>


>





>


>
>

>


>
|

|




>
|


>



>
>


>




|








|
>
|


|


>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
# Homophonies

# Si un verbe du 1ᵉʳ groupe à l’infinitif est présent, toutes ses formes conjuguées homophones seront ajoutées.

# Envisager les automatismes suivants:
# V1: présent 3pl -> nom /adj /3sg (accrochent accroche) (alternent alterne)
# V1: infinitif -> nom pl (boucher bouchers)
# V1: infinitif+imparfait -> nom /ppas (accusée accusées accuser accusés accusez)
# V1: 1pl -> nom (aiguillon aiguillons)
# V2: présent 3sg -> nom /ppas (abrutie abruties abrutis abrutit)

a as à ha ah
abaisse abaisses abaissent abbesse abbesses
aboie aboies aboient abois
abord abord abhorre abhorres abhorrent
ace aces ès esse esses
accès axer
accent accents axant
accueil accueils accueille accueilles accueillent
accro accros accroc accrocs
achat achats hacha hachas
achète achètes achètent hachette hachettes
acier aciers assied assieds
acre acres âcre âcres
action actions axions
adhérant adhérent adhérents
affect affects affecte affectes affectent
affin affins afin
afflue afflues affluent afflux
ai ait aie aies aient ais hé eh es haie haies hais hait est et
air airs aire aires ère ères hère hères erre erres errent ers haire haires
ail aille ailles aillent aïe haï haïe haïs haïes
aile ailes elle elles hèle hèles hèlent
allaiterais allaiterez allaiterait halèterai halèterais halèterait halèteraient halèterez
allaiteras halètera halèteras
allaiterons allaiteront halèterons halèteront
aller allers allée allées
altère altères altèrent haltère haltères
amande amandes amende amendes amendent
amandaie amandaies amender
amanderaie amanderaies amenderais amenderait amenderaient
amen amène amènes amènent
ampli amplis emplis emplit
an ans en
anchois échoient échoit échoie échoient échouas échoua
antre antres entre entres entrent
appas appât appâts happa happas
appareil appareils appareille appareilles appareillent
appel appels appelle appelles appellent
aperçu aperçue aperçues aperçus aperçut
après apprêt apprêts
appui appuis appuie appuies appuient
acquis acquit acquits
ares arrhes art arts
archée archées archer archers archet archets
arête arêtes arrête arrêtes arrêtent
assassinat assassinats assassina assassinas assassinât
assignat assignats assigna assignas assignât
assimilat assimilats assimila assimilas assimilât
atèle atèles attelle attelles attellent
attentat attentats attenta attentas attentât
attribut attributs attribue attribues attribuent
au aux ô eau eaux haut hauts
auteur auteurs auteure auteures hauteur hauteurs
avait avais avaient avez avé haver
aval avals avale avales avalent
bafouillons bafouions
bagage baguage bagages baguages
bai bais baie baies baient bée bées béent
bail baille bailles baillent bâille bâilles bâillent bâillent baye bayes bayent
bâillon bâillons baillons bayons
bal bals balle balles
balade balades baladent ballade ballades
balai balais balaie balaies balaient ballet ballets
banc bancs ban bans
bar bars barre barres barrent bard bards
baron barons barrons
bas bât bâts bah
bassinet bassinets bassiner
basilic basilics basilique basiliques
bâton bâtons battons
beau beaux baux
beignet beignets baigner
bête bêtes bette bettes
beur beurs beurre beurre beurrent
bit bits bite bites bitent bitte bittes bittent
bloc blocs bloque bloques bloquent
blouse blouses blousent blues
bluff bluffs bluffe bluffes bluffent
bois boit
boîte boîtes boite boite boitent
#boot boots boote bootes bootent
bond bonds bon bons
bord bords bore bores
boss bosse bosses bossent
bot bots botte bottes bottent
bouchère bouchères bouchèrent 
bouillie bouillies bouillis bouillit
boulaie boulaies boulet boulets bouler
bouleau bouleaux boulot boulots
bourg bourgs bourre bourres bourrent
bous boue boues bout bouts
box boxe boxes boxent
boycott boycotts boycotte boycottes boycottent
brandy brandys brandis brandit
braquet braquets braquer
bric brick bricks brique briques briquent
brigand brigands briguant
bure bures burent
but buts bute butes butent butte buttes buttent bûtes
cal cals cale cales calent
calcul calculs calcule calcules calculent
camouflet camouflets camoufler
camp camps quand quant khan khans

cache caches cachent cash
cachet cachets cacher
cadi cadis kadi kadis caddie caddies caddy caddys
cadran cadrans cadrant
caftan caftans cafetan cafetans caftant
cahot cahots chaos
cane canes canne cannes Cannes
cantique cantiques quantique quantiques
cap caps cape capes
car cars carre carres carrent quart quarts
caret carets carré carrés carrais carrait carraient carrez
carné carnée carnés carnées carnet carnets
carte cartes cartent kart karts
casher kasher cachèrent
ce se
céleri céleris sellerie selleries
celle celles sel sels selle selles sellent cèle cèles cèlent scelle scelles scellent
cendre cendres sandre sandres
cène saine saines scène scènes senne sennes sen Seine
censé censés censée censées sensé sensés sensée sensées
centon centons santon santons sentons
cep ceps cèpe cèpes
cerf cerfs serre serres serrent sers sert serf serfs
ces ses sais sait saie saies
cessions session sessions
cet cette sept set sets
chaine chaines chainent chaîne chaînes chaînent chêne chênes
chair chairs chaire chaires cher chers chère chères
chant chants champ champs
chaud chauds chaux show shows chaut
chaume chaumes chôme chômes chôment
chas chat chats chah chahs shah shahs schah schahs
cheikh cheikhs chèque chèques
chic chics chique chiques chiquent
choc chocs choque choques choquent
choix choie choies choient
choral chorals chorale chorales corral corrals
chut chute chutes chutent
ci si scie scies scient six sis
cilice cilices silice silices
cire cires cirent sire sires cirre cirres cirrhe cirrhes
ciré cirés cirer scierais scierait scieraient scierez
cite cites citent site sites scythe scythes
cité cités citer
clair clairs claire claires clerc clercs
clam clams clame clames clament
clause clauses close closes closent
clé clés clef clefs
clic clics clique cliques cliquent
cliquet cliquets cliquer
clou clous cloue cloues clouent
coffret coffrets coffrer
coin coins coing coings
coïncidant coïncident coïncidents
col cols colle colles collent khôl khôls
cola colas colla collas kola kolas
collet collets coller
coloris colorie colories colorient
combinat combinats combina combinas combinât
comète comètes commette commettes commettent
comité comités commiter
commis commit commits commite commites commitent
communicant communicants communiquant
complet complets complais complait complaît
compost composts composte compostes compostent
compteur compteurs conteur conteurs
comté comtés compter conter
concours concourt concourent concoures concoures
confie confies confient confis confit confits
connexion connexions connections
conseil conseils conseille conseilles conseillent
conseiller conseillers
consonne consonnes consone consones consonent
contact contacts contacte contactes contactent
#contant content contents comptant comptants
conte contes content compte comptes comptent comte comtes
continu continus continue continues continuent
convaincs convainc convins convint
convaincant convaincants convainquant
convergeant convergent convergents
convoi convois convoie convoies convoient
cool cools coule coules coulent
coq coqs coque coques coke cokes
cor cors corps
coron corons corromps corrompt
corset corsets corser corsé
cote cotes cotent côte côtes cotte cottes
côté côtés coter
cou cous coût coûts cout couts coup coups coud couds
coucher couchers
coule coules coulent cool
coulomb coulombs coulons
couplet couplets coupler
cour cours court courts coure coures courent courre
couvant couvent couvents
crachat crachats cracha crachas crachât
crack cracks craque craques craquent krak kraks crac krach krachs
créer créé créés créée créées crée crées créent
crème crèmes chrême chrêmes
crépi crépis crépit crépît
creuset creusets creuser
cri cris crie cries crient
cric crics crique criques criquent
criquet criquets criquer
crochet crochets crocher
crois croit croient croie croies croîs croît croix
croquet croquets croquer
cross crosse crosses
cru crus crue crues crû crûe crûs crûes crut crût
cuillère cuillères cuiller cuillers
cuir cuirs cuire
cumul cumuls cumule cumules cumulent
cumulet cumulets cumuler
cygne cygnes signe signes signent
dan damne damnes damnent
dans dent dents
danse danses dansent dense denses
date dates datent datte dattes
dé dés dès dais des
deal deals deale deales dealent
déblai déblais déblaie déblaies déblaient
déchu déchue déchues déchus déchut
décolère décolères décolèrent décollèrent
décor décors décore décores décorent
décrue décrues décrus décrut
défi défis défie défies défient défit défît
dégel dégels dégèle dégèles dégèlent
délai délais délaie délaies délaient
délégant délégants déléguant
délit délits délie délies délient
dément déments démens
démente démentes démentent
déni dénis dénie dénies dénient
départ départs dépare dépares déparent
dépens dépends dépend
desceller déceler desseller
désir désirs désire désires désirent
desserre desserres desserrent dessers dessert desserts
détail détails détaille détailles détaillent
dévierai dévierais dévierait dévierez dévirer
devin devins devint devînt
diagnostic diagnostics diagnostique diagnostiques diagnostiquent
différant différent différents différend différends
digest digests digeste digestes
dîne dînes dînent dyne dynes
dis dit dît dix
discours discourt discourent discoure discoures
discussion discussions discutions
dissolu dissolus dissolue dissolues dissolut dissolût
divergeant divergent divergents
dot dots dote dotes dotent
doigt doigts dois doit
don dons dont
dore dores dorent dors dort
doublet doublets doublé doublés doubler
du dû dus due dues dut
dur durs dure dures durent
dialysat dialysats dialysa dialysas dialysât
écho échos écot écots
éclair éclairs éclaire éclaires éclairent
écrie écries écrient écrit écrits écris
écrou écrous écroue écroues écrouent
égal égale égales égalent
égailler égayer
égard égards égare égares égarent
éjaculat éjaculats éjacula éjaculas éjaculât
élan élans hélant
élisais élisait élisaient élisez Élysée Élysées
émir émirs émirent
emploi emplois emploie emploies emploient
empreinte empreintes emprunte empruntes empruntent
ancrage ancrages encrage encrages
en-cours encours encourt encoure encoures encourent
enfer enfers enferre enferres enferrent
ennui ennuis ennuie ennuies ennuient
entretien entretiens entretient
entrée entrées entrer
entrevoie entrevoies entrevois entrevoit entrevoient
envie envies envi envient
envierons envieront environ environs
envoi envois envoie envoies envoient
envol envols envole envoles envolent
épais épée épées
épi épis épie épies épient
équivalant équivalent équivalents
errâmes Éram
essai essais essaie essaies essaient essaye essayes essayent
essor essors essore essores essorent
étagère étagères étagèrent
étai étais était étaient été étés étaie étaies
étain étains éteint éteins
étal étals étale étales étalent
étang étangs étant étends étend
être êtres hêtre hêtres
eu eus eue eues eus eut us eux euh
eusse eusses eussent us
éveil éveils éveille éveilles éveillent
excellant excellent excellents
exclu exclue exclues exclus exclut excluent
exempt exempts exempte exemptes exemptent
exil exils exile exiles exilent
expierai expierais expierait expierez expieraient expirer
exsudat exsudats exsuda exsudas exsudât
extrait extraits extrais extraient extraie extraies 
extravagant extravagants extravaguant
fabricant fabricants fabriquant
face faces fasse fasses fassent fasce fasces
facilité facilités faciliter
faire fer fers ferre ferres ferrent
faisan faisans faisant
fait faits fée fées
far fard fards phare phares
fatigant fatigants fatiguant
faufil faufils faufile faufiles faufilent
fausse fausses faussent fosses fosses
fausset faussets fossé fossés fausser
faux faut
faîte faîtes fait faits faite faites fête fêtes fêtent
fèces fesse fesses fessent
félicité félicités féliciter
ferment ferments fermant fermants
feuillet feuillets feuillée feuillées

fi fie fies fient fis fit fît
fiction fictions fixions
fief fiefs fieffe fieffes fieffent
fier fiers fière fières fièrent
fil fils file files filent fille filles
filet filets filer
film films filme filmes filment
filtrat filtrats filtra filtras filtrât
filtre filtres filtrent philtre philtres
fin fins faim faims feins feint
flamand flamands flamant flamants
flair flairs flaire flaires flairent
flan flan flanc flancs
fleur fleurs fleure fleures fleurent
fleuret fleurets fleurer
flic flics flique fliques fliquent
flou flous floue floues flouent
folio folios foliot foliots
foi fois foie foies
font fonts fond fonds
forçat forçats força forças forçât
forgeron forgerons forgeront
foret forets forer forêt forêts
format formats forma formas formât
fort forts for fore fores forent fors
fou fous fout
foule foules foulent full fulls
four fours fourre fourres fourrent

frai frais fraie fraies fraient fret frets
frêne frênes freine freines freinent
fumée fumées fumé fumet fumets fumer
fus fut fût fûts futs
futé futés futée futées futaie futaies
gal gals gale gales galle galles
gang gangs gangue gangues
garantie garanties garantis garantit
gaule gaules goal goals
gai gais gaie gaies gay gays gué gués guet guets
gaieté gaietés gaîté gaîtés guetter
gaz gaze gazes gazent
gel gels gèle gèles gèlent
gène gènes gêne gênes gênent
genet genets genêt genêts gêner
gin gins jean jeans jinn jinns djinn djinns
glaciaire glaciaires glacière glacières glacèrent
golf golfs golfe golfes golfent
gosse gosses gausse gausses gaussent gauss Gauss
goulet goulets goulée goulées
grâce grâces grasse grasses
granit granits granite granites granitent
gré grès
grill grills gril grils grille grilles grillent
guère guerre guerres
hâle hâles halle halles hall halls

harde hardes arde ardes ardent
hausse hausses haussent os
haute hautes hôte hôtes hotte hotte ôte ôtes ôtent
héro héros héraut hérauts
heur heure heures heurt heurts
hochet hochets hocher
homme hommes ohm ohms heaume heaumes
Hun Huns un uns
hune hunes une unes
hunnique hunniques unique uniques
hutte huttes ut
hydrolysat hydrolysats hydrolysa hydrolysas hydrolysât
hyène hyènes yen yens
i y hie hies
il ils île îles
impair impairs impaire impaires imper impers
incarnat incarnats incarna incarnas incarnât
indic indics indique indiques indiquent
infect infects infecte infectes infectent
infiltrat infiltrats infiltra infiltras infiltrât
influx influe influes influent
institut instituts institue institues instituent
intercession intercessions intersession intersessions
internat internats interna internas internât
intriguant intrigant intrigants
jar jars jard jards jarre jarres
jardinet jardinets jardiner
jet jets jette jettes jettent geai geais jais
jeune jeunes jeûne jeûnes jeûnent
joie joies joua jouas
joue joues jouent joug jougs
jouer jouet jouets
kermès kermesse kermesses
kit kits quitte quittes quittent
la là las
labour labours laboure laboures labourent
lac lacs laque laques laquent
lacet lacets lacer lasser
laïc laïcs laïque laïques
laid laids lait laits laie laies lai les
laîche laîches laiche laîches lèche lèches lèchent
légat légats légua léguas
legs lègue lègues lèguent

lest lests leste lestes lestent
leur leurs leurre leurres leurrent
levée levées lever levers
lieu lieux lieue lieues
lice lices lisse lisses lissent lys
lis lit lits lie lies lient
lisser lissé lissée lissés lissées lycée lycées
lire lires lyre lyres
livret livrets livrer livrée livrée
lob lobs lobe lobes
loch lochs loque loques
loi lois loua louas
loir loirs Loir Loire
loup loups loue loues louent
louerai louerais louerait loueraient louerez lourer
lourd lourds loure loures lourent
luth luths luttes luttes luttent lut lute lutes lutent
lux luxe luxes luxent
lyophilisat lyophilisats lyophilisa lyophilisas lyophilisât
ma mas mât mâts
maçon maçons massons
macro macros maquereau maquereaux
magazine magazines magasine magasines magasinent
mai mais mes met mets
main mains maint maints
maintien maintiens maintient
maire maires mer mers mère mères
maison maisons méson mésons
maître maîtres mètre mètres mettre
major majors majore majores majorent
mal mâle mâles malle malles
mante mantes mente mentes mentent menthe menthes
manteau manteaux mentaux
marais marée marées marrais marrait marraient
marchand marchands marchant
marché marchés marcher
mare mares marre marres marrent marc marcs
marée marées marrer
mari maris marie maries marient Marie marrie marries marri marris
mark marks marque marques marquent
marocain marocains maroquin maroquins
maroquine maroquines maroquinent
martel martèle martèles martèlent
mate mates matent math maths mâte mâtes mâtent mat mats
matinée matinées mâtiner
mec mecs Mecque
mél mêle mêles mêlent
ménager ménagers
mess messe messes
meurs meurt mœurs
mi mie mies mis mit mît
microfilm microfilms microfilme microfilmes microfilment
miction mictions mixions
mime mimes miment
minet minets miner
minerai minerais minerait mineraient minerez
mir mirs mire mires mirent myrrhe myrrhes
mission missions
mite mites mythe mythes
moka mokas moqua moquas
mol mols mole moles molle molles môle môles
mon mont monts
monitorat monitorats monitora monitoras monitorât
mort morts mors mords mord maure maures
mot mots maux
moi mois
mou mous moult moût moûts mouds moud moue moues
muais muait muaient muet muets
mur murs mûr mûrs mûre mûres mure mures murent
muret murets murer
mu mus mû mue mues muent
nais nait nez né née
navigant navigants naviguant
nécessité nécessités nécessiter
négligeant négligent négligents
ni nid nids nie nies nient
niais niait niaient
nô nos
noix noie noies noient noua nouas
nom noms non
nome nomes nomme nommes nomment
notre nôtre nôtres
nourrice nourrices nourrisse nourrisses nourrissent
nous noue noues nouent
nui nuis nuit nuits
octroi octrois octroie octroies octroient
œil œils œille œilles œillent
œillet œillets œiller
oie oies ois oit oient
on ont
or ors hors
#orc orcs orque orques
ornais orner
ou où houx houe houes hou
ouate ouates watt watts
oubli oublis oublie oublies oublient
oui ouï ouïs ouïe ouïes ouïs ouït
pagaie pagaies pagaient pagaïe pagaïes pagaye pagayes pagayent pagaille pagailles
pain pains pin pins peins peint
pair pairs paire paires père pères perds perd pers
paix pet pets paie paies paient
pal pals pale pales pâle pâles
palier paliers pallier
pan pans paon paons pend pends
panse panses pansent pense penses pensent
pensé pensée pensées penser panser
par part parts par pare pares parent pars
parais parait paraît parer
parant parent parents
parc parcs parque parques parquent Parque Parques
parcours parcourt parcourent parcoure parcoures
paresse paresses paressent paraisse paraisses paraissent
pari paris parie paries parient Paris
parquet parquets parquer
parti partis partie parties partit partît
pâté pâtés pâtée pâtées
paume paumes paument pomme pommes pomment
paumier paumiers pommier pommiers paumiez
pause pauses pose poses posent
peau peaux pot pots Po Pau
pêche pêches pèche pèches pèchent
péché péchés pêcher pêchers pécher
peigné peignés peignée peignées peignez peigniez
peine peines peinent penne pennes pêne pênes
pèle pèles pèlent pelle pelles pellent
pellet pellets peler peller
pensionnat pensionnats pensionna pensionnas pensionnât
perce perces percent perse perses
percée percées percer Persée
percheron percherons percheront
pet pets pète pètes pètent
peu peux peut
pi pis pies
pic pics pique piques piquent
pinson pinsons pinçons
piquer piqué piqués piquée piquées piquet piquets
pissat pissats pissa pissas pissât
piton pitons python pythons
placet placets placer
plagiat plagiats plagia plagias plagiât
plaid plaids plaide plaides plaident
plain plains plaint plaints plein pleins
plaine plaines pleine pleines
plainte plaintes plinthe plinthes
plais plaît plait plaie plaies
plan plans plant plants
pleur pleurs pleure pleures pleurent
pli plis plie plies plient
plus plut
police polices policent polisse polisses polissent
poêle poêles poil poils
poignée poignées poignet poignets poignez poignais poignait poignaient
poids pois poix pouah
poins point points poing poings
polissoir polissoirs polissoire polissoires
pont ponts ponds pond
porc porcs port ports pore pores
pool pools poule poules
post poste postes postent
pou poux pouls
pouf poufs pouffe pouffes pouffent
pouce pouces pousse pousses poussent
poule poules pull pulls
pourvoi pourvois pourvoit pourvoient pourvoie pourvoies
précédant précédent précédents
pressant pressants pressens pressent
pressante pressantes pressente pressentes pressentent
prêt prêts près pré prés
primat primats prima primas primât
prix pris prit prît prie pries prient
profil profils profile profiles profilent
pronostic pronostics pronostique pronostiques pronostiquent
provoc provocs provoque provoques provoquent
provocant provocants provoquant
pu pue pues pus put
puce puces pucent pusse pusses pussent
puis puits
quadrillion quadrillions quadrillons
quadruplet quadruplets quadrupler
quintuplet quintuplets quintupler
rappel rappels rappelle rappelles rappellent
racket rackets raquette raquettes rackette rackettes rackettent
radie radies radient radis
raffinat raffinats raffina raffinas raffinât
rai rais raie raies raient
raid raids raide raides
rail rails raille railles raillent raye rayes rayent
rainette rainettes reinette reinettes
rallie rallies rallient rallye rallyes
RAM rame rames rament
rauque rauques roc rocs roque roques roquent
rayon rayons
recel recels recèle recèles recèlent
recours recourt recourent recoure recoures
recrue recrues recrus recrut recrût
recueil recueils recueille recueilles recueillent
recul reculs recule recules reculent
reflux reflue reflues refluent
régal régals régale régale régalent
reine reines renne rennes rêne rênes
relai relais relaie relaies relaient relaye relayes relayent
remblai remblais remblaie remblaies remblaient
renvoi renvois renvoie renvoies renvoient
repaire repaires repère repères repèrent reperds reperd
repli replis replie replies replient
ressenti ressentis ressentit
resserre resserres resserrent ressers ressert
ressors ressort ressorts
résidant résident résidents
restaurant restaurants restaurent
résultat résultats résulta résultât
réveil réveils réveille réveilles réveillent
revive revives revivent
rhum rhums rhume rhumes rom roms ROM Rome
ricochet ricochets ricocher
ris rit rient rie ries riz
rivet rivets river
rock rocks roc rocs roque roques roquent
roder rôder
romps rompt rond ronds
rot rots rôt rôts
roue roues rouent roux
ru rus rue rues ruent
sac sacs saque saques saquent
sachet sachets sachez
sacret sacrets sacré sacrer
saillie saillies saillis saillit saillît
saine saines scène scènes
salariat salariats salaria salarias salariât
sale sales salent salles salles
salut saluts salue salues saluent
saoul saouls soûl soûls saoule saoules saoulent soûle soûles soûlent soul souls
santé santés sentais sentait sentaient sentez
sang sangs sans cent cents sens sent cens
saoul saouls saoule saoules saoulent soûl soûls soûle soûles soûlent soul souls soule soules soulent
saké sakés saquer
satire satires satyre satyres
satirique satiriques satyrique satyriques
saurez saurer
saut sauts sot sots sceau sceaux seau seaux
saute sautes sautent sotte sottes
savon savons
scier sied siéent seyait seyaient siée siéent
scieur scieurs sieur sieurs
script scripts scripte scriptes scriptent
sèche sèches sèchent seiche seiches
secours secourt secourent secoure secoures
secouerai secouerais secouerait secouraient secouerez secourais secourait secouraient secourez secourrai secourrais secourrait secourraient secourrez
secouerons secoueront secourons secourrons secourront
sein seins saint saints sain sains ceins ceint ceints seing seings
serein sereins serin serins
serment serments serrement serrements
ses ces sais sait
shoot shoots shoote shootes shootent
si sis scie scies scient
sifflet sifflets siffler
signal signale signales signalent
signet signets signer
ski skis skie skies skient
soi soie soies soit sois soient
sol sols sole soles saule saules
somme sommes somment
sommeil sommeils sommeille sommeilles sommeillent
sommet sommets sommer
son sons sont
sonnet sonnets sonner
sors sort sorts
sortie sorties sortis sortit
sou sous soue soues
souci soucis soucie soucies soucient
souper soupers sous-paie sous-paies sous-paient
soupir soupirs soupire soupires soupirent
soutien soutiens soutient
soufflet soufflets soufflé soufflés souffler
soufre soufres souffre souffres souffrent
souk souks souque souques souquent
souris sourit sourient sourie souries
sprint sprints sprinte sprintes sprintent
statue statues statuent statut statuts status
stock stocks stocke stockes stockent
stop stops stoppe stoppes stoppent
stress stresse stresses stressent
su sus sue sues sut suent
subis subit subits
substitut substituts substitue substitues substituent
suce suces sucent susse susses sussent
sui suis suit suie suies

suffocant suffocants suffoquant
sur surs sure sures sûr sûre sûrs sûres surent
surf surfs surfe surfes surfent
surfait surfaits surfer
survie survies survis survit
survol survols survole survoles survolent
suspens suspends suspend
syndic syndics syndique syndiques syndiquent
syndicat syndicats syndiqua syndiquas
ta tas
tache taches tâche tâches tâchent
taie taies tes thé thés tais tait
tain teint teints thym thyms tin tins tint teins
taira tairas terra terras
taire ter terre terres terrent
taise taises taisent thèse thèses
tant temps tends tend taon taons
tante tantes tente tentes tentent
tapir tapirs tapirent
tapis tapit tapît
tare tares tard
tarif tarifs tarife tarifes tarifent
taule taules tôle tôles
teinte teintes teintent tinte tintes tintent
tendron tendrons tendront
terme termes thermes
test tests teste testes testent
tête têtes tète tètes tètent
tic tics tique tiques tiquent

tien tiens tient
tir tirs tire tires tirent
tiret tirets tirais tirait tiraient
tirant tyran tyrans
toast toasts toaste toastes toastent
toc toque toques toquent
toi toit toits
tome tomme tomes tommes
ton tons thon thons tond tonds
tort torts tore tores taure taures tord tords tors
tournoi tournois tournoie tournoies tournoient
tout toux
tous tousse tousses toussent
tract tracts tracte tractes tractent
trafic trafics trafique trafiques trafiquent
tram trams trame trames trament
transfert transferts transfère transfères transfèrent
transit transits transite transites transitent
travail travaille travailles travaillent
très trait traits trais traie traies traient
treuil treuils treuille treuilles treuillent
tri tris trie tries trient
tribu tribus tribut tributs
triplet triplets tripler
troc trocs troque troques troquent
troquet troquets troquer
troll trolls trolle trolles trollent
troller trolley trolleys trollais trollait trollaient trollez
trou trous troue troues trouent
truc trucs truque truques truquent
trust trusts truste trustes trustent
tu tus tue tues tuent tut
tutorat tutorats tutora tutoras tutorât
usa usas USA
usager usagers usagé usagée usagés usagées
vacant vacants vaquant
vais vé vés
vain vains vin vins vint vingt vaincs vainc
vaine vaines veine veines viennes
vairon vairons verrons verront
val vals valent
valet valets valais valait valaient valez vallée vallées
vallon vallons valons
vaux vaut vau veau veaux vos
vent vents vend vends van vans
ver vers verre verres vert verts vair
verrat verrats verra verras
verset versets verser
veule veules veulent
veux veut vœu vœux
vil vils vile viles ville villes
vie vies vis vit
vis vice vices visse visses vissent
viol viols viole violes violent
violant violent violents
violat violats viola violas violât
violet violets violer violé violés violée violées
vicier vissiez
voix voie voies voient vois voit voua vouas
voir voire
vol vols vole voles volent
volet volets voler volée volées
vomi vomis vomit
vous voue voues vouent
zigzag zigzags zigzague zigzagues zigzaguent
zigzagant zigzagants zigzaguant

# verbes semblables
ancrer encrer
exaucer exhausser
détoner détonner
différencier différentier
#goûter goutter (+ goûter(s))
#lacer lasser (+ lacet)
#panser penser (+ pensée)
#pêcher pécher (+ péché)
#teinter tinter (+ teinte)
#celer sceller seller (+ scellé)
#vanter venter (+ vente)

# confusion -aire -èrent
alimentaire alimentaires alimentèrent
arbitraire arbitraires arbitrèrent
argumentaire argumentaires argumentèrent
articulaire articulaires articulèrent
bénéficiaire bénéficiaires bénéficièrent
calcaire calcaires calquèrent
capitulaire capitulaires capitulèrent
circulaire circulaires circulèrent
commentaire commentaires commentèrent
contraire contraires contrèrent
corsaire corsaires corsèrent
disciplinaire disciplinaires disciplinèrent
dispensaire dispensaires dispensèrent
démissionnaire démissionnaires démissionnèrent
filaire filaires filèrent
fonctionnaire fonctionnaires fonctionnèrent
formulaire formulaires formulèrent
hypothécaire hypothécaires hypothéquèrent
imaginaire imaginaires imaginèrent
intercalaire intercalaires intercalèrent
inventaire inventaires inventèrent
jugulaire jugulaires jugulèrent
mandataire mandataires mandatèrent
militaire militaires militèrent
modulaire modulaires modulèrent
notaire notaires notèrent
parasitaire parasitaires parasitèrent
plagiaire plagiaires plagièrent
plantaire plantaires plantèrent
primaire primaires primèrent
questionnaire questionnaires questionnèrent
révolutionnaire révolutionnaires révolutionnèrent
salaire salaires salèrent
sommaire sommaires sommèrent
soumissionnaire soumissionnaires soumissionnèrent
stationnaire stationnaires stationnèrent
suicidaire suicidaires suicidèrent
tambourinaire tambourinaires tambourinèrent
tarifaire tarifaires tarifèrent
véhiculaire véhiculaires véhiculèrent

# confusions -ier -iez
amandier amandiers amendiez
aventurier aventuriers aventuriez
balancier balanciers balanciez
bombardier bombardiers bombardiez
bouclier boucliers boucliez
boitier boitiers boîtier boîtiers boitiez
cantonnier cantonniers cantonniez
carrossier carrossiers carrossiez
cellier celliers scelliez
chantier chantiers chantiez
charcutier charcutiers charcutiez
chicanier chicaniers chicaniez
chiffonnier chiffonniers chiffonniez
collier colliers colliez
coudrier coudriers coudriez
cuirassier cuirassiers cuirassiez
cuisinier cuisiniers cuisiniez
câblier câbliers câbliez
drapier drapiers drapiez
encrier encriers encriez
fichier fichiers fichiez
financier financiers financiez
foncier fonciers fonciez
fourrier fourriers fourriez
fumier fumiers fumiez
gravier graviers graviez
grimacier grimaciers grimaciez
huilier huiliers huiliez
héritier héritiers héritiez
infirmier infirmiers infirmiez
jardinier jardiniers jardiniez
levier leviers leviez
limier limiers limiez
luthier luthiers luttiez
manufacturier manufacturiers manufacturiez
mûrier mûriers muriez
nourricier nourriciers nourrissiez
ouvrier ouvriers ouvriez
peuplier peupliers peupliez
pilier piliers piliez
placier placiers placiez
plombier plombiers plombiez
poivrier poivriers poivriez
pompier pompiers pompiez
portier portiers portiez
postier postiers postiez
préfacier préfaciers préfaciez
pédalier pédaliers pédaliez
ramier ramiers ramiez
routier routiers routiez
sentier sentiers sentiez
sommier sommiers sommiez
tablier tabliers tabliez
terrassier terrassiers terrassiez
terrier terriers terriez
verrier verriers verriez
vivier viviers viviez
vivrier vivriers vivriez


# Construire des liens avec les mots préfixés par une graphie élidée?
# laide laides l’aide l’aides l’aident
# l’ire lire lires lyre lyres
# l’or lors
# dard d’art d’arts
# 

Modified gc_lang/fr/dictionnaire/orthographe/FRANCAIS.dic from [3873c50f49] to [65d5c1566b].

more than 10,000 changes

Modified gc_lang/fr/modules-js/conj.js from [55db24a585] to [fdb0ca6eac].

1
2


3
4
5
6
7
8
9

10
11


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36


37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76


77
78
79
80
81
82

83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132


133

134
135
136
137
138

139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293
294
295
296
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
480
481
482
483
484
485
486
487





















488
489
490




491











492
493
494
495
496
497
498
499



500
// Grammalecte - Conjugueur
// License: GPL 3



"use strict";

${map}


let helpers = null; // module not loaded in Firefox content script


let _oData = {};


let _lVtyp = null;
let _lTags = null;
let _dPatternConj = {};
let _dVerb = {};


if (typeof(exports) !== 'undefined') {
    // used within Grammalecte library
    helpers = require("resource://grammalecte/helpers.js");
    _oData = JSON.parse(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
    _lVtyp = _oData.lVtyp;
    _lTags = _oData.lTags;
    _dPatternConj = _oData.dPatternConj;
    _dVerb = _oData.dVerb;
} else {
    // used within Firefox content script (conjugation panel).
    // can’t load JSON from here, so we do it in ui.js and send it here.
    self.port.on("provideConjData", function (sData) {
        _oData = JSON.parse(sData);
        _lVtyp = _oData.lVtyp;
        _lTags = _oData.lTags;
        _dPatternConj = _oData.dPatternConj;
        _dVerb = _oData.dVerb;
    });

}





const _zStartVoy = new RegExp("^[aeéiouœê]");
const _zNeedTeuph = new RegExp("[tdc]$");

const _dProSuj = new Map ([ [":1s", "je"], [":1ś", "je"], [":2s", "tu"], [":3s", "il"], [":1p", "nous"], [":2p", "vous"], [":3p", "ils"] ]);
const _dProObj = new Map ([ [":1s", "me "], [":1ś", "me "], [":2s", "te "], [":3s", "se "], [":1p", "nous "], [":2p", "vous "], [":3p", "se "] ]);
const _dProObjEl = new Map ([ [":1s", "m’"], [":1ś", "m’"], [":2s", "t’"], [":3s", "s’"], [":1p", "nous "], [":2p", "vous "], [":3p", "s’"] ]);
const _dImpePro = new Map ([ [":2s", "-toi"], [":1p", "-nous"], [":2p", "-vous"] ]);
const _dImpeProNeg = new Map ([ [":2s", "ne te "], [":1p", "ne nous "], [":2p", "ne vous "] ]);
const _dImpeProEn = new Map ([ [":2s", "-t’en"], [":1p", "-nous-en"], [":2p", "-vous-en"] ]);
const _dImpeProNegEn = new Map ([ [":2s", "ne t’en "], [":1p", "ne nous en "], [":2p", "ne vous en "] ]);

const _dGroup = new Map ([ ["0", "auxiliaire"], ["1", "1ᵉʳ groupe"], ["2", "2ᵉ groupe"], ["3", "3ᵉ groupe"] ]);

const _dTenseIdx = new Map ([ [":PQ", 0], [":Ip", 1], [":Iq", 2], [":Is", 3], [":If", 4], [":K", 5], [":Sp", 6], [":Sq", 7], [":E", 8] ]);


function isVerb (sVerb) {

    return _dVerb.hasOwnProperty(sVerb);
}

function getConj (sVerb, sTense, sWho) {
    // returns conjugation (can be an empty string)
    if (!_dVerb.hasOwnProperty(sVerb)) {
        return null;
    }
    if (!_dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx.get(sTense)]].hasOwnProperty(sWho)) {
        return "";
    }
    return _modifyStringWithSuffixCode(sVerb, _dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx.get(sTense)]][sWho]);

}

function hasConj (sVerb, sTense, sWho) {
    // returns false if no conjugation (also if empty) else true
    if (!_dVerb.hasOwnProperty(sVerb)) {
        return false;
    }
    if (_dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx.get(sTense)]].hasOwnProperty(sWho)
            && _dPatternConj[sTense][_lTags[_dVerb[sVerb][1]][_dTenseIdx.get(sTense)]][sWho]) {


        return true;
    }
    return false;
}

function getVtyp (sVerb) {

    // returns raw informations about sVerb
    if (!_dVerb.hasOwnProperty(sVerb)) {
        return null;
    }
    return _lVtyp[_dVerb[sVerb][0]];
}

function getSimil (sWord, sMorph) {

    if (!sMorph.includes(":V")) {
        return new Set();
    }
    let sInfi = sMorph.slice(1, sMorph.indexOf(" "));
    let tTags = _getTags(sInfi);
    let aSugg = new Set();
    if (sMorph.includes(":Q")) {
        // we suggest conjugated forms
        if (sMorph.includes(":V1")) {
            aSugg.add(sInfi);
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":1s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3p"));
        } else if (sMorph.includes(":V2")) {
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":1s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
        } else if (sMorph.includes(":V3")) {
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":1s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":1s"));
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":3s"));
        } else if (isMorph.includes(":V0a")) {
            aSugg.add("eus");
            aSugg.add("eut");
        } else {
            aSugg.add("étais");
            aSugg.add("était");
        }
        aSugg.delete("");
    } else {
        // we suggest past participles
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q1"));
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q2"));
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q3"));
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"));
        aSugg.delete("");
        // if there is only one past participle (epi inv), unreliable.
        if (aSugg.size === 1) {
            aSugg.clear();
        }


    }

    return aSugg;
}


function _getTags (sVerb) {

    // returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)
    if (!_dVerb.hasOwnProperty(sVerb)) {
        return null;
    }
    return _lTags[_dVerb[sVerb][1]];
}

function _getConjWithTags (sVerb, tTags, sTense, sWho) {
    // returns conjugation (can be an empty string)
    if (!_dPatternConj[sTense][tTags[_dTenseIdx.get(sTense)]].hasOwnProperty(sWho)) {
        return "";
    }
    return _modifyStringWithSuffixCode(sVerb, _dPatternConj[sTense][tTags[_dTenseIdx.get(sTense)]][sWho]);

}

function _hasConjWithTags (tTags, sTense, sWho) {
    // returns false if no conjugation (also if empty) else true
    if (_dPatternConj[sTense][tTags[_dTenseIdx.get(sTense)]].hasOwnProperty(sWho)
            && _dPatternConj[sTense][tTags[_dTenseIdx.get(sTense)]][sWho]) {
        return true;
    }
    return false;
}

function _modifyStringWithSuffixCode (sWord, sSfx) {
    // returns sWord modified by sSfx
    if (sSfx === "") {
        return "";
    }
    if (sSfx === "0") {
        return sWord;
    }
    try {
        if (sSfx[0] !== '0') {
            return sWord.slice(0, -(sSfx.charCodeAt(0)-48)) + sSfx.slice(1); // 48 is the ASCII code for "0"
        } else {
            return sWord + sSfx.slice(1);
        }
    }
    catch (e) {
        console.log(e);
        return "## erreur, code : " + sSfx + " ##";
    }
}



class Verb {

    constructor (sVerb) {
        if (typeof sVerb !== "string" || sVerb === "") {
            throw new TypeError ("The value should be a non-empty string");
        }
        this.sVerb = sVerb;
        this.sVerbAux = "";
        this._sRawInfo = getVtyp(this.sVerb);
        this.sInfo = this._readableInfo(this._sRawInfo);
        this._tTags = _getTags(sVerb);
        this._tTagsAux = _getTags(this.sVerbAux);
        this.bProWithEn = (this._sRawInfo[5] === "e");
        this.dConj = new Map ([
            [":Y", new Map ([
                ["label", "Infinitif"],
                [":Y", sVerb]
            ])],
            [":PQ", new Map ([
                ["label", "Participes passés et présent"],
                [":Q1", _getConjWithTags(sVerb, this._tTags, ":PQ", ":Q1")],
                [":Q2", _getConjWithTags(sVerb, this._tTags, ":PQ", ":Q2")],
                [":Q3", _getConjWithTags(sVerb, this._tTags, ":PQ", ":Q3")],
                [":Q4", _getConjWithTags(sVerb, this._tTags, ":PQ", ":Q4")],
                [":P", _getConjWithTags(sVerb, this._tTags, ":PQ", ":P")]
            ])],
            [":Ip", new Map ([
                ["label", "Présent"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":Ip", ":1s")],
                [":1ś", _getConjWithTags(sVerb, this._tTags, ":Ip", ":1ś")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":Ip", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":Ip", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":Ip", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":Ip", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":Ip", ":3p")]
            ])],
            [":Iq", new Map ([
                ["label", "Imparfait"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":Iq", ":1s")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":Iq", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":Iq", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":Iq", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":Iq", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":Iq", ":3p")]
            ])],
            [":Is", new Map ([
                ["label", "Passé simple"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":Is", ":1s")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":Is", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":Is", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":Is", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":Is", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":Is", ":3p")]
            ])],
            [":If", new Map ([
                ["label", "Futur"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":If", ":1s")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":If", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":If", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":If", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":If", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":If", ":3p")]
            ])],
            [":Sp", new Map ([
                ["label", "Présent subjonctif"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":Sp", ":1s")],
                [":1ś", _getConjWithTags(sVerb, this._tTags, ":Sp", ":1ś")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":Sp", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":Sp", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":Sp", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":Sp", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":Sp", ":3p")]
            ])],
            [":Sq", new Map ([
                ["label", "Imparfait subjonctif"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":Sq", ":1s")],
                [":1ś", _getConjWithTags(sVerb, this._tTags, ":Sq", ":1ś")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":Sq", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":Sq", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":Sq", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":Sq", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":Sq", ":3p")]
            ])],
            [":K", new Map ([
                ["label", "Conditionnel"],
                [":1s", _getConjWithTags(sVerb, this._tTags, ":K", ":1s")],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":K", ":2s")],
                [":3s", _getConjWithTags(sVerb, this._tTags, ":K", ":3s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":K", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":K", ":2p")],
                [":3p", _getConjWithTags(sVerb, this._tTags, ":K", ":3p")]
            ])],
            [":E", new Map ([
                ["label", "Impératif"],
                [":2s", _getConjWithTags(sVerb, this._tTags, ":E", ":2s")],
                [":1p", _getConjWithTags(sVerb, this._tTags, ":E", ":1p")],
                [":2p", _getConjWithTags(sVerb, this._tTags, ":E", ":2p")]
            ])]
        ]);
    };


    _readableInfo () {
        // returns readable infos
        this.sVerbAux = (this._sRawInfo.slice(7,8) == "e") ? "être" : "avoir";
        let sGroup = _dGroup.get(this._sRawInfo[0]);
        let sInfo = "";
        if (this._sRawInfo.slice(3,4) == "t") {
            sInfo = "transitif";
        } else if (this._sRawInfo.slice(4,5) == "n") {
            sInfo = "transitif indirect";
        } else if (this._sRawInfo.slice(2,3) == "i") {
            sInfo = "intransitif";
................................................................................
        if (this._sRawInfo.slice(6,7) == "m") {
            sInfo = sInfo + " impersonnel";
        }
        if (sInfo === "") {
            sInfo = "# erreur - code : " + this._sRawInfo;
        }
        return sGroup + " · " + sInfo;
    };

    infinitif (bPro, bNeg, bTpsCo, bInt, bFem) {
        let sInfi;
        if (bTpsCo) {
            sInfi = (bPro) ? "être" : this.sVerbAux;
        } else {
            sInfi = this.sVerb;
        }
        if (bPro) {
            if (this.bProWithEn) {
                sInfi = "s’en " + sInfi;
            } else {
                sInfi = (_zStartVoy.test(sInfi)) ? "s’" + sInfi : "se " + sInfi;
            }
        }
        if (bNeg) {
            sInfi = "ne pas " + sInfi;
        }
        if (bTpsCo) {
            sInfi += " " + this._seekPpas(bPro, bFem, (this._sRawInfo[5] == "r"));
        }
        if (bInt) {
            sInfi += " … ?";
        }
        return sInfi;
    };

    participePasse (sWho) {
        return this.dConj.get(":PQ").get(sWho);
    };

    participePresent (bPro, bNeg, bTpsCo, bInt, bFem) {
        if (!this.dConj.get(":PQ").get(":P")) {
            return "";
        }
        let sPartPre;
        if (bTpsCo) {
            sPartPre = (!bPro) ? _getConjWithTags(this.sVerbAux, this._tTagsAux, ":PQ", ":P") : getConj("être", ":PQ", ":P");
        } else {
            sPartPre = this.dConj.get(":PQ").get(":P");
        }
        if (sPartPre === "") {
            return "";
        }
        let bEli = _zStartVoy.test(sPartPre);
        if (bPro) {
            if (this.bProWithEn) {
                sPartPre = "s’en " + sPartPre;
            } else {
                sPartPre = (bEli) ? "s’" + sPartPre : "se " + sPartPre;
            }
        }
................................................................................
        if (bTpsCo) {
            sPartPre += " " + this._seekPpas(bPro, bFem, this._sRawInfo[5] == "r");
        }
        if (bInt) {
            sPartPre += " … ?";
        }
        return sPartPre;
    };

    conjugue (sTemps, sWho, bPro, bNeg, bTpsCo, bInt, bFem) {
        if (!this.dConj.get(sTemps).get(sWho)) {
            return "";
        }
        let sConj;
        if (!bTpsCo && bInt && sWho == ":1s" && this.dConj.get(sTemps)._get(":1ś", false)) {
            sWho = ":1ś";
        }
        if (bTpsCo) {
            sConj = (!bPro) ? _getConjWithTags(this.sVerbAux, this._tTagsAux, sTemps, sWho) : getConj("être", sTemps, sWho);
        } else {
            sConj = this.dConj.get(sTemps).get(sWho);
        }
        if (sConj === "") {
            return "";
        }
        let bEli = _zStartVoy.test(sConj);
        if (bPro) {
            if (!this.bProWithEn) {
                sConj = (bEli) ? _dProObjEl.get(sWho) + sConj : _dProObj.get(sWho) + sConj;
            } else {
                sConj = _dProObjEl.get(sWho) + "en " + sConj;
            }
        }
        if (bNeg) {
            sConj = (bEli && !bPro) ? "n’" + sConj : "ne " + sConj;
        }
        if (bInt) {
            if (sWho == ":3s" && !_zNeedTeuph.test(sConj)) {
                sConj += "-t";
            }
            sConj += "-" + this._getPronom(sWho, bFem);
        } else {
            if (sWho == ":1s" && bEli && !bNeg && !bPro) {
                sConj = "j’" + sConj;
            } else {
................................................................................
        if (bTpsCo) {
            sConj += " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
        }
        if (bInt) {
            sConj += " … ?";
        }
        return sConj;
    };

    _getPronom (sWho, bFem) {
        if (sWho == ":3s") {
            if (this._sRawInfo[5] == "r") {
                return "on";
            } else if (bFem) {
                return "elle";
            }
        } else if (sWho == ":3p" && bFem) {
            return "elles";
        }
        return _dProSuj.get(sWho);
    };

    imperatif (sWho, bPro, bNeg, bTpsCo, bFem) {
        if (!this.dConj.get(":E").get(sWho)) {
            return "";
        }
        let sImpe;
        if (bTpsCo) {
            sImpe = (!bPro) ? _getConjWithTags(this.sVerbAux, this._tTagsAux, ":E", sWho) : getConj("être", ":E", sWho);
        } else {
            sImpe = this.dConj.get(":E").get(sWho);
        }
        if (sImpe === "") {
            return "";
        }
        let bEli = _zStartVoy.test(sImpe);
        if (bNeg) {
            if (bPro) {
                if (!this.bProWithEn) {
                    sImpe = (bEli && sWho == ":2s") ? "ne t’" + sImpe + " pas" : _dImpeProNeg.get(sWho) + sImpe + " pas";
                } else {
                    sImpe = _dImpeProNegEn.get(sWho) + sImpe + " pas";
                }
            } else {
                sImpe = (bEli) ? "n’" + sImpe + " pas" : "ne " + sImpe + " pas";
            }
        } else if (bPro) {
            sImpe = (this.bProWithEn) ? sImpe + _dImpeProEn.get(sWho) : sImpe + _dImpePro.get(sWho);
        }
        if (bTpsCo) {
            return sImpe + " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
        }
        return sImpe;
    };

    _seekPpas (bPro, bFem, bPlur) {
        if (!bPro && this.sVerbAux == "avoir") {
            return this.dConj.get(":PQ").get(":Q1");
        }
        if (!bFem) {
            return (bPlur && this.dConj.get(":PQ").get(":Q2")) ? this.dConj.get(":PQ").get(":Q2") : this.dConj.get(":PQ").get(":Q1");
................................................................................
        }
        if (!bPlur) {
            return (this.dConj.get(":PQ").get(":Q3")) ? this.dConj.get(":PQ").get(":Q3") : this.dConj.get(":PQ").get(":Q1");
        }
        return (this.dConj.get(":PQ").get(":Q4")) ? this.dConj.get(":PQ").get(":Q4") : this.dConj.get(":PQ").get(":Q1");
    }
}






















if (typeof(exports) !== 'undefined') {
    // Used for Grammalecte library.
    // In content scripts, these variable are directly reachable




    exports.Verb = Verb;











    exports.isVerb = isVerb;
    exports.getConj = getConj;
    exports.hasConj = hasConj;
    exports.getVtyp = getVtyp;
    exports.getSimil = getSimil;
    exports._getTags = _getTags;
    exports._hasConjWithTags = _hasConjWithTags;
    exports._getConjWithTags = _getConjWithTags;



}


>
>






|
>
|
<
>
>
|
|
|
|

<
<
|
|
|
<
<
<
<
<
<
<
<
|
|
|
|
|
<
>
|
>
>
|
>

|
|

|
|
|
|
|
|
|

|

|

<
<
>
|
|

|
|
|
|
|
|
|
|
<
>
|

|
|
|
|
|
<
<
>
>
|
|
|
|

<
>
|
|
|
|
|
|

<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
|
|

<
<
>
|
|
|
|
|
|

|
|
|
|
|
<
>
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>










|

|
|








|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|



|
|
|
|
|
|



|
|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|



|
|
|


<
>




|







 







|












|












|



|







|






|







 







|






|



|






|


|

|






|







 







|











|
|







|






|



|

|





|





|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
<
|
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20


21
22
23








24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50


51
52
53
54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70


71
72
73
74
75
76
77

78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135


136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
294
295
...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508


509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
// Grammalecte - Conjugueur
// License: GPL 3
/*jslint esversion: 6*/
/*global console,require,exports,self,browser*/

"use strict";

${map}


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
}


var conj = {
    _lVtyp: [],
    _lTags: [],
    _dPatternConj: {},
    _dVerb: {},



    bInit: false,
    init: function (sJSONData) {
        try {








            let _oData = JSON.parse(sJSONData);
            this._lVtyp = _oData.lVtyp;
            this._lTags = _oData.lTags;
            this._dPatternConj = _oData.dPatternConj;
            this._dVerb = _oData.dVerb;

            this.bInit = true;
        }
        catch (e) {
            console.error(e);
        }
    },

    _zStartVoy: new RegExp("^[aeéiouœê]"),
    _zNeedTeuph: new RegExp("[tdc]$"),

    _dProSuj: new Map ([ [":1s", "je"], [":1ś", "je"], [":2s", "tu"], [":3s", "il"], [":1p", "nous"], [":2p", "vous"], [":3p", "ils"] ]),
    _dProObj: new Map ([ [":1s", "me "], [":1ś", "me "], [":2s", "te "], [":3s", "se "], [":1p", "nous "], [":2p", "vous "], [":3p", "se "] ]),
    _dProObjEl: new Map ([ [":1s", "m’"], [":1ś", "m’"], [":2s", "t’"], [":3s", "s’"], [":1p", "nous "], [":2p", "vous "], [":3p", "s’"] ]),
    _dImpePro: new Map ([ [":2s", "-toi"], [":1p", "-nous"], [":2p", "-vous"] ]),
    _dImpeProNeg: new Map ([ [":2s", "ne te "], [":1p", "ne nous "], [":2p", "ne vous "] ]),
    _dImpeProEn: new Map ([ [":2s", "-t’en"], [":1p", "-nous-en"], [":2p", "-vous-en"] ]),
    _dImpeProNegEn: new Map ([ [":2s", "ne t’en "], [":1p", "ne nous en "], [":2p", "ne vous en "] ]),

    _dGroup: new Map ([ ["0", "auxiliaire"], ["1", "1ᵉʳ groupe"], ["2", "2ᵉ groupe"], ["3", "3ᵉ groupe"] ]),

    _dTenseIdx: new Map ([ [":PQ", 0], [":Ip", 1], [":Iq", 2], [":Is", 3], [":If", 4], [":K", 5], [":Sp", 6], [":Sq", 7], [":E", 8] ]),



    isVerb: function (sVerb) {
        return this._dVerb.hasOwnProperty(sVerb);
    },

    getConj: function (sVerb, sTense, sWho) {
        // returns conjugation (can be an empty string)
        if (!this._dVerb.hasOwnProperty(sVerb)) {
            return null;
        }
        if (!this._dPatternConj[sTense][this._lTags[this._dVerb[sVerb][1]][this._dTenseIdx.get(sTense)]].hasOwnProperty(sWho)) {
            return "";
        }

        return this._modifyStringWithSuffixCode(sVerb, this._dPatternConj[sTense][this._lTags[this._dVerb[sVerb][1]][this._dTenseIdx.get(sTense)]][sWho]);
    },

    hasConj: function (sVerb, sTense, sWho) {
        // returns false if no conjugation (also if empty) else true
        if (!this._dVerb.hasOwnProperty(sVerb)) {
            return false;
        }


        if (this._dPatternConj[sTense][this._lTags[this._dVerb[sVerb][1]][this._dTenseIdx.get(sTense)]].hasOwnProperty(sWho)
                && this._dPatternConj[sTense][this._lTags[this._dVerb[sVerb][1]][this._dTenseIdx.get(sTense)]][sWho]) {
            return true;
        }
        return false;
    },


    getVtyp: function (sVerb) {
        // returns raw informations about sVerb
        if (!this._dVerb.hasOwnProperty(sVerb)) {
            return null;
        }
        return this._lVtyp[this._dVerb[sVerb][0]];
    },


    getSimil: function (sWord, sMorph, sFilter=null) {
        if (!sMorph.includes(":V")) {
            return new Set();
        }
        let sInfi = sMorph.slice(1, sMorph.indexOf(" "));
        let tTags = this._getTags(sInfi);
        let aSugg = new Set();
        if (sMorph.includes(":Q") || sMorph.includes(":Y")) {
            // we suggest conjugated forms
            if (sMorph.includes(":V1")) {
                aSugg.add(sInfi);
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":2p"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Iq", ":1s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Iq", ":3s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Iq", ":3p"));
            } else if (sMorph.includes(":V2")) {
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":1s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
            } else if (sMorph.includes(":V3")) {
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":1s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Is", ":1s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Is", ":3s"));
            } else if (sMorph.includes(":V0a")) {
                aSugg.add("eus");
                aSugg.add("eut");
            } else {
                aSugg.add("étais");
                aSugg.add("était");
            }
            aSugg.delete("");
        } else {
            // we suggest past participles
            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q1"));
            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q2"));
            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q3"));
            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q4"));
            aSugg.delete("");
            // if there is only one past participle (epi inv), unreliable.
            if (aSugg.size === 1) {
                aSugg.clear();
            }
            if (sMorph.includes(":V1")) {
                aSugg.add(sInfi);
            }
        }
        return aSugg;
    },



    _getTags: function (sVerb) {
        // returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)
        if (!this._dVerb.hasOwnProperty(sVerb)) {
            return null;
        }
        return this._lTags[this._dVerb[sVerb][1]];
    },

    _getConjWithTags: function (sVerb, tTags, sTense, sWho) {
        // returns conjugation (can be an empty string)
        if (!this._dPatternConj[sTense][tTags[this._dTenseIdx.get(sTense)]].hasOwnProperty(sWho)) {
            return "";
        }

        return this._modifyStringWithSuffixCode(sVerb, this._dPatternConj[sTense][tTags[this._dTenseIdx.get(sTense)]][sWho]);
    },

    _hasConjWithTags: function (tTags, sTense, sWho) {
        // returns false if no conjugation (also if empty) else true
        if (this._dPatternConj[sTense][tTags[this._dTenseIdx.get(sTense)]].hasOwnProperty(sWho)
                && this._dPatternConj[sTense][tTags[this._dTenseIdx.get(sTense)]][sWho]) {
            return true;
        }
        return false;
    },

    _modifyStringWithSuffixCode: function (sWord, sSfx) {
        // returns sWord modified by sSfx
        if (sSfx === "") {
            return "";
        }
        if (sSfx === "0") {
            return sWord;
        }
        try {
            if (sSfx[0] !== '0') {
                return sWord.slice(0, -(sSfx.charCodeAt(0)-48)) + sSfx.slice(1); // 48 is the ASCII code for "0"
            } else {
                return sWord + sSfx.slice(1);
            }
        }
        catch (e) {
            console.log(e);
            return "## erreur, code : " + sSfx + " ##";
        }
    }
};


class Verb {

    constructor (sVerb) {
        if (typeof sVerb !== "string" || sVerb === "") {
            throw new TypeError ("The value should be a non-empty string");
        }
        this.sVerb = sVerb;
        this.sVerbAux = "";
        this._sRawInfo = conj.getVtyp(this.sVerb);
        this.sInfo = this._readableInfo(this._sRawInfo);
        this._tTags = conj._getTags(sVerb);
        this._tTagsAux = conj._getTags(this.sVerbAux);
        this.bProWithEn = (this._sRawInfo[5] === "e");
        this.dConj = new Map ([
            [":Y", new Map ([
                ["label", "Infinitif"],
                [":Y", sVerb]
            ])],
            [":PQ", new Map ([
                ["label", "Participes passés et présent"],
                [":Q1", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q1")],
                [":Q2", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q2")],
                [":Q3", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q3")],
                [":Q4", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q4")],
                [":P", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":P")]
            ])],
            [":Ip", new Map ([
                ["label", "Présent"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":1s")],
                [":1ś", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":1ś")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":3p")]
            ])],
            [":Iq", new Map ([
                ["label", "Imparfait"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":1s")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":Iq", ":3p")]
            ])],
            [":Is", new Map ([
                ["label", "Passé simple"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":1s")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":Is", ":3p")]
            ])],
            [":If", new Map ([
                ["label", "Futur"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":If", ":1s")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":If", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":If", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":If", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":If", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":If", ":3p")]
            ])],
            [":Sp", new Map ([
                ["label", "Présent subjonctif"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":1s")],
                [":1ś", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":1ś")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":Sp", ":3p")]
            ])],
            [":Sq", new Map ([
                ["label", "Imparfait subjonctif"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":1s")],
                [":1ś", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":1ś")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":Sq", ":3p")]
            ])],
            [":K", new Map ([
                ["label", "Conditionnel"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":K", ":1s")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":K", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":K", ":3s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":K", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":K", ":2p")],
                [":3p", conj._getConjWithTags(sVerb, this._tTags, ":K", ":3p")]
            ])],
            [":E", new Map ([
                ["label", "Impératif"],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":E", ":2s")],
                [":1p", conj._getConjWithTags(sVerb, this._tTags, ":E", ":1p")],
                [":2p", conj._getConjWithTags(sVerb, this._tTags, ":E", ":2p")]
            ])]
        ]);

    }

    _readableInfo () {
        // returns readable infos
        this.sVerbAux = (this._sRawInfo.slice(7,8) == "e") ? "être" : "avoir";
        let sGroup = conj._dGroup.get(this._sRawInfo[0]);
        let sInfo = "";
        if (this._sRawInfo.slice(3,4) == "t") {
            sInfo = "transitif";
        } else if (this._sRawInfo.slice(4,5) == "n") {
            sInfo = "transitif indirect";
        } else if (this._sRawInfo.slice(2,3) == "i") {
            sInfo = "intransitif";
................................................................................
        if (this._sRawInfo.slice(6,7) == "m") {
            sInfo = sInfo + " impersonnel";
        }
        if (sInfo === "") {
            sInfo = "# erreur - code : " + this._sRawInfo;
        }
        return sGroup + " · " + sInfo;
    }

    infinitif (bPro, bNeg, bTpsCo, bInt, bFem) {
        let sInfi;
        if (bTpsCo) {
            sInfi = (bPro) ? "être" : this.sVerbAux;
        } else {
            sInfi = this.sVerb;
        }
        if (bPro) {
            if (this.bProWithEn) {
                sInfi = "s’en " + sInfi;
            } else {
                sInfi = (conj._zStartVoy.test(sInfi)) ? "s’" + sInfi : "se " + sInfi;
            }
        }
        if (bNeg) {
            sInfi = "ne pas " + sInfi;
        }
        if (bTpsCo) {
            sInfi += " " + this._seekPpas(bPro, bFem, (this._sRawInfo[5] == "r"));
        }
        if (bInt) {
            sInfi += " … ?";
        }
        return sInfi;
    }

    participePasse (sWho) {
        return this.dConj.get(":PQ").get(sWho);
    }

    participePresent (bPro, bNeg, bTpsCo, bInt, bFem) {
        if (!this.dConj.get(":PQ").get(":P")) {
            return "";
        }
        let sPartPre;
        if (bTpsCo) {
            sPartPre = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":PQ", ":P") : conj.getConj("être", ":PQ", ":P");
        } else {
            sPartPre = this.dConj.get(":PQ").get(":P");
        }
        if (sPartPre === "") {
            return "";
        }
        let bEli = conj._zStartVoy.test(sPartPre);
        if (bPro) {
            if (this.bProWithEn) {
                sPartPre = "s’en " + sPartPre;
            } else {
                sPartPre = (bEli) ? "s’" + sPartPre : "se " + sPartPre;
            }
        }
................................................................................
        if (bTpsCo) {
            sPartPre += " " + this._seekPpas(bPro, bFem, this._sRawInfo[5] == "r");
        }
        if (bInt) {
            sPartPre += " … ?";
        }
        return sPartPre;
    }

    conjugue (sTemps, sWho, bPro, bNeg, bTpsCo, bInt, bFem) {
        if (!this.dConj.get(sTemps).get(sWho)) {
            return "";
        }
        let sConj;
        if (!bTpsCo && bInt && sWho == ":1s" && this.dConj.get(sTemps).gl_get(":1ś", false)) {
            sWho = ":1ś";
        }
        if (bTpsCo) {
            sConj = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, sTemps, sWho) : conj.getConj("être", sTemps, sWho);
        } else {
            sConj = this.dConj.get(sTemps).get(sWho);
        }
        if (sConj === "") {
            return "";
        }
        let bEli = conj._zStartVoy.test(sConj);
        if (bPro) {
            if (!this.bProWithEn) {
                sConj = (bEli) ? conj._dProObjEl.get(sWho) + sConj : conj._dProObj.get(sWho) + sConj;
            } else {
                sConj = conj._dProObjEl.get(sWho) + "en " + sConj;
            }
        }
        if (bNeg) {
            sConj = (bEli && !bPro) ? "n’" + sConj : "ne " + sConj;
        }
        if (bInt) {
            if (sWho == ":3s" && !conj._zNeedTeuph.test(sConj)) {
                sConj += "-t";
            }
            sConj += "-" + this._getPronom(sWho, bFem);
        } else {
            if (sWho == ":1s" && bEli && !bNeg && !bPro) {
                sConj = "j’" + sConj;
            } else {
................................................................................
        if (bTpsCo) {
            sConj += " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
        }
        if (bInt) {
            sConj += " … ?";
        }
        return sConj;
    }

    _getPronom (sWho, bFem) {
        if (sWho == ":3s") {
            if (this._sRawInfo[5] == "r") {
                return "on";
            } else if (bFem) {
                return "elle";
            }
        } else if (sWho == ":3p" && bFem) {
            return "elles";
        }
        return conj._dProSuj.get(sWho);
    }

    imperatif (sWho, bPro, bNeg, bTpsCo, bFem) {
        if (!this.dConj.get(":E").get(sWho)) {
            return "";
        }
        let sImpe;
        if (bTpsCo) {
            sImpe = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":E", sWho) : conj.getConj("être", ":E", sWho);
        } else {
            sImpe = this.dConj.get(":E").get(sWho);
        }
        if (sImpe === "") {
            return "";
        }
        let bEli = conj._zStartVoy.test(sImpe);
        if (bNeg) {
            if (bPro) {
                if (!this.bProWithEn) {
                    sImpe = (bEli && sWho == ":2s") ? "ne t’" + sImpe + " pas" : conj._dImpeProNeg.get(sWho) + sImpe + " pas";
                } else {
                    sImpe = conj._dImpeProNegEn.get(sWho) + sImpe + " pas";
                }
            } else {
                sImpe = (bEli) ? "n’" + sImpe + " pas" : "ne " + sImpe + " pas";
            }
        } else if (bPro) {
            sImpe = (this.bProWithEn) ? sImpe + conj._dImpeProEn.get(sWho) : sImpe + conj._dImpePro.get(sWho);
        }
        if (bTpsCo) {
            return sImpe + " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
        }
        return sImpe;
    }

    _seekPpas (bPro, bFem, bPlur) {
        if (!bPro && this.sVerbAux == "avoir") {
            return this.dConj.get(":PQ").get(":Q1");
        }
        if (!bFem) {
            return (bPlur && this.dConj.get(":PQ").get(":Q2")) ? this.dConj.get(":PQ").get(":Q2") : this.dConj.get(":PQ").get(":Q1");
................................................................................
        }
        if (!bPlur) {
            return (this.dConj.get(":PQ").get(":Q3")) ? this.dConj.get(":PQ").get(":Q3") : this.dConj.get(":PQ").get(":Q1");
        }
        return (this.dConj.get(":PQ").get(":Q4")) ? this.dConj.get(":PQ").get(":Q4") : this.dConj.get(":PQ").get(":Q1");
    }
}


// Initialization
if (!conj.bInit && typeof(browser) !== 'undefined') {
    // WebExtension (but not in Worker)
    conj.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/conj_data.json")));
} else if (!conj.bInit && typeof(require) !== 'undefined') {
    // Add-on SDK and Thunderbird
    conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
} else if ( !conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") {
    // used within Firefox content script (conjugation panel).
    // can’t load JSON from here, so we do it in ui.js and send it here.
    self.port.on("provideConjData", function (sJSONData) {
        conj.init(sJSONData);
    });    
} else if (conj.bInit){
    console.log("Module conj déjà initialisé");
} else {
    console.log("Module conj non initialisé");
}


if (typeof(exports) !== 'undefined') {


    exports._lVtyp = conj._lVtyp;
    exports._lTags = conj._lTags;
    exports._dPatternConj = conj._dPatternConj;
    exports._dVerb = conj._dVerb;
    exports.init = conj.init;
    exports._zStartVoy = conj._zStartVoy;
    exports._zNeedTeuph = conj._zNeedTeuph;
    exports._dProSuj = conj._dProSuj;
    exports._dProObj = conj._dProObj;
    exports._dProObjEl = conj._dProObjEl;
    exports._dImpePro = conj._dImpePro;
    exports._dImpeProNeg = conj._dImpeProNeg;
    exports._dImpeProEn = conj._dImpeProEn;
    exports._dImpeProNegEn = conj._dImpeProNegEn;
    exports._dGroup = conj._dGroup;
    exports._dTenseIdx = conj._dTenseIdx;
    exports.isVerb = conj.isVerb;
    exports.getConj = conj.getConj;
    exports.hasConj = conj.hasConj;
    exports.getVtyp = conj.getVtyp;
    exports.getSimil = conj.getSimil;
    exports._getTags = conj._getTags;

    exports._getConjWithTags = conj._getConjWithTags;
    exports._hasConjWithTags = conj._hasConjWithTags;
    exports._modifyStringWithSuffixCode = conj._modifyStringWithSuffixCode;
    exports.Verb = Verb;
}

Modified gc_lang/fr/modules-js/conj_data.json from [71266ea76e] to [73c9d13d66].

cannot compute difference between binary files

Modified gc_lang/fr/modules-js/cregex.js from [eb814cc494] to [97d67d03aa].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

















































//// Grammalecte - Compiled regular expressions


///// Lemme
const zLemma = new RegExp("^>([a-zà-öø-ÿ0-9Ā-ʯ][a-zà-öø-ÿ0-9Ā-ʯ-]+)");

///// Masculin / féminin / singulier / pluriel
const zGender = new RegExp(":[mfe]");
const zNumber = new RegExp(":[spi]");

///// Nom et adjectif
const zNA = new RegExp(":[NA]");

//// nombre
const zNAs = new RegExp(":[NA].*:s");
const zNAp = new RegExp(":[NA].*:p");
const zNAi = new RegExp(":[NA].*:i");
const zNAsi = new RegExp(":[NA].*:[si]");
const zNApi = new RegExp(":[NA].*:[pi]");

//// genre
const zNAm = new RegExp(":[NA].*:m");
const zNAf = new RegExp(":[NA].*:f");
const zNAe = new RegExp(":[NA].*:e");
const zNAme = new RegExp(":[NA].*:[me]");
const zNAfe = new RegExp(":[NA].*:[fe]");

//// nombre et genre
// singuilier
const zNAms = new RegExp(":[NA].*:m.*:s");
const zNAfs = new RegExp(":[NA].*:f.*:s");
const zNAes = new RegExp(":[NA].*:e.*:s");
const zNAmes = new RegExp(":[NA].*:[me].*:s");
const zNAfes = new RegExp(":[NA].*:[fe].*:s");

// singulier et invariable
const zNAmsi = new RegExp(":[NA].*:m.*:[si]");
const zNAfsi = new RegExp(":[NA].*:f.*:[si]");
const zNAesi = new RegExp(":[NA].*:e.*:[si]");
const zNAmesi = new RegExp(":[NA].*:[me].*:[si]");
const zNAfesi = new RegExp(":[NA].*:[fe].*:[si]");

// pluriel
const zNAmp = new RegExp(":[NA].*:m.*:p");
const zNAfp = new RegExp(":[NA].*:f.*:p");
const zNAep = new RegExp(":[NA].*:e.*:p");
const zNAmep = new RegExp(":[NA].*:[me].*:p");
const zNAfep = new RegExp(":[NA].*:[me].*:p");

// pluriel et invariable
const zNAmpi = new RegExp(":[NA].*:m.*:[pi]");
const zNAfpi = new RegExp(":[NA].*:f.*:[pi]");
const zNAepi = new RegExp(":[NA].*:e.*:[pi]");
const zNAmepi = new RegExp(":[NA].*:[me].*:[pi]");
const zNAfepi = new RegExp(":[NA].*:[fe].*:[pi]");

//// Divers
const zAD = new RegExp(":[AB]");

///// Verbe
const zVconj = new RegExp(":[123][sp]");
const zVconj123 = new RegExp(":V[123].*:[123][sp]");

///// Nom | Adjectif | Verbe
const zNVconj = new RegExp(":(?:N|[123][sp])");
const zNAVconj = new RegExp(":(?:N|A|[123][sp])");

///// Spécifique
const zNnotA = new RegExp(":N(?!:A)");
const zPNnotA = new RegExp(":(?:N(?!:A)|Q)");

///// Noms propres
const zNP = new RegExp(":(?:M[12P]|T)");
const zNPm = new RegExp(":(?:M[12P]|T):m");
const zNPf = new RegExp(":(?:M[12P]|T):f");
const zNPe = new RegExp(":(?:M[12P]|T):e");


///// FONCTIONS

function getLemmaOfMorph (sMorph) {
    return zLemma.exec(sMorph)[1];
}

function checkAgreement (l1, l2) {
    // check number agreement
    if (!mbInv(l1) && !mbInv(l2)) {
        if (mbSg(l1) && !mbSg(l2)) {
            return false;
        }
        if (mbPl(l1) && !mbPl(l2)) {
            return false;
        }
    }
    // check gender agreement
    if (mbEpi(l1) || mbEpi(l2)) {
        return true;
    }
    if (mbMas(l1) && !mbMas(l2)) {
        return false;
    }
    if (mbFem(l1) && !mbFem(l2)) {
        return false;
    }
    return true;
}

function checkConjVerb (lMorph, sReqConj) {
    return lMorph.some(s  =>  s.includes(sReqConj));
}

function getGender (lMorph) {
    // returns gender of word (':m', ':f', ':e' or empty string).
    let sGender = "";
    for (let sMorph of lMorph) {
        let m = zGender.exec(sMorph);
        if (m) {
            if (!sGender) {
                sGender = m[0];
            } else if (sGender != m[0]) {
                return ":e";
            }
        }
    }
    return sGender;
}

function getNumber (lMorph) {
    // returns number of word (':s', ':p', ':i' or empty string).
    let sNumber = "";
    for (let sMorph of lMorph) {
        let m = zNumber.exec(sWord);
        if (m) {
            if (!sNumber) {
                sNumber = m[0];
            } else if (sNumber != m[0]) {
                return ":i";
            }
        }
    }
    return sNumber;
}

// NOTE :  isWhat (lMorph)    returns true   if lMorph contains nothing else than What
//         mbWhat (lMorph)    returns true   if lMorph contains What at least once

//// isXXX = it’s certain

function isNom (lMorph) {
    return lMorph.every(s  =>  s.includes(":N"));
}

function isNomNotAdj (lMorph) {
    return lMorph.every(s  =>  zNnotA.test(s));
}

function isAdj (lMorph) {
    return lMorph.every(s  =>  s.includes(":A"));
}

function isNomAdj (lMorph) {
    return lMorph.every(s  =>  zNA.test(s));
}

function isNomVconj (lMorph) {
    return lMorph.every(s  =>  zNVconj.test(s));
}

function isInv (lMorph) {
    return lMorph.every(s  =>  s.includes(":i"));
}
function isSg (lMorph) {
    return lMorph.every(s  =>  s.includes(":s"));
}
function isPl (lMorph) {
    return lMorph.every(s  =>  s.includes(":p"));
}
function isEpi (lMorph) {
    return lMorph.every(s  =>  s.includes(":e"));
}
function isMas (lMorph) {
    return lMorph.every(s  =>  s.includes(":m"));
}
function isFem (lMorph) {
    return lMorph.every(s  =>  s.includes(":f"));
}


//// mbXXX = MAYBE XXX

function mbNom (lMorph) {
    return lMorph.some(s  =>  s.includes(":N"));
}

function mbAdj (lMorph) {
    return lMorph.some(s  =>  s.includes(":A"));
}

function mbAdjNb (lMorph) {
    return lMorph.some(s  =>  zAD.test(s));
}

function mbNomAdj (lMorph) {
    return lMorph.some(s  =>  zNA.test(s));
}

function mbNomNotAdj (lMorph) {
    let b = false;
    for (let s of lMorph) {
        if (s.includes(":A")) {
            return false;
        }
        if (s.includes(":N")) {
            b = true;
        }
    }
    return b;
}

function mbPpasNomNotAdj (lMorph) {
    return lMorph.some(s  =>  zPNnotA.test(s));
}

function mbVconj (lMorph) {
    return lMorph.some(s  =>  zVconj.test(s));
}

function mbVconj123 (lMorph) {
    return lMorph.some(s  =>  zVconj123.test(s));
}

function mbMG (lMorph) {
    return lMorph.some(s  =>  s.includes(":G"));
}

function mbInv (lMorph) {
    return lMorph.some(s  =>  s.includes(":i"));
}
function mbSg (lMorph) {
    return lMorph.some(s  =>  s.includes(":s"));
}
function mbPl (lMorph) {
    return lMorph.some(s  =>  s.includes(":p"));
}
function mbEpi (lMorph) {
    return lMorph.some(s  =>  s.includes(":e"));
}
function mbMas (lMorph) {
    return lMorph.some(s  =>  s.includes(":m"));
}
function mbFem (lMorph) {
    return lMorph.some(s  =>  s.includes(":f"));
}

function mbNpr (lMorph) {
    return lMorph.some(s  =>  zNP.test(s));
}

function mbNprMasNotFem (lMorph) {
    if (lMorph.some(s  =>  zNPf.test(s))) {
        return false;
    }
    return lMorph.some(s  =>  zNPm.test(s));
}



exports.getLemmaOfMorph = getLemmaOfMorph;
exports.checkAgreement = checkAgreement;
exports.checkConjVerb = checkConjVerb;
exports.getGender = getGender;
exports.getNumber = getNumber;
exports.isNom = isNom;
exports.isNomNotAdj = isNomNotAdj;
exports.isAdj = isAdj;
exports.isNomAdj = isNomAdj;
exports.isNomVconj = isNomVconj;
exports.isInv = isInv;
exports.isSg = isSg;
exports.isPl = isPl;
exports.isEpi = isEpi;
exports.isMas = isMas;
exports.isFem = isFem;
exports.mbNom = mbNom;
exports.mbAdj = mbAdj;
exports.mbAdjNb = mbAdjNb;
exports.mbNomAdj = mbNomAdj;
exports.mbNomNotAdj = mbNomNotAdj;
exports.mbPpasNomNotAdj = mbPpasNomNotAdj;
exports.mbVconj = mbVconj;
exports.mbVconj123 = mbVconj123;
exports.mbMG = mbMG;
exports.mbInv = mbInv;
exports.mbSg = mbSg;
exports.mbPl = mbPl;
exports.mbEpi = mbEpi;
exports.mbMas = mbMas;
exports.mbFem = mbFem;
exports.mbNpr = mbNpr;
exports.mbNprMasNotFem = mbNprMasNotFem;


















































|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
//// Grammalecte - Compiled regular expressions
/*jslint esversion: 6*/


var cregex = {
    ///// Lemme
    _zLemma: new RegExp(">([a-zà-öø-ÿ0-9Ā-ʯ][a-zà-öø-ÿ0-9Ā-ʯ-]+)"),

    ///// Masculin / féminin / singulier / pluriel
    _zGender: new RegExp(":[mfe]"),
    _zNumber: new RegExp(":[spi]"),

    ///// Nom et adjectif
    _zNA: new RegExp(":[NA]"),

    //// nombre
    _zNAs: new RegExp(":[NA].*:s"),
    _zNAp: new RegExp(":[NA].*:p"),
    _zNAi: new RegExp(":[NA].*:i"),
    _zNAsi: new RegExp(":[NA].*:[si]"),
    _zNApi: new RegExp(":[NA].*:[pi]"),

    //// genre
    _zNAm: new RegExp(":[NA].*:m"),
    _zNAf: new RegExp(":[NA].*:f"),
    _zNAe: new RegExp(":[NA].*:e"),
    _zNAme: new RegExp(":[NA].*:[me]"),
    _zNAfe: new RegExp(":[NA].*:[fe]"),

    //// nombre et genre
    // singuilier
    _zNAms: new RegExp(":[NA].*:m.*:s"),
    _zNAfs: new RegExp(":[NA].*:f.*:s"),
    _zNAes: new RegExp(":[NA].*:e.*:s"),
    _zNAmes: new RegExp(":[NA].*:[me].*:s"),
    _zNAfes: new RegExp(":[NA].*:[fe].*:s"),

    // singulier et invariable
    _zNAmsi: new RegExp(":[NA].*:m.*:[si]"),
    _zNAfsi: new RegExp(":[NA].*:f.*:[si]"),
    _zNAesi: new RegExp(":[NA].*:e.*:[si]"),
    _zNAmesi: new RegExp(":[NA].*:[me].*:[si]"),
    _zNAfesi: new RegExp(":[NA].*:[fe].*:[si]"),

    // pluriel
    _zNAmp: new RegExp(":[NA].*:m.*:p"),
    _zNAfp: new RegExp(":[NA].*:f.*:p"),
    _zNAep: new RegExp(":[NA].*:e.*:p"),
    _zNAmep: new RegExp(":[NA].*:[me].*:p"),
    _zNAfep: new RegExp(":[NA].*:[me].*:p"),

    // pluriel et invariable
    _zNAmpi: new RegExp(":[NA].*:m.*:[pi]"),
    _zNAfpi: new RegExp(":[NA].*:f.*:[pi]"),
    _zNAepi: new RegExp(":[NA].*:e.*:[pi]"),
    _zNAmepi: new RegExp(":[NA].*:[me].*:[pi]"),
    _zNAfepi: new RegExp(":[NA].*:[fe].*:[pi]"),

    //// Divers
    _zAD: new RegExp(":[AB]"),

    ///// Verbe
    _zVconj: new RegExp(":[123][sp]"),
    _zVconj123: new RegExp(":V[123].*:[123][sp]"),

    ///// Nom | Adjectif | Verbe
    _zNVconj: new RegExp(":(?:N|[123][sp])"),
    _zNAVconj: new RegExp(":(?:N|A|[123][sp])"),

    ///// Spécifique
    _zNnotA: new RegExp(":N(?!:A)"),
    _zPNnotA: new RegExp(":(?:N(?!:A)|Q)"),

    ///// Noms propres
    _zNP: new RegExp(":(?:M[12P]|T)"),
    _zNPm: new RegExp(":(?:M[12P]|T):m"),
    _zNPf: new RegExp(":(?:M[12P]|T):f"),
    _zNPe: new RegExp(":(?:M[12P]|T):e"),


    ///// FONCTIONS

    getLemmaOfMorph: function (sMorph) {
        return this._zLemma.exec(sMorph)[1];
    },

    checkAgreement: function (l1, l2) {
        // check number agreement
        if (!this.mbInv(l1) && !this.mbInv(l2)) {
            if (this.mbSg(l1) && !this.mbSg(l2)) {
                return false;
            }
            if (this.mbPl(l1) && !this.mbPl(l2)) {
                return false;
            }
        }
        // check gender agreement
        if (this.mbEpi(l1) || this.mbEpi(l2)) {
            return true;
        }
        if (this.mbMas(l1) && !this.mbMas(l2)) {
            return false;
        }
        if (this.mbFem(l1) && !this.mbFem(l2)) {
            return false;
        }
        return true;
    },

    checkConjVerb: function (lMorph, sReqConj) {
        return lMorph.some(s  =>  s.includes(sReqConj));
    },

    getGender: function (lMorph) {
        // returns gender of word (':m', ':f', ':e' or empty string).
        let sGender = "";
        for (let sMorph of lMorph) {
            let m = this._zGender.exec(sMorph);
            if (m) {
                if (!sGender) {
                    sGender = m[0];
                } else if (sGender != m[0]) {
                    return ":e";
                }
            }
        }
        return sGender;
    },

    getNumber: function (lMorph) {
        // returns number of word (':s', ':p', ':i' or empty string).
        let sNumber = "";
        for (let sMorph of lMorph) {
            let m = this._zNumber.exec(sWord);
            if (m) {
                if (!sNumber) {
                    sNumber = m[0];
                } else if (sNumber != m[0]) {
                    return ":i";
                }
            }
        }
        return sNumber;
    },

    // NOTE :  isWhat (lMorph)    returns true   if lMorph contains nothing else than What
    //         mbWhat (lMorph)    returns true   if lMorph contains What at least once

    //// isXXX = it’s certain

    isNom: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":N"));
    },

    isNomNotAdj: function (lMorph) {
        return lMorph.every(s  =>  this._zNnotA.test(s));
    },

    isAdj: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":A"));
    },

    isNomAdj: function (lMorph) {
        return lMorph.every(s  =>  this._zNA.test(s));
    },

    isNomVconj: function (lMorph) {
        return lMorph.every(s  =>  this._zNVconj.test(s));
    },

    isInv: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":i"));
    },
    isSg: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":s"));
    },
    isPl: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":p"));
    },
    isEpi: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":e"));
    },
    isMas: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":m"));
    },
    isFem: function (lMorph) {
        return lMorph.every(s  =>  s.includes(":f"));
    },


    //// mbXXX = MAYBE XXX

    mbNom: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":N"));
    },

    mbAdj: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":A"));
    },

    mbAdjNb: function (lMorph) {
        return lMorph.some(s  =>  this._zAD.test(s));
    },

    mbNomAdj: function (lMorph) {
        return lMorph.some(s  =>  this._zNA.test(s));
    },

    mbNomNotAdj: function (lMorph) {
        let b = false;
        for (let s of lMorph) {
            if (s.includes(":A")) {
                return false;
            }
            if (s.includes(":N")) {
                b = true;
            }
        }
        return b;
    },

    mbPpasNomNotAdj: function (lMorph) {
        return lMorph.some(s  =>  this._zPNnotA.test(s));
    },

    mbVconj: function (lMorph) {
        return lMorph.some(s  =>  this._zVconj.test(s));
    },

    mbVconj123: function (lMorph) {
        return lMorph.some(s  =>  this._zVconj123.test(s));
    },

    mbMG: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":G"));
    },

    mbInv: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":i"));
    },
    mbSg: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":s"));
    },
    mbPl: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":p"));
    },
    mbEpi: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":e"));
    },
    mbMas: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":m"));
    },
    mbFem: function (lMorph) {
        return lMorph.some(s  =>  s.includes(":f"));
    },

    mbNpr: function (lMorph) {
        return lMorph.some(s  =>  this._zNP.test(s));
    },

    mbNprMasNotFem: function (lMorph) {
        if (lMorph.some(s  =>  this._zNPf.test(s))) {
            return false;
        }
        return lMorph.some(s  =>  this._zNPm.test(s));
    }
};


if (typeof(exports) !== 'undefined') {
    exports._zLemma = cregex._zLemma;
    exports._zGender = cregex._zGender;
    exports._zNumber = cregex._zNumber;
    exports._zNA = cregex._zNA;
    exports._zNAs = cregex._zNAs;
    exports._zNAp = cregex._zNAp;
    exports._zNAi = cregex._zNAi;
    exports._zNAsi = cregex._zNAsi;
    exports._zNApi = cregex._zNApi;
    exports._zNAm = cregex._zNAm;
    exports._zNAf = cregex._zNAf;
    exports._zNAe = cregex._zNAe;
    exports._zNAme = cregex._zNAme;
    exports._zNAfe = cregex._zNAfe;
    exports._zNAms = cregex._zNAms;
    exports._zNAfs = cregex._zNAfs;
    exports._zNAes = cregex._zNAes;
    exports._zNAmes = cregex._zNAmes;
    exports._zNAfes = cregex._zNAfes;
    exports._zNAmsi = cregex._zNAmsi;
    exports._zNAfsi = cregex._zNAfsi;
    exports._zNAesi = cregex._zNAesi;
    exports._zNAmesi = cregex._zNAmesi;
    exports._zNAfesi = cregex._zNAfesi;
    exports._zNAmp = cregex._zNAmp;
    exports._zNAfp = cregex._zNAfp;
    exports._zNAep = cregex._zNAep;
    exports._zNAmep = cregex._zNAmep;
    exports._zNAfep = cregex._zNAfep;
    exports._zNAmpi = cregex._zNAmpi;
    exports._zNAfpi = cregex._zNAfpi;
    exports._zNAepi = cregex._zNAepi;
    exports._zNAmepi = cregex._zNAmepi;
    exports._zNAfepi = cregex._zNAfepi;
    exports._zAD = cregex._zAD;
    exports._zVconj = cregex._zVconj;
    exports._zVconj123 = cregex._zVconj123;
    exports._zNVconj = cregex._zNVconj;
    exports._zNAVconj = cregex._zNAVconj;
    exports._zNnotA = cregex._zNnotA;
    exports._zPNnotA = cregex._zPNnotA;
    exports._zNP = cregex._zNP;
    exports._zNPm = cregex._zNPm;
    exports._zNPf = cregex._zNPf;
    exports._zNPe = cregex._zNPe;
    exports.getLemmaOfMorph = cregex.getLemmaOfMorph;
    exports.checkAgreement = cregex.checkAgreement;
    exports.checkConjVerb = cregex.checkConjVerb;
    exports.getGender = cregex.getGender;
    exports.getNumber = cregex.getNumber;
    exports.isNom = cregex.isNom;
    exports.isNomNotAdj = cregex.isNomNotAdj;
    exports.isAdj = cregex.isAdj;
    exports.isNomAdj = cregex.isNomAdj;
    exports.isNomVconj = cregex.isNomVconj;
    exports.isInv = cregex.isInv;
    exports.isSg = cregex.isSg;
    exports.isPl = cregex.isPl;
    exports.isEpi = cregex.isEpi;
    exports.isMas = cregex.isMas;
    exports.isFem = cregex.isFem;
    exports.mbNom = cregex.mbNom;
    exports.mbAdj = cregex.mbAdj;
    exports.mbAdjNb = cregex.mbAdjNb;
    exports.mbNomAdj = cregex.mbNomAdj;
    exports.mbNomNotAdj = cregex.mbNomNotAdj;
    exports.mbPpasNomNotAdj = cregex.mbPpasNomNotAdj;
    exports.mbVconj = cregex.mbVconj;
    exports.mbVconj123 = cregex.mbVconj123;
    exports.mbMG = cregex.mbMG;
    exports.mbInv = cregex.mbInv;
    exports.mbSg = cregex.mbSg;
    exports.mbPl = cregex.mbPl;
    exports.mbEpi = cregex.mbEpi;
    exports.mbMas = cregex.mbMas;
    exports.mbFem = cregex.mbFem;
    exports.mbNpr = cregex.mbNpr;
    exports.mbNprMasNotFem = cregex.mbNprMasNotFem;
}

Modified gc_lang/fr/modules-js/gce_analyseur.js from [7588af7481] to [e2613ddcd2].

1

2
3
4
5
6
7
8
..
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//// GRAMMAR CHECKING ENGINE PLUGIN: Parsing functions for French language


function rewriteSubject (s1, s2) {
    // s1 is supposed to be prn/patr/npr (M[12P])
    if (s2 == "lui") {
        return "ils";
    }
    if (s2 == "moi") {
................................................................................
        return "vous";
    }
    if (s2 == "eux") {
        return "ils";
    }
    if (s2 == "elle" || s2 == "elles") {
        // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
        if (cr.mbNprMasNotFem(_dAnalyses._get(s1, ""))) {
            return "ils";
        }
        // si épicène, indéterminable, mais OSEF, le féminin l’emporte
        return "elles";
    }
    return s1 + " et " + s2;
}

function apposition (sWord1, sWord2) {
    // returns true if nom + nom (no agreement required)
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    return cr.mbNomNotAdj(_dAnalyses._get(sWord2, "")) && cr.mbPpasNomNotAdj(_dAnalyses._get(sWord1, ""));
}

function isAmbiguousNAV (sWord) {
    // words which are nom|adj and verb are ambiguous (except être and avoir)
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return false;
    }
    if (!cr.mbNomAdj(_dAnalyses._get(sWord, "")) || sWord == "est") {
        return false;
    }
    if (cr.mbVconj(_dAnalyses._get(sWord, "")) && !cr.mbMG(_dAnalyses._get(sWord, ""))) {
        return true;
    }
    return false;
}

function isAmbiguousAndWrong (sWord1, sWord2, sReqMorphNA, sReqMorphConj) {
    //// use it if sWord1 won’t be a verb; word2 is assumed to be true via isAmbiguousNAV
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses._get(sWord2, null);
    if (!a2 || a2.length === 0) {
        return false;
    }
    if (cr.checkConjVerb(a2, sReqMorphConj)) {
        // verb word2 is ok
        return false;
    }
    let a1 = _dAnalyses._get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return false;
    }
    if (cr.checkAgreement(a1, a2) && (cr.mbAdj(a2) || cr.mbAdj(a1))) {
        return false;
    }
    return true;
}

function isVeryAmbiguousAndWrong (sWord1, sWord2, sReqMorphNA, sReqMorphConj, bLastHopeCond) {
    //// use it if sWord1 can be also a verb; word2 is assumed to be true via isAmbiguousNAV
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses._get(sWord2, null)
    if (!a2 || a2.length === 0) {
        return false;
    }
    if (cr.checkConjVerb(a2, sReqMorphConj)) {
        // verb word2 is ok
        return false;
    }
    let a1 = _dAnalyses._get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return false;
    }
    if (cr.checkAgreement(a1, a2) && (cr.mbAdj(a2) || cr.mbAdjNb(a1))) {
        return false;
    }
    // now, we know there no agreement, and conjugation is also wrong
    if (cr.isNomAdj(a1)) {
        return true;
    }
    //if cr.isNomAdjVerb(a1): # considered true
    if (bLastHopeCond) {
        return true;
    }
    return false;
}

function checkAgreement (sWord1, sWord2) {
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses._get(sWord2, null)
    if (!a2 || a2.length === 0) {
        return true;
    }
    let a1 = _dAnalyses._get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return true;
    }
    return cr.checkAgreement(a1, a2);
}

function mbUnit (s) {
    if (/[µ\/⁰¹²³⁴⁵⁶⁷⁸⁹Ωℓ·]/.test(s)) {
        return true;
    }
    if (s.length > 1 && s.length < 16 && s.slice(0, 1)._isLowerCase() && (!s.slice(1)._isLowerCase() || /[0-9]/.test(s))) {
        return true;
    }
    return false;
}


//// Syntagmes
................................................................................
const _zEndOfNG2 = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");
const _zEndOfNG3 = new RegExp ("^ *, +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");

function isEndOfNG (dDA, s, iOffset) {
    if (_zEndOfNG1.test(s)) {
        return true;
    }
    let m = _zEndOfNG2._exec2(s, ["$"]);
    if (m && morphex(dDA, [iOffset+m.start[1], m[1]], ":[VR]", ":[NAQP]")) {
        return true;
    }
    m = _zEndOfNG3._exec2(s, ["$"]);
    if (m && !morph(dDA, [iOffset+m.start[1], m[1]], ":[NA]", false)) {
        return true;
    }
    return false;
}


................................................................................
const _zNextIsNotCOD2 = new RegExp ("^ +(?:[mtsnj](e +|’)|[nv]ous |tu |ils? |elles? )");
const _zNextIsNotCOD3 = new RegExp ("^ +([a-zéèî][a-zà-öA-Zø-ÿÀ-ÖØ-ßĀ-ʯ-]+)");

function isNextNotCOD (dDA, s, iOffset) {
    if (_zNextIsNotCOD1.test(s) || _zNextIsNotCOD2.test(s)) {
        return true;
    }
    let m = _zNextIsNotCOD3._exec2(s, ["$"]);
    if (m && morphex(dDA, [iOffset+m.start[1], m[1]], ":[123][sp]", ":[DM]")) {
        return true;
    }
    return false;
}


................................................................................
const _zNextIsVerb1 = new RegExp ("^ +[nmts](?:e |’)");
const _zNextIsVerb2 = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");

function isNextVerb (dDA, s, iOffset) {
    if (_zNextIsVerb1.test(s)) {
        return true;
    }
    let m = _zNextIsVerb2._exec2(s, ["$"]);
    if (m && morph(dDA, [iOffset+m.start[1], m[1]], ":[123][sp]", false)) {
        return true;
    }
    return false;
}


//// Exceptions

const aREGULARPLURAL = new Set(["abricot", "amarante", "aubergine", "acajou", "anthracite", "brique", "caca", "café",
                                "carotte", "cerise", "chataigne", "corail", "citron", "crème", "grave", "groseille",
                                "jonquille", "marron", "olive", "pervenche", "prune", "sable"]);
const aSHOULDBEVERB = new Set(["aller", "manger"]);

>







 







|











|







|


|








|



|



|



|








|



|



|



|



|


|








|



|



|






|







 







|



|







 







|







 







|













1
2
3
4
5
6
7
8
9
..
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//// GRAMMAR CHECKING ENGINE PLUGIN: Parsing functions for French language
/*jslint esversion: 6*/

function rewriteSubject (s1, s2) {
    // s1 is supposed to be prn/patr/npr (M[12P])
    if (s2 == "lui") {
        return "ils";
    }
    if (s2 == "moi") {
................................................................................
        return "vous";
    }
    if (s2 == "eux") {
        return "ils";
    }
    if (s2 == "elle" || s2 == "elles") {
        // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
        if (cregex.mbNprMasNotFem(_dAnalyses.gl_get(s1, ""))) {
            return "ils";
        }
        // si épicène, indéterminable, mais OSEF, le féminin l’emporte
        return "elles";
    }
    return s1 + " et " + s2;
}

function apposition (sWord1, sWord2) {
    // returns true if nom + nom (no agreement required)
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    return cregex.mbNomNotAdj(_dAnalyses.gl_get(sWord2, "")) && cregex.mbPpasNomNotAdj(_dAnalyses.gl_get(sWord1, ""));
}

function isAmbiguousNAV (sWord) {
    // words which are nom|adj and verb are ambiguous (except être and avoir)
    if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
        return false;
    }
    if (!cregex.mbNomAdj(_dAnalyses.gl_get(sWord, "")) || sWord == "est") {
        return false;
    }
    if (cregex.mbVconj(_dAnalyses.gl_get(sWord, "")) && !cregex.mbMG(_dAnalyses.gl_get(sWord, ""))) {
        return true;
    }
    return false;
}

function isAmbiguousAndWrong (sWord1, sWord2, sReqMorphNA, sReqMorphConj) {
    //// use it if sWord1 won’t be a verb; word2 is assumed to be true via isAmbiguousNAV
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses.gl_get(sWord2, null);
    if (!a2 || a2.length === 0) {
        return false;
    }
    if (cregex.checkConjVerb(a2, sReqMorphConj)) {
        // verb word2 is ok
        return false;
    }
    let a1 = _dAnalyses.gl_get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return false;
    }
    if (cregex.checkAgreement(a1, a2) && (cregex.mbAdj(a2) || cregex.mbAdj(a1))) {
        return false;
    }
    return true;
}

function isVeryAmbiguousAndWrong (sWord1, sWord2, sReqMorphNA, sReqMorphConj, bLastHopeCond) {
    //// use it if sWord1 can be also a verb; word2 is assumed to be true via isAmbiguousNAV
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses.gl_get(sWord2, null);
    if (!a2 || a2.length === 0) {
        return false;
    }
    if (cregex.checkConjVerb(a2, sReqMorphConj)) {
        // verb word2 is ok
        return false;
    }
    let a1 = _dAnalyses.gl_get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return false;
    }
    if (cregex.checkAgreement(a1, a2) && (cregex.mbAdj(a2) || cregex.mbAdjNb(a1))) {
        return false;
    }
    // now, we know there no agreement, and conjugation is also wrong
    if (cregex.isNomAdj(a1)) {
        return true;
    }
    //if cregex.isNomAdjVerb(a1): # considered true
    if (bLastHopeCond) {
        return true;
    }
    return false;
}

function checkAgreement (sWord1, sWord2) {
    // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let a2 = _dAnalyses.gl_get(sWord2, null);
    if (!a2 || a2.length === 0) {
        return true;
    }
    let a1 = _dAnalyses.gl_get(sWord1, null);
    if (!a1 || a1.length === 0) {
        return true;
    }
    return cregex.checkAgreement(a1, a2);
}

function mbUnit (s) {
    if (/[µ\/⁰¹²³⁴⁵⁶⁷⁸⁹Ωℓ·]/.test(s)) {
        return true;
    }
    if (s.length > 1 && s.length < 16 && s.slice(0, 1).gl_isLowerCase() && (!s.slice(1).gl_isLowerCase() || /[0-9]/.test(s))) {
        return true;
    }
    return false;
}


//// Syntagmes
................................................................................
const _zEndOfNG2 = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");
const _zEndOfNG3 = new RegExp ("^ *, +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");

function isEndOfNG (dDA, s, iOffset) {
    if (_zEndOfNG1.test(s)) {
        return true;
    }
    let m = _zEndOfNG2.gl_exec2(s, ["$"]);
    if (m && morphex(dDA, [iOffset+m.start[1], m[1]], ":[VR]", ":[NAQP]")) {
        return true;
    }
    m = _zEndOfNG3.gl_exec2(s, ["$"]);
    if (m && !morph(dDA, [iOffset+m.start[1], m[1]], ":[NA]", false)) {
        return true;
    }
    return false;
}


................................................................................
const _zNextIsNotCOD2 = new RegExp ("^ +(?:[mtsnj](e +|’)|[nv]ous |tu |ils? |elles? )");
const _zNextIsNotCOD3 = new RegExp ("^ +([a-zéèî][a-zà-öA-Zø-ÿÀ-ÖØ-ßĀ-ʯ-]+)");

function isNextNotCOD (dDA, s, iOffset) {
    if (_zNextIsNotCOD1.test(s) || _zNextIsNotCOD2.test(s)) {
        return true;
    }
    let m = _zNextIsNotCOD3.gl_exec2(s, ["$"]);
    if (m && morphex(dDA, [iOffset+m.start[1], m[1]], ":[123][sp]", ":[DM]")) {
        return true;
    }
    return false;
}


................................................................................
const _zNextIsVerb1 = new RegExp ("^ +[nmts](?:e |’)");
const _zNextIsVerb2 = new RegExp ("^ +([a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ][a-zà-öA-Zø-ÿÀ-Ö0-9_Ø-ßĀ-ʯ-]+)");

function isNextVerb (dDA, s, iOffset) {
    if (_zNextIsVerb1.test(s)) {
        return true;
    }
    let m = _zNextIsVerb2.gl_exec2(s, ["$"]);
    if (m && morph(dDA, [iOffset+m.start[1], m[1]], ":[123][sp]", false)) {
        return true;
    }
    return false;
}


//// Exceptions

const aREGULARPLURAL = new Set(["abricot", "amarante", "aubergine", "acajou", "anthracite", "brique", "caca", "café",
                                "carotte", "cerise", "chataigne", "corail", "citron", "crème", "grave", "groseille",
                                "jonquille", "marron", "olive", "pervenche", "prune", "sable"]);
const aSHOULDBEVERB = new Set(["aller", "manger"]);

Modified gc_lang/fr/modules-js/gce_date_verif.js from [de4d3b5e04] to [f30dbe242e].

1

2
3
4
5
6
7
8
//// GRAMMAR CHECKING ENGINE PLUGIN


// Check date validity

// WARNING: when creating a Date, month must be between 0 and 11


const _lDay = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"];

>







1
2
3
4
5
6
7
8
9
//// GRAMMAR CHECKING ENGINE PLUGIN
/*jslint esversion: 6*/

// Check date validity

// WARNING: when creating a Date, month must be between 0 and 11


const _lDay = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"];

Modified gc_lang/fr/modules-js/gce_suggestions.js from [66a9ce5ee4] to [0d3c06e52f].

1


2

3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
//// GRAMMAR CHECKING ENGINE PLUGIN: Suggestion mechanisms




const conj = require("resource://grammalecte/fr/conj.js");
const mfsp = require("resource://grammalecte/fr/mfsp.js");
const phonet = require("resource://grammalecte/fr/phonet.js");



//// verbs

function suggVerb (sFlex, sWho, funcSugg2=null) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sStem of stem(sFlex)) {
        let tTags = conj._getTags(sStem);
        if (tTags) {
            // we get the tense
            let aTense = new Set();
            for (let sMorph of _dAnalyses._get(sFlex, [])) {
                let m;
                let zVerb = new RegExp (sStem+" .*?(:(?:Y|I[pqsf]|S[pq]|K))", "g");
                while (m = zVerb.exec(sMorph)) {
                    // stem must be used in regex to prevent confusion between different verbs (e.g. sauras has 2 stems: savoir and saurer)
                    if (m) {
                        if (m[1] === ":Y") {
                            aTense.add(":Ip");
                            aTense.add(":Iq");
                            aTense.add(":Is");
                        } else if (m[1] === ":P") {
................................................................................
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
}

function suggVerbInfi (sFlex) {
    //return stem(sFlex).join("|");
    return [ for (sStem of stem(sFlex)) if (conj.isVerb(sStem)) sStem ].join("|");
}


const _dQuiEst = new Map ([
    ["je", ":1s"], ["j’", ":1s"], ["j’en", ":1s"], ["j’y", ":1s"],
    ["tu", ":2s"], ["il", ":3s"], ["on", ":3s"], ["elle", ":3s"],
    ["nous", ":1p"], ["vous", ":2p"], ["ils", ":3p"], ["elles", ":3p"]
................................................................................
    } else if (cMode == ":S") {
        lMode = _lSubjonctif;
    } else if (cMode.startsWith(":I") || cMode.startsWith(":S")) {
        lMode = [cMode];
    } else {
        return "";
    }
    let sWho = _dQuiEst._get(sSuj.toLowerCase(), null);
    if (!sWho) {
        if (sSuj[0]._isLowerCase()) { // pas un pronom, ni un nom propre
            return "";
        }
        sWho = ":3s";
    }
    let aSugg = new Set();
    for (let sStem of stem(sFlex)) {
        let tTags = conj._getTags(sStem);
................................................................................

function suggPlur (sFlex, sWordToAgree=null) {
    // returns plural forms assuming sFlex is singular
    if (sWordToAgree) {
        if (!_dAnalyses.has(sWordToAgree) && !_storeMorphFromFSA(sWordToAgree)) {
            return "";
        }
        let sGender = cr.getGender(_dAnalyses._get(sWordToAgree, []));
        if (sGender == ":m") {
            return suggMasPlur(sFlex);
        } else if (sGender == ":f") {
            return suggFemPlur(sFlex);
        }
    }
    let aSugg = new Set();
................................................................................
    return "";
}

function suggMasSing (sFlex, bSuggSimil=false) {
    // returns masculine singular forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses._get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":m") || sMorph.includes(":e")) {
                aSugg.add(suggSing(sFlex));
            } else {
                let sStem = cr.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    mfsp.getMasForm(sStem, false).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cr.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q1") && conj.hasConj(sVerb, ":PQ", ":Q3")) {
                // We also check if the verb has a feminine form.
                // If not, we consider it’s better to not suggest the masculine one, as it can be considered invariable.
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q1"));
            }
        }
    }
................................................................................
    return "";
}

function suggMasPlur (sFlex, bSuggSimil=false) {
    // returns masculine plural forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses._get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":m") || sMorph.includes(":e")) {
                aSugg.add(suggPlur(sFlex));
            } else {
                let sStem = cr.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    mfsp.getMasForm(sStem, true).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cr.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q2")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q2"));
            } else if (conj.hasConj(sVerb, ":PQ", ":Q1")) {
                let sSugg = conj.getConj(sVerb, ":PQ", ":Q1");
                // it is necessary to filter these flexions, like “succédé” or “agi” that are not masculine plural
                if (sSugg.endsWith("s")) {
                    aSugg.add(sSugg);
................................................................................
}


function suggFemSing (sFlex, bSuggSimil=false) {
    // returns feminine singular forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses._get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":f") || sMorph.includes(":e")) {
                aSugg.add(suggSing(sFlex));
            } else {
                let sStem = cr.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    aSugg.add(sStem);
                }
            }
        } else {
            // a verb
            let sVerb = cr.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q3")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q3"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[si]")) {
................................................................................
    return "";
}

function suggFemPlur (sFlex, bSuggSimil=false) {
    // returns feminine plural forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses._get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":f") || sMorph.includes(":e")) {
                aSugg.add(suggPlur(sFlex));
            } else {
                let sStem = cr.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    aSugg.add(sStem+"s");
                }
            }
        } else {
            // a verb
            let sVerb = cr.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q4")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q4"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[pi]")) {
................................................................................
    return false;
}

function switchGender (sFlex, bPlur=null) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    if (bPlur === null) {
        for (let sMorph of _dAnalyses._get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                if (sMorph.includes(":s")) {
                    aSugg.add(suggMasSing(sFlex));
                } else if (sMorph.includes(":p")) {
                    aSugg.add(suggMasPlur(sFlex));
                }
            } else if (sMorph.includes(":m")) {
................................................................................
                } else {
                    aSugg.add(suggFemSing(sFlex));
                    aSugg.add(suggFemPlur(sFlex));
                }
            }
        }
    } else if (bPlur) {
        for (let sMorph of _dAnalyses._get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                aSugg.add(suggMasPlur(sFlex));
            } else if (sMorph.includes(":m")) {
                aSugg.add(suggFemPlur(sFlex));
            }
        }
    } else {
        for (let sMorph of _dAnalyses._get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                aSugg.add(suggMasSing(sFlex));
            } else if (sMorph.includes(":m")) {
                aSugg.add(suggFemSing(sFlex));
            }
        }
    }
................................................................................
        return Array.from(aSugg).join("|");
    }
    return "";
}

function switchPlural (sFlex) {
    let aSugg = new Set();
    for (let sMorph of _dAnalyses._get(sFlex, [])) { // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
        if (sMorph.includes(":s")) {
            aSugg.add(suggPlur(sFlex));
        } else if (sMorph.includes(":p")) {
            aSugg.add(suggSing(sFlex));
        }
    }
    if (aSugg.size > 0) {
................................................................................
function hasSimil (sWord, sPattern=null) {
    return phonet.hasSimil(sWord, sPattern);
}

function suggSimil (sWord, sPattern) {
    // return list of words phonetically similar to sWord and whom POS is matching sPattern
    let aSugg = phonet.selectSimil(sWord, sPattern);
    for (let sMorph of _dAnalyses._get(sWord, [])) {
        for (let e of conj.getSimil(sWord, sMorph)) {
            aSugg.add(e); 
        }
    }
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
................................................................................
        return "ce|cet";
    }
    return "ce";
}

function suggLesLa (sWord) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    if (_dAnalyses._get(sWord, []).some(s  =>  s.includes(":p"))) {
        return "les|la";
    }
    return "la";
}

function formatNumber (s) {
    let nLen = s.length;
    if (nLen <= 4 ) {
        return s;
    }
    let sRes = "";
    // nombre ordinaire
    let nEnd = nLen;
    while (nEnd > 0) {
        let nStart = Math.max(nEnd-3, 0);
        sRes = sRes ? s.slice(nStart, nEnd) + " " + sRes : sRes = s.slice(nStart, nEnd);
        nEnd = nEnd - 3;
    }
    // binaire
    if (/^[01]+$/.test(s)) {
        nEnd = nLen;
        let sBin = "";
        while (nEnd > 0) {
            let nStart = Math.max(nEnd-4, 0);
            sBin = sBin ? s.slice(nStart, nEnd) + " " + sBin : sBin = s.slice(nStart, nEnd);
            nEnd = nEnd - 4;
        }
        sRes += "|" + sBin;
    }
    // numéros de téléphone
    if (nLen == 10) {
        if (s.startsWith("0")) {
            sRes += "|" + s.slice(0,2) + " " + s.slice(2,4) + " " + s.slice(4,6) + " " + s.slice(6,8) + " " + s.slice(8);   // téléphone français
            if (s[1] == "4" && (s[2]=="7" || s[2]=="8" || s[2]=="9")) {
                sRes += "|" + s.slice(0,4) + " " + s.slice(4,6) + " " + s.slice(6,8) + " " + s.slice(8);    // mobile belge
            }
            sRes += "|" + s.slice(0,3) + " " + s.slice(3,6) + " " + s.slice(6,8) + " " + s.slice(8);        // téléphone suisse
        }
        sRes += "|" + s.slice(0,4) + " " + s.slice(4,7) + "-" + s.slice(7);                                 // téléphone canadien ou américain
    } else if (nLen == 9 && s.startsWith("0")) {
        sRes += "|" + s.slice(0,3) + " " + s.slice(3,5) + " " + s.slice(5,7) + " " + s.slice(7,9);          // fixe belge 1
        sRes += "|" + s.slice(0,2) + " " + s.slice(2,5) + " " + s.slice(5,7) + " " + s.slice(7,9);          // fixe belge 2
    }
    return sRes;
}

function formatNF (s) {
    try {
        let m = /NF[  -]?(C|E|P|Q|S|X|Z|EN(?:[  -]ISO|))[  -]?([0-9]+(?:[\/‑-][0-9]+|))/i.exec(s);

>
>

>
|
|
|
>












|

|
|







 







|
<







 







|

|







 







|







 







|





|






|







 







|





|






|







 







|





|






|







 







|





|






|







 







|







 







|







|







 







|







 







|
|







 







|







|







|








|







|

|

|

|

|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
//// GRAMMAR CHECKING ENGINE PLUGIN: Suggestion mechanisms
/*jslint esversion: 6*/
/*global require*/

if (typeof(require) !== 'undefined') {
    var conj = require("resource://grammalecte/fr/conj.js");
    var mfsp = require("resource://grammalecte/fr/mfsp.js");
    var phonet = require("resource://grammalecte/fr/phonet.js");
}


//// verbs

function suggVerb (sFlex, sWho, funcSugg2=null) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sStem of stem(sFlex)) {
        let tTags = conj._getTags(sStem);
        if (tTags) {
            // we get the tense
            let aTense = new Set();
            for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
                let m;
                let zVerb = new RegExp (">"+sStem+" .*?(:(?:Y|I[pqsf]|S[pq]|K))", "g");
                while ((m = zVerb.exec(sMorph)) !== null) {
                    // stem must be used in regex to prevent confusion between different verbs (e.g. sauras has 2 stems: savoir and saurer)
                    if (m) {
                        if (m[1] === ":Y") {
                            aTense.add(":Ip");
                            aTense.add(":Iq");
                            aTense.add(":Is");
                        } else if (m[1] === ":P") {
................................................................................
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
}

function suggVerbInfi (sFlex) {
    return stem(sFlex).filter(sStem => conj.isVerb(sStem)).join("|");

}


const _dQuiEst = new Map ([
    ["je", ":1s"], ["j’", ":1s"], ["j’en", ":1s"], ["j’y", ":1s"],
    ["tu", ":2s"], ["il", ":3s"], ["on", ":3s"], ["elle", ":3s"],
    ["nous", ":1p"], ["vous", ":2p"], ["ils", ":3p"], ["elles", ":3p"]
................................................................................
    } else if (cMode == ":S") {
        lMode = _lSubjonctif;
    } else if (cMode.startsWith(":I") || cMode.startsWith(":S")) {
        lMode = [cMode];
    } else {
        return "";
    }
    let sWho = _dQuiEst.gl_get(sSuj.toLowerCase(), null);
    if (!sWho) {
        if (sSuj[0].gl_isLowerCase()) { // pas un pronom, ni un nom propre
            return "";
        }
        sWho = ":3s";
    }
    let aSugg = new Set();
    for (let sStem of stem(sFlex)) {
        let tTags = conj._getTags(sStem);
................................................................................

function suggPlur (sFlex, sWordToAgree=null) {
    // returns plural forms assuming sFlex is singular
    if (sWordToAgree) {
        if (!_dAnalyses.has(sWordToAgree) && !_storeMorphFromFSA(sWordToAgree)) {
            return "";
        }
        let sGender = cregex.getGender(_dAnalyses.gl_get(sWordToAgree, []));
        if (sGender == ":m") {
            return suggMasPlur(sFlex);
        } else if (sGender == ":f") {
            return suggFemPlur(sFlex);
        }
    }
    let aSugg = new Set();
................................................................................
    return "";
}

function suggMasSing (sFlex, bSuggSimil=false) {
    // returns masculine singular forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":m") || sMorph.includes(":e")) {
                aSugg.add(suggSing(sFlex));
            } else {
                let sStem = cregex.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    mfsp.getMasForm(sStem, false).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q1") && conj.hasConj(sVerb, ":PQ", ":Q3")) {
                // We also check if the verb has a feminine form.
                // If not, we consider it’s better to not suggest the masculine one, as it can be considered invariable.
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q1"));
            }
        }
    }
................................................................................
    return "";
}

function suggMasPlur (sFlex, bSuggSimil=false) {
    // returns masculine plural forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":m") || sMorph.includes(":e")) {
                aSugg.add(suggPlur(sFlex));
            } else {
                let sStem = cregex.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    mfsp.getMasForm(sStem, true).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q2")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q2"));
            } else if (conj.hasConj(sVerb, ":PQ", ":Q1")) {
                let sSugg = conj.getConj(sVerb, ":PQ", ":Q1");
                // it is necessary to filter these flexions, like “succédé” or “agi” that are not masculine plural
                if (sSugg.endsWith("s")) {
                    aSugg.add(sSugg);
................................................................................
}


function suggFemSing (sFlex, bSuggSimil=false) {
    // returns feminine singular forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":f") || sMorph.includes(":e")) {
                aSugg.add(suggSing(sFlex));
            } else {
                let sStem = cregex.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    aSugg.add(sStem);
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q3")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q3"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[si]")) {
................................................................................
    return "";
}

function suggFemPlur (sFlex, bSuggSimil=false) {
    // returns feminine plural forms
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
        if (!sMorph.includes(":V")) {
            // not a verb
            if (sMorph.includes(":f") || sMorph.includes(":e")) {
                aSugg.add(suggPlur(sFlex));
            } else {
                let sStem = cregex.getLemmaOfMorph(sMorph);
                if (mfsp.isFemForm(sStem)) {
                    aSugg.add(sStem+"s");
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q4")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q4"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[pi]")) {
................................................................................
    return false;
}

function switchGender (sFlex, bPlur=null) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    let aSugg = new Set();
    if (bPlur === null) {
        for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                if (sMorph.includes(":s")) {
                    aSugg.add(suggMasSing(sFlex));
                } else if (sMorph.includes(":p")) {
                    aSugg.add(suggMasPlur(sFlex));
                }
            } else if (sMorph.includes(":m")) {
................................................................................
                } else {
                    aSugg.add(suggFemSing(sFlex));
                    aSugg.add(suggFemPlur(sFlex));
                }
            }
        }
    } else if (bPlur) {
        for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                aSugg.add(suggMasPlur(sFlex));
            } else if (sMorph.includes(":m")) {
                aSugg.add(suggFemPlur(sFlex));
            }
        }
    } else {
        for (let sMorph of _dAnalyses.gl_get(sFlex, [])) {
            if (sMorph.includes(":f")) {
                aSugg.add(suggMasSing(sFlex));
            } else if (sMorph.includes(":m")) {
                aSugg.add(suggFemSing(sFlex));
            }
        }
    }
................................................................................
        return Array.from(aSugg).join("|");
    }
    return "";
}

function switchPlural (sFlex) {
    let aSugg = new Set();
    for (let sMorph of _dAnalyses.gl_get(sFlex, [])) { // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
        if (sMorph.includes(":s")) {
            aSugg.add(suggPlur(sFlex));
        } else if (sMorph.includes(":p")) {
            aSugg.add(suggSing(sFlex));
        }
    }
    if (aSugg.size > 0) {
................................................................................
function hasSimil (sWord, sPattern=null) {
    return phonet.hasSimil(sWord, sPattern);
}

function suggSimil (sWord, sPattern) {
    // return list of words phonetically similar to sWord and whom POS is matching sPattern
    let aSugg = phonet.selectSimil(sWord, sPattern);
    for (let sMorph of _dAnalyses.gl_get(sWord, [])) {
        for (let e of conj.getSimil(sWord, sMorph, sPattern)) {
            aSugg.add(e); 
        }
    }
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
................................................................................
        return "ce|cet";
    }
    return "ce";
}

function suggLesLa (sWord) {
    // we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    if (_dAnalyses.gl_get(sWord, []).some(s  =>  s.includes(":p"))) {
        return "les|la";
    }
    return "la";
}

function formatNumber (s) {
    let nLen = s.length;
    if (nLen < 4 ) {
        return s;
    }
    let sRes = "";
    // nombre ordinaire
    let nEnd = nLen;
    while (nEnd > 0) {
        let nStart = Math.max(nEnd-3, 0);
        sRes = sRes ? s.slice(nStart, nEnd) + "" + sRes : sRes = s.slice(nStart, nEnd);
        nEnd = nEnd - 3;
    }
    // binaire
    if (/^[01]+$/.test(s)) {
        nEnd = nLen;
        let sBin = "";
        while (nEnd > 0) {
            let nStart = Math.max(nEnd-4, 0);
            sBin = sBin ? s.slice(nStart, nEnd) + "" + sBin : sBin = s.slice(nStart, nEnd);
            nEnd = nEnd - 4;
        }
        sRes += "|" + sBin;
    }
    // numéros de téléphone
    if (nLen == 10) {
        if (s.startsWith("0")) {
            sRes += "|" + s.slice(0,2) + "" + s.slice(2,4) + " " + s.slice(4,6) + " " + s.slice(6,8) + " " + s.slice(8);   // téléphone français
            if (s[1] == "4" && (s[2]=="7" || s[2]=="8" || s[2]=="9")) {
                sRes += "|" + s.slice(0,4) + "" + s.slice(4,6) + " " + s.slice(6,8) + " " + s.slice(8);    // mobile belge
            }
            sRes += "|" + s.slice(0,3) + "" + s.slice(3,6) + " " + s.slice(6,8) + " " + s.slice(8);        // téléphone suisse
        }
        sRes += "|" + s.slice(0,4) + "" + s.slice(4,7) + "-" + s.slice(7);                                 // téléphone canadien ou américain
    } else if (nLen == 9 && s.startsWith("0")) {
        sRes += "|" + s.slice(0,3) + "" + s.slice(3,5) + " " + s.slice(5,7) + " " + s.slice(7,9);          // fixe belge 1
        sRes += "|" + s.slice(0,2) + "" + s.slice(2,5) + " " + s.slice(5,7) + " " + s.slice(7,9);          // fixe belge 2
    }
    return sRes;
}

function formatNF (s) {
    try {
        let m = /NF[  -]?(C|E|P|Q|S|X|Z|EN(?:[  -]ISO|))[  -]?([0-9]+(?:[\/‑-][0-9]+|))/i.exec(s);

Modified gc_lang/fr/modules-js/lexicographe.js from [7e54b6b49b] to [fd0872dfca].

1
2


3
4
5
6

7
8

9
10
11
12
13
14
15
16
17
...
153
154
155
156
157
158
159
































160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183




184










185
186
187


188
189
190
191
192
193





194
195
196
197
198
199
200
201

202
203
204
205

206
207
208
209
210
211
212

213
214

215
216
217
218

219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

267

// Grammalecte - Lexicographe
// License: MPL 2



"use strict";

${string}




const helpers = require("resource://grammalecte/helpers.js");


const _dTAGS = new Map ([
    [':G', "[mot grammatical]"],
    [':N', " nom,"],
    [':A', " adjectif,"],
    [':M1', " prénom,"],
    [':M2', " patronyme,"],
................................................................................

    ['en', " pronom adverbial"],
    ["m'en", " (me) pronom personnel objet + (en) pronom adverbial"],
    ["t'en", " (te) pronom personnel objet + (en) pronom adverbial"],
    ["s'en", " (se) pronom personnel objet + (en) pronom adverbial"]
]);


































class Lexicographe {

    constructor (oDict) {
        this.oDict = oDict;
        this._zElidedPrefix = new RegExp ("^([dljmtsncç]|quoiqu|lorsqu|jusqu|puisqu|qu)['’](.+)", "i");
        this._zCompoundWord = new RegExp ("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-((?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|t-(?:il|elle|on)|y|en|[mts][’'](?:y|en)|les?|l[aà]|[mt]oi|leur|lui|je|tu|ils?|elles?|on|[nv]ous)$", "i");
        this._zTag = new RegExp ("[:;/][a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ*][^:;/]*", "g");
    };

    analyzeText (sText) {
        sText = sText.replace(/[.,.?!:;…\/()\[\]“”«»"„{}–—#+*<>%=\n]/g, " ").replace(/\s+/g, " ");
        let iStart = 0;
        let iEnd = 0;
        let sHtml = '<div class="paragraph">\n';
        while ((iEnd = sText.indexOf(" ", iStart)) !== -1) {
            sHtml += this.analyzeWord(sText.slice(iStart, iEnd));
            iStart = iEnd + 1;
        }
        sHtml += this.analyzeWord(sText.slice(iStart));
        return sHtml + '</div>\n';
    }

    analyzeWord (sWord) {




        try {










            if (!sWord) {
                return "";
            }


            if (sWord._count("-") > 4) {
                return '<p><b class="mbok">' + sWord + "</b> <s>:</s> élément complexe indéterminé</p>\n";
            }
            if (sWord._isDigit()) {
                return '<p><b class="nb">' + sWord + "</b> <s>:</s> nombre</p>\n";
            }






            let sHtml = "";
            // préfixes élidés
            let m = this._zElidedPrefix.exec(sWord);
            if (m !== null) {
                sWord = m[2];
                sHtml += "<p><b>" + m[1] + "’</b> <s>:</s> " + _dPFX.get(m[1].toLowerCase()) + " </p>\n";
            }

            // mots composés
            let m2 = this._zCompoundWord.exec(sWord);
            if (m2 !== null) {
                sWord = m2[1];

            }
            // Morphologies
            let lMorph = this.oDict.getMorph(sWord);
            if (lMorph.length === 1) {
                sHtml += "<p><b>" + sWord + "</b> <s>:</s> " + this.formatTags(lMorph[0]) + "</p>\n";
            } else if (lMorph.length > 1) {
                sHtml += "<p><b>" + sWord + "</b><ul><li>" + [for (s of lMorph) if (s.includes(":")) this.formatTags(s)].join(" </li><li> ") + "</li></ul></p>\n";

            } else {
                sHtml += '<p><b class="unknown">' + sWord + "</b> <s>:</s>  absent du dictionnaire<p>\n";

            }
            // suffixe d’un mot composé
            if (m2) {
                sHtml += "<p>-<b>" + m2[2] + "</b> <s>:</s> " + this._formatSuffix(m2[2].toLowerCase()) + "</p>\n";

            }
            // Verbes
            //let aVerb = new Set([ for (s of lMorph) if (s.includes(":V")) s.slice(1, s.indexOf(" ")) ]);
            return sHtml;
        }
        catch (e) {
            helpers.logerror(e);

            return "#erreur";
        }
    };

    formatTags (sTags) {
        let sRes = "";
        sTags = sTags.replace(/V([0-3][ea]?)[itpqnmr_eaxz]+/, "V$1");
        let m;
        while ((m = this._zTag.exec(sTags)) !== null) {
            sRes += _dTAGS.get(m[0]);
            if (sRes.length > 100) {
                break;
................................................................................
            sRes += " [" + sTags.slice(1, sTags.indexOf(" ")) + "]";
        }
        if (!sRes) {
            sRes = "#Erreur. Étiquette inconnue : [" + sTags + "]";
            helpers.echo(sRes);
            return sRes;
        }
        return sRes._trimRight(",");
    };

    _formatSuffix (s) {
        if (s.startsWith("t-")) {
            return "“t” euphonique +" + _dAD.get(s.slice(2));
        }
        if (!s.includes("-")) {
            return _dAD.get(s.replace("’", "'"));
        }
        if (s.endsWith("ous")) {
            s += '2';
        }
        let nPos = s.indexOf("-");
        return _dAD.get(s.slice(0, nPos)) + " +" + _dAD.get(s.slice(nPos+1));
    };
}



exports.Lexicographe = Lexicographe;



>
>




>


>
|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
>
>
>
>

>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
<
<
|
<
|
>
>
>
>
>
|
<
<
<
<
|
<
|
>
|
|
|
|
>
|
<
|
|
<
<
<
>
|
<
>
|
<
<
<
>

<
<
<



>
|
|
<

|







 







|
|













|



>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

204








205





206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226


227

228
229
230
231
232
233
234




235

236
237
238
239
240
241
242
243

244
245



246
247

248
249



250
251



252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// Grammalecte - Lexicographe
// License: MPL 2
/*jslint esversion: 6*/
/*global require,exports*/

"use strict";

${string}
${map}


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");
}

const _dTAGS = new Map ([
    [':G', "[mot grammatical]"],
    [':N', " nom,"],
    [':A', " adjectif,"],
    [':M1', " prénom,"],
    [':M2', " patronyme,"],
................................................................................

    ['en', " pronom adverbial"],
    ["m'en", " (me) pronom personnel objet + (en) pronom adverbial"],
    ["t'en", " (te) pronom personnel objet + (en) pronom adverbial"],
    ["s'en", " (se) pronom personnel objet + (en) pronom adverbial"]
]);

const _dSeparator = new Map ([
    ['.', "point"],
    ['·', "point médian"],
    ['…', "points de suspension"],
    [':', "deux-points"],
    [';', "point-virgule"],
    [',', "virgule"],
    ['?', "point d’interrogation"],
    ['!', "point d’exclamation"],
    ['(', "parenthèse ouvrante"],
    [')', "parenthèse fermante"],
    ['[', "crochet ouvrante"],
    [']', "crochet fermante"],
    ['{', "accolade ouvrante"],
    ['}', "accolade fermante"],
    ['-', "tiret"],
    ['—', "tiret cadratin"],
    ['–', "tiret demi-cadratin"],
    ['«', "guillemet ouvrant (chevrons)"],
    ['»', "guillemet fermant (chevrons)"],
    ['“', "guillemet ouvrant double"],
    ['”', "guillemet fermant double"],
    ['‘', "guillemet ouvrant"],
    ['’', "guillemet fermant"],
    ['/', "signe de la division"],
    ['+', "signe de l’addition"],
    ['*', "signe de la multiplication"],
    ['=', "signe de l’égalité"],
    ['<', "inférieur à"],
    ['>', "supérieur à"],
]);


class Lexicographe {

    constructor (oDict) {
        this.oDict = oDict;
        this._zElidedPrefix = new RegExp ("^([dljmtsncç]|quoiqu|lorsqu|jusqu|puisqu|qu)['’](.+)", "i");
        this._zCompoundWord = new RegExp ("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-((?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|t-(?:il|elle|on)|y|en|[mts][’'](?:y|en)|les?|l[aà]|[mt]oi|leur|lui|je|tu|ils?|elles?|on|[nv]ous)$", "i");
        this._zTag = new RegExp ("[:;/][a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ*][^:;/]*", "g");

    }














    getInfoForToken (oToken) {
        // Token: .sType, .sValue, .nStart, .nEnd
        // return a list [type, token_string, values]
        let m = null;
        try {
            switch (oToken.sType) {
                case 'SEPARATOR':
                    return { sType: oToken.sType, sValue: oToken.sValue, aLabel: [_dSeparator.gl_get(oToken.sValue, "caractère indéterminé")] };
                    break;
                case 'NUM':
                    return { sType: oToken.sType, sValue: oToken.sValue, aLabel: ["nombre"] };
                    break;
                case 'LINK':
                    return { sType: oToken.sType, sValue: oToken.sValue.slice(0,40)+"…", aLabel: ["hyperlien"] };
                    break;
                case 'ELPFX':
                    let sTemp = oToken.sValue.replace("’", "").replace("'", "").replace("`", "").toLowerCase();
                    return { sType: oToken.sType, sValue: oToken.sValue, aLabel: [_dPFX.gl_get(sTemp, "préfixe élidé inconnu")] };
                    break;
                case 'WORD': 
                    if (oToken.sValue.gl_count("-") > 4) {


                        return { sType: "COMPLEX", sValue: oToken.sValue, aLabel: ["élément complexe indéterminé"] };

                    }
                    else if (this.oDict.isValidToken(oToken.sValue)) {
                        let lMorph = this.oDict.getMorph(oToken.sValue);
                        let aElem = [];
                        for (let s of lMorph){
                            if (s.includes(":"))  aElem.push( this._formatTags(s) );
                        }




                        return { sType: oToken.sType, sValue: oToken.sValue, aLabel: aElem};

                    }
                    else if (m = this._zCompoundWord.exec(oToken.sValue)) {
                        // mots composés
                        let lMorph = this.oDict.getMorph(m[1]);
                        let aElem = [];
                        for (let s of lMorph){
                            if (s.includes(":"))  aElem.push( this._formatTags(s) );
                        }

                        aElem.push("-" + m[2] + ": " + this._formatSuffix(m[2].toLowerCase()));
                        return { sType: oToken.sType, sValue: oToken.sValue, aLabel: aElem };



                    }
                    else {

                        return { sType: "UNKNOWN", sValue: oToken.sValue, aLabel: ["inconnu du dictionnaire"] };
                    }



                    break;
            }



        }
        catch (e) {
            helpers.logerror(e);
        }
        return null;
    }


    _formatTags (sTags) {
        let sRes = "";
        sTags = sTags.replace(/V([0-3][ea]?)[itpqnmr_eaxz]+/, "V$1");
        let m;
        while ((m = this._zTag.exec(sTags)) !== null) {
            sRes += _dTAGS.get(m[0]);
            if (sRes.length > 100) {
                break;
................................................................................
            sRes += " [" + sTags.slice(1, sTags.indexOf(" ")) + "]";
        }
        if (!sRes) {
            sRes = "#Erreur. Étiquette inconnue : [" + sTags + "]";
            helpers.echo(sRes);
            return sRes;
        }
        return sRes.gl_trimRight(",");
    }

    _formatSuffix (s) {
        if (s.startsWith("t-")) {
            return "“t” euphonique +" + _dAD.get(s.slice(2));
        }
        if (!s.includes("-")) {
            return _dAD.get(s.replace("’", "'"));
        }
        if (s.endsWith("ous")) {
            s += '2';
        }
        let nPos = s.indexOf("-");
        return _dAD.get(s.slice(0, nPos)) + " +" + _dAD.get(s.slice(nPos+1));
    }
}


if (typeof(exports) !== 'undefined') {
    exports.Lexicographe = Lexicographe;
}

Modified gc_lang/fr/modules-js/mfsp.js from [eacc870aa5] to [4ade9720c3].

1


2
3
4


5
6
7
8
9


10
11
12
13
14
15
16

17









18

19


20

21
22

23
24
25
26
27
28
29


30
31


32
33
34
35
36
37
38
39
40
41
42


43
44


45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81




















82
83
84
85



// Grammalecte



"use strict";



const helpers = require("resource://grammalecte/helpers.js");
const echo = helpers.echo;

const oData = JSON.parse(helpers.loadFile("resource://grammalecte/fr/mfsp_data.json"));



// list of affix codes
const _lTagMiscPlur = oData.lTagMiscPlur;
const _lTagMasForm = oData.lTagMasForm;

// dictionary of words with uncommon plurals (-x, -ux, english, latin and italian plurals) and tags to generate them
const _dMiscPlur = helpers.objectToMap(oData.dMiscPlur);


// dictionary of feminine forms and tags to generate masculine forms (singular and plural)









const _dMasForm = helpers.objectToMap(oData.dMasForm);







function isFemForm (sWord) {

    // returns True if sWord exists in _dMasForm
    return _dMasForm.has(sWord);
}

function getMasForm (sWord, bPlur) {
    // returns masculine form with feminine form
    if (_dMasForm.has(sWord)) {


        return [ for (sTag of _whatSuffixCodes(sWord, bPlur))  _modifyStringWithSuffixCode(sWord, sTag) ];
    }


    return [];
}

function hasMiscPlural (sWord) {
    // returns True if sWord exists in dMiscPlur
    return _dMiscPlur.has(sWord);
}

function getMiscPlural (sWord) {
    // returns plural form with singular form
    if (_dMiscPlur.has(sWord)) {


        return [ for (sTag of _lTagMiscPlur[_dMiscPlur.get(sWord)].split("|"))  _modifyStringWithSuffixCode(sWord, sTag) ];
    }


    return [];
}

function _whatSuffixCodes (sWord, bPlur) {

    // necessary only for dMasFW
    let sSfx = _lTagMasForm[_dMasForm.get(sWord)];
    if (sSfx.includes("/")) {
        if (bPlur) {
            return sSfx.slice(sSfx.indexOf("/")+1).split("|");
        }
        return sSfx.slice(0, sSfx.indexOf("/")).split("|");
    }
    return sSfx.split("|");
}

function _modifyStringWithSuffixCode (sWord, sSfx) {
    // returns sWord modified by sSfx
    if (!sWord) {
        return "";
    }
    if (sSfx === "0") {
        return sWord;
    }
    try {
        if (sSfx[0] !== '0') {
            return sWord.slice(0, -(sSfx.charCodeAt(0)-48)) + sSfx.slice(1); // 48 is the ASCII code for "0"
        } else {
            return sWord + sSfx.slice(1);
        }
    }
    catch (e) {
        console.log(e);
        return "## erreur, code : " + sSfx + " ##";
    }
}























exports.isFemForm = isFemForm;
exports.getMasForm = getMasForm;
exports.hasMiscPlural = hasMiscPlural;
exports.getMiscPlural = getMiscPlural;




>
>



>
>
|
<
|
<

>
>
|
|
|
<
|
<
<
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>

<
>
|
|
|

|
|
|
>
>
|
|
>
>
|
|

|
|
|
|

|
|
|
>
>
|
|
>
>
|
|

<
>
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>
1
2
3
4
5
6
7
8
9

10

11
12
13
14
15
16

17


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Grammalecte
/*jslint esversion: 6*/
/*global console,require,exports,browser*/

"use strict";


if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");

}



var mfsp = {
    // list of affix codes
    _lTagMiscPlur: [],
    _lTagMasForm: [],

    // dictionary of words with uncommon plurals (-x, -ux, english, latin and italian plurals) and tags to generate them


    _dMiscPlur: new Map(),
    // dictionary of feminine forms and tags to generate masculine forms (singular and plural)
    _dMasForm: new Map(),

    bInit: false,
    init: function (sJSONData) {
        try {
            let _oData = JSON.parse(sJSONData);
            this._lTagMiscPlur = _oData.lTagMiscPlur;
            this._lTagMasForm = _oData.lTagMasForm;
            this._dMiscPlur = helpers.objectToMap(_oData.dMiscPlur);
            this._dMasForm = helpers.objectToMap(_oData.dMasForm);
            this.bInit = true;
        }
        catch (e) {
            console.error(e);
        }
    },


    isFemForm: function (sWord) {
        // returns True if sWord exists in this._dMasForm
        return this._dMasForm.has(sWord);
    },

    getMasForm: function (sWord, bPlur) {
        // returns masculine form with feminine form
        if (this._dMasForm.has(sWord)) {
            let aMasForm = [];
            for (let sTag of this._whatSuffixCode(sWord, bPlur)){
                aMasForm.push( this._modifyStringWithSuffixCode(sWord, sTag) );
            }
            return aMasForm;
        }
        return [];
    },

    hasMiscPlural: function (sWord) {
        // returns True if sWord exists in dMiscPlur
        return this._dMiscPlur.has(sWord);
    },

    getMiscPlural: function (sWord) {
        // returns plural form with singular form
        if (this._dMiscPlur.has(sWord)) {
            let aMiscPlural = [];
            for (let sTag of this._lTagMiscPlur[this._dMiscPlur.get(sWord)].split("|")){
                aMiscPlural.push( this._modifyStringWithSuffixCode(sWord, sTag) );
            }
            return aMiscPlural;
        }
        return [];
    },


    _whatSuffixCode: function (sWord, bPlur) {
        // necessary only for dMasFW
        let sSfx = this._lTagMasForm[this._dMasForm.get(sWord)];
        if (sSfx.includes("/")) {
            if (bPlur) {
                return sSfx.slice(sSfx.indexOf("/")+1).split("|");
            }
            return sSfx.slice(0, sSfx.indexOf("/")).split("|");
        }
        return sSfx.split("|");
    },

    _modifyStringWithSuffixCode: function (sWord, sSfx) {
        // returns sWord modified by sSfx
        if (!sWord) {
            return "";
        }
        if (sSfx === "0") {
            return sWord;
        }
        try {
            if (sSfx[0] !== '0') {
                return sWord.slice(0, -(sSfx.charCodeAt(0)-48)) + sSfx.slice(1); // 48 is the ASCII code for "0"
            } else {
                return sWord + sSfx.slice(1);
            }
        }
        catch (e) {
            console.log(e);
            return "## erreur, code : " + sSfx + " ##";
        }
    }
};


// Initialization
if (!mfsp.bInit && typeof(browser) !== 'undefined') {
    // WebExtension
    mfsp.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/mfsp_data.json")));
} else if (!mfsp.bInit && typeof(require) !== 'undefined') {
    // Add-on SDK and Thunderbird
    mfsp.init(helpers.loadFile("resource://grammalecte/fr/mfsp_data.json"));
} else if (mfsp.bInit){
    console.log("Module mfsp déjà initialisé");
} else {
    console.log("Module mfsp non initialisé");
}


if (typeof(exports) !== 'undefined') {
    exports._lTagMiscPlur = mfsp._lTagMiscPlur;
    exports._lTagMasForm = mfsp._lTagMasForm;
    exports._dMiscPlur = mfsp._dMiscPlur;
    exports._dMasForm = mfsp._dMasForm;
    exports.init = mfsp.init;
    exports.isFemForm = mfsp.isFemForm;
    exports.getMasForm = mfsp.getMasForm;
    exports.hasMiscPlural = mfsp.hasMiscPlural;
    exports.getMiscPlural = mfsp.getMiscPlural;
    exports._whatSuffixCode = mfsp._whatSuffixCode;
    exports._modifyStringWithSuffixCode = mfsp._modifyStringWithSuffixCode;
}

Modified gc_lang/fr/modules-js/mfsp_data.json from [9cc6f3064c] to [e5057cbf5b].

cannot compute difference between binary files

Modified gc_lang/fr/modules-js/phonet.js from [1ddd439263] to [b4e35b2c18].

1

2

3
4
5
6
7










8
9
10

11


12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34




35
36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67



















68
69
70

// Grammalecte - Suggestion phonétique



const helpers = require("resource://grammalecte/helpers.js");
const echo = helpers.echo;

const oData = JSON.parse(helpers.loadFile("resource://grammalecte/fr/phonet_data.json"));











const _dWord = helpers.objectToMap(oData.dWord);
const _lSet = oData.lSet;
const _dMorph = helpers.objectToMap(oData.dMorph);







function hasSimil (sWord, sPattern=null) {
    // return True if there is list of words phonetically similar to sWord
    if (!sWord) {
        return false;
    }
    if (_dWord.has(sWord)) {
        if (sPattern) {
            return getSimil(sWord).some(sSimil => _dMorph._get(sSimil, []).some(sMorph => sMorph.search(sPattern) >= 0));
        }
        return true;
    }
    if (sWord.slice(0,1)._isUpperCase()) {
        sWord = sWord.toLowerCase();
    }

    if (sPattern) {
        return getSimil(sWord).some(sSimil => _dMorph._get(sSimil, []).some(sMorph => sMorph.search(sPattern) >= 0));
    }
    return _dWord.has(sWord);
}

function getSimil (sWord) {




    // return list of words phonetically similar to sWord
    if (!sWord) {
        return [];
    }
    if (_dWord.has(sWord)) {
        return _lSet[_dWord.get(sWord)];
    }
    if (sWord.slice(0,1)._isUpperCase()) {
        sWord = sWord.toLowerCase();
    }
    if (_dWord.has(sWord)) {
        return _lSet[_dWord.get(sWord)];
    }

    return [];
}

function selectSimil (sWord, sPattern) {
    // return list of words phonetically similar to sWord and whom POS is matching sPattern
    if (!sPattern) {
        return new Set(getSimil(sWord));
    }
    let aSelect = new Set();
    for (let sSimil of getSimil(sWord)) {
        for (let sMorph of _dMorph._get(sSimil, [])) {
            if (sMorph.search(sPattern) >= 0) {
                aSelect.add(sSimil);
            }
        }
    }
    return aSelect;
}






















exports.hasSimil = hasSimil;
exports.getSimil = getSimil;
exports.selectSimil = selectSimil;


>

>
|
<
|
<

>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
>
>
|
>

|
|
|
|
|
|
|
|
|
|
|
|
|
<
>
|
|
|
|
|
|
<
>
>
>
>
|
|
|
|
|
|
|
|
|
<
|
|
|
>
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
1
2
3
4
5

6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Grammalecte - Suggestion phonétique
/*jslint esversion: 6*/

if (typeof(require) !== 'undefined') {
    var helpers = require("resource://grammalecte/helpers.js");

}



var phonet = {
    _dWord: new Map(),
    _lSet: [],
    _dMorph: new Map(),

    bInit: false,
    init: function (sJSONData) {
        try {
            let _oData = JSON.parse(sJSONData);
            this._dWord = helpers.objectToMap(_oData.dWord);
            this._lSet = _oData.lSet;
            this._dMorph = helpers.objectToMap(_oData.dMorph);
            this.bInit = true;
        }
        catch (e) {
            console.error(e);
        }
    },

    hasSimil: function (sWord, sPattern=null) {
        // return True if there is list of words phonetically similar to sWord
        if (!sWord) {
            return false;
        }
        if (this._dWord.has(sWord)) {
            if (sPattern) {
                return this.getSimil(sWord).some(sSimil => this._dMorph.gl_get(sSimil, []).some(sMorph => sMorph.search(sPattern) >= 0));
            }
            return true;
        }
        if (sWord.slice(0,1).gl_isUpperCase()) {
            sWord = sWord.toLowerCase();

            if (this._dWord.has(sWord)) {
                if (sPattern) {
                    return this.getSimil(sWord).some(sSimil => this._dMorph.gl_get(sSimil, []).some(sMorph => sMorph.search(sPattern) >= 0));
                }
                return true;
            }
        }

        return false;
    },

    getSimil: function (sWord) {
        // return list of words phonetically similar to sWord
        if (!sWord) {
            return [];
        }
        if (this._dWord.has(sWord)) {
            return this._lSet[this._dWord.get(sWord)];
        }
        if (sWord.slice(0,1).gl_isUpperCase()) {
            sWord = sWord.toLowerCase();

            if (this._dWord.has(sWord)) {
                return this._lSet[this._dWord.get(sWord)];
            }
        }
        return [];
    },

    selectSimil: function (sWord, sPattern) {
        // return list of words phonetically similar to sWord and whom POS is matching sPattern
        if (!sPattern) {
            return new Set(this.getSimil(sWord));
        }
        let aSelect = new Set();
        for (let sSimil of this.getSimil(sWord)) {
            for (let sMorph of this._dMorph.gl_get(sSimil, [])) {
                if (sMorph.search(sPattern) >= 0) {
                    aSelect.add(sSimil);
                }
            }
        }
        return aSelect;
    }
};


// Initialization
if (!phonet.bInit && typeof(browser) !== 'undefined') {
    // WebExtension
    phonet.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/phonet_data.json")));
} else if (!phonet.bInit && typeof(require) !== 'undefined') {
    // Add-on SDK and Thunderbird
    phonet.init(helpers.loadFile("resource://grammalecte/fr/phonet_data.json"));
} else if (phonet.bInit){
    console.log("Module phonet déjà initialisé");
} else {
    console.log("Module phonet non initialisé");
}


if (typeof(exports) !== 'undefined') {
    exports._dWord = phonet._dWord;
    exports._lSet = phonet._lSet;
    exports._dMorph = phonet._dMorph;
    exports.init = phonet.init;
    exports.hasSimil = phonet.hasSimil;
    exports.getSimil = phonet.getSimil;
    exports.selectSimil = phonet.selectSimil;
}

Modified gc_lang/fr/modules-js/phonet_data.json from [41faff5ff9] to [93017c34d1].

cannot compute difference between binary files

Modified gc_lang/fr/modules-js/textformatter.js from [694a6a3f2d] to [1785f80db7].

1


2
3
4
5
6
7
8
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280

281
282
283
284
285
// Grammalecte - text formatter



"use strict";

${map}


// Latin letters: http://unicode-table.com/fr/
................................................................................
    "nbsp_repair":                [ [/([\[(])[   ]([!?:;])/g, "$1$2"],
                                    [/(https?|ftp)[   ]:\/\//g, "$1://"],
                                    [/&([a-z]+)[   ];/g, "&$1;"],
                                    [/&#([0-9]+|x[0-9a-fA-F]+)[   ];/g, "&#$1;"] ],
    //// missing spaces
    "add_space_after_punctuation":[ [/[;!…](?=[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ])/g, "$& "],
                                    [/[?](?=[A-ZÀ-ÖØ-ßĀ-ʯ])/g, "? "],
                                    [/\.(?=[a-zA-Zà-öÀ-Öø-ÿØ-ßĀ-ʯ][a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ])/g, ". "],
                                    [/\.(?=À)/g, ". "],
                                    [/[,:](?=[a-zA-Zà-öÀ-Öø-ÿØ-ßĀ-ʯ])/g, "$& "],
                                    [/([a-zA-Zà-öÀ-Öø-ÿØ-ßĀ-ʯ]),(?=[0-9])/g, "$1, "] ],
    "add_space_around_hyphens":   [ [/ [-–—](?=[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ"«“'‘])/g, "$& "],
                                    [/([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ"»”'’])([-–—]) /g, "$1 $2 "] ],
    "add_space_repair":           [ [/DnT, ([wA])\b/g, "DnT,$1"] ],
    //// erase
................................................................................
                                    [/^(qu|lorsqu|puisqu|quoiqu|presqu|jusqu|aujourd|entr|quelqu|prud) /ig, "$1’"] ],
    "ma_1letter_lowercase":       [ [/[  ]([ldjnmtscç]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"] ],
    "ma_1letter_uppercase":       [ [/[  ]([LDJNMTSCÇ]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"],
                                    [/^([LDJNMTSCÇ]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"] ]
};


const dDefaultOptions = new Map ([
    ["ts_units", true],
    ["start_of_paragraph", true],
    ["end_of_paragraph", true],
    ["between_words", true],
    ["before_punctuation", true],
    ["within_parenthesis", true],
    ["within_square_brackets", true],
................................................................................
    ["etc", true],
    ["missing_hyphens", true],
    ["ma_word", true],
    ["ma_1letter_lowercase", false],
    ["ma_1letter_uppercase", false]
]);

const dOptions = dDefaultOptions._shallowCopy();


class TextFormatter {

    constructor () {
        this.sLang = "fr";
    };

    formatText (sText, dOpt=null) {
        if (dOpt !== null) {
            dOptions._updateOnlyExistingKeys(dOpt);
        }
        for (let [sOptName, bVal] of dOptions) {
            if (bVal && oReplTable.has(sOptName)) {
                for (let [zRgx, sRep] of oReplTable[sOptName]) {
                    sText = sText.replace(zRgx, sRep);
                }
            }
        }
        return sText;
    };


    getDefaultOptions () {
        return dDefaultOptions;
    }
}


if (typeof(exports) !== 'undefined') {
    exports.TextFormatter = TextFormatter;
    exports.oReplTable = oReplTable;
}

>
>







 







|







 







|







 







|






|



|

|







<
|
>

|


>





1
2
3
4
5
6
7
8
9
10
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
// Grammalecte - text formatter
/*jslint esversion: 6*/
/*global exports*/

"use strict";

${map}


// Latin letters: http://unicode-table.com/fr/
................................................................................
    "nbsp_repair":                [ [/([\[(])[   ]([!?:;])/g, "$1$2"],
                                    [/(https?|ftp)[   ]:\/\//g, "$1://"],
                                    [/&([a-z]+)[   ];/g, "&$1;"],
                                    [/&#([0-9]+|x[0-9a-fA-F]+)[   ];/g, "&#$1;"] ],
    //// missing spaces
    "add_space_after_punctuation":[ [/[;!…](?=[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ])/g, "$& "],
                                    [/[?](?=[A-ZÀ-ÖØ-ßĀ-ʯ])/g, "? "],
                                    [/\.(?=[A-ZÀ-ÖØ-ßĀ-ʯ][a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ])/g, ". "],
                                    [/\.(?=À)/g, ". "],
                                    [/[,:](?=[a-zA-Zà-öÀ-Öø-ÿØ-ßĀ-ʯ])/g, "$& "],
                                    [/([a-zA-Zà-öÀ-Öø-ÿØ-ßĀ-ʯ]),(?=[0-9])/g, "$1, "] ],
    "add_space_around_hyphens":   [ [/ [-–—](?=[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ"«“'‘])/g, "$& "],
                                    [/([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ"»”'’])([-–—]) /g, "$1 $2 "] ],
    "add_space_repair":           [ [/DnT, ([wA])\b/g, "DnT,$1"] ],
    //// erase
................................................................................
                                    [/^(qu|lorsqu|puisqu|quoiqu|presqu|jusqu|aujourd|entr|quelqu|prud) /ig, "$1’"] ],
    "ma_1letter_lowercase":       [ [/[  ]([ldjnmtscç]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"] ],
    "ma_1letter_uppercase":       [ [/[  ]([LDJNMTSCÇ]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"],
                                    [/^([LDJNMTSCÇ]) (?=[aàeéêiîoôuyhAÀEÉÊIÎOÔUYH])/g, "$1’"] ]
};


const dTFDefaultOptions = new Map ([
    ["ts_units", true],
    ["start_of_paragraph", true],
    ["end_of_paragraph", true],
    ["between_words", true],
    ["before_punctuation", true],
    ["within_parenthesis", true],
    ["within_square_brackets", true],
................................................................................
    ["etc", true],
    ["missing_hyphens", true],
    ["ma_word", true],
    ["ma_1letter_lowercase", false],
    ["ma_1letter_uppercase", false]
]);

const dTFOptions = dTFDefaultOptions.gl_shallowCopy();


class TextFormatter {

    constructor () {
        this.sLang = "fr";
    }

    formatText (sText, dOpt=null) {
        if (dOpt !== null) {
            dTFOptions.gl_updateOnlyExistingKeys(dOpt);
        }
        for (let [sOptName, bVal] of dTFOptions) {
            if (bVal && oReplTable.has(sOptName)) {
                for (let [zRgx, sRep] of oReplTable[sOptName]) {
                    sText = sText.replace(zRgx, sRep);
                }
            }
        }
        return sText;

    }

    getDefaultOptions () {
        return dTFDefaultOptions;
    }
}


if (typeof(exports) !== 'undefined') {
    exports.TextFormatter = TextFormatter;
    exports.oReplTable = oReplTable;
}

Modified gc_lang/fr/modules/conj.py from [55e5497434] to [ec8e754549].

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
91
92
93
94
95
96
97

















98
99
100
101
102
103
104
def getVtyp (sVerb):
    "returns raw informations about sVerb"
    if sVerb not in _dVerb:
        return None
    return _lVtyp[_dVerb[sVerb][0]]


def getSimil (sWord, sMorph):
    if ":V" not in sMorph:
        return set()
    sInfi = sMorph[1:sMorph.find(" ")]
    tTags = _getTags(sInfi)
    aSugg = set()
    if ":Q" in sMorph:
        # we suggest conjugated forms
        if ":V1" in sMorph:
            aSugg.add(sInfi)
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":1s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
................................................................................
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q2"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q3"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"))
        aSugg.discard("")
        # if there is only one past participle (epi inv), unreliable.
        if len(aSugg) == 1:
            aSugg.clear()

















    return aSugg


def _getTags (sVerb):
    "returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)"
    if sVerb not in _dVerb:
        return None







|





|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
def getVtyp (sVerb):
    "returns raw informations about sVerb"
    if sVerb not in _dVerb:
        return None
    return _lVtyp[_dVerb[sVerb][0]]


def getSimil (sWord, sMorph, sFilter=None):
    if ":V" not in sMorph:
        return set()
    sInfi = sMorph[1:sMorph.find(" ")]
    tTags = _getTags(sInfi)
    aSugg = set()
    if ":Q" in sMorph or ":Y" in sMorph:
        # we suggest conjugated forms
        if ":V1" in sMorph:
            aSugg.add(sInfi)
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":1s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
................................................................................
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q2"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q3"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"))
        aSugg.discard("")
        # if there is only one past participle (epi inv), unreliable.
        if len(aSugg) == 1:
            aSugg.clear()
        if ":V1" in sMorph:
            aSugg.add(sInfi)
    return aSugg


def getConjSimilInfiV1 (sInfi):
    if sInfi not in _dVerb:
        return set()
    tTags = _getTags(sInfi)
    aSugg = set()
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":2s"))
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3p"))
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Is", ":1s"))
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
    aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":2p"))
    aSugg.discard("")
    return aSugg


def _getTags (sVerb):
    "returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)"
    if sVerb not in _dVerb:
        return None

Modified gc_lang/fr/modules/conj_data.py from [964dbf9799] to [96768c85b8].

cannot compute difference between binary files

Modified gc_lang/fr/modules/gce_suggestions.py from [69bb078e98] to [e839f7efe5].

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
    aSugg = set()
    for sStem in stem(sFlex):
        tTags = conj._getTags(sStem)
        if tTags:
            # we get the tense
            aTense = set()
            for sMorph in _dAnalyses.get(sFlex, []): # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
                for m in re.finditer(sStem+" .*?(:(?:Y|I[pqsf]|S[pq]|K|P))", sMorph):
                    # stem must be used in regex to prevent confusion between different verbs (e.g. sauras has 2 stems: savoir and saurer)
                    if m:
                        if m.group(1) == ":Y":
                            aTense.add(":Ip")
                            aTense.add(":Iq")
                            aTense.add(":Is")
                        elif m.group(1) == ":P":
................................................................................


def suggSimil (sWord, sPattern=None):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    aSugg = phonet.selectSimil(sWord, sPattern)
    for sMorph in _dAnalyses.get(sWord, []):
        for e in conj.getSimil(sWord, sMorph):
            aSugg.add(e)
        #aSugg = aSugg.union(conj.getSimil(sWord, sMorph))
    if aSugg:
        return "|".join(aSugg)
    return ""


................................................................................
    return "la"


_zBinary = re.compile("^[01]+$")

def formatNumber (s):
    nLen = len(s)
    if nLen <= 4:
        return s
    sRes = ""
    # nombre ordinaire
    nEnd = nLen
    while nEnd > 0:
        nStart = max(nEnd-3, 0)
        sRes = s[nStart:nEnd] + " " + sRes  if sRes  else s[nStart:nEnd]







|







 







|







 







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
    aSugg = set()
    for sStem in stem(sFlex):
        tTags = conj._getTags(sStem)
        if tTags:
            # we get the tense
            aTense = set()
            for sMorph in _dAnalyses.get(sFlex, []): # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
                for m in re.finditer(">"+sStem+" .*?(:(?:Y|I[pqsf]|S[pq]|K|P))", sMorph):
                    # stem must be used in regex to prevent confusion between different verbs (e.g. sauras has 2 stems: savoir and saurer)
                    if m:
                        if m.group(1) == ":Y":
                            aTense.add(":Ip")
                            aTense.add(":Iq")
                            aTense.add(":Is")
                        elif m.group(1) == ":P":
................................................................................


def suggSimil (sWord, sPattern=None):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    aSugg = phonet.selectSimil(sWord, sPattern)
    for sMorph in _dAnalyses.get(sWord, []):
        for e in conj.getSimil(sWord, sMorph, sPattern):
            aSugg.add(e)
        #aSugg = aSugg.union(conj.getSimil(sWord, sMorph))
    if aSugg:
        return "|".join(aSugg)
    return ""


................................................................................
    return "la"


_zBinary = re.compile("^[01]+$")

def formatNumber (s):
    nLen = len(s)
    if nLen < 4:
        return s
    sRes = ""
    # nombre ordinaire
    nEnd = nLen
    while nEnd > 0:
        nStart = max(nEnd-3, 0)
        sRes = s[nStart:nEnd] + " " + sRes  if sRes  else s[nStart:nEnd]

Modified gc_lang/fr/modules/mfsp_data.py from [1852623acf] to [8457d42cd4].

cannot compute difference between binary files

Modified gc_lang/fr/modules/phonet.py from [31589198ae] to [d03956eafb].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
        return False
    if sWord in _dWord:
        if sPattern:
            return any(re.search(sPattern, sMorph)  for sSimil in getSimil(sWord)  for sMorph in _dMorph.get(sSimil, []))
        return True
    if sWord[0:1].isupper():
        sWord = sWord.lower()
    if sWord in _dWord:
        if sPattern:
            return any(re.search(sPattern, sMorph)  for sSimil in getSimil(sWord)  for sMorph in _dMorph.get(sSimil, []))
        return True
    return False


def getSimil (sWord):
    "return list of words phonetically similar to sWord"
    if not sWord:
        return []
    if sWord in _dWord:
        return _lSet[_dWord[sWord]]
    if sWord[0:1].isupper():
        sWord = sWord.lower()
    if sWord in _dWord:
        return _lSet[_dWord[sWord]]
    return []


def selectSimil (sWord, sPattern):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    if not sPattern:
        return set(getSimil(sWord))
    aSelect = set()
    for sSimil in getSimil(sWord):
        for sMorph in _dMorph.get(sSimil, []):
            if re.search(sPattern, sMorph):
                aSelect.add(sSimil)
    return aSelect







|
|
|
|











|
|













14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
        return False
    if sWord in _dWord:
        if sPattern:
            return any(re.search(sPattern, sMorph)  for sSimil in getSimil(sWord)  for sMorph in _dMorph.get(sSimil, []))
        return True
    if sWord[0:1].isupper():
        sWord = sWord.lower()
        if sWord in _dWord:
            if sPattern:
                return any(re.search(sPattern, sMorph)  for sSimil in getSimil(sWord)  for sMorph in _dMorph.get(sSimil, []))
            return True
    return False


def getSimil (sWord):
    "return list of words phonetically similar to sWord"
    if not sWord:
        return []
    if sWord in _dWord:
        return _lSet[_dWord[sWord]]
    if sWord[0:1].isupper():
        sWord = sWord.lower()
        if sWord in _dWord:
            return _lSet[_dWord[sWord]]
    return []


def selectSimil (sWord, sPattern):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    if not sPattern:
        return set(getSimil(sWord))
    aSelect = set()
    for sSimil in getSimil(sWord):
        for sMorph in _dMorph.get(sSimil, []):
            if re.search(sPattern, sMorph):
                aSelect.add(sSimil)
    return aSelect

Modified gc_lang/fr/modules/phonet_data.py from [98fafd6c52] to [522351bc79].

cannot compute difference between binary files

Modified gc_lang/fr/modules/tests.py from [43f5975205] to [78ace698ff].

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    def setUpClass (cls):
        cls.lSet = [
            ["ce", "se"],
            ["ces", "ses", "sais", "sait"],
            ["cet", "cette", "sept", "set", "sets"],
            ["dé", "dés", "dès", "dais", "des"],
            ["don", "dons", "dont"],
            ["été", "étais", "était", "étai", "étés", "étaient"],
            ["faire", "fer", "fers", "ferre", "ferres", "ferrent"],
            ["fois", "foi", "foie", "foies"],
            ["la", "là", "las"],
            ["mes", "mets", "met", "mai", "mais"],
            ["mon", "mont", "monts"],
            ["mot", "mots", "maux"],
            ["moi", "mois"],
            ["notre", "nôtre", "nôtres"],
            ["or", "ors", "hors"],
            ["hou", "houe", "houes", "ou", "où", "houx"],
            ["peu", "peux", "peut"],
            ["ses", "ces", "sais", "sait"],
            ["son", "sons", "sont"],
            ["tes", "taie", "taies", "thé", "thés"],
            ["toi", "toit", "toits"],
            ["ton", "tons", "thon", "thons", "tond", "tonds"],
            ["voir", "voire"]
        ]

    def test_getsimil (self):
        for aSet in self.lSet:







|













|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    def setUpClass (cls):
        cls.lSet = [
            ["ce", "se"],
            ["ces", "ses", "sais", "sait"],
            ["cet", "cette", "sept", "set", "sets"],
            ["dé", "dés", "dès", "dais", "des"],
            ["don", "dons", "dont"],
            ["été", "étaie", "étaies", "étais", "était", "étai", "étés", "étaient"],
            ["faire", "fer", "fers", "ferre", "ferres", "ferrent"],
            ["fois", "foi", "foie", "foies"],
            ["la", "là", "las"],
            ["mes", "mets", "met", "mai", "mais"],
            ["mon", "mont", "monts"],
            ["mot", "mots", "maux"],
            ["moi", "mois"],
            ["notre", "nôtre", "nôtres"],
            ["or", "ors", "hors"],
            ["hou", "houe", "houes", "ou", "où", "houx"],
            ["peu", "peux", "peut"],
            ["ses", "ces", "sais", "sait"],
            ["son", "sons", "sont"],
            ["tes", "tais", "tait", "taie", "taies", "thé", "thés"],
            ["toi", "toit", "toits"],
            ["ton", "tons", "thon", "thons", "tond", "tonds"],
            ["voir", "voire"]
        ]

    def test_getsimil (self):
        for aSet in self.lSet:

Modified gc_lang/fr/oxt/About/About.py from [03886f10df] to [030798e09e].

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89







90
91
92
93
94
95
96

97
98
99
100
101



102
103
104
105
106
107
108
109
    def run (self, sLang):
        try:
            dUI = ab_strings.getUI(sLang)

            # dialog
            self.xDialog = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialogModel', self.ctx)
            self.xDialog.Width = 160
            self.xDialog.Height = 175
            self.xDialog.Title = dUI.get('windowtitle', "#err")
            xWindowSize = helpers.getWindowSize()
            self.xDialog.PositionX = int((xWindowSize.Width / 2) - (self.xDialog.Width / 2))
            self.xDialog.PositionY = int((xWindowSize.Height / 2) - (self.xDialog.Height / 2))
            
            # xWidgets
            hspace = 60
            nLblWidth = 140
            nLblHeight = 20
            nDescWidth = 140
            nDescHeight = 40
            nURLcolor = 0x4444FF
            
            xFD0 = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFD0.Height = 20
            #xFD0.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFD0.Name = "Verdana"
            
................................................................................
            xFD2.Name = "Verdana"

            xFD3 = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFD3.Height = 12
            xFD3.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFD3.Name = "Verdana"
            
            # Infos
            lblTitle = self._addWidget('lblTitle', 'FixedText', 60, 5, 100, 20, Label = dUI.get('title', "#err"), Align = 0, FontDescriptor = xFD0)
            lblVersion = self._addWidget('lblVersion', 'FixedText', 62, 25, 80, 10, Label = dUI.get('version', "#err"), Align = 0, FontDescriptor = xFD2)
            lblLicense = self._addWidget('lblLicense', 'FixedText', 62, 35, 80, 10, Label = dUI.get('license', "#err"), Align = 0, FontDescriptor = xFD2)
            lblWebsite = self._addWidget('lblWebsite', 'FixedHyperlink', 62, 45, 60, 10, Label = dUI.get('website', "#err"), Align = 0, \
                                         URL="http://www.dicollecte.org/grammalecte", FontDescriptor = xFD1, TextColor = nURLcolor)

            # logo
            xDefaultContext = self.ctx.ServiceManager.DefaultContext
            xPackageInfoProvider = xDefaultContext.getValueByName("/singletons/com.sun.star.deployment.PackageInformationProvider")
            sExtPath = xPackageInfoProvider.getPackageLocation("French.linguistic.resources.from.Dicollecte.by.OlivierR")
            imgLogo = self._addWidget('imgLogo', 'ImageControl', 5, 5, 50, 50, ImageURL = sExtPath+"/img/logo100.png", Border = 0, ScaleMode = 1)









            # Python version
            self._addWidget('lblpython', 'FixedText', 10, 60, 140, 10, Align = 1, TextColor = 0x888888, FontDescriptor = xFD2, \
                            Label = dUI.get('pythonver', "#err") + "{0[0]}.{0[1]}.{0[2]}".format(sys.version_info))

            # other
            line = self._addWidget('line', 'FixedLine', 10, 73, nDescWidth, 10)


            lblMsg = self._addWidget('lblMsg', 'FixedText', 10, 85, nDescWidth, 10, Label = dUI.get('message', "#err"), FontDescriptor = xFD2, Align = 1)
            lblURL1 = self._addWidget('lblURL1', 'FixedHyperlink', 10, 95, nDescWidth, 10, Label = dUI.get('sponsor', "#err"), \
                                      Align = 1, URL="http://www.lamouette.org/", FontDescriptor = xFD3, TextColor = nURLcolor)
            imgSponsor = self._addWidget('imgSponsor', 'ImageControl', 5, 107, 150, 50, ImageURL = sExtPath+"/img/LaMouette_small.png", Border = 0, ScaleMode = 1)
            lblURL2 = self._addWidget('lblURL2', 'FixedHyperlink', 10, 160, nDescWidth, 10, Label = dUI.get('link', "#err"), \



                                      Align = 1, URL="http://www.dicollecte.org/grammalecte/soutiens.php", FontDescriptor = xFD1, TextColor = nURLcolor)
            # button            
            #button = self._addWidget('close', 'Button', self.xDialog.Width - 25, self.xDialog.Height - 20, 20, 14, \
            #                         Label = dUI.get('close', "#err"), FontDescriptor = xFD1, TextColor = 0x004400)
            
            # container
            self.xContainer = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialog', self.ctx)
            self.xContainer.setModel(self.xDialog)







|






<

<
<
<







 







<
<
<
<
<
<
<




|
>

>
>
>
>
>
>
>

|



|

>
|
|
|
|
|
>
>
>
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50

51



52
53
54
55
56
57
58
..
66
67
68
69
70
71
72







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    def run (self, sLang):
        try:
            dUI = ab_strings.getUI(sLang)

            # dialog
            self.xDialog = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialogModel', self.ctx)
            self.xDialog.Width = 160
            self.xDialog.Height = 320
            self.xDialog.Title = dUI.get('windowtitle', "#err")
            xWindowSize = helpers.getWindowSize()
            self.xDialog.PositionX = int((xWindowSize.Width / 2) - (self.xDialog.Width / 2))
            self.xDialog.PositionY = int((xWindowSize.Height / 2) - (self.xDialog.Height / 2))
            
            # xWidgets

            nLblWidth = 140



            nURLcolor = 0x4444FF
            
            xFD0 = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFD0.Height = 20
            #xFD0.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFD0.Name = "Verdana"
            
................................................................................
            xFD2.Name = "Verdana"

            xFD3 = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFD3.Height = 12
            xFD3.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFD3.Name = "Verdana"
            







            # logo
            xDefaultContext = self.ctx.ServiceManager.DefaultContext
            xPackageInfoProvider = xDefaultContext.getValueByName("/singletons/com.sun.star.deployment.PackageInformationProvider")
            sExtPath = xPackageInfoProvider.getPackageLocation("French.linguistic.resources.from.Dicollecte.by.OlivierR")
            #imgLogo = self._addWidget('imgLogo', 'ImageControl', 5, 5, 50, 50, ImageURL = sExtPath+"/img/logo100.png", Border = 0, ScaleMode = 1)
            imgMainLogo = self._addWidget('imgMainLogo', 'ImageControl', 5, 5, 150, 80, ImageURL = sExtPath+"/img/logo120_text.png", Border = 0, ScaleMode = 1)

            # Infos
            #lblTitle = self._addWidget('lblTitle', 'FixedText', 60, 5, 100, 20, Label = dUI.get('title', "#err"), Align = 0, FontDescriptor = xFD0)            
            lblVersion = self._addWidget('lblVersion', 'FixedText', 5, 90, nLblWidth, 10, Label = dUI.get('version', "#err"), Align = 1, FontDescriptor = xFD2)
            lblLicense = self._addWidget('lblLicense', 'FixedText', 5, 100, nLblWidth, 10, Label = dUI.get('license', "#err"), Align = 1, FontDescriptor = xFD2)
            lblWebsite = self._addWidget('lblWebsite', 'FixedHyperlink', 5, 110, nLblWidth, 10, Label = dUI.get('website', "#err"), Align = 1, \
                                         URL="http://www.dicollecte.org/?from=grammalecte-lo", FontDescriptor = xFD1, TextColor = nURLcolor)

            # Python version
            self._addWidget('lblpython', 'FixedText', 10, 125, nLblWidth, 10, Align = 1, TextColor = 0x888888, FontDescriptor = xFD2, \
                            Label = dUI.get('pythonver', "#err") + "{0[0]}.{0[1]}.{0[2]}".format(sys.version_info))

            # other
            line = self._addWidget('line', 'FixedLine', 10, 140, nLblWidth, 10)

            # sponsors
            lblMsg = self._addWidget('lblMsg', 'FixedText', 10, 155, nLblWidth, 10, Label = dUI.get('message', "#err"), FontDescriptor = xFD2, Align = 1)
            lblURL1 = self._addWidget('lblURL1', 'FixedHyperlink', 10, 170, nLblWidth, 10, Label = dUI.get('sponsor', "#err"), \
                                      Align = 1, URL="http://lamouette.org/?from=grammalecte-lo", FontDescriptor = xFD3, TextColor = nURLcolor)
            imgSponsor = self._addWidget('imgSponsor', 'ImageControl', 5, 180, 150, 50, ImageURL = sExtPath+"/img/LaMouette_small.png", Border = 0, ScaleMode = 1)
            lblURL2 = self._addWidget('lblURL2', 'FixedHyperlink', 10, 235, nLblWidth, 10, Label = dUI.get('sponsor2', "#err"), \
                                      Align = 1, URL="https://www.algoo.fr/?from=grammalecte-lo", FontDescriptor = xFD3, TextColor = nURLcolor)
            imgSponsor2 = self._addWidget('imgSponsor2', 'ImageControl', 5, 245, 150, 50, ImageURL = sExtPath+"/img/Algoo_logo.png", Border = 0, ScaleMode = 1)
            lblURL3 = self._addWidget('lblURL3', 'FixedHyperlink', 10, 300, nLblWidth, 10, Label = dUI.get('link', "#err"), \
                                      Align = 1, URL="http://www.dicollecte.org/#thanks", FontDescriptor = xFD1, TextColor = nURLcolor)
            # button            
            #button = self._addWidget('close', 'Button', self.xDialog.Width - 25, self.xDialog.Height - 20, 20, 14, \
            #                         Label = dUI.get('close', "#err"), FontDescriptor = xFD1, TextColor = 0x004400)
            
            # container
            self.xContainer = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialog', self.ctx)
            self.xContainer.setModel(self.xDialog)

Modified gc_lang/fr/oxt/About/ab_strings.py from [e915407fb3] to [cb9cefc663].

13
14
15
16
17
18
19

20
21
22
23
24
25
26
..
28
29
30
31
32
33
34

35
36
37
38
39
            "license": "Licence : GPL 3",
            "website": "Site web",

            "pythonver": "Machine virtuelle Python : v",

            "message": "Avec le soutien de",
            "sponsor": "La Mouette…",

            "link": "… et de nombreux contributeurs.",

            "close": "~OK"
          },
    "en": {
            "windowtitle": "About…",
            "title": "Grammalecte",
................................................................................
            "license": "License: GPL 3",
            "website": "Web site",

            "pythonver": "Python virtual machine: v",

            "message": "With the support of",
            "sponsor": "La Mouette…",

            "link": "… and many contributors.",

            "close": "~OK"
          }
}







>







 







>





13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
29
30
31
32
33
34
35
36
37
38
39
40
41
            "license": "Licence : GPL 3",
            "website": "Site web",

            "pythonver": "Machine virtuelle Python : v",

            "message": "Avec le soutien de",
            "sponsor": "La Mouette…",
            "sponsor2": "Algoo…",
            "link": "… et de nombreux contributeurs.",

            "close": "~OK"
          },
    "en": {
            "windowtitle": "About…",
            "title": "Grammalecte",
................................................................................
            "license": "License: GPL 3",
            "website": "Web site",

            "pythonver": "Python virtual machine: v",

            "message": "With the support of",
            "sponsor": "La Mouette…",
            "sponsor2": "Algoo…",
            "link": "… and many contributors.",

            "close": "~OK"
          }
}

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/README_dict_fr.txt from [b339c2b007] to [5f4220f497].

1
2
3
4
5
6
7
8
9
10
11
_______________________________________________________________________________

   DICTIONNAIRES ORTHOGRAPHIQUES FRANÇAIS
   version 6.1

   Olivier R. - dicollecte<at>free<dot>fr
   Dicollecte : http://www.dicollecte.org/

   Licence :
     MPL : Mozilla Public License
     version 2.0  --  http://www.mozilla.org/MPL/2.0/



|







1
2
3
4
5
6
7
8
9
10
11
_______________________________________________________________________________

   DICTIONNAIRES ORTHOGRAPHIQUES FRANÇAIS
   version 6.2

   Olivier R. - dicollecte<at>free<dot>fr
   Dicollecte : http://www.dicollecte.org/

   Licence :
     MPL : Mozilla Public License
     version 2.0  --  http://www.mozilla.org/MPL/2.0/

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff from [72d1113ea1] to [9ff9f77367].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v6.1
# par Olivier R. -- licence MPL 2.0
# Généré le 03-06-2017 à 22:26
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.




|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v6.2
# par Olivier R. -- licence MPL 2.0
# Généré le 26-07-2017 à 09:33
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.dic from [e917007d9d] to [15ed4f1dbd].

1
2
3
4
5
6
7
8
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
529
530
531
532
533
534
535

536
537
538
539
540
541
542
...
651
652
653
654
655
656
657

658
659
660
661
662
663
664
...
896
897
898
899
900
901
902

903
904
905
906
907
908
909
....
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
....
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
....
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
....
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
....
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
....
3217
3218
3219
3220
3221
3222
3223

3224
3225
3226
3227
3228
3229
3230
....
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473
3474
3475
....
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
....
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
....
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
....
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
....
6210
6211
6212
6213
6214
6215
6216

6217
6218
6219
6220
6221
6222
6223
....
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
....
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085

9086
9087
9088
9089
9090
9091
9092
....
9307
9308
9309
9310
9311
9312
9313

9314
9315
9316
9317
9318
9319
9320
....
9758
9759
9760
9761
9762
9763
9764

9765
9766
9767
9768
9769
9770
9771
....
9900
9901
9902
9903
9904
9905
9906

9907
9908
9909
9910
9911
9912
9913
.....
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
.....
11399
11400
11401
11402
11403
11404
11405

11406
11407
11408
11409
11410
11411
11412
.....
11726
11727
11728
11729
11730
11731
11732


11733
11734
11735
11736
11737
11738
11739
.....
12550
12551
12552
12553
12554
12555
12556

12557
12558
12559
12560
12561
12562
12563
.....
12647
12648
12649
12650
12651
12652
12653

12654
12655
12656
12657
12658
12659
12660
.....
15085
15086
15087
15088
15089
15090
15091

15092
15093
15094
15095
15096
15097
15098
.....
15106
15107
15108
15109
15110
15111
15112

15113
15114
15115
15116
15117
15118
15119
.....
15609
15610
15611
15612
15613
15614
15615

15616
15617
15618
15619
15620
15621
15622
.....
16759
16760
16761
16762
16763
16764
16765

16766
16767
16768
16769
16770
16771
16772
.....
17890
17891
17892
17893
17894
17895
17896

17897
17898
17899
17900
17901
17902
17903
.....
18232
18233
18234
18235
18236
18237
18238

18239
18240
18241
18242
18243
18244
18245
.....
18632
18633
18634
18635
18636
18637
18638
18639
18640
18641
18642
18643
18644
18645
18646
18647
.....
19626
19627
19628
19629
19630
19631
19632

19633
19634
19635
19636
19637
19638
19639
.....
24296
24297
24298
24299
24300
24301
24302

24303
24304
24305
24306
24307
24308
24309
.....
24742
24743
24744
24745
24746
24747
24748

24749
24750
24751
24752
24753
24754
24755
.....
25820
25821
25822
25823
25824
25825
25826

25827
25828
25829
25830
25831
25832
25833
.....
27613
27614
27615
27616
27617
27618
27619

27620
27621
27622
27623
27624
27625
27626
.....
28412
28413
28414
28415
28416
28417
28418

28419
28420
28421
28422
28423
28424
28425
.....
28461
28462
28463
28464
28465
28466
28467

28468
28469
28470
28471
28472
28473
28474
.....
29091
29092
29093
29094
29095
29096
29097

29098
29099
29100
29101
29102
29103
29104
.....
29806
29807
29808
29809
29810
29811
29812

29813
29814
29815
29816
29817
29818
29819
.....
32415
32416
32417
32418
32419
32420
32421

32422
32423
32424
32425
32426
32427
32428
.....
34197
34198
34199
34200
34201
34202
34203


34204
34205
34206
34207
34208
34209
34210
.....
34232
34233
34234
34235
34236
34237
34238

34239
34240
34241
34242
34243
34244
34245
.....
34827
34828
34829
34830
34831
34832
34833

34834
34835
34836
34837
34838
34839
34840
.....
35033
35034
35035
35036
35037
35038
35039


35040
35041
35042
35043
35044
35045
35046
.....
36200
36201
36202
36203
36204
36205
36206

36207
36208
36209
36210
36211
36212
36213
.....
36410
36411
36412
36413
36414
36415
36416

36417
36418
36419
36420
36421
36422
36423
.....
37080
37081
37082
37083
37084
37085
37086

37087
37088
37089
37090
37091
37092
37093
.....
40503
40504
40505
40506
40507
40508
40509

40510
40511
40512
40513
40514
40515
40516
.....
41655
41656
41657
41658
41659
41660
41661

41662
41663
41664
41665
41666
41667
41668
.....
41771
41772
41773
41774
41775
41776
41777

41778
41779
41780
41781
41782
41783
41784

41785
41786
41787
41788
41789
41790
41791
.....
42277
42278
42279
42280
42281
42282
42283


42284
42285
42286
42287
42288
42289
42290
.....
42666
42667
42668
42669
42670
42671
42672

42673
42674
42675
42676
42677
42678
42679
.....
42907
42908
42909
42910
42911
42912
42913

42914
42915
42916
42917
42918
42919
42920
.....
45910
45911
45912
45913
45914
45915
45916

45917
45918
45919
45920
45921
45922
45923
.....
46208
46209
46210
46211
46212
46213
46214

46215
46216
46217
46218
46219
46220
46221
.....
46280
46281
46282
46283
46284
46285
46286

46287
46288
46289
46290
46291
46292
46293
.....
52664
52665
52666
52667
52668
52669
52670

52671
52672
52673
52674
52675
52676
52677
.....
55094
55095
55096
55097
55098
55099
55100
55101
55102
55103
55104
55105
55106
55107
55108
55109
.....
58116
58117
58118
58119
58120
58121
58122

58123
58124
58125
58126
58127
58128
58129
.....
59816
59817
59818
59819
59820
59821
59822

59823
59824
59825
59826
59827
59828
59829
.....
60063
60064
60065
60066
60067
60068
60069

60070

60071
60072
60073
60074
60075
60076
60077
.....
60208
60209
60210
60211
60212
60213
60214

60215
60216
60217
60218
60219
60220
60221
.....
60624
60625
60626
60627
60628
60629
60630

60631
60632
60633
60634
60635
60636
60637
.....
60901
60902
60903
60904
60905
60906
60907

60908
60909
60910
60911
60912
60913
60914
.....
61354
61355
61356
61357
61358
61359
61360
61361
61362
61363
61364
61365
61366
61367
61368
61369
.....
62769
62770
62771
62772
62773
62774
62775

62776
62777
62778
62779
62780
62781
62782
.....
62852
62853
62854
62855
62856
62857
62858


62859
62860
62861

62862
62863
62864
62865
62866
62867
62868
.....
63292
63293
63294
63295
63296
63297
63298

63299
63300
63301
63302
63303
63304
63305
.....
68940
68941
68942
68943
68944
68945
68946

68947
68948
68949
68950
68951
68952
68953
.....
69198
69199
69200
69201
69202
69203
69204

69205
69206
69207
69208
69209
69210
69211
.....
71783
71784
71785
71786
71787
71788
71789

71790
71791
71792
71793
71794
71795
71796
.....
73460
73461
73462
73463
73464
73465
73466

73467
73468
73469
73470
73471
73472
73473
.....
73611
73612
73613
73614
73615
73616
73617

73618

73619
73620
73621
73622
73623
73624
73625
.....
73656
73657
73658
73659
73660
73661
73662

73663
73664
73665
73666
73667
73668
73669
.....
76259
76260
76261
76262
76263
76264
76265

76266
76267
76268
76269
76270
76271
76272
.....
77388
77389
77390
77391
77392
77393
77394

77395
77396
77397
77398
77399
77400
77401
.....
78636
78637
78638
78639
78640
78641
78642

78643
78644
78645
78646
78647
78648
78649
80033
&
1er/--
1ers/--
1re/--
1res/--
1ʳᵉ/--
1ʳᵉˢ/--
................................................................................
Aïcha/L'D'Q'
Aïd/L'D'Q'
Aida/L'D'Q'
Aidan/L'D'Q'
Aïd-el-Adha/L'
Aïd-el-Kébir/L'
Aiden/L'D'Q'
Aignan
Aigoual/L'D'
Aigrain/L'D'Q'
Aimé/L'D'Q'
Aimée/L'D'Q'
Ain/L'
Airaines/L'D'Q'
Airbnb/L'D'Q'
................................................................................
Arion/L'D'Q'
Aristarque/L'D'Q'
Aristide/L'D'Q'
Aristophane/L'D'Q'
Aristote/L'D'Q'
Arizona/L'D'
Arjuna/L'D'Q'

Arkansas/L'D'
Arkema/L'D'Q'
Arkham/L'D'Q'
Arkhangelsk/L'D'Q'
Arlene/L'D'Q'
Arlène/L'D'Q'
Arles/L'D'Q'
................................................................................
Aurélien/L'D'Q'
Aurelio/L'D'Q'
Auriane/L'D'Q'
Aurillac/L'D'Q'
Auriol/L'D'Q'
Aurore/L'D'Q'
Auschwitz/L'D'Q'

Austerlitz/L'D'Q'
Austin/L'D'Q'
Australasie/L'D'Q'
Australie/L'D'
Australie-Méridionale/L'D'
Australie-Occidentale/L'D'
Austrasie/L'D'
................................................................................
Benoîte
Benozillo
Benpro
Bentama
Bentham
Bentley
Benveniste

Berchem-Sainte-Agathe
Berck
Bercy
Bérenger
Bérengère
Bérénice
Bérézina
................................................................................
Caine
Caïphe
Caire
Caitlin
Caitlyn
Calabre
Calais

Calc
Calcutta
Calderón
Caleb
Calédonie
Calestienne
Calgary
................................................................................
Chostakovitch
Chris
Christa
Christel
Christèle
Christelle
Christian

Christiane
Christie
Christina
Christine
Christmas
Christoffel
Christoph
................................................................................
Cincinnati
Cindy
Ciney
Ciotat
Circassie
Circé
Cirey-sur-Vezouze

Cisjordanie
Cîteaux
Citroën
City
Claire
Clamart
Clara
................................................................................
Eure-et-Loir/L'D'
Euripide/L'D'Q'
Eurobaromètre/S*
Eurogroupe/L'
Euronext/L'D'Q'
Europe/L'D'
Europol/D'Q'

Eurozone/L'
Eurydice/L'D'Q'
Eusèbe/L'D'Q'
Euterpe/L'D'Q'
Eva/L'D'Q'
Éva/L'D'Q'
Évaine/L'D'Q'
................................................................................
Fayard
Fayçal
Fayette
Fécamp
Fed
FedEx
Federer

Federico
Fehling
Feist
Feïza
Feldane
Felicia
Félicie
................................................................................
Halluin/L'D'Q'
Ham/L'D'Q'
Hamas
Hambourg
Hamel
Hamid/L'D'Q'
Hamilton

Hamme
HammerFall
Hammourabi
Hamont-Achel/L'D'Q'
Hampshire
Ham-sur-Heure-Nalinnes/L'D'Q'
Hamza/L'D'Q'
................................................................................
Howard
Hubble
Hubei
Hubert/L'D'Q'
Hubscher
Hudson/L'D'Q'
Huelgoat

Hugo/L'D'Q'
Hugo/L'D'Q'
Hugues/L'D'Q'
Huguette
Hulshout/L'D'Q'
Hume
Hun/S.
................................................................................
IMSI/L'D'Q'
INED/L'D'Q'
INPI/L'D'Q'
INRA/L'D'Q'
INRI/L'D'Q'
INRIA/L'D'Q'
INSA/L'D'Q'
INSERM/L'D'Q'
IP/L'D'Q'
IRA/L'
IRD/L'D'Q'
IRFM/L'D'Q'
IRL
IRM/L'D'Q'
IRSTEA/L'D'Q'
................................................................................
Ingrid/L'D'Q'
Inkscape/L'D'Q'
Inn/L'D'
Inna/L'D'Q'
Innsmouth/L'D'Q'
Inovia/L'D'Q'
Insee/L'D'Q'

Insulinde/L'D'
Intel/L'D'Q'
Internet/D'Q'
Interpol/D'Q'
Io/L'D'Q'
Ionesco/L'D'Q'
Ioulia/L'D'Q'
................................................................................
Léonore
Léontine
Léopold
Léopoldine
Leopoldt
Léopoldville
Leroy

Lesbos
Lesieur
Lesley
Leslie
Lesneven
Lesotho
Lesse
................................................................................
Noisy-le-Grand
Noisy-le-Sec
Nokia
Nolan
Nolwenn
Nora
Norbert
Nord
Nord-Kivu
Nord-Pas-de-Calais
Nord-du-Québec
Nordine
Norfolk
Norique
Norma
................................................................................
Reidemeister
Reiko
Reims
Reiten
Relecq-Kerhuon
Rellich
Rembrandt

Rémi
Remich
Remire-Montjoly
Remus
Rémy
Renaix
Renan
................................................................................
Rosita
Rosny-sous-Bois
Ross
Rossini
Rossinière
Rostand
Roswell
Roth
Roth
Rothbard
Rothschild
Rotin
Rotselaar
Rotterdam
Roubaix
................................................................................
additionnelle/F*
additionnellement/D'Q'
additionner/a4p+
additionneuse/F*
additive/F*
additivement/D'Q'
additivité/S*
addon/S*
adducteur/S*
adduction/S*
adduit/S*
adèle/S*

adelphophagie/S*
adénine/S*
adénite/S*
adénocarcinome/S*
adénogramme/S*
adénoïde/S*
adénoïdectomie/S*
................................................................................
aérobie/S*
aérobie/S*
aérobiologie/S*
aérobiologique/S*
aérobiose/S*
aérobique/S*
aérocâble/S*

aéro-club/S*
aérocolie/S*
aérodigestive/F*
aérodistorsion/S*
aérodrome/S*
aérodynamicienne/F*
aérodynamique/S*
................................................................................
agroalimentaire/S*
agro-alimentaire/S*
agroalimentaire/S*
agro-alimentaire/S*
agrobiologie/S*
agrobiologique/S*
agrobiologiste/S*

agrocarburant/S*
agro-carburant/S*
agrochimie/S*
agrochimique/S*
agrochimiste/S*
agroclimatique/S*
agro-climatique/S*
................................................................................
aillade/S*
ailler/a2p+
ailleurs/L'D'Q'
ailloli/S*
aimable/S*
aimablement/D'Q'
aimant/S*

aimantation/S*
aimante/F*
aimanter/a4p+
aimantin/S*
aimantine/F*
aimée/F*
aimer/a4p+
................................................................................
amathie/S*
amatir/f2p+
amatrice/F*
amaurose/S*
amazone/S*
amazonienne/F*
amazonite/S*
ambages/D'Q'
ambassade/S*
ambassadrice/F*
ambiance/S*
ambiancer/a1p.
ambianceuse/F*
ambiante/F*
ambidextre/S*
................................................................................
annuité/S*
annulabilité/S*
annulable/S*
annulaire/S*
annulation/S*
annulative/F*
annulatrice/F*

annuler/a4p+
annuus
anoblir/f4p+
anoblissante/F*
anoblissement/S*
anode/S*
anodine/F*
................................................................................
antiémeute/L'D'Q'
antienne/S*
antienzyme/S*
anti-enzyme/S*
antiépileptique/S*
antiesclavagiste/S*
antiétatique/S*


antifading/S*
antifascisme/S*
antifasciste/S*
antiféminisme/S*
antiféministe/S*
antiferment/S*
antiferroélectricité/S*
................................................................................
arc/S*
arcade/S*
arcane/S*
arcanson/S*
arcasse/S*
arcature/S*
arc-boutant/L'D'Q'

arc-bouter/a4p+
arccos
arccosh
arccotan
arccotanh
arc-doubleau/L'D'Q'
arceau/X*
................................................................................
archontat/S*
archonte/S*
archosaurien/S*
archure/S*
arçon/S*
arçonner/a2p+
arcs-boutants/D'Q'

arcs-doubleaux/D'Q'
arcs-en-ciel/D'Q'
arcsin
arcsinh
arctan
arctanh
arctique/S*
................................................................................
bascule/S.
basculement/S.
basculer/a0p+
basculeur/S.
bas-culotte/S.
bas-de-casse
base/S.

base-ball/S.
baselle/S.
baser/a0p+
bas-fond/S.
basicité/S.
baside/S.
basidiomycète/S.
................................................................................
basilique/S.
basin/S.
basiphile/S.
basique/S.
basiquement
bas-jointée/F.
basket/S.

basket-ball/S.
basketteuse/F.
bas-mât/S.
basmati/S.
basocellulaire/S.
basoche/S.
basochienne/F.
................................................................................
bernard-l'hermite
berne/S.
berner/a0p+
berneuse/F.
bernicle/S.
bernique
bernique/S.

berrichonne/F.
bersaglier/S.
berthon/S.
bertillonnage/S.
béryl/S.
bérylliose/S.
béryllium/S.
................................................................................
bongo/S.
bonheur/S.
bonheur-du-jour
bonheurs-du-jour
bonhomie/S.
bonhomme
bonhomme/S.

boni/S.
bonichon/S.
bonifiante/F.
bonification/S.
bonifier/a0p+
boniment/S.
bonimenter/a0p.
................................................................................
bugne/S.
bugrane/S.
buguée/F.
build/S.
building/S.
buire/S.
buis

buisson/S.
buisson-ardent
buissonnante/F.
buissonnet/S.
buissonneuse/W.
buissonnière/F.
buissons-ardents
................................................................................
cadrer/a0p+
cadreuse/F.
cadriciel/S.
caduc/S.
caducée/S.
caducifoliée/F.
caducité/S.

caduque/S.
cæcale/W.
cæcotrophie/S.
cæcum/S.
caennaise/F.
cænogenèse/S.
cæsine
................................................................................
camping-car/S.
camping-caravaning/S.
camping-gaz
campinoise/F.
campo/S.
campus
camuse/F.
canada
canada/S.
canadianisme/S.
canadienne/F.
canado-américaine/F.
canaille/S.
canaillement
canaillerie/S.
canaillocratie/S.
................................................................................
caucasique/S.
cauchemar/S.
cauchemarder/a0p.
cauchemardesque/S.
cauchemardeuse/W.
caucus
caudale/W.

caudataire/S.
caudataire/S.
caudillo/S.
caudine/S.
caudrette/S.
caulescente/F.
caulicole/S.
................................................................................
corruptrice/F.
corsage/S.
corsaire/S.
corse/S.
corselet/S.
corser/a0p+
corset/S.

corseter/b0p+
corseterie/S.
corsetière/F.
corso/S.
cortège/S.
cortès
cortex
................................................................................
covenant/S.
covendeuse/F.
cover-girl/S.
covoiturage/S.
covoiturer/a0p+
covoitureuse/F.
covolume/S.

cow-boy/S.
cowper/S.
coxale/W.
coxalgie/S.
coxalgique/S.
coxarthrose/S.
coxer/a0p+
................................................................................
cytotoxique/S.
czar/S.
czardas
czimbalum/S.
d
d/||--
dB/||--

dacryoadénite/S.
dacryocystite/S.
dactyle/S.
dactylique/S.
dactylo/S.
dactylogramme/S.
dactylographe/S.
................................................................................
dénombrabilité/S.
dénombrable/S.
dénombrement/S.
dénombrer/a0p+
dénominateur/S.
dénomination/S.
dénominative/F.

dénommer/a0p+
dénoncer/a0p+
dénonciation/S.
dénonciatrice/F.
dénotation/S.
dénotationnelle/F.
dénotative/F.
................................................................................
désincorporer/a0p+
désincrustation/S.
désincruster/a0p+
désinculper/a0p+
désindenter/a0p+
désindexation/S.
désindexer/a0p+

désindustrialisation/S.
désindustrialiser/a0p+
désinence/S.
désinentielle/F.
désinfectante/F.
désinfecter/a0p+
désinfection/S.
................................................................................
désinviter/a0p+
désinvolte/S.
désinvoltement
désinvolture/S.
désir/S.
désirabilité/S.
désirable/S.

désirer/a0p+
désireuse/W.
désistement/S.
désister/a0p+
desman/S.
desmine/S.
desmodonte/S.
................................................................................
diarrhée/S.
diarrhéique/S.
diarthrose/S.
diascope/S.
diascopie/S.
diascordium/S.
diaspora/S.

diastase/S.
diastasique/S.
diastème/S.
diastéréo-isomère/S.
diastole/S.
diastolique/S.
diastratique/S.
................................................................................
diversement
diverses
diversifiable/S.
diversification/S.
diversifier/a0p+
diversiforme/S.
diversion/S.

diversité/S.
diverticule/S.
diverticulite/S.
diverticulose/S.
divertimento/S.
divertir/f0p+
divertissante/F.
................................................................................
endoénergétique/S*
endogame/S*
endogamie/S*
endogamique/S*
endogée/F*
endogène/S*
endogénéité/S*

endolocalisation/S*
endolorir/f2p+
endolorissement/S*
endolymphe/S*
endomètre/S*
endométriose/S*
endométrite/S*
................................................................................
ethmoïdale/W*
ethmoïde/S*
ethmoïdite/S*
ethnarchie/S*
ethnarque/S*
ethnicisation/S*
ethniciser/a2p+


ethnicité/S*
ethnico-religieuse/W*
ethnie/S*
ethnique/S*
ethniquement/D'Q'
ethnobiologie/S*
ethnobotanique/S*
................................................................................
ethnométhodologue/S*
ethnomusicologie/S*
ethnomusicologue/S*
ethnonyme/S*
ethnonymie/S*
ethnopsychiatrie/S*
ethnopsychologie/S*

ethnoreligieuse/W*
éthographie/S*
éthologie/S*
éthologique/S*
éthologiste/S*
éthologue/S*
ethos/L'D'Q'
................................................................................
exode/S*
exoderme/S*
exogame/S*
exogamie/S*
exogamique/S*
exogène/S*
exogénéité/S*

exomphale/S*
exon/S*
exondation/S*
exondement/S*
exonder/a3p+
exonération/S*
exonérer/c4p+
................................................................................
extensionnelle/F*
extensité/S*
extensive/F*
extensivement/L'D'Q'
extensivité/S*
extenso
extensomètre/S*


exténuante/F*
exténuation/S*
exténuée/F*
exténuement/S*
exténuer/a4p+
extérieur/S*
extérieure/F*
................................................................................
filoselle/S.
filou/S.
filoutage/S.
filouter/a0p+
filouterie/S.
filovirus
fils

filtrable/S.
filtrage/S.
filtrante/F.
filtrat/S.
filtration/S.
filtre/S.
filtre-presse
................................................................................
flanquer/a0p+
flapie/F.
flaque/S.
flaquer/a0p.
flash/A.
flashage/S.
flash-back

flash-ball/S.
flasher/a0p+
flasheuse/F.
flashmètre/S.
flashy
flasque/S.
flasquement
................................................................................
foutou/S.
foutrale/F.
foutraque/S.
foutre/S.
foutre/tM
foutredieu
foutrement

foutriquet/S.
foutue/F.
fovéa/S.
fovéale/W.
fox
foxée/F.
fox-hound/S.
................................................................................
haptique/S*
haptonomie/S*
haptonomique/S*
haquebute/S.
haquenée/S.
haquet/S.
hara-kiri/S.

harangue/S.
haranguer/a0p+
harangueuse/F.
haras
harassante/F.
harassement/S.
harasser/a0p+
................................................................................
hors-bilan
hors-bord
hors-champ
hors-concours
hors-cote
hors-cote
hors-d'œuvre

horse-ball/S.
horse-guard/S.
horse-power
horse-pox
hors-jeu
hors-la-loi
hors-ligne
................................................................................
hoyau/X.
hpz/||--
http/S=
huard/S.
huart/S.
hub/S.
hublot/S.

huche/S.
hucher/a0p+
huchet/S.
hue
huée/S.
huer/a0p+
huerta/S.

huguenote/F.
huilage/S*
huile/S*
huiler/a2p+
huilerie/S*
huileuse/W*
huilière/F*
................................................................................
hypertrophier/a4p+
hypertrophique/S*
hyperuricémie/S*
hypervariable/S*
hyperventilation/S*
hyperventiler/a1p.
hypervigilance/S*


hyperviscosité/S*
hyperviseur/S*
hypervitaminose/S*
hyphe/S*
hypholome/S*
hypnagogique/S*
hypnogramme/S*
................................................................................
illisibilité/S*
illisible/S*
illisiblement/D'Q'
illogique/S*
illogiquement/D'Q'
illogisme/S*
illuminante/F*

illumination/S*
illuminative/F*
illuminatrice/F*
illuminée/F*
illuminer/a4p+
illuminisme/S*
illusion/S*
................................................................................
imparisyllabique/S*
imparité/S*
impartageable/S*
impartiale/W*
impartialement/D'Q'
impartialité/S*
impartir/fC

impasse/S*
impassibilité/S*
impassible/S*
impassiblement/D'Q'
impatiemment/D'Q'
impatience/S*
impatiens/L'D'Q'
................................................................................
jeuniste/S.
jeunotte/F.
jigger/S.
jihad/S.
jihadisme/S.
jihadiste/S.
jingle/S.

jiu-jitsu
joaillerie/S.
joaillière/F.
job/S.
job/S.
jobarde/F.
jobarder/a0p+
................................................................................
kabic/S.
kabig/S.
kabuki/S.
kabyle/S.
kacha/S.
kachoube/S.
kaddish/S.

kafir/S.
kafkaïenne/F.
kaïnite/S.
kaiser/S.
kakapo/S.
kakatoès
kakawi/S.
................................................................................
karst/S.
karstification/S.
karstique/S.
karstologie/S.
kart/S.
karting/S.
kascher

kashrout
kat/U.||--
kata/S.
katakana
katakana/S.
katal/Um
katana/S.
................................................................................
multidevise/S.
multidiffusion/S.
multidimensionnalité/S.
multidimensionnelle/F.
multidirectionnalité/S.
multidirectionnelle/F.
multidisciplinaire/S.

multiethnique/S.
multi-ethnique/S.
multifactorielle/F.
multifamiliale/W.
multifilaire/S.
multiflore/S.
multifonction/S.
................................................................................
oligoasthénotératospermie/S*
oligocène/S*
oligochète/S*
oligoclase/S*
oligodendrocyte/S*
oligodendrogliome/S*
oligoélément/S*
oligoélément/S*
oligo-élément/S*
oligo-élément/S*
oligogalacturonate/S*
oligo-galacturonate/S*
oligomère/S*
oligomérique/S*
oligomérisation/S*
oligonucléotide/S*
................................................................................
perceptiblement
perception/S.
perceptionnisme/S.
perceptionniste/S.
perceptive/F.
perceptrice/F.
perceptuelle/F.

percer/a0p+
percerette/S.
perceuse/F.
percevable/S.
percevoir/pK
perche/S.
percher/a0p+
................................................................................
pizza/S.
pizzaiolo/I.
pizzaïolo/S.
pizzeria/S.
pizzicato/I.
placage/S.
placard/S.

placarder/a0p+
placardisation/S.
placardiser/a0p+
place/S.
placebo/S.
placement/S.
placenta/S.
................................................................................
plâtrerie/S.
plâtreuse/W.
plâtrière/F.
plats-bords
plausibilité/S.
plausible/S.
plausiblement

play-back

play-boy/S.
playlist/S.
play-list/S.
playon/S.
pléban/S.
plèbe/S.
plébéienne/F.
................................................................................
ployage/S.
ployante/F.
ployer/a0p+
pluche/S.
plucher/a0p.
plucheuse/W.
plugin/S.

pluie/S.
plumage/S.
plumaison/S.
plumard/S.
plumasseau/X.
plumasserie/S.
plumassière/F.
................................................................................
polychète/S.
polychlorobenzène/S.
polychlorure/S.
polychroïque/S.
polychroïsme/S.
polychrome/S.
polychromie/S.

polycistronique/S.
polyclinique/S.
polycondensat/S.
polycondensation/S.
polycopie/S.
polycopier/a0p+
polycourant
................................................................................
pop-corn
pope/S.
popeline/S.
popinée/S.
poplitée/F.
popote/S.
popotin/S.

populace/S.
populacière/F.
populage/S.
populaire/S.
populairement
popularisation/S.
populariser/a0p+
................................................................................
poulaille/S.
poulailler/S.
poulaine/F.
poulamon/S.
poularde/S.
poulbot/S.
poule/S.
poulet/S.
poulette/S.
pouliage/S.
pouliche/S.
poulie/S.
pouliner/a0p.
poulinière/S.
poulinière/S.
pouliot/S.
................................................................................
protoplasme/S.
protoplasmique/S.
protoplaste/S.
protoptère/S.
protosulfure/S.
prototypage/S.
prototype/S.

prototypique/S.
prototypiste/S.
protoure/S.
protoxyde/S.
protozoaire/S.
protozoologie/S.
protractile/S.
................................................................................
prudemment
prudence/S.
prudente/F.
prudentielle/F.
pruderie/S.
prud'homale/W.
prud'homie/S.


prud'homme/S.
prudhommerie/S.
prudhommesque/S.

pruine/S.
prune
prune/S.
pruneau/X.
prunelaie/S.
prunelée/S.
prunelle/S.
................................................................................
pusillanime/S.
pusillanimement
pusillanimité/S.
pustule/S.
pustuler/a0p+
pustuleuse/W.
putain/S.

putassière/F.
putative/F.
pute/S.
putier/S.
putiet/S.
putois
putréfaction/S.
................................................................................
sceau/X.
sceau-de-Salomon
sceaux-de-Salomon
scélérate/F.
scélératement
scélératesse/S.
scellage/S.

scellement/S.
sceller/a0p+
scénarimage/S.
scenario/I.
scénario/S.
scénarisation/S.
scénariser/a0p+
................................................................................
scripturale/W.
scripturalisme/S.
scrofulaire/S.
scrofulariacée/S.
scrofule/S.
scrofuleuse/W.
scrogneugneu/X.

scrolling/S.
scrotale/W.
scrotum/S.
scrub/S.
scrubber/S.
scrupule/S.
scrupuleuse/W.
................................................................................
stariser/a0p+
starlette/S.
staroste/S.
star-system/S.
starter/S.
starting-block/S.
starting-gate/S.

start-up/S.
stase/S.
stater/a0p+
statère/S.
stathouder/S.
stathoudérat/S.
statice/S.
................................................................................
syrah/S.
syriaque/S.
syriaque/S.
syrienne/F.
syringe/S.
syringomyélie/S.
syrinx

syrphe/S.
sysadmin/S.
systématicienne/F.
systématicité/S.
systématique/S.
systématique/S.
systématiquement
................................................................................
tagliatelle/S.
tagme/S.
taguer/a0p+
tagueuse/F.
tahitienne/F.
taïaut
taï-chi

taï-chi-chuan

taie/S.
taïga/S.
taiji/S.
taijiquan/S.
taïkonaute/S.
taillable/S.
taillade/S.
................................................................................
taleb/S.
talent/S.
talentueuse/W.
talentueusement
taler/a0p+
taleth/S.
talibane/F.

talion/S.
talisman/S.
talismanique/S.
talith/S.
talitre/S.
talkies-walkies
talkie-walkie
................................................................................
trantran/S.
trapèze/S.
trapéziste/S.
trapézoèdre/S.
trapézoïdale/W.
trapézoïde/S.
trappe/S.

trappeuse/F.
trappillon/S.
trappiste/S.
trappistine/S.
trapue/F.
traque/S.
traquée/F.
................................................................................
ultimement/D'Q'
ultimité/S*
ultimo
ultra/S*
ultrabasique/S*
ultracentrifugation/S*
ultracentrifugeuse/S*

ultra-chic/S*
ultracolonialisme/S*
ultra-colonialisme/S*
ultracolonialiste/S*
ultra-colonialiste/S*
ultraconfidentielle/F*
ultra-confidentielle/F*
................................................................................
vibrato/S.
vibratoire/S.
vibrer/a0p+
vibreur/S.
vibrion/S.
vibrionner/a0p.
vibrisse/S.

vibromasseur/S.
vicaire/S.
vicariale/W.
vicariance/S.
vicariante/F.
vicariat/S.
vice/S.
|







 







|







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







<







 







>







 







>







 







<







 







>







 







<







 







|




>







 







>







 







>







 







>







 







|







 







>







 







>
>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







|
|







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>
>







 







>







 







>







 







>
>







 







>







 







>







 







>







 







>







 







>







 







>







>







 







>
>







 







>







 







>







 







>







 







>







 







>







 







>







 







<
<







 







>







 







>







 







>
|
>







 







>







 







>







 







>







 







<
|







 







>







 







>
>



>







 







>







 







>







 







>







 







>







 







>







 







>

>







 







>







 







>







 







>







 







>







1
2
3
4
5
6
7
8
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
....
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
....
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
....
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
....
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
....
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
....
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
....
3526
3527
3528
3529
3530
3531
3532

3533
3534
3535
3536
3537
3538
3539
....
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
....
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
....
5485
5486
5487
5488
5489
5490
5491

5492
5493
5494
5495
5496
5497
5498
....
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
....
6391
6392
6393
6394
6395
6396
6397

6398
6399
6400
6401
6402
6403
6404
....
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
....
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
....
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
....
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
.....
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
.....
11413
11414
11415
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
.....
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
.....
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
.....
12665
12666
12667
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679
.....
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15117
15118
.....
15126
15127
15128
15129
15130
15131
15132
15133
15134
15135
15136
15137
15138
15139
15140
.....
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
.....
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793
16794
16795
.....
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
17923
17924
17925
17926
17927
.....
18256
18257
18258
18259
18260
18261
18262
18263
18264
18265
18266
18267
18268
18269
18270
.....
18657
18658
18659
18660
18661
18662
18663
18664
18665
18666
18667
18668
18669
18670
18671
18672
.....
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
.....
24322
24323
24324
24325
24326
24327
24328
24329
24330
24331
24332
24333
24334
24335
24336
.....
24769
24770
24771
24772
24773
24774
24775
24776
24777
24778
24779
24780
24781
24782
24783
.....
25848
25849
25850
25851
25852
25853
25854
25855
25856
25857
25858
25859
25860
25861
25862
.....
27642
27643
27644
27645
27646
27647
27648
27649
27650
27651
27652
27653
27654
27655
27656
.....
28442
28443
28444
28445
28446
28447
28448
28449
28450
28451
28452
28453
28454
28455
28456
.....
28492
28493
28494
28495
28496
28497
28498
28499
28500
28501
28502
28503
28504
28505
28506
.....
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
.....
29839
29840
29841
29842
29843
29844
29845
29846
29847
29848
29849
29850
29851
29852
29853
.....
32449
32450
32451
32452
32453
32454
32455
32456
32457
32458
32459
32460
32461
32462
32463
.....
34232
34233
34234
34235
34236
34237
34238
34239
34240
34241
34242
34243
34244
34245
34246
34247
.....
34269
34270
34271
34272
34273
34274
34275
34276
34277
34278
34279
34280
34281
34282
34283
.....
34865
34866
34867
34868
34869
34870
34871
34872
34873
34874
34875
34876
34877
34878
34879
.....
35072
35073
35074
35075
35076
35077
35078
35079
35080
35081
35082
35083
35084
35085
35086
35087
.....
36241
36242
36243
36244
36245
36246
36247
36248
36249
36250
36251
36252
36253
36254
36255
.....
36452
36453
36454
36455
36456
36457
36458
36459
36460
36461
36462
36463
36464
36465
36466
.....
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
.....
40547
40548
40549
40550
40551
40552
40553
40554
40555
40556
40557
40558
40559
40560
40561
.....
41700
41701
41702
41703
41704
41705
41706
41707
41708
41709
41710
41711
41712
41713
41714
.....
41817
41818
41819
41820
41821
41822
41823
41824
41825
41826
41827
41828
41829
41830
41831
41832
41833
41834
41835
41836
41837
41838
41839
.....
42325
42326
42327
42328
42329
42330
42331
42332
42333
42334
42335
42336
42337
42338
42339
42340
.....
42716
42717
42718
42719
42720
42721
42722
42723
42724
42725
42726
42727
42728
42729
42730
.....
42958
42959
42960
42961
42962
42963
42964
42965
42966
42967
42968
42969
42970
42971
42972
.....
45962
45963
45964
45965
45966
45967
45968
45969
45970
45971
45972
45973
45974
45975
45976
.....
46261
46262
46263
46264
46265
46266
46267
46268
46269
46270
46271
46272
46273
46274
46275
.....
46334
46335
46336
46337
46338
46339
46340
46341
46342
46343
46344
46345
46346
46347
46348
.....
52719
52720
52721
52722
52723
52724
52725
52726
52727
52728
52729
52730
52731
52732
52733
.....
55150
55151
55152
55153
55154
55155
55156


55157
55158
55159
55160
55161
55162
55163
.....
58170
58171
58172
58173
58174
58175
58176
58177
58178
58179
58180
58181
58182
58183
58184
.....
59871
59872
59873
59874
59875
59876
59877
59878
59879
59880
59881
59882
59883
59884
59885
.....
60119
60120
60121
60122
60123
60124
60125
60126
60127
60128
60129
60130
60131
60132
60133
60134
60135
.....
60266
60267
60268
60269
60270
60271
60272
60273
60274
60275
60276
60277
60278
60279
60280
.....
60683
60684
60685
60686
60687
60688
60689
60690
60691
60692
60693
60694
60695
60696
60697
.....
60961
60962
60963
60964
60965
60966
60967
60968
60969
60970
60971
60972
60973
60974
60975
.....
61415
61416
61417
61418
61419
61420
61421

61422
61423
61424
61425
61426
61427
61428
61429
.....
62829
62830
62831
62832
62833
62834
62835
62836
62837
62838
62839
62840
62841
62842
62843
.....
62913
62914
62915
62916
62917
62918
62919
62920
62921
62922
62923
62924
62925
62926
62927
62928
62929
62930
62931
62932
.....
63356
63357
63358
63359
63360
63361
63362
63363
63364
63365
63366
63367
63368
63369
63370
.....
69005
69006
69007
69008
69009
69010
69011
69012
69013
69014
69015
69016
69017
69018
69019
.....
69264
69265
69266
69267
69268
69269
69270
69271
69272
69273
69274
69275
69276
69277
69278
.....
71850
71851
71852
71853
71854
71855
71856
71857
71858
71859
71860
71861
71862
71863
71864
.....
73528
73529
73530
73531
73532
73533
73534
73535
73536
73537
73538
73539
73540
73541
73542
.....
73680
73681
73682
73683
73684
73685
73686
73687
73688
73689
73690
73691
73692
73693
73694
73695
73696
.....
73727
73728
73729
73730
73731
73732
73733
73734
73735
73736
73737
73738
73739
73740
73741
.....
76331
76332
76333
76334
76335
76336
76337
76338
76339
76340
76341
76342
76343
76344
76345
.....
77461
77462
77463
77464
77465
77466
77467
77468
77469
77470
77471
77472
77473
77474
77475
.....
78710
78711
78712
78713
78714
78715
78716
78717
78718
78719
78720
78721
78722
78723
78724
80108
&
1er/--
1ers/--
1re/--
1res/--
1ʳᵉ/--
1ʳᵉˢ/--
................................................................................
Aïcha/L'D'Q'
Aïd/L'D'Q'
Aida/L'D'Q'
Aidan/L'D'Q'
Aïd-el-Adha/L'
Aïd-el-Kébir/L'
Aiden/L'D'Q'
Aignan/L'D'Q'
Aigoual/L'D'
Aigrain/L'D'Q'
Aimé/L'D'Q'
Aimée/L'D'Q'
Ain/L'
Airaines/L'D'Q'
Airbnb/L'D'Q'
................................................................................
Arion/L'D'Q'
Aristarque/L'D'Q'
Aristide/L'D'Q'
Aristophane/L'D'Q'
Aristote/L'D'Q'
Arizona/L'D'
Arjuna/L'D'Q'
Arkady/L'D'Q'
Arkansas/L'D'
Arkema/L'D'Q'
Arkham/L'D'Q'
Arkhangelsk/L'D'Q'
Arlene/L'D'Q'
Arlène/L'D'Q'
Arles/L'D'Q'
................................................................................
Aurélien/L'D'Q'
Aurelio/L'D'Q'
Auriane/L'D'Q'
Aurillac/L'D'Q'
Auriol/L'D'Q'
Aurore/L'D'Q'
Auschwitz/L'D'Q'
Austen/L'D'Q'
Austerlitz/L'D'Q'
Austin/L'D'Q'
Australasie/L'D'Q'
Australie/L'D'
Australie-Méridionale/L'D'
Australie-Occidentale/L'D'
Austrasie/L'D'
................................................................................
Benoîte
Benozillo
Benpro
Bentama
Bentham
Bentley
Benveniste
Bérangère
Berchem-Sainte-Agathe
Berck
Bercy
Bérenger
Bérengère
Bérénice
Bérézina
................................................................................
Caine
Caïphe
Caire
Caitlin
Caitlyn
Calabre
Calais
Calaisis
Calc
Calcutta
Calderón
Caleb
Calédonie
Calestienne
Calgary
................................................................................
Chostakovitch
Chris
Christa
Christel
Christèle
Christelle
Christian
Christiana
Christiane
Christie
Christina
Christine
Christmas
Christoffel
Christoph
................................................................................
Cincinnati
Cindy
Ciney
Ciotat
Circassie
Circé
Cirey-sur-Vezouze
Cisco
Cisjordanie
Cîteaux
Citroën
City
Claire
Clamart
Clara
................................................................................
Eure-et-Loir/L'D'
Euripide/L'D'Q'
Eurobaromètre/S*
Eurogroupe/L'
Euronext/L'D'Q'
Europe/L'D'
Europol/D'Q'
Eurotunnel/L'D'Q'
Eurozone/L'
Eurydice/L'D'Q'
Eusèbe/L'D'Q'
Euterpe/L'D'Q'
Eva/L'D'Q'
Éva/L'D'Q'
Évaine/L'D'Q'
................................................................................
Fayard
Fayçal
Fayette
Fécamp
Fed
FedEx
Federer
Federica
Federico
Fehling
Feist
Feïza
Feldane
Felicia
Félicie
................................................................................
Halluin/L'D'Q'
Ham/L'D'Q'
Hamas
Hambourg
Hamel
Hamid/L'D'Q'
Hamilton
Hamlet/L'D'Q'
Hamme
HammerFall
Hammourabi
Hamont-Achel/L'D'Q'
Hampshire
Ham-sur-Heure-Nalinnes/L'D'Q'
Hamza/L'D'Q'
................................................................................
Howard
Hubble
Hubei
Hubert/L'D'Q'
Hubscher
Hudson/L'D'Q'
Huelgoat
Hugh/L'D'Q'
Hugo/L'D'Q'
Hugo/L'D'Q'
Hugues/L'D'Q'
Huguette
Hulshout/L'D'Q'
Hume
Hun/S.
................................................................................
IMSI/L'D'Q'
INED/L'D'Q'
INPI/L'D'Q'
INRA/L'D'Q'
INRI/L'D'Q'
INRIA/L'D'Q'
INSA/L'D'Q'

IP/L'D'Q'
IRA/L'
IRD/L'D'Q'
IRFM/L'D'Q'
IRL
IRM/L'D'Q'
IRSTEA/L'D'Q'
................................................................................
Ingrid/L'D'Q'
Inkscape/L'D'Q'
Inn/L'D'
Inna/L'D'Q'
Innsmouth/L'D'Q'
Inovia/L'D'Q'
Insee/L'D'Q'
Inserm/L'D'Q'
Insulinde/L'D'
Intel/L'D'Q'
Internet/D'Q'
Interpol/D'Q'
Io/L'D'Q'
Ionesco/L'D'Q'
Ioulia/L'D'Q'
................................................................................
Léonore
Léontine
Léopold
Léopoldine
Leopoldt
Léopoldville
Leroy
Lesage
Lesbos
Lesieur
Lesley
Leslie
Lesneven
Lesotho
Lesse
................................................................................
Noisy-le-Grand
Noisy-le-Sec
Nokia
Nolan
Nolwenn
Nora
Norbert

Nord-Kivu
Nord-Pas-de-Calais
Nord-du-Québec
Nordine
Norfolk
Norique
Norma
................................................................................
Reidemeister
Reiko
Reims
Reiten
Relecq-Kerhuon
Rellich
Rembrandt
Remi
Rémi
Remich
Remire-Montjoly
Remus
Rémy
Renaix
Renan
................................................................................
Rosita
Rosny-sous-Bois
Ross
Rossini
Rossinière
Rostand
Roswell

Roth
Rothbard
Rothschild
Rotin
Rotselaar
Rotterdam
Roubaix
................................................................................
additionnelle/F*
additionnellement/D'Q'
additionner/a4p+
additionneuse/F*
additive/F*
additivement/D'Q'
additivité/S*
add-on/S*
adducteur/S*
adduction/S*
adduit/S*
adèle/S*
adelphe/S*
adelphophagie/S*
adénine/S*
adénite/S*
adénocarcinome/S*
adénogramme/S*
adénoïde/S*
adénoïdectomie/S*
................................................................................
aérobie/S*
aérobie/S*
aérobiologie/S*
aérobiologique/S*
aérobiose/S*
aérobique/S*
aérocâble/S*
aéroclub/S*
aéro-club/S*
aérocolie/S*
aérodigestive/F*
aérodistorsion/S*
aérodrome/S*
aérodynamicienne/F*
aérodynamique/S*
................................................................................
agroalimentaire/S*
agro-alimentaire/S*
agroalimentaire/S*
agro-alimentaire/S*
agrobiologie/S*
agrobiologique/S*
agrobiologiste/S*
agrobusiness/L'D'Q'
agrocarburant/S*
agro-carburant/S*
agrochimie/S*
agrochimique/S*
agrochimiste/S*
agroclimatique/S*
agro-climatique/S*
................................................................................
aillade/S*
ailler/a2p+
ailleurs/L'D'Q'
ailloli/S*
aimable/S*
aimablement/D'Q'
aimant/S*
aimantable/S*
aimantation/S*
aimante/F*
aimanter/a4p+
aimantin/S*
aimantine/F*
aimée/F*
aimer/a4p+
................................................................................
amathie/S*
amatir/f2p+
amatrice/F*
amaurose/S*
amazone/S*
amazonienne/F*
amazonite/S*
ambage/S*
ambassade/S*
ambassadrice/F*
ambiance/S*
ambiancer/a1p.
ambianceuse/F*
ambiante/F*
ambidextre/S*
................................................................................
annuité/S*
annulabilité/S*
annulable/S*
annulaire/S*
annulation/S*
annulative/F*
annulatrice/F*
annulement/S*
annuler/a4p+
annuus
anoblir/f4p+
anoblissante/F*
anoblissement/S*
anode/S*
anodine/F*
................................................................................
antiémeute/L'D'Q'
antienne/S*
antienzyme/S*
anti-enzyme/S*
antiépileptique/S*
antiesclavagiste/S*
antiétatique/S*
antiétatisme/S*
antifa/S*
antifading/S*
antifascisme/S*
antifasciste/S*
antiféminisme/S*
antiféministe/S*
antiferment/S*
antiferroélectricité/S*
................................................................................
arc/S*
arcade/S*
arcane/S*
arcanson/S*
arcasse/S*
arcature/S*
arc-boutant/L'D'Q'
arc-boutement
arc-bouter/a4p+
arccos
arccosh
arccotan
arccotanh
arc-doubleau/L'D'Q'
arceau/X*
................................................................................
archontat/S*
archonte/S*
archosaurien/S*
archure/S*
arçon/S*
arçonner/a2p+
arcs-boutants/D'Q'
arcs-boutements
arcs-doubleaux/D'Q'
arcs-en-ciel/D'Q'
arcsin
arcsinh
arctan
arctanh
arctique/S*
................................................................................
bascule/S.
basculement/S.
basculer/a0p+
basculeur/S.
bas-culotte/S.
bas-de-casse
base/S.
baseball/S.
base-ball/S.
baselle/S.
baser/a0p+
bas-fond/S.
basicité/S.
baside/S.
basidiomycète/S.
................................................................................
basilique/S.
basin/S.
basiphile/S.
basique/S.
basiquement
bas-jointée/F.
basket/S.
basketball/S.
basket-ball/S.
basketteuse/F.
bas-mât/S.
basmati/S.
basocellulaire/S.
basoche/S.
basochienne/F.
................................................................................
bernard-l'hermite
berne/S.
berner/a0p+
berneuse/F.
bernicle/S.
bernique
bernique/S.
bernoise/F.
berrichonne/F.
bersaglier/S.
berthon/S.
bertillonnage/S.
béryl/S.
bérylliose/S.
béryllium/S.
................................................................................
bongo/S.
bonheur/S.
bonheur-du-jour
bonheurs-du-jour
bonhomie/S.
bonhomme
bonhomme/S.
bonhommie/S.
boni/S.
bonichon/S.
bonifiante/F.
bonification/S.
bonifier/a0p+
boniment/S.
bonimenter/a0p.
................................................................................
bugne/S.
bugrane/S.
buguée/F.
build/S.
building/S.
buire/S.
buis
buissaie/S.
buisson/S.
buisson-ardent
buissonnante/F.
buissonnet/S.
buissonneuse/W.
buissonnière/F.
buissons-ardents
................................................................................
cadrer/a0p+
cadreuse/F.
cadriciel/S.
caduc/S.
caducée/S.
caducifoliée/F.
caducité/S.
caduque/F.
caduque/S.
cæcale/W.
cæcotrophie/S.
cæcum/S.
caennaise/F.
cænogenèse/S.
cæsine
................................................................................
camping-car/S.
camping-caravaning/S.
camping-gaz
campinoise/F.
campo/S.
campus
camuse/F.
canada/S.
canadair/S.
canadianisme/S.
canadienne/F.
canado-américaine/F.
canaille/S.
canaillement
canaillerie/S.
canaillocratie/S.
................................................................................
caucasique/S.
cauchemar/S.
cauchemarder/a0p.
cauchemardesque/S.
cauchemardeuse/W.
caucus
caudale/W.
caudalie/S.
caudataire/S.
caudataire/S.
caudillo/S.
caudine/S.
caudrette/S.
caulescente/F.
caulicole/S.
................................................................................
corruptrice/F.
corsage/S.
corsaire/S.
corse/S.
corselet/S.
corser/a0p+
corset/S.
corsetage/S.
corseter/b0p+
corseterie/S.
corsetière/F.
corso/S.
cortège/S.
cortès
cortex
................................................................................
covenant/S.
covendeuse/F.
cover-girl/S.
covoiturage/S.
covoiturer/a0p+
covoitureuse/F.
covolume/S.
cowboy/S.
cow-boy/S.
cowper/S.
coxale/W.
coxalgie/S.
coxalgique/S.
coxarthrose/S.
coxer/a0p+
................................................................................
cytotoxique/S.
czar/S.
czardas
czimbalum/S.
d
d/||--
dB/||--
daba/S.
dacryoadénite/S.
dacryocystite/S.
dactyle/S.
dactylique/S.
dactylo/S.
dactylogramme/S.
dactylographe/S.
................................................................................
dénombrabilité/S.
dénombrable/S.
dénombrement/S.
dénombrer/a0p+
dénominateur/S.
dénomination/S.
dénominative/F.
dénommable/S.
dénommer/a0p+
dénoncer/a0p+
dénonciation/S.
dénonciatrice/F.
dénotation/S.
dénotationnelle/F.
dénotative/F.
................................................................................
désincorporer/a0p+
désincrustation/S.
désincruster/a0p+
désinculper/a0p+
désindenter/a0p+
désindexation/S.
désindexer/a0p+
désindividualiser/a0p+
désindustrialisation/S.
désindustrialiser/a0p+
désinence/S.
désinentielle/F.
désinfectante/F.
désinfecter/a0p+
désinfection/S.
................................................................................
désinviter/a0p+
désinvolte/S.
désinvoltement
désinvolture/S.
désir/S.
désirabilité/S.
désirable/S.
désirante/F.
désirer/a0p+
désireuse/W.
désistement/S.
désister/a0p+
desman/S.
desmine/S.
desmodonte/S.
................................................................................
diarrhée/S.
diarrhéique/S.
diarthrose/S.
diascope/S.
diascopie/S.
diascordium/S.
diaspora/S.
diasporique/S.
diastase/S.
diastasique/S.
diastème/S.
diastéréo-isomère/S.
diastole/S.
diastolique/S.
diastratique/S.
................................................................................
diversement
diverses
diversifiable/S.
diversification/S.
diversifier/a0p+
diversiforme/S.
diversion/S.
diversitaire/S.
diversité/S.
diverticule/S.
diverticulite/S.
diverticulose/S.
divertimento/S.
divertir/f0p+
divertissante/F.
................................................................................
endoénergétique/S*
endogame/S*
endogamie/S*
endogamique/S*
endogée/F*
endogène/S*
endogénéité/S*
endogroupe/S*
endolocalisation/S*
endolorir/f2p+
endolorissement/S*
endolymphe/S*
endomètre/S*
endométriose/S*
endométrite/S*
................................................................................
ethmoïdale/W*
ethmoïde/S*
ethmoïdite/S*
ethnarchie/S*
ethnarque/S*
ethnicisation/S*
ethniciser/a2p+
ethnicisme/S*
ethniciste/S*
ethnicité/S*
ethnico-religieuse/W*
ethnie/S*
ethnique/S*
ethniquement/D'Q'
ethnobiologie/S*
ethnobotanique/S*
................................................................................
ethnométhodologue/S*
ethnomusicologie/S*
ethnomusicologue/S*
ethnonyme/S*
ethnonymie/S*
ethnopsychiatrie/S*
ethnopsychologie/S*
ethno-raciale/W*
ethnoreligieuse/W*
éthographie/S*
éthologie/S*
éthologique/S*
éthologiste/S*
éthologue/S*
ethos/L'D'Q'
................................................................................
exode/S*
exoderme/S*
exogame/S*
exogamie/S*
exogamique/S*
exogène/S*
exogénéité/S*
exogroupe/S*
exomphale/S*
exon/S*
exondation/S*
exondement/S*
exonder/a3p+
exonération/S*
exonérer/c4p+
................................................................................
extensionnelle/F*
extensité/S*
extensive/F*
extensivement/L'D'Q'
extensivité/S*
extenso
extensomètre/S*
extensométrie/S*
extensométrique/S*
exténuante/F*
exténuation/S*
exténuée/F*
exténuement/S*
exténuer/a4p+
extérieur/S*
extérieure/F*
................................................................................
filoselle/S.
filou/S.
filoutage/S.
filouter/a0p+
filouterie/S.
filovirus
fils
filsdeputerie/S.
filtrable/S.
filtrage/S.
filtrante/F.
filtrat/S.
filtration/S.
filtre/S.
filtre-presse
................................................................................
flanquer/a0p+
flapie/F.
flaque/S.
flaquer/a0p.
flash/A.
flashage/S.
flash-back
flashball/S.
flash-ball/S.
flasher/a0p+
flasheuse/F.
flashmètre/S.
flashy
flasque/S.
flasquement
................................................................................
foutou/S.
foutrale/F.
foutraque/S.
foutre/S.
foutre/tM
foutredieu
foutrement
foutrerie/S.
foutriquet/S.
foutue/F.
fovéa/S.
fovéale/W.
fox
foxée/F.
fox-hound/S.
................................................................................
haptique/S*
haptonomie/S*
haptonomique/S*
haquebute/S.
haquenée/S.
haquet/S.
hara-kiri/S.
haram
harangue/S.
haranguer/a0p+
harangueuse/F.
haras
harassante/F.
harassement/S.
harasser/a0p+
................................................................................
hors-bilan
hors-bord
hors-champ
hors-concours
hors-cote
hors-cote
hors-d'œuvre
horseball/S.
horse-ball/S.
horse-guard/S.
horse-power
horse-pox
hors-jeu
hors-la-loi
hors-ligne
................................................................................
hoyau/X.
hpz/||--
http/S=
huard/S.
huart/S.
hub/S.
hublot/S.
hubris/L'D'Q'
huche/S.
hucher/a0p+
huchet/S.
hue
huée/S.
huer/a0p+
huerta/S.
hugolienne/F*
huguenote/F.
huilage/S*
huile/S*
huiler/a2p+
huilerie/S*
huileuse/W*
huilière/F*
................................................................................
hypertrophier/a4p+
hypertrophique/S*
hyperuricémie/S*
hypervariable/S*
hyperventilation/S*
hyperventiler/a1p.
hypervigilance/S*
hyperviolence/S*
hyperviolente/F*
hyperviscosité/S*
hyperviseur/S*
hypervitaminose/S*
hyphe/S*
hypholome/S*
hypnagogique/S*
hypnogramme/S*
................................................................................
illisibilité/S*
illisible/S*
illisiblement/D'Q'
illogique/S*
illogiquement/D'Q'
illogisme/S*
illuminante/F*
illuminati/L'D'Q'
illumination/S*
illuminative/F*
illuminatrice/F*
illuminée/F*
illuminer/a4p+
illuminisme/S*
illusion/S*
................................................................................
imparisyllabique/S*
imparité/S*
impartageable/S*
impartiale/W*
impartialement/D'Q'
impartialité/S*
impartir/fC
impassable/S*
impasse/S*
impassibilité/S*
impassible/S*
impassiblement/D'Q'
impatiemment/D'Q'
impatience/S*
impatiens/L'D'Q'
................................................................................
jeuniste/S.
jeunotte/F.
jigger/S.
jihad/S.
jihadisme/S.
jihadiste/S.
jingle/S.
jinn/S.
jiu-jitsu
joaillerie/S.
joaillière/F.
job/S.
job/S.
jobarde/F.
jobarder/a0p+
................................................................................
kabic/S.
kabig/S.
kabuki/S.
kabyle/S.
kacha/S.
kachoube/S.
kaddish/S.
kadi/S.
kafir/S.
kafkaïenne/F.
kaïnite/S.
kaiser/S.
kakapo/S.
kakatoès
kakawi/S.
................................................................................
karst/S.
karstification/S.
karstique/S.
karstologie/S.
kart/S.
karting/S.
kascher
kasher
kashrout
kat/U.||--
kata/S.
katakana
katakana/S.
katal/Um
katana/S.
................................................................................
multidevise/S.
multidiffusion/S.
multidimensionnalité/S.
multidimensionnelle/F.
multidirectionnalité/S.
multidirectionnelle/F.
multidisciplinaire/S.
multidisciplinarité/S.
multiethnique/S.
multi-ethnique/S.
multifactorielle/F.
multifamiliale/W.
multifilaire/S.
multiflore/S.
multifonction/S.
................................................................................
oligoasthénotératospermie/S*
oligocène/S*
oligochète/S*
oligoclase/S*
oligodendrocyte/S*
oligodendrogliome/S*
oligoélément/S*


oligo-élément/S*
oligogalacturonate/S*
oligo-galacturonate/S*
oligomère/S*
oligomérique/S*
oligomérisation/S*
oligonucléotide/S*
................................................................................
perceptiblement
perception/S.
perceptionnisme/S.
perceptionniste/S.
perceptive/F.
perceptrice/F.
perceptuelle/F.
perceptuellement
percer/a0p+
percerette/S.
perceuse/F.
percevable/S.
percevoir/pK
perche/S.
percher/a0p+
................................................................................
pizza/S.
pizzaiolo/I.
pizzaïolo/S.
pizzeria/S.
pizzicato/I.
placage/S.
placard/S.
placardage/S.
placarder/a0p+
placardisation/S.
placardiser/a0p+
place/S.
placebo/S.
placement/S.
placenta/S.
................................................................................
plâtrerie/S.
plâtreuse/W.
plâtrière/F.
plats-bords
plausibilité/S.
plausible/S.
plausiblement
playback/S.
play-back/S.
playboy/S.
play-boy/S.
playlist/S.
play-list/S.
playon/S.
pléban/S.
plèbe/S.
plébéienne/F.
................................................................................
ployage/S.
ployante/F.
ployer/a0p+
pluche/S.
plucher/a0p.
plucheuse/W.
plugin/S.
plug-in/S.
pluie/S.
plumage/S.
plumaison/S.
plumard/S.
plumasseau/X.
plumasserie/S.
plumassière/F.
................................................................................
polychète/S.
polychlorobenzène/S.
polychlorure/S.
polychroïque/S.
polychroïsme/S.
polychrome/S.
polychromie/S.
polychromique/S.
polycistronique/S.
polyclinique/S.
polycondensat/S.
polycondensation/S.
polycopie/S.
polycopier/a0p+
polycourant
................................................................................
pop-corn
pope/S.
popeline/S.
popinée/S.
poplitée/F.
popote/S.
popotin/S.
popstar/S.
populace/S.
populacière/F.
populage/S.
populaire/S.
populairement
popularisation/S.
populariser/a0p+
................................................................................
poulaille/S.
poulailler/S.
poulaine/F.
poulamon/S.
poularde/S.
poulbot/S.
poule/S.

poulette/F.
pouliage/S.
pouliche/S.
poulie/S.
pouliner/a0p.
poulinière/S.
poulinière/S.
pouliot/S.
................................................................................
protoplasme/S.
protoplasmique/S.
protoplaste/S.
protoptère/S.
protosulfure/S.
prototypage/S.
prototype/S.
prototyper/a0p+
prototypique/S.
prototypiste/S.
protoure/S.
protoxyde/S.
protozoaire/S.
protozoologie/S.
protractile/S.
................................................................................
prudemment
prudence/S.
prudente/F.
prudentielle/F.
pruderie/S.
prud'homale/W.
prud'homie/S.
prudhommale/W.
prudhomme/S.
prud'homme/S.
prudhommerie/S.
prudhommesque/S.
prudhommie/S.
pruine/S.
prune
prune/S.
pruneau/X.
prunelaie/S.
prunelée/S.
prunelle/S.
................................................................................
pusillanime/S.
pusillanimement
pusillanimité/S.
pustule/S.
pustuler/a0p+
pustuleuse/W.
putain/S.
putasserie/S.
putassière/F.
putative/F.
pute/S.
putier/S.
putiet/S.
putois
putréfaction/S.
................................................................................
sceau/X.
sceau-de-Salomon
sceaux-de-Salomon
scélérate/F.
scélératement
scélératesse/S.
scellage/S.
scellé/S.
scellement/S.
sceller/a0p+
scénarimage/S.
scenario/I.
scénario/S.
scénarisation/S.
scénariser/a0p+
................................................................................
scripturale/W.
scripturalisme/S.
scrofulaire/S.
scrofulariacée/S.
scrofule/S.
scrofuleuse/W.
scrogneugneu/X.
scroller/a0p.
scrolling/S.
scrotale/W.
scrotum/S.
scrub/S.
scrubber/S.
scrupule/S.
scrupuleuse/W.
................................................................................
stariser/a0p+
starlette/S.
staroste/S.
star-system/S.
starter/S.
starting-block/S.
starting-gate/S.
startup/S.
start-up/S.
stase/S.
stater/a0p+
statère/S.
stathouder/S.
stathoudérat/S.
statice/S.
................................................................................
syrah/S.
syriaque/S.
syriaque/S.
syrienne/F.
syringe/S.
syringomyélie/S.
syrinx
syro-libanaise/F.
syrphe/S.
sysadmin/S.
systématicienne/F.
systématicité/S.
systématique/S.
systématique/S.
systématiquement
................................................................................
tagliatelle/S.
tagme/S.
taguer/a0p+
tagueuse/F.
tahitienne/F.
taïaut
taï-chi
taïchi/S.
taï-chi-chuan
taïchichuan/S.
taie/S.
taïga/S.
taiji/S.
taijiquan/S.
taïkonaute/S.
taillable/S.
taillade/S.
................................................................................
taleb/S.
talent/S.
talentueuse/W.
talentueusement
taler/a0p+
taleth/S.
talibane/F.
talibée/F.
talion/S.
talisman/S.
talismanique/S.
talith/S.
talitre/S.
talkies-walkies
talkie-walkie
................................................................................
trantran/S.
trapèze/S.
trapéziste/S.
trapézoèdre/S.
trapézoïdale/W.
trapézoïde/S.
trappe/S.
trapper/a0p+
trappeuse/F.
trappillon/S.
trappiste/S.
trappistine/S.
trapue/F.
traque/S.
traquée/F.
................................................................................
ultimement/D'Q'
ultimité/S*
ultimo
ultra/S*
ultrabasique/S*
ultracentrifugation/S*
ultracentrifugeuse/S*
ultrachic/S*
ultra-chic/S*
ultracolonialisme/S*
ultra-colonialisme/S*
ultracolonialiste/S*
ultra-colonialiste/S*
ultraconfidentielle/F*
ultra-confidentielle/F*
................................................................................
vibrato/S.
vibratoire/S.
vibrer/a0p+
vibreur/S.
vibrion/S.
vibrionner/a0p.
vibrisse/S.
vibro/S.
vibromasseur/S.
vicaire/S.
vicariale/W.
vicariance/S.
vicariante/F.
vicariat/S.
vice/S.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.aff from [e59049a83a] to [2943eb6b1b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “MODERNE” v6.1
# par Olivier R. -- licence MPL 2.0
# Généré le 03-06-2017 à 22:26
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.




|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “MODERNE” v6.2
# par Olivier R. -- licence MPL 2.0
# Généré le 26-07-2017 à 09:33
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.dic from [cfbaa4802e] to [4be27e23e8].

1
2
3
4
5
6
7
8
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
529
530
531
532
533
534
535

536
537
538
539
540
541
542
...
651
652
653
654
655
656
657

658
659
660
661
662
663
664
...
896
897
898
899
900
901
902

903
904
905
906
907
908
909
....
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
....
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
....
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
....
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
....
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
....
3217
3218
3219
3220
3221
3222
3223

3224
3225
3226
3227
3228
3229
3230
....
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
....
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
....
3594
3595
3596
3597
3598
3599
3600

3601
3602
3603
3604
3605
3606
3607
....
4296
4297
4298
4299
4300
4301
4302

4303
4304
4305
4306
4307
4308
4309
....
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
....
6209
6210
6211
6212
6213
6214
6215

6216
6217
6218
6219
6220
6221
6222
....
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
....
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066

9067
9068
9069
9070
9071
9072
9073
....
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
....
9731
9732
9733
9734
9735
9736
9737

9738
9739
9740
9741
9742
9743
9744
....
9872
9873
9874
9875
9876
9877
9878

9879
9880
9881
9882
9883
9884
9885
.....
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
.....
11352
11353
11354
11355
11356
11357
11358

11359
11360
11361
11362
11363
11364
11365
.....
11668
11669
11670
11671
11672
11673
11674


11675
11676
11677
11678
11679
11680
11681
.....
12472
12473
12474
12475
12476
12477
12478

12479
12480
12481
12482
12483
12484
12485
.....
12569
12570
12571
12572
12573
12574
12575

12576
12577
12578
12579
12580
12581
12582
.....
14953
14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
.....
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
.....
15469
15470
15471
15472
15473
15474
15475

15476
15477
15478
15479
15480
15481
15482
.....
16592
16593
16594
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
.....
17715
17716
17717
17718
17719
17720
17721

17722
17723
17724
17725
17726
17727
17728
.....
18055
18056
18057
18058
18059
18060
18061

18062
18063
18064
18065
18066
18067
18068
.....
18452
18453
18454
18455
18456
18457
18458

18459
18460
18461
18462
18463
18464
18465
.....
19428
19429
19430
19431
19432
19433
19434

19435
19436
19437
19438
19439
19440
19441
.....
24029
24030
24031
24032
24033
24034
24035

24036
24037
24038
24039
24040
24041
24042
.....
24472
24473
24474
24475
24476
24477
24478
24479
24480
24481
24482
24483
24484
24485
24486
.....
25530
25531
25532
25533
25534
25535
25536

25537
25538
25539
25540
25541
25542
25543
.....
27316
27317
27318
27319
27320
27321
27322

27323
27324
27325
27326
27327
27328
27329
.....
28114
28115
28116
28117
28118
28119
28120

28121
28122
28123
28124
28125
28126
28127
.....
28163
28164
28165
28166
28167
28168
28169

28170
28171
28172
28173
28174
28175
28176
.....
28793
28794
28795
28796
28797
28798
28799

28800
28801
28802
28803
28804
28805
28806
.....
29507
29508
29509
29510
29511
29512
29513

29514
29515
29516
29517
29518
29519
29520
.....
30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
30630
30631
30632
.....
32080
32081
32082
32083
32084
32085
32086

32087
32088
32089
32090
32091
32092
32093
.....
33849
33850
33851
33852
33853
33854
33855


33856
33857
33858
33859
33860
33861
33862
.....
33884
33885
33886
33887
33888
33889
33890

33891
33892
33893
33894
33895
33896
33897
.....
34478
34479
34480
34481
34482
34483
34484

34485
34486
34487
34488
34489
34490
34491
.....
34684
34685
34686
34687
34688
34689
34690


34691
34692
34693
34694
34695
34696
34697
.....
35807
35808
35809
35810
35811
35812
35813

35814
35815
35816
35817
35818
35819
35820
.....
36017
36018
36019
36020
36021
36022
36023
36024
36025
36026
36027
36028
36029
36030
36031
.....
36680
36681
36682
36683
36684
36685
36686

36687
36688
36689
36690
36691
36692
36693
.....
40056
40057
40058
40059
40060
40061
40062

40063
40064
40065
40066
40067
40068
40069
.....
41188
41189
41190
41191
41192
41193
41194
41195
41196
41197
41198
41199
41200
41201
41202
.....
41301
41302
41303
41304
41305
41306
41307

41308
41309
41310
41311
41312
41313
41314

41315
41316
41317
41318
41319
41320
41321
.....
41799
41800
41801
41802
41803
41804
41805


41806
41807
41808
41809
41810
41811
41812
.....
42184
42185
42186
42187
42188
42189
42190

42191
42192
42193
42194
42195
42196
42197
.....
42370
42371
42372
42373
42374
42375
42376
42377
42378
42379
42380
42381
42382
42383
42384
.....
42425
42426
42427
42428
42429
42430
42431

42432
42433
42434
42435
42436
42437
42438
.....
52022
52023
52024
52025
52026
52027
52028

52029
52030
52031
52032
52033
52034
52035
.....
54369
54370
54371
54372
54373
54374
54375
54376
54377
54378
54379
54380
54381
54382
54383
54384
.....
57331
57332
57333
57334
57335
57336
57337

57338
57339
57340
57341
57342
57343
57344
.....
58993
58994
58995
58996
58997
58998
58999

59000
59001
59002
59003
59004
59005
59006
.....
59236
59237
59238
59239
59240
59241
59242
59243
59244
59245
59246
59247
59248
59249
59250
59251
.....
59379
59380
59381
59382
59383
59384
59385

59386
59387
59388
59389
59390
59391
59392
.....
59415
59416
59417
59418
59419
59420
59421
59422
59423
59424
59425
59426
59427
59428
59429
.....
59434
59435
59436
59437
59438
59439
59440
59441
59442
59443
59444
59445
59446
59447
59448
.....
59794
59795
59796
59797
59798
59799
59800

59801
59802
59803
59804
59805
59806
59807
.....
60068
60069
60070
60071
60072
60073
60074

60075
60076
60077
60078
60079
60080
60081
.....
60466
60467
60468
60469
60470
60471
60472
60473
60474
60475
60476
60477
60478
60479
60480
60481
.....
61863
61864
61865
61866
61867
61868
61869

61870
61871
61872
61873
61874
61875
61876
.....
61944
61945
61946
61947
61948
61949
61950
61951
61952
61953
61954
61955

61956
61957
61958
61959
61960
61961
61962
.....
62370
62371
62372
62373
62374
62375
62376

62377
62378
62379
62380
62381
62382
62383
.....
67945
67946
67947
67948
67949
67950
67951

67952
67953
67954
67955
67956
67957
67958
.....
68192
68193
68194
68195
68196
68197
68198

68199
68200
68201
68202
68203
68204
68205
.....
70723
70724
70725
70726
70727
70728
70729
70730
70731
70732
70733
70734
70735
70736
70737
.....
72382
72383
72384
72385
72386
72387
72388

72389
72390
72391
72392
72393
72394
72395
.....
72531
72532
72533
72534
72535
72536
72537
72538
72539
72540
72541
72542
72543
72544
72545
72546
.....
72576
72577
72578
72579
72580
72581
72582

72583
72584
72585
72586
72587
72588
72589
.....
75113
75114
75115
75116
75117
75118
75119

75120
75121
75122
75123
75124
75125
75126
.....
76217
76218
76219
76220
76221
76222
76223
76224
76225
76226
76227
76228
76229
76230
76231
.....
77429
77430
77431
77432
77433
77434
77435

77436
77437
77438
77439
77440
77441
77442
78805
&
1er/--
1ers/--
1re/--
1res/--
1ʳᵉ/--
1ʳᵉˢ/--
................................................................................
Aïcha/L'D'Q'
Aïd/L'D'Q'
Aida/L'D'Q'
Aidan/L'D'Q'
Aïd-el-Adha/L'
Aïd-el-Kébir/L'
Aiden/L'D'Q'
Aignan
Aigoual/L'D'
Aigrain/L'D'Q'
Aimé/L'D'Q'
Aimée/L'D'Q'
Ain/L'
Airaines/L'D'Q'
Airbnb/L'D'Q'
................................................................................
Arion/L'D'Q'
Aristarque/L'D'Q'
Aristide/L'D'Q'
Aristophane/L'D'Q'
Aristote/L'D'Q'
Arizona/L'D'
Arjuna/L'D'Q'

Arkansas/L'D'
Arkema/L'D'Q'
Arkham/L'D'Q'
Arkhangelsk/L'D'Q'
Arlene/L'D'Q'
Arlène/L'D'Q'
Arles/L'D'Q'
................................................................................
Aurélien/L'D'Q'
Aurelio/L'D'Q'
Auriane/L'D'Q'
Aurillac/L'D'Q'
Auriol/L'D'Q'
Aurore/L'D'Q'
Auschwitz/L'D'Q'

Austerlitz/L'D'Q'
Austin/L'D'Q'
Australasie/L'D'Q'
Australie/L'D'
Australie-Méridionale/L'D'
Australie-Occidentale/L'D'
Austrasie/L'D'
................................................................................
Benoîte
Benozillo
Benpro
Bentama
Bentham
Bentley
Benveniste

Berchem-Sainte-Agathe
Berck
Bercy
Bérenger
Bérengère
Bérénice
Bérézina
................................................................................
Caine
Caïphe
Caire
Caitlin
Caitlyn
Calabre
Calais

Calc
Calcutta
Calderón
Caleb
Calédonie
Calestienne
Calgary
................................................................................
Chostakovitch
Chris
Christa
Christel
Christèle
Christelle
Christian

Christiane
Christie
Christina
Christine
Christmas
Christoffel
Christoph
................................................................................
Cincinnati
Cindy
Ciney
Ciotat
Circassie
Circé
Cirey-sur-Vezouze

Cisjordanie
Cîteaux
Citroën
City
Claire
Clamart
Clara
................................................................................
Eure-et-Loir/L'D'
Euripide/L'D'Q'
Eurobaromètre/S*
Eurogroupe/L'
Euronext/L'D'Q'
Europe/L'D'
Europol/D'Q'

Eurozone/L'
Eurydice/L'D'Q'
Eusèbe/L'D'Q'
Euterpe/L'D'Q'
Eva/L'D'Q'
Éva/L'D'Q'
Évaine/L'D'Q'
................................................................................
Fayard
Fayçal
Fayette
Fécamp
Fed
FedEx
Federer

Federico
Fehling
Feist
Feïza
Feldane
Felicia
Félicie
................................................................................
Halluin/L'D'Q'
Ham/L'D'Q'
Hamas
Hambourg
Hamel
Hamid/L'D'Q'
Hamilton

Hamme
HammerFall
Hammourabi
Hamont-Achel/L'D'Q'
Hampshire
Ham-sur-Heure-Nalinnes/L'D'Q'
Hamza/L'D'Q'
................................................................................
Howard
Hubble
Hubei
Hubert/L'D'Q'
Hubscher
Hudson/L'D'Q'
Huelgoat

Hugo/L'D'Q'
Hugo/L'D'Q'
Hugues/L'D'Q'
Huguette
Hulshout/L'D'Q'
Hume
Hun/S.
................................................................................
IMSI/L'D'Q'
INED/L'D'Q'
INPI/L'D'Q'
INRA/L'D'Q'
INRI/L'D'Q'
INRIA/L'D'Q'
INSA/L'D'Q'
INSERM/L'D'Q'
IP/L'D'Q'
IRA/L'
IRD/L'D'Q'
IRFM/L'D'Q'
IRL
IRM/L'D'Q'
IRSTEA/L'D'Q'
................................................................................
Ingrid/L'D'Q'
Inkscape/L'D'Q'
Inn/L'D'
Inna/L'D'Q'
Innsmouth/L'D'Q'
Inovia/L'D'Q'
Insee/L'D'Q'

Insulinde/L'D'
Intel/L'D'Q'
Internet/D'Q'
Interpol/D'Q'
Io/L'D'Q'
Ionesco/L'D'Q'
Ioulia/L'D'Q'
................................................................................
Léonore
Léontine
Léopold
Léopoldine
Leopoldt
Léopoldville
Leroy

Lesbos
Lesieur
Lesley
Leslie
Lesneven
Lesotho
Lesse
................................................................................
Noisy-le-Grand
Noisy-le-Sec
Nokia
Nolan
Nolwenn
Nora
Norbert
Nord
Nord-Kivu
Nord-Pas-de-Calais
Nord-du-Québec
Nordine
Norfolk
Norique
Norma
................................................................................
Reidemeister
Reiko
Reims
Reiten
Relecq-Kerhuon
Rellich
Rembrandt

Rémi
Remich
Remire-Montjoly
Remus
Rémy
Renaix
Renan
................................................................................
Rosita
Rosny-sous-Bois
Ross
Rossini
Rossinière
Rostand
Roswell
Roth
Roth
Rothbard
Rothschild
Rotin
Rotselaar
Rotterdam
Roubaix
................................................................................
additionnelle/F*
additionnellement/D'Q'
additionner/a4p+
additionneuse/F*
additive/F*
additivement/D'Q'
additivité/S*
addon/S*
adducteur/S*
adduction/S*
adduit/S*
adèle/S*

adelphophagie/S*
adénine/S*
adénite/S*
adénocarcinome/S*
adénogramme/S*
adénoïde/S*
adénoïdectomie/S*
................................................................................
aérobie/S*
aérobie/S*
aérobiologie/S*
aérobiologique/S*
aérobiose/S*
aérobique/S*
aérocâble/S*
aéro-club/S*
aérocolie/S*
aérodigestive/F*
aérodistorsion/S*
aérodrome/S*
aérodynamicienne/F*
aérodynamique/S*
aérodynamique/S*
................................................................................
agripper/a4p+
agritourisme/S*
agroalimentaire/S*
agroalimentaire/S*
agrobiologie/S*
agrobiologique/S*
agrobiologiste/S*

agrocarburant/S*
agro-carburant/S*
agrochimie/S*
agrochimique/S*
agrochimiste/S*
agroclimatique/S*
agro-climatique/S*
................................................................................
aillade/S*
ailler/a2p+
ailleurs/L'D'Q'
ailloli/S*
aimable/S*
aimablement/D'Q'
aimant/S*

aimantation/S*
aimante/F*
aimanter/a4p+
aimantin/S*
aimantine/F*
aimée/F*
aimer/a4p+
................................................................................
amathie/S*
amatir/f2p+
amatrice/F*
amaurose/S*
amazone/S*
amazonienne/F*
amazonite/S*
ambages/D'Q'
ambassade/S*
ambassadrice/F*
ambiance/S*
ambiancer/a1p.
ambianceuse/F*
ambiante/F*
ambidextre/S*
................................................................................
annuité/S*
annulabilité/S*
annulable/S*
annulaire/S*
annulation/S*
annulative/F*
annulatrice/F*

annuler/a4p+
annuus
anoblir/f4p+
anoblissante/F*
anoblissement/S*
anode/S*
anodine/F*
................................................................................
antiémétique/S*
antiémeute/L'D'Q'
antienne/S*
antienzyme/S*
antiépileptique/S*
antiesclavagiste/S*
antiétatique/S*


antifading/S*
antifascisme/S*
antifasciste/S*
antiféminisme/S*
antiféministe/S*
antiferment/S*
antiferroélectricité/S*
................................................................................
arc/S*
arcade/S*
arcane/S*
arcanson/S*
arcasse/S*
arcature/S*
arc-boutant/L'D'Q'

arc-bouter/a4p+
arccos
arccosh
arccotan
arccotanh
arc-doubleau/L'D'Q'
arceau/X*
................................................................................
archontat/S*
archonte/S*
archosaurien/S*
archure/S*
arçon/S*
arçonner/a2p+
arcs-boutants/D'Q'

arcs-doubleaux/D'Q'
arcs-en-ciel/D'Q'
arcsin
arcsinh
arctan
arctanh
arctique/S*
................................................................................
bascule/S.
basculement/S.
basculer/a0p+
basculeur/S.
bas-culotte/S.
bas-de-casse
base/S.
base-ball/S.
baselle/S.
baser/a0p+
bas-fond/S.
basicité/S.
baside/S.
basidiomycète/S.
basidiomycète/S.
................................................................................
basilique/S.
basin/S.
basiphile/S.
basique/S.
basiquement
bas-jointée/F.
basket/S.
basket-ball/S.
basketteuse/F.
bas-mât/S.
basmati/S.
basocellulaire/S.
basoche/S.
basochienne/F.
bas-officier/S.
................................................................................
bernard-l'hermite
berne/S.
berner/a0p+
berneuse/F.
bernicle/S.
bernique
bernique/S.

berrichonne/F.
bersaglier/S.
berthon/S.
bertillonnage/S.
béryl/S.
bérylliose/S.
béryllium/S.
................................................................................
bondonnière/S.
bondrée/S.
bonellie/S.
bongo/S.
bonheur/S.
bonheur-du-jour
bonheurs-du-jour
bonhomie/S.
bonhomme
bonhomme/S.
boni/S.
bonichon/S.
bonifiante/F.
bonification/S.
bonifier/a0p+
boniment/S.
bonimenter/a0p.
................................................................................
bugne/S.
bugrane/S.
buguée/F.
build/S.
building/S.
buire/S.
buis

buisson/S.
buisson-ardent
buissonnante/F.
buissonnet/S.
buissonneuse/W.
buissonnière/F.
buissons-ardents
................................................................................
cadrer/a0p+
cadreuse/F.
cadriciel/S.
caduc/S.
caducée/S.
caducifoliée/F.
caducité/S.

caduque/S.
cæcale/W.
cæcotrophie/S.
cæcum/S.
caennaise/F.
cænogenèse/S.
cæsine
................................................................................
camping-caravaning/S.
camping-gaz
campinoise/F.
campo/S.
campus
camuse/F.
canada/S.

canadianisme/S.
canadienne/F.
canado-américaine/F.
canaille/S.
canaillement
canaillerie/S.
canaillocratie/S.
................................................................................
caucasique/S.
cauchemar/S.
cauchemarder/a0p.
cauchemardesque/S.
cauchemardeuse/W.
caucus
caudale/W.

caudataire/S.
caudataire/S.
caudillo/S.
caudine/S.
caudrette/S.
caulescente/F.
caulicole/S.
................................................................................
corruptrice/F.
corsage/S.
corsaire/S.
corse/S.
corselet/S.
corser/a0p+
corset/S.

corseter/b0p+
corseterie/S.
corsetière/F.
corso/S.
cortège/S.
cortès
cortex
................................................................................
covenant/S.
covendeuse/F.
cover-girl/S.
covoiturage/S.
covoiturer/a0p+
covoitureuse/F.
covolume/S.
cow-boy/S.
cowper/S.
coxale/W.
coxalgie/S.
coxalgique/S.
coxarthrose/S.
coxer/a0p+
coxofémorale/W.
................................................................................
cytotoxicité/S.
cytotoxique/S.
czardas
czimbalum/S.
d
d/||--
dB/||--

dacryoadénite/S.
dacryocystite/S.
dactyle/S.
dactylique/S.
dactylo/S.
dactylogramme/S.
dactylographe/S.
................................................................................
dénombrabilité/S.
dénombrable/S.
dénombrement/S.
dénombrer/a0p+
dénominateur/S.
dénomination/S.
dénominative/F.

dénommer/a0p+
dénoncer/a0p+
dénonciation/S.
dénonciatrice/F.
dénotation/S.
dénotationnelle/F.
dénotative/F.
................................................................................
désincorporer/a0p+
désincrustation/S.
désincruster/a0p+
désinculper/a0p+
désindenter/a0p+
désindexation/S.
désindexer/a0p+

désindustrialisation/S.
désindustrialiser/a0p+
désinence/S.
désinentielle/F.
désinfectante/F.
désinfecter/a0p+
désinfection/S.
................................................................................
désinviter/a0p+
désinvolte/S.
désinvoltement
désinvolture/S.
désir/S.
désirabilité/S.
désirable/S.

désirer/a0p+
désireuse/W.
désistement/S.
désister/a0p+
desman/S.
desmine/S.
desmodonte/S.
................................................................................
diarrhée/S.
diarrhéique/S.
diarthrose/S.
diascope/S.
diascopie/S.
diascordium/S.
diaspora/S.

diastase/S.
diastasique/S.
diastème/S.
diastéréo-isomère/S.
diastole/S.
diastolique/S.
diastratique/S.
................................................................................
diversement
diverses
diversifiable/S.
diversification/S.
diversifier/a0p+
diversiforme/S.
diversion/S.

diversité/S.
diverticule/S.
diverticulite/S.
diverticulose/S.
divertimento/S.
divertir/f0p+
divertissante/F.
................................................................................
écocertifiée/F*
écocide/S*
écocitoyenne/F*
écocitoyenneté/S*
écoconception/S*
écoconduite/S*
écoconstruction/S*
éco-construction/S*
écoemballage/S*
éco-environnementale/F*
écœurante/F*
écœurement/S*
écœurer/a2p+
écogeste/S*
écohabitat/S*
................................................................................
endoénergétique/S*
endogame/S*
endogamie/S*
endogamique/S*
endogée/F*
endogène/S*
endogénéité/S*

endolocalisation/S*
endolorir/f2p+
endolorissement/S*
endolymphe/S*
endomètre/S*
endométriose/S*
endométrite/S*
................................................................................
ethmoïdale/W*
ethmoïde/S*
ethmoïdite/S*
ethnarchie/S*
ethnarque/S*
ethnicisation/S*
ethniciser/a2p+


ethnicité/S*
ethnico-religieuse/W*
ethnie/S*
ethnique/S*
ethniquement/D'Q'
ethnobiologie/S*
ethnobotanique/S*
................................................................................
ethnométhodologue/S*
ethnomusicologie/S*
ethnomusicologue/S*
ethnonyme/S*
ethnonymie/S*
ethnopsychiatrie/S*
ethnopsychologie/S*

ethnoreligieuse/W*
éthographie/S*
éthologie/S*
éthologique/S*
éthologiste/S*
éthologue/S*
ethos/L'D'Q'
................................................................................
exode/S*
exoderme/S*
exogame/S*
exogamie/S*
exogamique/S*
exogène/S*
exogénéité/S*

exomphale/S*
exon/S*
exondation/S*
exondement/S*
exonder/a3p+
exonération/S*
exonérer/c4p+
................................................................................
extensionnelle/F*
extensité/S*
extensive/F*
extensivement/L'D'Q'
extensivité/S*
extenso
extensomètre/S*


exténuante/F*
exténuation/S*
exténuée/F*
exténuement/S*
exténuer/a4p+
extérieur/S*
extérieure/F*
................................................................................
filoselle/S.
filou/S.
filoutage/S.
filouter/a0p+
filouterie/S.
filovirus
fils

filtrable/S.
filtrage/S.
filtrante/F.
filtrat/S.
filtration/S.
filtre/S.
filtre-presse
................................................................................
flanquer/a0p+
flapie/F.
flaque/S.
flaquer/a0p.
flash/A.
flashage/S.
flash-back
flash-ball/S.
flasher/a0p+
flasheuse/F.
flashmètre/S.
flashy
flasque/S.
flasquement
flatter/a0p+
................................................................................
foutou/S.
foutrale/F.
foutraque/S.
foutre/S.
foutre/tM
foutredieu
foutrement

foutriquet/S.
foutue/F.
fovéa/S.
fovéale/W.
fox
foxée/F.
fox-hound/S.
................................................................................
haptique/S*
haptonomie/S*
haptonomique/S*
haquebute/S.
haquenée/S.
haquet/S.
hara-kiri/S.

harangue/S.
haranguer/a0p+
harangueuse/F.
haras
harassante/F.
harassement/S.
harasser/a0p+
................................................................................
hors-bilan
hors-bord
hors-champ
hors-concours
hors-cote
hors-cote
hors-d'œuvre
horse-ball/S.
horse-guard/S.
horse-power
horse-pox
hors-jeu
hors-la-loi
hors-ligne
hors-média
................................................................................
hoyau/X.
hpz/||--
http/S=
huard/S.
huart/S.
hub/S.
hublot/S.

huche/S.
hucher/a0p+
huchet/S.
hue
huée/S.
huer/a0p+
huerta/S.

huguenote/F.
huilage/S*
huile/S*
huiler/a2p+
huilerie/S*
huileuse/W*
huilière/F*
................................................................................
hypertrophier/a4p+
hypertrophique/S*
hyperuricémie/S*
hypervariable/S*
hyperventilation/S*
hyperventiler/a1p.
hypervigilance/S*


hyperviscosité/S*
hyperviseur/S*
hypervitaminose/S*
hyphe/S*
hypholome/S*
hypnagogique/S*
hypnogramme/S*
................................................................................
illisibilité/S*
illisible/S*
illisiblement/D'Q'
illogique/S*
illogiquement/D'Q'
illogisme/S*
illuminante/F*

illumination/S*
illuminative/F*
illuminatrice/F*
illuminée/F*
illuminer/a4p+
illuminisme/S*
illusion/S*
................................................................................
immunodéficiente/F*
immunodéficitaire/S*
immunodépresseur/S*
immunodépression/S*
immunodépressive/F*
immunodéprimée/F*
immunofluorescence/S*
immuno-fluorescence/S*
immunogène/S*
immunogénétique/S*
immunogénicité/S*
immunogénique/S*
immunoglobuline/S*
immunohistochimie/S*
immunologie/S*
................................................................................
imparisyllabique/S*
imparité/S*
impartageable/S*
impartiale/W*
impartialement/D'Q'
impartialité/S*
impartir/fC

impasse/S*
impassibilité/S*
impassible/S*
impassiblement/D'Q'
impatiemment/D'Q'
impatience/S*
impatiens/L'D'Q'
................................................................................
multidevise/S.
multidiffusion/S.
multidimensionnalité/S.
multidimensionnelle/F.
multidirectionnalité/S.
multidirectionnelle/F.
multidisciplinaire/S.

multiethnique/S.
multifactorielle/F.
multifamiliale/W.
multifilaire/S.
multiflore/S.
multifonction/S.
multifonctionnalité/S.
................................................................................
oligoasthénotératospermie/S*
oligocène/S*
oligochète/S*
oligoclase/S*
oligodendrocyte/S*
oligodendrogliome/S*
oligoélément/S*
oligoélément/S*
oligo-élément/S*
oligogalacturonate/S*
oligo-galacturonate/S*
oligomère/S*
oligomérique/S*
oligomérisation/S*
oligonucléotide/S*
oligo-nucléotide/S*
................................................................................
perceptiblement
perception/S.
perceptionnisme/S.
perceptionniste/S.
perceptive/F.
perceptrice/F.
perceptuelle/F.

percer/a0p+
percerette/S.
perceuse/F.
percevable/S.
percevoir/pK
perche/S.
percher/a0p+
................................................................................
pixellisation/S.
pizza/S.
pizzaïolo/S.
pizzeria/S.
pizzicato/I.
placage/S.
placard/S.

placarder/a0p+
placardisation/S.
placardiser/a0p+
place/S.
placebo/S.
placement/S.
placenta/S.
................................................................................
plâtrerie/S.
plâtreuse/W.
plâtrière/F.
plats-bords
plausibilité/S.
plausible/S.
plausiblement
play-back
play-boy/S.
playlist/S.
playon/S.
pléban/S.
plèbe/S.
plébéienne/F.
plébiscitaire/S.
plébiscite/S.
................................................................................
ployage/S.
ployante/F.
ployer/a0p+
pluche/S.
plucher/a0p.
plucheuse/W.
plugin/S.

pluie/S.
plumage/S.
plumaison/S.
plumard/S.
plumasseau/X.
plumasserie/S.
plumassière/F.
................................................................................
pluriannuelle/F.
pluricellulaire/S.
pluriculturelle/F.
pluridimensionnalité/S.
pluridimensionnelle/F.
pluridisciplinaire/S.
pluridisciplinaire/S.
pluri-disciplinaire/S.
pluridisciplinarité/S.
plurielle/F.
pluriethnique/S.
plurilatérale/W.
plurilingue/S.
plurilinguisme/S.
plurimillénaire/S.
................................................................................
pluripartite/S.
pluripotence/S.
pluripotente/F.
pluriséculaire/S.
plurisousharmonique/S.
plurispécifique/S.
plurithématique/S.
pluri-thématique/S.
plurithérapie/S.
plurivalente/F.
plurivocité/S.
plurivoque/S.
plus
plus
plusieurs
................................................................................
polychète/S.
polychlorobenzène/S.
polychlorure/S.
polychroïque/S.
polychroïsme/S.
polychrome/S.
polychromie/S.

polycistronique/S.
polyclinique/S.
polycondensat/S.
polycondensation/S.
polycopie/S.
polycopier/a0p+
polycourant
................................................................................
pop-corn
pope/S.
popeline/S.
popinée/S.
poplitée/F.
popote/S.
popotin/S.

populace/S.
populacière/F.
populage/S.
populaire/S.
populairement
popularisation/S.
populariser/a0p+
................................................................................
poulaille/S.
poulailler/S.
poulaine/F.
poulamon/S.
poularde/S.
poulbot/S.
poule/S.
poulet/S.
poulette/S.
pouliage/S.
pouliche/S.
poulie/S.
pouliner/a0p.
poulinière/S.
poulinière/S.
pouliot/S.
................................................................................
protoplasme/S.
protoplasmique/S.
protoplaste/S.
protoptère/S.
protosulfure/S.
prototypage/S.
prototype/S.

prototypique/S.
prototypiste/S.
protoure/S.
protoxyde/S.
protozoaire/S.
protozoologie/S.
protractile/S.
................................................................................
pruche/S.
prude/S.
prudemment
prudence/S.
prudente/F.
prudentielle/F.
pruderie/S.
prud'homale/W.
prud'homie/S.
prud'homme/S.
prudhommerie/S.
prudhommesque/S.

pruine/S.
prune
prune/S.
pruneau/X.
prunelaie/S.
prunelée/S.
prunelle/S.
................................................................................
pusillanime/S.
pusillanimement
pusillanimité/S.
pustule/S.
pustuler/a0p+
pustuleuse/W.
putain/S.

putassière/F.
putative/F.
pute/S.
putier/S.
putiet/S.
putois
putréfaction/S.
................................................................................
sceau/X.
sceau-de-Salomon
sceaux-de-Salomon
scélérate/F.
scélératement
scélératesse/S.
scellage/S.

scellement/S.
sceller/a0p+
scénarimage/S.
scénario/S.
scénarisation/S.
scénariser/a0p+
scénariste/S.
................................................................................
scripturale/W.
scripturalisme/S.
scrofulaire/S.
scrofulariacée/S.
scrofule/S.
scrofuleuse/W.
scrogneugneu/X.

scrolling/S.
scrotale/W.
scrotum/S.
scrub/S.
scrubber/S.
scrupule/S.
scrupuleuse/W.
................................................................................
stariser/a0p+
starlette/S.
staroste/S.
star-system/S.
starter/S.
starting-block/S.
starting-gate/S.
start-up/S.
stase/S.
stater/a0p+
statère/S.
stathouder/S.
stathoudérat/S.
statice/S.
statif/S.
................................................................................
syrah/S.
syriaque/S.
syriaque/S.
syrienne/F.
syringe/S.
syringomyélie/S.
syrinx

syrphe/S.
sysadmin/S.
systématicienne/F.
systématicité/S.
systématique/S.
systématique/S.
systématiquement
................................................................................
tagine/S.
tagliatelle/S.
tagme/S.
taguer/a0p+
tagueuse/F.
tahitienne/F.
taïaut
taï-chi
taï-chi-chuan
taie/S.
taïga/S.
taiji/S.
taijiquan/S.
taïkonaute/S.
taillable/S.
taillade/S.
................................................................................
taleb/S.
talent/S.
talentueuse/W.
talentueusement
taler/a0p+
taleth/S.
talibane/F.

talion/S.
talisman/S.
talismanique/S.
talith/S.
talitre/S.
talkies-walkies
talkie-walkie
................................................................................
trantran/S.
trapèze/S.
trapéziste/S.
trapézoèdre/S.
trapézoïdale/W.
trapézoïde/S.
trappe/S.

trappeuse/F.
trappillon/S.
trappiste/S.
trappistine/S.
trapue/F.
traque/S.
traquée/F.
................................................................................
ultimement/D'Q'
ultimité/S*
ultimo
ultra/S*
ultrabasique/S*
ultracentrifugation/S*
ultracentrifugeuse/S*
ultra-chic/S*
ultracolonialisme/S*
ultracolonialiste/S*
ultraconfidentielle/F*
ultraconservatrice/F*
ultracourte/F*
ultradienne/F*
ultradroite/S*
................................................................................
vibrato/S.
vibratoire/S.
vibrer/a0p+
vibreur/S.
vibrion/S.
vibrionner/a0p.
vibrisse/S.

vibromasseur/S.
vicaire/S.
vicariale/W.
vicariance/S.
vicariante/F.
vicariat/S.
vice/S.
|







 







|







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







>







 







<







 







>







 







>







 







<







 







>







 







<







 







|




>







 







|







 







>







 







>







 







|







 







>







 







>
>







 







>







 







>







 







|







 







|







 







>







 







|
|
|







 







>







 







>







 







>







 







>







 







>







 







|







 







>







 







>







 







>







 







>







 







>







 







>







 







<







 







>







 







>
>







 







>







 







>







 







>
>







 







>







 







|







 







>







 







>







 







|







 







>







>







 







>
>







 







>







 







<







 







>







 







>







 







<
<







 







>







 







>







 







|
|







 







>







 







<







 







<







 







>







 







>







 







<
|







 







>







 







|
<
|


>







 







>







 







>







 







>







 







|







 







>







 







|
|







 







>







 







>







 







|







 







>







1
2
3
4
5
6
7
8
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
....
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
....
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
....
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
....
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
....
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
....
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
....
3525
3526
3527
3528
3529
3530
3531

3532
3533
3534
3535
3536
3537
3538
....
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
....
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
....
5484
5485
5486
5487
5488
5489
5490

5491
5492
5493
5494
5495
5496
5497
....
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
....
6390
6391
6392
6393
6394
6395
6396

6397
6398
6399
6400
6401
6402
6403
....
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
....
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
....
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
....
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
.....
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
.....
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
.....
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
.....
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
.....
12586
12587
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
12599
12600
.....
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
.....
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
.....
15487
15488
15489
15490
15491
15492
15493
15494
15495
15496
15497
15498
15499
15500
15501
.....
16611
16612
16613
16614
16615
16616
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626
16627
.....
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
.....
18075
18076
18077
18078
18079
18080
18081
18082
18083
18084
18085
18086
18087
18088
18089
.....
18473
18474
18475
18476
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487
.....
19450
19451
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
.....
24052
24053
24054
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064
24065
24066
.....
24496
24497
24498
24499
24500
24501
24502
24503
24504
24505
24506
24507
24508
24509
24510
.....
25554
25555
25556
25557
25558
25559
25560
25561
25562
25563
25564
25565
25566
25567
25568
.....
27341
27342
27343
27344
27345
27346
27347
27348
27349
27350
27351
27352
27353
27354
27355
.....
28140
28141
28142
28143
28144
28145
28146
28147
28148
28149
28150
28151
28152
28153
28154
.....
28190
28191
28192
28193
28194
28195
28196
28197
28198
28199
28200
28201
28202
28203
28204
.....
28821
28822
28823
28824
28825
28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
.....
29536
29537
29538
29539
29540
29541
29542
29543
29544
29545
29546
29547
29548
29549
29550
.....
30648
30649
30650
30651
30652
30653
30654

30655
30656
30657
30658
30659
30660
30661
.....
32109
32110
32111
32112
32113
32114
32115
32116
32117
32118
32119
32120
32121
32122
32123
.....
33879
33880
33881
33882
33883
33884
33885
33886
33887
33888
33889
33890
33891
33892
33893
33894
.....
33916
33917
33918
33919
33920
33921
33922
33923
33924
33925
33926
33927
33928
33929
33930
.....
34511
34512
34513
34514
34515
34516
34517
34518
34519
34520
34521
34522
34523
34524
34525
.....
34718
34719
34720
34721
34722
34723
34724
34725
34726
34727
34728
34729
34730
34731
34732
34733
.....
35843
35844
35845
35846
35847
35848
35849
35850
35851
35852
35853
35854
35855
35856
35857
.....
36054
36055
36056
36057
36058
36059
36060
36061
36062
36063
36064
36065
36066
36067
36068
.....
36717
36718
36719
36720
36721
36722
36723
36724
36725
36726
36727
36728
36729
36730
36731
.....
40094
40095
40096
40097
40098
40099
40100
40101
40102
40103
40104
40105
40106
40107
40108
.....
41227
41228
41229
41230
41231
41232
41233
41234
41235
41236
41237
41238
41239
41240
41241
.....
41340
41341
41342
41343
41344
41345
41346
41347
41348
41349
41350
41351
41352
41353
41354
41355
41356
41357
41358
41359
41360
41361
41362
.....
41840
41841
41842
41843
41844
41845
41846
41847
41848
41849
41850
41851
41852
41853
41854
41855
.....
42227
42228
42229
42230
42231
42232
42233
42234
42235
42236
42237
42238
42239
42240
42241
.....
42414
42415
42416
42417
42418
42419
42420

42421
42422
42423
42424
42425
42426
42427
.....
42468
42469
42470
42471
42472
42473
42474
42475
42476
42477
42478
42479
42480
42481
42482
.....
52066
52067
52068
52069
52070
52071
52072
52073
52074
52075
52076
52077
52078
52079
52080
.....
54414
54415
54416
54417
54418
54419
54420


54421
54422
54423
54424
54425
54426
54427
.....
57374
57375
57376
57377
57378
57379
57380
57381
57382
57383
57384
57385
57386
57387
57388
.....
59037
59038
59039
59040
59041
59042
59043
59044
59045
59046
59047
59048
59049
59050
59051
.....
59281
59282
59283
59284
59285
59286
59287
59288
59289
59290
59291
59292
59293
59294
59295
59296
.....
59424
59425
59426
59427
59428
59429
59430
59431
59432
59433
59434
59435
59436
59437
59438
.....
59461
59462
59463
59464
59465
59466
59467

59468
59469
59470
59471
59472
59473
59474
.....
59479
59480
59481
59482
59483
59484
59485

59486
59487
59488
59489
59490
59491
59492
.....
59838
59839
59840
59841
59842
59843
59844
59845
59846
59847
59848
59849
59850
59851
59852
.....
60113
60114
60115
60116
60117
60118
60119
60120
60121
60122
60123
60124
60125
60126
60127
.....
60512
60513
60514
60515
60516
60517
60518

60519
60520
60521
60522
60523
60524
60525
60526
.....
61908
61909
61910
61911
61912
61913
61914
61915
61916
61917
61918
61919
61920
61921
61922
.....
61990
61991
61992
61993
61994
61995
61996
61997

61998
61999
62000
62001
62002
62003
62004
62005
62006
62007
62008
.....
62416
62417
62418
62419
62420
62421
62422
62423
62424
62425
62426
62427
62428
62429
62430
.....
67992
67993
67994
67995
67996
67997
67998
67999
68000
68001
68002
68003
68004
68005
68006
.....
68240
68241
68242
68243
68244
68245
68246
68247
68248
68249
68250
68251
68252
68253
68254
.....
70772
70773
70774
70775
70776
70777
70778
70779
70780
70781
70782
70783
70784
70785
70786
.....
72431
72432
72433
72434
72435
72436
72437
72438
72439
72440
72441
72442
72443
72444
72445
.....
72581
72582
72583
72584
72585
72586
72587
72588
72589
72590
72591
72592
72593
72594
72595
72596
.....
72626
72627
72628
72629
72630
72631
72632
72633
72634
72635
72636
72637
72638
72639
72640
.....
75164
75165
75166
75167
75168
75169
75170
75171
75172
75173
75174
75175
75176
75177
75178
.....
76269
76270
76271
76272
76273
76274
76275
76276
76277
76278
76279
76280
76281
76282
76283
.....
77481
77482
77483
77484
77485
77486
77487
77488
77489
77490
77491
77492
77493
77494
77495
78858
&
1er/--
1ers/--
1re/--
1res/--
1ʳᵉ/--
1ʳᵉˢ/--
................................................................................
Aïcha/L'D'Q'
Aïd/L'D'Q'
Aida/L'D'Q'
Aidan/L'D'Q'
Aïd-el-Adha/L'
Aïd-el-Kébir/L'
Aiden/L'D'Q'
Aignan/L'D'Q'
Aigoual/L'D'
Aigrain/L'D'Q'
Aimé/L'D'Q'
Aimée/L'D'Q'
Ain/L'
Airaines/L'D'Q'
Airbnb/L'D'Q'
................................................................................
Arion/L'D'Q'
Aristarque/L'D'Q'
Aristide/L'D'Q'
Aristophane/L'D'Q'
Aristote/L'D'Q'
Arizona/L'D'
Arjuna/L'D'Q'
Arkady/L'D'Q'
Arkansas/L'D'
Arkema/L'D'Q'
Arkham/L'D'Q'
Arkhangelsk/L'D'Q'
Arlene/L'D'Q'
Arlène/L'D'Q'
Arles/L'D'Q'
................................................................................
Aurélien/L'D'Q'
Aurelio/L'D'Q'
Auriane/L'D'Q'
Aurillac/L'D'Q'
Auriol/L'D'Q'
Aurore/L'D'Q'
Auschwitz/L'D'Q'
Austen/L'D'Q'
Austerlitz/L'D'Q'
Austin/L'D'Q'
Australasie/L'D'Q'
Australie/L'D'
Australie-Méridionale/L'D'
Australie-Occidentale/L'D'
Austrasie/L'D'
................................................................................
Benoîte
Benozillo
Benpro
Bentama
Bentham
Bentley
Benveniste
Bérangère
Berchem-Sainte-Agathe
Berck
Bercy
Bérenger
Bérengère
Bérénice
Bérézina
................................................................................
Caine
Caïphe
Caire
Caitlin
Caitlyn
Calabre
Calais
Calaisis
Calc
Calcutta
Calderón
Caleb
Calédonie
Calestienne
Calgary
................................................................................
Chostakovitch
Chris
Christa
Christel
Christèle
Christelle
Christian
Christiana
Christiane
Christie
Christina
Christine
Christmas
Christoffel
Christoph
................................................................................
Cincinnati
Cindy
Ciney
Ciotat
Circassie
Circé
Cirey-sur-Vezouze
Cisco
Cisjordanie
Cîteaux
Citroën
City
Claire
Clamart
Clara
................................................................................
Eure-et-Loir/L'D'
Euripide/L'D'Q'
Eurobaromètre/S*
Eurogroupe/L'
Euronext/L'D'Q'
Europe/L'D'
Europol/D'Q'
Eurotunnel/L'D'Q'
Eurozone/L'
Eurydice/L'D'Q'
Eusèbe/L'D'Q'
Euterpe/L'D'Q'
Eva/L'D'Q'
Éva/L'D'Q'
Évaine/L'D'Q'
................................................................................
Fayard
Fayçal
Fayette
Fécamp
Fed
FedEx
Federer
Federica
Federico
Fehling
Feist
Feïza
Feldane
Felicia
Félicie
................................................................................
Halluin/L'D'Q'
Ham/L'D'Q'
Hamas
Hambourg
Hamel
Hamid/L'D'Q'
Hamilton
Hamlet/L'D'Q'
Hamme
HammerFall
Hammourabi
Hamont-Achel/L'D'Q'
Hampshire
Ham-sur-Heure-Nalinnes/L'D'Q'
Hamza/L'D'Q'
................................................................................
Howard
Hubble
Hubei
Hubert/L'D'Q'
Hubscher
Hudson/L'D'Q'
Huelgoat
Hugh/L'D'Q'
Hugo/L'D'Q'
Hugo/L'D'Q'
Hugues/L'D'Q'
Huguette
Hulshout/L'D'Q'
Hume
Hun/S.
................................................................................
IMSI/L'D'Q'
INED/L'D'Q'
INPI/L'D'Q'
INRA/L'D'Q'
INRI/L'D'Q'
INRIA/L'D'Q'
INSA/L'D'Q'

IP/L'D'Q'
IRA/L'
IRD/L'D'Q'
IRFM/L'D'Q'
IRL
IRM/L'D'Q'
IRSTEA/L'D'Q'
................................................................................
Ingrid/L'D'Q'
Inkscape/L'D'Q'
Inn/L'D'
Inna/L'D'Q'
Innsmouth/L'D'Q'
Inovia/L'D'Q'
Insee/L'D'Q'
Inserm/L'D'Q'
Insulinde/L'D'
Intel/L'D'Q'
Internet/D'Q'
Interpol/D'Q'
Io/L'D'Q'
Ionesco/L'D'Q'
Ioulia/L'D'Q'
................................................................................
Léonore
Léontine
Léopold
Léopoldine
Leopoldt
Léopoldville
Leroy
Lesage
Lesbos
Lesieur
Lesley
Leslie
Lesneven
Lesotho
Lesse
................................................................................
Noisy-le-Grand
Noisy-le-Sec
Nokia
Nolan
Nolwenn
Nora
Norbert

Nord-Kivu
Nord-Pas-de-Calais
Nord-du-Québec
Nordine
Norfolk
Norique
Norma
................................................................................
Reidemeister
Reiko
Reims
Reiten
Relecq-Kerhuon
Rellich
Rembrandt
Remi
Rémi
Remich
Remire-Montjoly
Remus
Rémy
Renaix
Renan
................................................................................
Rosita
Rosny-sous-Bois
Ross
Rossini
Rossinière
Rostand
Roswell

Roth
Rothbard
Rothschild
Rotin
Rotselaar
Rotterdam
Roubaix
................................................................................
additionnelle/F*
additionnellement/D'Q'
additionner/a4p+
additionneuse/F*
additive/F*
additivement/D'Q'
additivité/S*
add-on/S*
adducteur/S*
adduction/S*
adduit/S*
adèle/S*
adelphe/S*
adelphophagie/S*
adénine/S*
adénite/S*
adénocarcinome/S*
adénogramme/S*
adénoïde/S*
adénoïdectomie/S*
................................................................................
aérobie/S*
aérobie/S*
aérobiologie/S*
aérobiologique/S*
aérobiose/S*
aérobique/S*
aérocâble/S*
aéroclub/S*
aérocolie/S*
aérodigestive/F*
aérodistorsion/S*
aérodrome/S*
aérodynamicienne/F*
aérodynamique/S*
aérodynamique/S*
................................................................................
agripper/a4p+
agritourisme/S*
agroalimentaire/S*
agroalimentaire/S*
agrobiologie/S*
agrobiologique/S*
agrobiologiste/S*
agrobusiness/L'D'Q'
agrocarburant/S*
agro-carburant/S*
agrochimie/S*
agrochimique/S*
agrochimiste/S*
agroclimatique/S*
agro-climatique/S*
................................................................................
aillade/S*
ailler/a2p+
ailleurs/L'D'Q'
ailloli/S*
aimable/S*
aimablement/D'Q'
aimant/S*
aimantable/S*
aimantation/S*
aimante/F*
aimanter/a4p+
aimantin/S*
aimantine/F*
aimée/F*
aimer/a4p+
................................................................................
amathie/S*
amatir/f2p+
amatrice/F*
amaurose/S*
amazone/S*
amazonienne/F*
amazonite/S*
ambage/S*
ambassade/S*
ambassadrice/F*
ambiance/S*
ambiancer/a1p.
ambianceuse/F*
ambiante/F*
ambidextre/S*
................................................................................
annuité/S*
annulabilité/S*
annulable/S*
annulaire/S*
annulation/S*
annulative/F*
annulatrice/F*
annulement/S*
annuler/a4p+
annuus
anoblir/f4p+
anoblissante/F*
anoblissement/S*
anode/S*
anodine/F*
................................................................................
antiémétique/S*
antiémeute/L'D'Q'
antienne/S*
antienzyme/S*
antiépileptique/S*
antiesclavagiste/S*
antiétatique/S*
antiétatisme/S*
antifa/S*
antifading/S*
antifascisme/S*
antifasciste/S*
antiféminisme/S*
antiféministe/S*
antiferment/S*
antiferroélectricité/S*
................................................................................
arc/S*
arcade/S*
arcane/S*
arcanson/S*
arcasse/S*
arcature/S*
arc-boutant/L'D'Q'
arc-boutement
arc-bouter/a4p+
arccos
arccosh
arccotan
arccotanh
arc-doubleau/L'D'Q'
arceau/X*
................................................................................
archontat/S*
archonte/S*
archosaurien/S*
archure/S*
arçon/S*
arçonner/a2p+
arcs-boutants/D'Q'
arcs-boutements
arcs-doubleaux/D'Q'
arcs-en-ciel/D'Q'
arcsin
arcsinh
arctan
arctanh
arctique/S*
................................................................................
bascule/S.
basculement/S.
basculer/a0p+
basculeur/S.
bas-culotte/S.
bas-de-casse
base/S.
baseball/S.
baselle/S.
baser/a0p+
bas-fond/S.
basicité/S.
baside/S.
basidiomycète/S.
basidiomycète/S.
................................................................................
basilique/S.
basin/S.
basiphile/S.
basique/S.
basiquement
bas-jointée/F.
basket/S.
basketball/S.
basketteuse/F.
bas-mât/S.
basmati/S.
basocellulaire/S.
basoche/S.
basochienne/F.
bas-officier/S.
................................................................................
bernard-l'hermite
berne/S.
berner/a0p+
berneuse/F.
bernicle/S.
bernique
bernique/S.
bernoise/F.
berrichonne/F.
bersaglier/S.
berthon/S.
bertillonnage/S.
béryl/S.
bérylliose/S.
béryllium/S.
................................................................................
bondonnière/S.
bondrée/S.
bonellie/S.
bongo/S.
bonheur/S.
bonheur-du-jour
bonheurs-du-jour
bonhomme
bonhomme/S.
bonhommie/S.
boni/S.
bonichon/S.
bonifiante/F.
bonification/S.
bonifier/a0p+
boniment/S.
bonimenter/a0p.
................................................................................
bugne/S.
bugrane/S.
buguée/F.
build/S.
building/S.
buire/S.
buis
buissaie/S.
buisson/S.
buisson-ardent
buissonnante/F.
buissonnet/S.
buissonneuse/W.
buissonnière/F.
buissons-ardents
................................................................................
cadrer/a0p+
cadreuse/F.
cadriciel/S.
caduc/S.
caducée/S.
caducifoliée/F.
caducité/S.
caduque/F.
caduque/S.
cæcale/W.
cæcotrophie/S.
cæcum/S.
caennaise/F.
cænogenèse/S.
cæsine
................................................................................
camping-caravaning/S.
camping-gaz
campinoise/F.
campo/S.
campus
camuse/F.
canada/S.
canadair/S.
canadianisme/S.
canadienne/F.
canado-américaine/F.
canaille/S.
canaillement
canaillerie/S.
canaillocratie/S.
................................................................................
caucasique/S.
cauchemar/S.
cauchemarder/a0p.
cauchemardesque/S.
cauchemardeuse/W.
caucus
caudale/W.
caudalie/S.
caudataire/S.
caudataire/S.
caudillo/S.
caudine/S.
caudrette/S.
caulescente/F.
caulicole/S.
................................................................................
corruptrice/F.
corsage/S.
corsaire/S.
corse/S.
corselet/S.
corser/a0p+
corset/S.
corsetage/S.
corseter/b0p+
corseterie/S.
corsetière/F.
corso/S.
cortège/S.
cortès
cortex
................................................................................
covenant/S.
covendeuse/F.
cover-girl/S.
covoiturage/S.
covoiturer/a0p+
covoitureuse/F.
covolume/S.
cowboy/S.
cowper/S.
coxale/W.
coxalgie/S.
coxalgique/S.
coxarthrose/S.
coxer/a0p+
coxofémorale/W.
................................................................................
cytotoxicité/S.
cytotoxique/S.
czardas
czimbalum/S.
d
d/||--
dB/||--
daba/S.
dacryoadénite/S.
dacryocystite/S.
dactyle/S.
dactylique/S.
dactylo/S.
dactylogramme/S.
dactylographe/S.
................................................................................
dénombrabilité/S.
dénombrable/S.
dénombrement/S.
dénombrer/a0p+
dénominateur/S.
dénomination/S.
dénominative/F.
dénommable/S.
dénommer/a0p+
dénoncer/a0p+
dénonciation/S.
dénonciatrice/F.
dénotation/S.
dénotationnelle/F.
dénotative/F.
................................................................................
désincorporer/a0p+
désincrustation/S.
désincruster/a0p+
désinculper/a0p+
désindenter/a0p+
désindexation/S.
désindexer/a0p+
désindividualiser/a0p+
désindustrialisation/S.
désindustrialiser/a0p+
désinence/S.
désinentielle/F.
désinfectante/F.
désinfecter/a0p+
désinfection/S.
................................................................................
désinviter/a0p+
désinvolte/S.
désinvoltement
désinvolture/S.
désir/S.
désirabilité/S.
désirable/S.
désirante/F.
désirer/a0p+
désireuse/W.
désistement/S.
désister/a0p+
desman/S.
desmine/S.
desmodonte/S.
................................................................................
diarrhée/S.
diarrhéique/S.
diarthrose/S.
diascope/S.
diascopie/S.
diascordium/S.
diaspora/S.
diasporique/S.
diastase/S.
diastasique/S.
diastème/S.
diastéréo-isomère/S.
diastole/S.
diastolique/S.
diastratique/S.
................................................................................
diversement
diverses
diversifiable/S.
diversification/S.
diversifier/a0p+
diversiforme/S.
diversion/S.
diversitaire/S.
diversité/S.
diverticule/S.
diverticulite/S.
diverticulose/S.
divertimento/S.
divertir/f0p+
divertissante/F.
................................................................................
écocertifiée/F*
écocide/S*
écocitoyenne/F*
écocitoyenneté/S*
écoconception/S*
écoconduite/S*
écoconstruction/S*

écoemballage/S*
éco-environnementale/F*
écœurante/F*
écœurement/S*
écœurer/a2p+
écogeste/S*
écohabitat/S*
................................................................................
endoénergétique/S*
endogame/S*
endogamie/S*
endogamique/S*
endogée/F*
endogène/S*
endogénéité/S*
endogroupe/S*
endolocalisation/S*
endolorir/f2p+
endolorissement/S*
endolymphe/S*
endomètre/S*
endométriose/S*
endométrite/S*
................................................................................
ethmoïdale/W*
ethmoïde/S*
ethmoïdite/S*
ethnarchie/S*
ethnarque/S*
ethnicisation/S*
ethniciser/a2p+
ethnicisme/S*
ethniciste/S*
ethnicité/S*
ethnico-religieuse/W*
ethnie/S*
ethnique/S*
ethniquement/D'Q'
ethnobiologie/S*
ethnobotanique/S*
................................................................................
ethnométhodologue/S*
ethnomusicologie/S*
ethnomusicologue/S*
ethnonyme/S*
ethnonymie/S*
ethnopsychiatrie/S*
ethnopsychologie/S*
ethno-raciale/W*
ethnoreligieuse/W*
éthographie/S*
éthologie/S*
éthologique/S*
éthologiste/S*
éthologue/S*
ethos/L'D'Q'
................................................................................
exode/S*
exoderme/S*
exogame/S*
exogamie/S*
exogamique/S*
exogène/S*
exogénéité/S*
exogroupe/S*
exomphale/S*
exon/S*
exondation/S*
exondement/S*
exonder/a3p+
exonération/S*
exonérer/c4p+
................................................................................
extensionnelle/F*
extensité/S*
extensive/F*
extensivement/L'D'Q'
extensivité/S*
extenso
extensomètre/S*
extensométrie/S*
extensométrique/S*
exténuante/F*
exténuation/S*
exténuée/F*
exténuement/S*
exténuer/a4p+
extérieur/S*
extérieure/F*
................................................................................
filoselle/S.
filou/S.
filoutage/S.
filouter/a0p+
filouterie/S.
filovirus
fils
filsdeputerie/S.
filtrable/S.
filtrage/S.
filtrante/F.
filtrat/S.
filtration/S.
filtre/S.
filtre-presse
................................................................................
flanquer/a0p+
flapie/F.
flaque/S.
flaquer/a0p.
flash/A.
flashage/S.
flash-back
flashball/S.
flasher/a0p+
flasheuse/F.
flashmètre/S.
flashy
flasque/S.
flasquement
flatter/a0p+
................................................................................
foutou/S.
foutrale/F.
foutraque/S.
foutre/S.
foutre/tM
foutredieu
foutrement
foutrerie/S.
foutriquet/S.
foutue/F.
fovéa/S.
fovéale/W.
fox
foxée/F.
fox-hound/S.
................................................................................
haptique/S*
haptonomie/S*
haptonomique/S*
haquebute/S.
haquenée/S.
haquet/S.
hara-kiri/S.
haram
harangue/S.
haranguer/a0p+
harangueuse/F.
haras
harassante/F.
harassement/S.
harasser/a0p+
................................................................................
hors-bilan
hors-bord
hors-champ
hors-concours
hors-cote
hors-cote
hors-d'œuvre
horseball/S.
horse-guard/S.
horse-power
horse-pox
hors-jeu
hors-la-loi
hors-ligne
hors-média
................................................................................
hoyau/X.
hpz/||--
http/S=
huard/S.
huart/S.
hub/S.
hublot/S.
hubris/L'D'Q'
huche/S.
hucher/a0p+
huchet/S.
hue
huée/S.
huer/a0p+
huerta/S.
hugolienne/F*
huguenote/F.
huilage/S*
huile/S*
huiler/a2p+
huilerie/S*
huileuse/W*
huilière/F*
................................................................................
hypertrophier/a4p+
hypertrophique/S*
hyperuricémie/S*
hypervariable/S*
hyperventilation/S*
hyperventiler/a1p.
hypervigilance/S*
hyperviolence/S*
hyperviolente/F*
hyperviscosité/S*
hyperviseur/S*
hypervitaminose/S*
hyphe/S*
hypholome/S*
hypnagogique/S*
hypnogramme/S*
................................................................................
illisibilité/S*
illisible/S*
illisiblement/D'Q'
illogique/S*
illogiquement/D'Q'
illogisme/S*
illuminante/F*
illuminati/L'D'Q'
illumination/S*
illuminative/F*
illuminatrice/F*
illuminée/F*
illuminer/a4p+
illuminisme/S*
illusion/S*
................................................................................
immunodéficiente/F*
immunodéficitaire/S*
immunodépresseur/S*
immunodépression/S*
immunodépressive/F*
immunodéprimée/F*
immunofluorescence/S*

immunogène/S*
immunogénétique/S*
immunogénicité/S*
immunogénique/S*
immunoglobuline/S*
immunohistochimie/S*
immunologie/S*
................................................................................
imparisyllabique/S*
imparité/S*
impartageable/S*
impartiale/W*
impartialement/D'Q'
impartialité/S*
impartir/fC
impassable/S*
impasse/S*
impassibilité/S*
impassible/S*
impassiblement/D'Q'
impatiemment/D'Q'
impatience/S*
impatiens/L'D'Q'
................................................................................
multidevise/S.
multidiffusion/S.
multidimensionnalité/S.
multidimensionnelle/F.
multidirectionnalité/S.
multidirectionnelle/F.
multidisciplinaire/S.
multidisciplinarité/S.
multiethnique/S.
multifactorielle/F.
multifamiliale/W.
multifilaire/S.
multiflore/S.
multifonction/S.
multifonctionnalité/S.
................................................................................
oligoasthénotératospermie/S*
oligocène/S*
oligochète/S*
oligoclase/S*
oligodendrocyte/S*
oligodendrogliome/S*
oligoélément/S*


oligogalacturonate/S*
oligo-galacturonate/S*
oligomère/S*
oligomérique/S*
oligomérisation/S*
oligonucléotide/S*
oligo-nucléotide/S*
................................................................................
perceptiblement
perception/S.
perceptionnisme/S.
perceptionniste/S.
perceptive/F.
perceptrice/F.
perceptuelle/F.
perceptuellement
percer/a0p+
percerette/S.
perceuse/F.
percevable/S.
percevoir/pK
perche/S.
percher/a0p+
................................................................................
pixellisation/S.
pizza/S.
pizzaïolo/S.
pizzeria/S.
pizzicato/I.
placage/S.
placard/S.
placardage/S.
placarder/a0p+
placardisation/S.
placardiser/a0p+
place/S.
placebo/S.
placement/S.
placenta/S.
................................................................................
plâtrerie/S.
plâtreuse/W.
plâtrière/F.
plats-bords
plausibilité/S.
plausible/S.
plausiblement
playback/S.
playboy/S.
playlist/S.
playon/S.
pléban/S.
plèbe/S.
plébéienne/F.
plébiscitaire/S.
plébiscite/S.
................................................................................
ployage/S.
ployante/F.
ployer/a0p+
pluche/S.
plucher/a0p.
plucheuse/W.
plugin/S.
plug-in/S.
pluie/S.
plumage/S.
plumaison/S.
plumard/S.
plumasseau/X.
plumasserie/S.
plumassière/F.
................................................................................
pluriannuelle/F.
pluricellulaire/S.
pluriculturelle/F.
pluridimensionnalité/S.
pluridimensionnelle/F.
pluridisciplinaire/S.
pluridisciplinaire/S.

pluridisciplinarité/S.
plurielle/F.
pluriethnique/S.
plurilatérale/W.
plurilingue/S.
plurilinguisme/S.
plurimillénaire/S.
................................................................................
pluripartite/S.
pluripotence/S.
pluripotente/F.
pluriséculaire/S.
plurisousharmonique/S.
plurispécifique/S.
plurithématique/S.

plurithérapie/S.
plurivalente/F.
plurivocité/S.
plurivoque/S.
plus
plus
plusieurs
................................................................................
polychète/S.
polychlorobenzène/S.
polychlorure/S.
polychroïque/S.
polychroïsme/S.
polychrome/S.
polychromie/S.
polychromique/S.
polycistronique/S.
polyclinique/S.
polycondensat/S.
polycondensation/S.
polycopie/S.
polycopier/a0p+
polycourant
................................................................................
pop-corn
pope/S.
popeline/S.
popinée/S.
poplitée/F.
popote/S.
popotin/S.
popstar/S.
populace/S.
populacière/F.
populage/S.
populaire/S.
populairement
popularisation/S.
populariser/a0p+
................................................................................
poulaille/S.
poulailler/S.
poulaine/F.
poulamon/S.
poularde/S.
poulbot/S.
poule/S.

poulette/F.
pouliage/S.
pouliche/S.
poulie/S.
pouliner/a0p.
poulinière/S.
poulinière/S.
pouliot/S.
................................................................................
protoplasme/S.
protoplasmique/S.
protoplaste/S.
protoptère/S.
protosulfure/S.
prototypage/S.
prototype/S.
prototyper/a0p+
prototypique/S.
prototypiste/S.
protoure/S.
protoxyde/S.
protozoaire/S.
protozoologie/S.
protractile/S.
................................................................................
pruche/S.
prude/S.
prudemment
prudence/S.
prudente/F.
prudentielle/F.
pruderie/S.
prudhommale/W.

prudhomme/S.
prudhommerie/S.
prudhommesque/S.
prudhommie/S.
pruine/S.
prune
prune/S.
pruneau/X.
prunelaie/S.
prunelée/S.
prunelle/S.
................................................................................
pusillanime/S.
pusillanimement
pusillanimité/S.
pustule/S.
pustuler/a0p+
pustuleuse/W.
putain/S.
putasserie/S.
putassière/F.
putative/F.
pute/S.
putier/S.
putiet/S.
putois
putréfaction/S.
................................................................................
sceau/X.
sceau-de-Salomon
sceaux-de-Salomon
scélérate/F.
scélératement
scélératesse/S.
scellage/S.
scellé/S.
scellement/S.
sceller/a0p+
scénarimage/S.
scénario/S.
scénarisation/S.
scénariser/a0p+
scénariste/S.
................................................................................
scripturale/W.
scripturalisme/S.
scrofulaire/S.
scrofulariacée/S.
scrofule/S.
scrofuleuse/W.
scrogneugneu/X.
scroller/a0p.
scrolling/S.
scrotale/W.
scrotum/S.
scrub/S.
scrubber/S.
scrupule/S.
scrupuleuse/W.
................................................................................
stariser/a0p+
starlette/S.
staroste/S.
star-system/S.
starter/S.
starting-block/S.
starting-gate/S.
startup/S.
stase/S.
stater/a0p+
statère/S.
stathouder/S.
stathoudérat/S.
statice/S.
statif/S.
................................................................................
syrah/S.
syriaque/S.
syriaque/S.
syrienne/F.
syringe/S.
syringomyélie/S.
syrinx
syro-libanaise/F.
syrphe/S.
sysadmin/S.
systématicienne/F.
systématicité/S.
systématique/S.
systématique/S.
systématiquement
................................................................................
tagine/S.
tagliatelle/S.
tagme/S.
taguer/a0p+
tagueuse/F.
tahitienne/F.
taïaut
taïchi/S.
taïchichuan/S.
taie/S.
taïga/S.
taiji/S.
taijiquan/S.
taïkonaute/S.
taillable/S.
taillade/S.
................................................................................
taleb/S.
talent/S.
talentueuse/W.
talentueusement
taler/a0p+
taleth/S.
talibane/F.
talibée/F.
talion/S.
talisman/S.
talismanique/S.
talith/S.
talitre/S.
talkies-walkies
talkie-walkie
................................................................................
trantran/S.
trapèze/S.
trapéziste/S.
trapézoèdre/S.
trapézoïdale/W.
trapézoïde/S.
trappe/S.
trapper/a0p+
trappeuse/F.
trappillon/S.
trappiste/S.
trappistine/S.
trapue/F.
traque/S.
traquée/F.
................................................................................
ultimement/D'Q'
ultimité/S*
ultimo
ultra/S*
ultrabasique/S*
ultracentrifugation/S*
ultracentrifugeuse/S*
ultrachic/S*
ultracolonialisme/S*
ultracolonialiste/S*
ultraconfidentielle/F*
ultraconservatrice/F*
ultracourte/F*
ultradienne/F*
ultradroite/S*
................................................................................
vibrato/S.
vibratoire/S.
vibrer/a0p+
vibreur/S.
vibrion/S.
vibrionner/a0p.
vibrisse/S.
vibro/S.
vibromasseur/S.
vicaire/S.
vicariale/W.
vicariance/S.
vicariante/F.
vicariat/S.
vice/S.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff from [f5624fc7bf] to [c48aa6e466].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v6.1
# par Olivier R. -- licence MPL 2.0
# Généré le 03-06-2017 à 22:26
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.




|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v6.2
# par Olivier R. -- licence MPL 2.0
# Généré le 26-07-2017 à 09:33
# Pour améliorer le dictionnaire, allez sur http://www.dicollecte.org/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.dic from [5191f244cd] to [1c3d8999ad].

1
2
3
4
5
6
7
8
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
529
530
531
532
533
534
535

536
537
538
539
540
541
542
...
651
652
653
654
655
656
657

658
659
660
661
662
663
664
...
896
897
898
899
900
901
902

903
904
905
906
907
908
909
....
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
....
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
....
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
....
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
....
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
....
3217
3218
3219
3220
3221
3222
3223

3224
3225
3226
3227
3228
3229
3230
....
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
....
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
....
3594
3595
3596
3597
3598
3599
3600

3601
3602
3603
3604
3605
3606
3607
....
4294
4295
4296
4297
4298
4299
4300

4301
4302
4303
4304
4305
4306
4307
....
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
....
6206
6207
6208
6209
6210
6211
6212

6213
6214
6215
6216
6217
6218
6219
....
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
....
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062

9063
9064
9065
9066
9067
9068
9069
....
9723
9724
9725
9726
9727
9728
9729

9730
9731
9732
9733
9734
9735
9736
....
9864
9865
9866
9867
9868
9869
9870

9871
9872
9873
9874
9875
9876
9877
.....
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
.....
11343
11344
11345
11346
11347
11348
11349

11350
11351
11352
11353
11354
11355
11356
.....
11660
11661
11662
11663
11664
11665
11666


11667
11668
11669
11670
11671
11672
11673
.....
12464
12465
12466
12467
12468
12469
12470

12471
12472
12473
12474
12475
12476
12477
.....
12560
12561
12562
12563
12564
12565
12566

12567
12568
12569
12570
12571
12572
12573
.....
15450
15451
15452
15453
15454
15455
15456

15457
15458
15459
15460
15461
15462
15463
.....
17699
17700
17701
17702
17703
17704
17705

17706
17707
17708
17709
17710
17711
17712
.....
18040
18041
18042
18043
18044
18045
18046

18047
18048
18049
18050
18051
18052
18053
.....
18439
18440
18441
18442
18443
18444
18445

18446
18447
18448
18449
18450
18451
18452
.....
19418
19419
19420
19421
19422
19423
19424

19425
19426
19427
19428
19429
19430
19431
.....
24015
24016
24017
24018
24019
24020
24021

24022
24023
24024
24025
24026
24027
24028
.....
25520
25521
25522
25523
25524
25525
25526

25527
25528
25529
25530
25531
25532
25533
.....
27305
27306
27307
27308
27309
27310
27311

27312
27313
27314
27315
27316
27317
27318
.....
28103
28104
28105
28106
28107
28108
28109

28110
28111
28112
28113
28114
28115
28116
.....
28152
28153
28154
28155
28156
28157
28158

28159
28160
28161
28162
28163
28164
28165
.....
28781
28782
28783
28784
28785
28786
28787

28788
28789
28790
28791
28792
28793
28794
.....
29497
29498
29499
29500
29501
29502
29503

29504
29505
29506
29507
29508
29509
29510
.....
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623
30624
30625
30626
.....
32074
32075
32076
32077
32078
32079
32080

32081
32082
32083
32084
32085
32086
32087
.....
33850
33851
33852
33853
33854
33855
33856


33857
33858
33859
33860
33861
33862
33863
.....
33885
33886
33887
33888
33889
33890
33891

33892
33893
33894
33895
33896
33897
33898
.....
34481
34482
34483
34484
34485
34486
34487

34488
34489
34490
34491
34492
34493
34494
.....
34687
34688
34689
34690
34691
34692
34693


34694
34695
34696
34697
34698
34699
34700
.....
35813
35814
35815
35816
35817
35818
35819

35820
35821
35822
35823
35824
35825
35826
.....
36691
36692
36693
36694
36695
36696
36697

36698
36699
36700
36701
36702
36703
36704
.....
40055
40056
40057
40058
40059
40060
40061

40062
40063
40064
40065
40066
40067
40068
.....
41280
41281
41282
41283
41284
41285
41286

41287
41288
41289
41290
41291
41292
41293

41294
41295
41296
41297
41298
41299
41300
.....
41775
41776
41777
41778
41779
41780
41781


41782
41783
41784
41785
41786
41787
41788
.....
42162
42163
42164
42165
42166
42167
42168

42169
42170
42171
42172
42173
42174
42175
.....
42347
42348
42349
42350
42351
42352
42353
42354
42355
42356
42357
42358
42359
42360
42361
.....
42402
42403
42404
42405
42406
42407
42408

42409
42410
42411
42412
42413
42414
42415
.....
51969
51970
51971
51972
51973
51974
51975

51976
51977
51978
51979
51980
51981
51982
.....
54310
54311
54312
54313
54314
54315
54316
54317
54318
54319
54320
54321
54322
54323
54324
54325
.....
57268
57269
57270
57271
57272
57273
57274

57275
57276
57277
57278
57279
57280
57281
.....
58920
58921
58922
58923
58924
58925
58926

58927
58928
58929
58930
58931
58932
58933
.....
59306
59307
59308
59309
59310
59311
59312

59313
59314
59315
59316
59317
59318
59319
.....
59342
59343
59344
59345
59346
59347
59348
59349
59350
59351
59352
59353
59354
59355
59356
.....
59361
59362
59363
59364
59365
59366
59367
59368
59369
59370
59371
59372
59373
59374
59375
.....
59719
59720
59721
59722
59723
59724
59725

59726
59727
59728
59729
59730
59731
59732
.....
59995
59996
59997
59998
59999
60000
60001

60002
60003
60004
60005
60006
60007
60008
.....
60390
60391
60392
60393
60394
60395
60396
60397
60398
60399
60400
60401
60402
60403
60404
60405
.....
61785
61786
61787
61788
61789
61790
61791

61792
61793
61794
61795
61796
61797
61798
.....
62290
62291
62292
62293
62294
62295
62296

62297
62298
62299
62300
62301
62302
62303
.....
67852
67853
67854
67855
67856
67857
67858

67859
67860
67861
67862
67863
67864
67865
.....
68096
68097
68098
68099
68100
68101
68102

68103
68104
68105
68106
68107
68108
68109
.....
72283
72284
72285
72286
72287
72288
72289

72290
72291
72292
72293
72294
72295
72296
.....
72477
72478
72479
72480
72481
72482
72483

72484
72485
72486
72487
72488
72489
72490
.....
75013
75014
75015
75016
75017
75018
75019

75020
75021
75022
75023
75024
75025
75026
.....
77331
77332
77333
77334
77335
77336
77337

77338
77339
77340
77341
77342
77343
77344
78701
&
1er/--
1ers/--
1re/--
1res/--
1ʳᵉ/--
1ʳᵉˢ/--
................................................................................
Aïcha/L'D'Q'
Aïd/L'D'Q'
Aida/L'D'Q'
Aidan/L'D'Q'
Aïd-el-Adha/L'
Aïd-el-Kébir/L'
Aiden/L'D'Q'
Aignan
Aigoual/L'D'
Aigrain/L'D'Q'
Aimé/L'D'Q'
Aimée/L'D'Q'
Ain/L'
Airaines/L'D'Q'
Airbnb/L'D'Q'
................................................................................
Arion/L'D'Q'
Aristarque/L'D'Q'
Aristide/L'D'Q'
Aristophane/L'D'Q'
Aristote/L'D'Q'
Arizona/L'D'
Arjuna/L'D'Q'

Arkansas/L'D'
Arkema/L'D'Q'
Arkham/L'D'Q'
Arkhangelsk/L'D'Q'
Arlene/L'D'Q'
Arlène/L'D'Q'
Arles/L'D'Q'
................................................................................
Aurélien/L'D'Q'
Aurelio/L'D'Q'
Auriane/L'D'Q'
Aurillac/L'D'Q'
Auriol/L'D'Q'
Aurore/L'D'Q'
Auschwitz/L'D'Q'

Austerlitz/L'D'Q'
Austin/L'D'Q'
Australasie/L'D'Q'
Australie/L'D'
Australie-Méridionale/L'D'
Australie-Occidentale/L'D'
Austrasie/L'D'
................................................................................
Benoîte
Benozillo
Benpro
Bentama
Bentham
Bentley
Benveniste

Berchem-Sainte-Agathe
Berck
Bercy
Bérenger
Bérengère
Bérénice
Bérézina
................................................................................
Caine
Caïphe
Caire
Caitlin
Caitlyn
Calabre
Calais

Calc
Calcutta
Calderón
Caleb
Calédonie
Calestienne
Calgary
................................................................................
Chostakovitch
Chris
Christa
Christel
Christèle
Christelle
Christian

Christiane
Christie
Christina
Christine
Christmas
Christoffel
Christoph
................................................................................
Cincinnati
Cindy
Ciney
Ciotat
Circassie
Circé
Cirey-sur-Vezouze

Cisjordanie
Cîteaux
Citroën
City
Claire
Clamart
Clara
................................................................................
Eure-et-Loir/L'D'
Euripide/L'D'Q'
Eurobaromètre/S*
Eurogroupe/L'
Euronext/L'D'Q'
Europe/L'D'
Europol/D'Q'

Eurozone/L'
Eurydice/L'D'Q'
Eusèbe/L'D'Q'
Euterpe/L'D'Q'
Eva/L'D'Q'
Éva/L'D'Q'
Évaine/L'D'Q'
................................................................................
Fayard
Fayçal
Fayette
Fécamp
Fed
FedEx
Federer

Federico
Fehling
Feist
Feïza
Feldane
Felicia
Félicie
................................................................................
Halluin/L'D'Q'
Ham/L'D'Q'
Hamas
Hambourg
Hamel
Hamid/L'D'Q'
Hamilton

Hamme
HammerFall
Hammourabi
Hamont-Achel/L'D'Q'
Hampshire
Ham-sur-Heure-Nalinnes/L'D'Q'
Hamza/L'D'Q'
................................................................................
Howard
Hubble
Hubei
Hubert/L'D'Q'
Hubscher
Hudson/L'D'Q'
Huelgoat

Hugo/L'D'Q'
Hugo/L'D'Q'
Hugues/L'D'Q'
Huguette
Hulshout/L'D'Q'
Hume
Hun/S.
................................................................................
IMSI/L'D'Q'
INED/L'D'Q'
INPI/L'D'Q'
INRA/L'D'Q'
INRI/L'D'Q'
INRIA/L'D'Q'
INSA/L'D'Q'
INSERM/L'D'Q'
IP/L'D'Q'
IRA/L'
IRD/L'D'Q'
IRFM/L'D'Q'
IRL
IRM/L'D'Q'
IRSTEA/L'D'Q'
................................................................................
Ingrid/L'D'Q'
Inkscape/L'D'Q'
Inn/L'D'
Inna/L'D'Q'
Innsmouth/L'D'Q'
Inovia/L'D'Q'
Insee/L'D'Q'

Insulinde/L'D'
Intel/L'D'Q'
Internet/D'Q'
Interpol/D'Q'
Io/L'D'Q'
Ionesco/L'D'Q'
Ioulia/L'D'Q'
................................................................................
Léonore
Léontine
Léopold
Léopoldine
Leopoldt
Léopoldville
Leroy

Lesbos
Lesieur
Lesley
Leslie
Lesneven
Lesotho
Lesse
................................................................................
Noisy-le-Grand
Noisy-le-Sec
Nokia
Nolan
Nolwenn
Nora
Norbert
Nord
Nord-Kivu
Nord-Pas-de-Calais
Nord-du-Québec
Nordine
Norfolk
Norique
Norma
................................................................................
Reidemeister
Reiko
Reims
Reiten
Relecq-Kerhuon
Rellich
Rembrandt

Rémi
Remich
Remire-Montjoly
Remus
Rémy
Renaix
Renan
................................................................................
Rosita
Rosny-sous-Bois
Ross
Rossini
Rossinière
Rostand
Roswell
Roth
Roth
Rothbard
Rothschild
Rotin
Rotselaar
Rotterdam
Roubaix
................................................................................
additionnelle/F*
additionnellement/D'Q'
additionner/a4p+
additionneuse/F*
additive/F*
additivement/D'Q'
additivité/S*
addon/S*
adducteur/S*
adduction/S*
adduit/S*
adèle/S*

adelphophagie/S*
adénine/S*
adénite/S*
adénocarcinome/S*
adénogramme/S*
adénoïde/S*
adénoïdectomie/S*
................................................................................
agripper/a4p+
agritourisme/S*
agroalimentaire/S*
agroalimentaire/S*
agrobiologie/S*
agrobiologique/S*
agrobiologiste/S*

agrocarburant/S*
agro-carburant/S*
agrochimie/S*
agrochimique/S*
agrochimiste/S*
agroclimatique/S*
agro-climatique/S*
................................................................................
aillade/S*
ailler/a2p+
ailleurs/L'D'Q'
ailloli/S*
aimable/S*
aimablement/D'Q'
aimant/S*

aimantation/S*
aimante/F*
aimanter/a4p+
aimantin/S*
aimantine/F*
aimée/F*
aimer/a4p+
................................................................................
amathie/S*
amatir/f2p+
amatrice/F*
amaurose/S*
amazone/S*
amazonienne/F*
amazonite/S*
ambages/D'Q'
ambassade/S*
ambassadrice/F*
ambiance/S*
ambiancer/a1p.
ambianceuse/F*
ambiante/F*
ambidextre/S*
................................................................................
annuité/S*
annulabilité/S*
annulable/S*
annulaire/S*
annulation/S*
annulative/F*
annulatrice/F*

annuler/a4p+
annuus
anoblir/f4p+
anoblissante/F*
anoblissement/S*
anode/S*
anodine/F*
................................................................................
antienne/S*
antienzyme/S*
antiépileptique/S*
antiesclavagiste/S*
antiestrogène/S*
antiestrogène/S*
antiétatique/S*


antifading/S*
antifascisme/S*
antifasciste/S*
antiféminisme/S*
antiféministe/S*
antiferment/S*
antiferroélectricité/S*
................................................................................
arc/S*
arcade/S*
arcane/S*
arcanson/S*
arcasse/S*
arcature/S*
arcboutant/S*

arcbouter/a4p+
arccos
arccosh
arccotan
arccotanh
arcdoubleau/X*
arceau/X*
................................................................................
archivolte/S*
archontat/S*
archonte/S*
archosaurien/S*
archure/S*
arçon/S*
arçonner/a2p+

arcs-en-ciel/D'Q'
arcsin
arcsinh
arctan
arctanh
arctique/S*
arcure/S*
................................................................................
bernard-l'ermite
berne/S.
berner/a0p+
berneuse/F.
bernicle/S.
bernique
bernique/S.

berrichonne/F.
bersaglier/S.
berthon/S.
bertillonnage/S.
béryl/S.
bérylliose/S.
béryllium/S.
................................................................................
bugne/S.
bugrane/S.
b