Grammalecte  Check-in [0dba21491a]

Overview
Comment:[build] check if rules have same id
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | build
Files: files | file ages | folders
SHA3-256: 0dba21491a1ec5223aeba119e899c5ebee0ab3bd9ade3ce894e7efb62259673b
User & Date: olr on 2017-05-03 08:00:11
Other Links: manifest | tags
Context
2017-05-03
10:03
[build] use named groups in regex check-in: c761d5a874 user: olr tags: trunk, build
08:00
[build] check if rules have same id check-in: 0dba21491a user: olr tags: trunk, build
2017-05-01
10:46
[build] useless conditions check-in: c4e9c97a0e user: olr tags: trunk, build
Changes

Modified compile_rules.py from [94acd166e0] to [2d30706580].

1
2
3
4
5
6
7
8
9
10
11
12


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












+
+








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


DEF = {}
FUNCTIONS = []

RULESET = set()     # set of rule-ids to check if there is several rules with the same id

JSREGEXES = {}

WORDLIMITLEFT  = r"(?<![\w.,–-])"   # r"(?<![-.,—])\b"  seems slower
WORDLIMITRIGHT = r"(?![\w–-])"      # r"\b(?!-—)"       seems slower


def prepareFunction (s):
177
178
179
180
181
182
183



184
185
186
187
188
189

190
191
192
193
194
195
196
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201







+
+
+





-
+







    if m:
        cWordLimitLeft = m.group(1)[0]
        cCaseMode = m.group(1)[1]
        cWordLimitRight = m.group(1)[2]
        sOption = m.group(2)[1:]  if m.group(2)  else False
        if m.group(3):
            sRuleId =  m.group(3)[1:-1]
            if sRuleId in RULESET:
                print("# Warning. Several rules have the same id: " + sRuleId)
            RULESET.add(sRuleId)
        nPriority = dOptPriority.get(sOption, 4)
        if m.group(4):
            nPriority = int(m.group(4)[1:])
        s = s[m.end(0):]
    else:
        print("Warning. No option defined at line: " + sLineId)
        print("# Warning. No option defined at line: " + sLineId)

    #### REGEX TRIGGER
    i = s.find(" <<-")
    if i == -1:
        print("# Error: no condition at line " + sLineId)
        return None
    sRegex = s[:i].strip()
218
219
220
221
222
223
224
225

226
227
228

229
230
231
232
233
234
235
223
224
225
226
227
228
229

230
231
232

233
234
235
236
237
238
239
240







-
+


-
+







    for sDef, sRepl in DEF.items():
        sRegex = sRegex.replace(sDef, sRepl)

    ## count number of groups (must be done before modifying the regex)
    nGroup = countGroupInRegex(sRegex)
    if nGroup > 0:
        if not tGroups:
            print("# warning: groups positioning code for JavaScript should be defined at line " + sLineId)
            print("# Warning: groups positioning code for JavaScript should be defined at line " + sLineId)
        else:
            if nGroup != len(tGroups):
                print("# error: groups positioning code irrelevant at line " + sLineId)
                print("# Error: groups positioning code irrelevant at line " + sLineId)

    ## word limit
    if cWordLimitLeft == '[' and not sRegex.startswith(("^", '’', "'", ",")):
        sRegex = WORDLIMITLEFT + sRegex
    if cWordLimitRight == ']' and not sRegex.endswith(("$", '’', "'", ",")):
        sRegex = sRegex + WORDLIMITRIGHT

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
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







-
+




-
+

-
+



-
+




-
+



-
+

-
+




-
+






-
+




-
+











-
+







            sURL = mURL.group(1).strip()
            sMsg = sMsg[:mURL.start(0)].strip()
        if sMsg[0:1] == "=":
            sMsg = prepareFunction(sMsg[1:])
            FUNCTIONS.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)")
                    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)")
                    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 =")
                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")
            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)")
                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)")
                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 =")
            print("# Error in action at line " + sIdAction + ":  This action looks like code. Line should begin with =")

    if cAction == "-":
        ## error detected
        if not sAction:
            print("# error in action at line " + sIdAction + ":  This action is empty.")
            print("# Error in action at line " + sIdAction + ":  This action is empty.")
        if sAction[0:1] == "=":
            FUNCTIONS.append(("s"+sIdAction, sAction[1:]))
            sAction = "=s"+sIdAction
        elif sAction.startswith('"') and sAction.endswith('"'):
            sAction = sAction[1:-1]
        if not sMsg:
            print("# error in action at line " + sIdAction + ":  the message is empty.")
            print("# Error in action at line " + sIdAction + ":  the message is empty.")
        return [sCondition, cAction, sAction, iGroup, sMsg, sURL]
    elif cAction == "~":
        ## text preprocessor
        if not sAction:
            print("# error in action at line " + sIdAction + ":  This action is empty.")
            print("# Error in action at line " + sIdAction + ":  This action is empty.")
        if sAction[0:1] == "=":
            FUNCTIONS.append(("p"+sIdAction, sAction[1:]))
            sAction = "=p"+sIdAction
        elif sAction.startswith('"') and sAction.endswith('"'):
            sAction = sAction[1:-1]
        return [sCondition, cAction, sAction, iGroup]
    elif cAction == "=":
        ## disambiguator
        if sAction[0:1] == "=":
            sAction = sAction[1:]
        if not sAction:
            print("# error in action at line " + sIdAction + ":  This action is empty.")
            print("# Error in action at line " + sIdAction + ":  This action is empty.")
        FUNCTIONS.append(("d"+sIdAction, sAction))
        sAction = "d"+sIdAction
        return [sCondition, cAction, sAction]
    elif cAction == ">":
        ## no action, break loop if condition is False
        return [sCondition, cAction, ""]
    else:

Modified gc_lang/fr/rules.grx from [6773fc0960] to [cda47f3642].

420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434







-
+







# Patronymes composés avec Le/La/Les
__[s]__  [A-ZÉÈÂÎ][\w-]+[-–—]L(?:es?|a) [A-ZÉÈÂÎ][\w-]+ <<- ~>> =\0.replace(" ", "_")
# IP
__[s]__  \d+[.:]\d+[.:]\d+[.:]\d+  <<- ~>> *
# mètres (m)
__[s>__  "\d+ (m) "  @@w <<- ~1>> _
# heures
__[s]__  (?:à |)[012]?\d[h:]\d\d(?:[m:]\d\ds?|) <<- ~>> *
__[s]__  (?:de |à |)[012]?\d[h:]\d\d(?:[m:]\d\ds?|) <<- ~>> *
# crochets
__[s]__  \[…\] <<- ~>> *
__[s]__  \[({w_1})\] @@1
    <<- \1.isdigit() ~>> *
    <<- __else__ ~>> _
__[s]__  \(…\)
    <<- ->> […]                                                                                     # Pour indiquer une troncature de texte, on utilise usuellement des crochets.
1891
1892
1893
1894
1895
1896
1897
1898

1899
1900
1901
1902
1903
1904
1905
1891
1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904
1905







-
+







    <<- \0.endswith("s") ->> Ils|ils                                                                # Erreur de numérisation ?
    <<- __else__ ->> Il|il                                                                          # Erreur de numérisation ?

TEST: __ocr__ {{Us}} arrive demain.


# il / i1 / if / 11
__[i]/ocr(ocr_il_ils2)__
__[i]/ocr(ocr_il_ils3)__
    [i1][1f]s?
    <<- not \0.endswith("s") ->> Il|il                                                              # Erreur de numérisation ?
    <<- __else__ ->> Ils|ils                                                                        # Erreur de numérisation ?

TEST: __ocr__ {{i1s}} en savent beaucoup trop pour leur propre bien.


3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111
3112
3113
3114
3100
3101
3102
3103
3104
3105
3106

3107
3108
3109
3110
3111
3112
3113
3114







-
+







    ne ([cç]’) @@3 <<- -1>> s’                                              # Confusion. Ce chien, ce chat… Se demander, se croire…
__[i]/conf(conf_ce_conj_prep)__
    (se) (?:qu[ei]?|dont|malgré|pourquoi|avec|pour|par) @@0 <<- -1>> ce     # Confusion. Exemples : ce bâtiment, se perdre.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=2440
__[i]/conf(conf_qui_se_verbe)__
    qui (ce) ({w_2})  @@4,$
    <<- morphex(\2, ":V", ":[NAQ].*:[me]") or before(r"(?i)\b[cs]e +")
    -1>> se                                                                 # Confusion probable. Exemples : ce bâtiment, se perdre.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=2440
__[i]/conf(conf_ce_être)__
__[i]/conf(conf_ceux_ce_être)__
    (ceux) (?:ne |)(?:sont|serai(?:en|)[ts]?|f[uû](?:ren|)t|n’(?!ayant|étant)\w+) @@0
    <<- -1>> ce                                                             # Confusion.|http://www.intellego.fr/soutien-scolaire-6eme/aide-scolaire-francais/ce-ceux-ou-se/3829
__[s]/conf(conf_ce_ne_être_doit)__
    ([sS]e) n(?:e |’)({être}|d[eouû]\w+|p[oeuû]\w+)  @@0,$
    <<- morph(\2, ">(?:être|pouvoir|devoir) .*:3s", False)
    -1>> ce                                                                 # Confusion probable.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=2440
__[i]/conf(conf_ce_ne)__
3451
3452
3453
3454
3455
3456
3457
3458

3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460

3461
3462
3463
3464
3465
3466
3467
3468







-
+


-
+







TEST: Elle va regarder ça de plus {{prêt}}.


# quand / quant / qu’en
__[i]/conf(conf_quant_à)__
    (?<![dD]e )(quand) (?:à|aux?)  @@0
    <<- not morph(word(-1), ">(?:arriver|venir|à|revenir|partir|aller) ") -1>> quant                # Confusion probable. Quand = à quel moment. Quant à = à propos de.
__[i]/conf(conf_quand)__    quant(?! à| aux?| est[ -]il d(?:es?|u) ) <<- ->> quand                  # Confusion. Quand = à quel moment. Quant à = à propos de.
__[i]/conf(conf_quand1)__   quant(?! à| aux?| est[ -]il d(?:es?|u) ) <<- ->> quand                  # Confusion. Quand = à quel moment. Quant à = à propos de.
__[i]/conf(conf_qu_en1)__   (quan[dt]) est[ -]il d(?:es?|u) @@0 <<- -1>> qu’en                      # Confusion. Ce qu’il en est de… → Qu’en est-il de… ?
__[i]/conf(conf_qu_en2)__   (quan[dt]) ({w_2}ant) @@0,$ <<- morph(\2, ":P", False) -1>> qu’en       # Confusion probable.
__[i]/conf(conf_quand)__
__[i]/conf(conf_quand2)__
    (qu en) (?:je|tu|ils?) @@0
    <<- not after("^ +ne s(?:ai[st]|u[st]|urent|avai(?:[ts]|ent)) ") -1>> quand                     # Confusion probable. Pour évoquer un moment, écrivez :

TEST: {{Quant}} est-il du chien ?
TEST: {{Quand}} à ma santé, elle est défaillante.
TEST: {{Quant}} ils…
TEST: {{quant}} je…
6956
6957
6958
6959
6960
6961
6962
6963

6964
6965
6966
6967
6968
6969
6970
6956
6957
6958
6959
6960
6961
6962

6963
6964
6965
6966
6967
6968
6969
6970







-
+







    comme même <<- morph(word(1), ":(?:Os|C)", False, True) ->> quand même                # Confusion probable.|http://fr.wiktionary.org/wiki/quand_m%C3%AAme

TEST: {{comme même}} il y va fort, le saligaud !
TEST: La météo disait qu’il ferait beau temps, mais il pleut {{comme même}}…


# quel que soit / quoi qu’il en soit
__[i]/conf(conf_quel_que_soit)__
__[i]/conf(conf_quel_que_soit1)__
    quelques? soi(?:ent|t|s|)
    <<- ->> quel que soit|quelle que soit|quels que soient|quelles que soient             # Confusion.|https://fr.wiktionary.org/wiki/quel_que_soit
__[i]/conf(conf_quoi_qu_il_en_soit)__
    quoiqu il en soit <<- not morph(word(1), ":[AQ]", False) ->> quoi qu’il en soit       # Confusion.|https://fr.wiktionary.org/wiki/quoi_qu%E2%80%99il_en_soit

TEST: {{quelques soient}} les avantages d’un correcteur…
TEST: {{quoiqu’il en soit}}, nous ne nous laisserons pas faire, vous pouvez compter sur nous.
7101
7102
7103
7104
7105
7106
7107
7108

7109
7110
7111
7112
7113
7114
7115
7101
7102
7103
7104
7105
7106
7107

7108
7109
7110
7111
7112
7113
7114
7115







-
+








__[i]/conf(conf_prep_soi)__
    (?:chez|don de|sur|avec|pour) (soit) @@$ <<- not after(" soit ") -1>> soi                       # Confusion probable.
__[i]/conf(conf_en_soi)__
    (?<!’)en (soit)  @@3
    <<- morph(word(1), ":[GY]", True, True) and not before("(?i)quel(?:s|les?|) qu $|on $|il $") and not after(" soit ")
    -1>> soi                                                                                        # Confusion probable.
__[i]/conf(conf_quel_que_soit)__
__[i]/conf(conf_quel_que_soit2)__
    quel(?:le|)s? que (soi(?:es?|)) @@$ <<- -1>> soit|soient                                        # Confusion probable. 
__[i]/conf(conf_soi_même1)__
    (soi[tes]s? mêmes?) @@$
    <<- morph(word(-1), ":[YQ]|>(?:avec|contre|par|pour|sur) ", False, True) -1>> soi-même          # Confusion probable : moi-même, toi-même, lui-même, elle-même, soi-même, elles-mêmes, eux-mêmes.
__[i]/conf(conf_soi_même2)__
    soi[tes]s?-mêmes? <<- ->> soi-même                                                              # Confusion : moi-même, toi-même, lui-même, elle-même, soi-même, elles-mêmes, eux-mêmes.

8024
8025
8026
8027
8028
8029
8030
8031

8032
8033
8034
8035
8036
8037
8038
8024
8025
8026
8027
8028
8029
8030

8031
8032
8033
8034
8035
8036
8037
8038







-
+







TEST: Ils la laissèrent {{malades}}.
TEST: Ils la laissent prendre le train.
TEST: Elle te laisse finir le travail.
TEST: Je me laisse de quoi finir.
TEST: Il te laisse trois jours de délai.


__[i]/ppas(ppas_me_te_laisser_adj)__
__[i]/ppas(ppas_nous_les_laisser_adj)__
    (nous|les) +(laiss\w*) +({w_3})  @@0,w,$
    <<- morph(\2, ">laisser ", False) and morphex(\3, ":[AQ].*:s", ":(?:[YG]|[AQ].*:[ip])")
    and (\1.endswith("es") or ( \1.endswith("us") and not \2.endswith("ons") )) -3>> =suggPlur(@)   # Accord avec « \1 » : « \3 » devrait être au pluriel.

TEST: je les laisse {{indifférent}}.
TEST: elle nous laissera {{perdu}} dans nos délires.
TEST: je les laisse indifférents.
8549
8550
8551
8552
8553
8554
8555
8556

8557
8558
8559
8560

8561
8562
8563
8564

8565
8566
8567
8568

8569
8570
8571
8572

8573
8574
8575
8576
8577
8578

8579
8580
8581
8582
8583
8584
8585
8549
8550
8551
8552
8553
8554
8555

8556
8557
8558
8559

8560
8561
8562
8563

8564
8565
8566
8567

8568
8569
8570
8571

8572
8573
8574
8575
8576
8577

8578
8579
8580
8581
8582
8583
8584
8585







-
+



-
+



-
+



-
+



-
+





-
+







    and (morphex(\3, ":[NAQ].*:s", ":[GWpi]") or morphex(\3, ":[NAQ].*:m", ":[GWYfe]"))
    and (not re.search("^(?:elles|celles-(?:ci|là)|lesquelles)$", \1) or not morph(word(-1), ":R", False, False))
    -3>> =suggFemPlur(@)                                                     # Accord avec le sujet « \1 » : « \3 » devrait être au féminin pluriel.

TEST: elles se sentent {{perdu}}


__[i]/ppas(ppas_le_verbe)__
__[i]/ppas(ppas_le_verbe_pensée)__
    le ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2}[esx])  @@w,$
    <<- morph(\1, ">(?:trouver|considérer|croire|rendre|voilà) ", False) and morphex(\2, ":[AQ]:(?:[me]:p|f)", ":(?:G|Y|[AQ]:m:[is])")
    -2>> =suggMasSing(@)                                                     # Accord avec le COD “le” : « \2 » doit être au masculin singulier.
__[i]/ppas(ppas_la_verbe)__
__[i]/ppas(ppas_la_verbe_pensée)__
    la ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2}[uiéesx])  @@w,$
    <<- morph(\1, ">(?:trouver|considérer|croire|rendre|voilà) ", False) and morphex(\2, ":[AQ]:(?:[fe]:p|m)", ":(?:G|Y|[AQ]:f:[is])")
    -2>> =suggFemSing(@)                                                     # Accord avec le COD “la” : « \2 » doit être au féminin singulier.
__[i]/ppas(ppas_les_verbe)__
__[i]/ppas(ppas_les_verbe_pensée)__
    les ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2})  @@w,$
    <<- morph(\1, ">(?:trouver|considérer|croire|rendre|voilà) ", False) and morphex(\2, ":[AQ].*:s", ":(?:G|Y|[AQ].*:[ip])")
    -2>> =suggPlur(@)                                                        # Accord avec le COD “les” : « \2 » doit être au pluriel.
__[i]/ppas(ppas_me_te_verbe)__
__[i]/ppas(ppas_me_te_verbe_pensée)__
    ([mt]e) ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2}[sx])  @@0,w,$
    <<- morph(\2, ">(?:trouver|considérer|croire|rendre|voilà) ", False) and morphex(\3, ":[AQ].*:p", ":(?:G|Y|[AQ].*:[is])")
    -3>> =suggSing(@)                                                        # Accord avec le pronom “\1” : « \3 » doit être au singulier.
__[i]/ppas(ppas_se_verbe)__
__[i]/ppas(ppas_se_verbe_pensée)__
    se ((?:trouv|consid[éè]r|cr[ouû]|rend)\w*) +({w_3})  @@w,$
    <<- morph(\1, ">(?:trouver|considérer|croire|rendre) .*:3s", False) and morphex(\2, ":[AQ].*:p", ":(?:G|Y|[AQ].*:[is])")
    -2>> =suggSing(@)                                                        # Accord avec le pronom “se” (le verbe étant au singulier) : « \2 » doit être au singulier.
    <<- morph(\1, ">(?:trouver|considérer|croire|rendre) .*:3p", False) and morphex(\2, ":[AQ].*:s", ":(?:G|Y|[AQ].*:[ip])")
    -2>> =suggSing(@)                                                        # Accord avec le pronom “se” (le verbe étant au pluriel) : « \2 » doit être au pluriel.
__[i]/ppas(ppas_nous_verbe)__
__[i]/ppas(ppas_nous_verbe_pensée)__
    nous ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2})  @@w,$
    <<- ( morphex(\1, ">(?:trouver|considérer|croire|rendre|voilà) ", ":1p")
    or (morph(\1, ">(?:trouver|considérer|croire) .*:1p", False) and before(r"\bn(?:ous|e) +$")) )
    and morphex(\2, ":[AQ].*:s", ":(?:G|Y|[AQ].*:[ip])")
    -2>> =suggPlur(@)                                                        # Accord avec le pronom “nous” : « \2 » doit être au pluriel.
#__[i]/ppas(ppas_vous_verbe)__
#    vous ((?:trouv|consid[éè]r|cr[ouû]|rend|voilà)\w*) +({w_2})  @@w,$
8679
8680
8681
8682
8683
8684
8685
8686

8687
8688
8689
8690
8691
8692
8693
8679
8680
8681
8682
8683
8684
8685

8686
8687
8688
8689
8690
8691
8692
8693







-
+







    <<- morph(\1, ">avoir ", False) and morphex(\2, ":Q.*:(?:f|m:p)", ":m:[si]")
    -2>> =suggMasSing(@)
    # Le participe passé devrait être au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais

TEST: des hommes, des femmes, des enfants qui ne leur avaient {{faits}} que du bien.


__[i]/ppas(ppas_avoir)__
__[i]/ppas(ppas_avoir_ppas_mas_sing)__
    avoir +({w_2})  @@$
    <<- not re.search("(?i)^(?:confiance|cours|envie|peine|prise|crainte|cure|affaire|hâte|force|recours)$", \1)
    and morphex(\1, ":Q.*:(?:f|m:p)", ":m:[si]") and before("(?i)(?:après +$|sans +$|pour +$|que? +$|quand +$|, +$|^ *$)")
    -1>> =suggMasSing(@)
    # Le participe passé devrait être au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais

TEST: Il a {{prit}} le train.
8788
8789
8790
8791
8792
8793
8794
8795

8796
8797
8798
8799
8800
8801
8802
8788
8789
8790
8791
8792
8793
8794

8795
8796
8797
8798
8799
8800
8801
8802







-
+







    and (morphex(\2, ":V[0-3]..t.*:Q.*:f", ":[GWme]") or morphex(\2, ":V[0-3]..t.*:Q.*:p", ":[GWsi]"))
    -2>> =suggMasSing(@)
    # Le participe passé devrait être au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais

TEST: ce que ça a {{donnée}}


__[i]/ppas(ppas_avoir)__
__[i]/ppas(ppas_avoir_conf_infi)__
    ({avoir}) +({w_2}e[rz])  @@0,$
    <<- not re.search("^(?:A|avions)$", \1) and morph(\1, ":V0a", False) and morph(\2, ":V.+:(?:Y|2p)", False)
    -2>> =suggVerbPpas(@, ":m:s")                                                                   # Incohérence avec « \1 » : « \2 » n’est pas un participe passé.
    <<- __also__ and \1 == "a" and \2.endswith("r") and not before(r"(?i)\b(?:[mtn]’|il +|on +|elle +)$")
    -1>> à                                                                                          # Confusion probable : “a” est une conjugaison du verbe avoir. Pour la préposition, écrivez :

TEST: Avoir {{marcher}} toute la journée m’a épuisée.
10235
10236
10237
10238
10239
10240
10241
10242
10243


10244
10245
10246
10247



10248
10249
10250
10251
10252
10253
10254
10235
10236
10237
10238
10239
10240
10241


10242
10243
10244



10245
10246
10247
10248
10249
10250
10251
10252
10253
10254







-
-
+
+

-
-
-
+
+
+







TEST: J’{{aimerai}} savoir ce dont il retourne.
TEST: dans tous les cas j’{{aimerai}} ne rien savoir
TEST: Je {{voudrai}} qu’il soit déjà là.
TEST: J’aimerai ces cours-là autant que les autres.
TEST: J’aimerai la danse et la musique, puisque vous l’exigez.


__[i>/vmode(vmode_j_aurais_aimé_que_avoir_être)__
    j’(aurai) +(?:aimé|souhaité|préféré|voulu) +(?:que? |> )  @@2
__[i>/vmode(vmode_j_aurais_aimé_que_avoir_être1)__
    j’(aurai) +(?:aimé|souhaité|préféré|voulu) +(?:que? |ne |> )  @@2
    <<- -1>> aurais|eusse                           # Pour un souhait passé, utilisez le conditionnel passé et non le futur antérieur. Exemple pour le futur antérieur : « quand j’aurai fini… »
__[i]/vmode(vmode_j_aurais_aimé_que_avoir_être)__
    j’(aurai) +(?:aimé|souhaité|préféré|voulu) +({infi}|ne)  @@2,$
    <<- morph(\2, ":[YX]", False)
__[i]/vmode(vmode_j_aurais_aimé_que_avoir_être2)__
    j’(aurai) +(?:aimé|souhaité|préféré|voulu) +(?:[nmtsl]’|)({infi})  @@2,$
    <<- morph(\2, ":Y", False)
    -1>> aurais|eusse                               # Pour un souhait passé, utilisez le conditionnel passé et non le futur antérieur. Exemple pour le futur antérieur : « quand j’aurai fini… »

TEST: J’{{aurai}} aimé nous offrir ce magnifique cadeau.
TEST: j’{{aurai}} voulu être un artiste.
TEST: j’{{aurai}} préféré ne pas avoir à l’entendre.
TEST: Quand j’en aurai fini avec eux, vous aurez du mal à les reconnaître.
TEST: Quand j’aurai fini ce boulot, je ne sais pas ce que je ferai.