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: build, trunk
08:00
[build] check if rules have same id check-in: 0dba21491a user: olr tags: build, trunk
2017-05-01
10:46
[build] useless conditions check-in: c4e9c97a0e user: olr tags: build, trunk
Changes

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

6
7
8
9
10
11
12


13
14
15
16
17
18
19
...
177
178
179
180
181
182
183



184
185
186
187
188
189
190
191
192
193
194
195
196
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
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
import json
from distutils import file_util


DEF = {}
FUNCTIONS = []



JSREGEXES = {}

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


def prepareFunction (s):
................................................................................
    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]



        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)

    #### REGEX TRIGGER
    i = s.find(" <<-")
    if i == -1:
        print("# Error: no condition at line " + sLineId)
        return None
    sRegex = s[:i].strip()
................................................................................
    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)
        else:
            if nGroup != len(tGroups):
                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

................................................................................
            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)")
            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
        if not sAction:
            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.")
        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.")
        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.")
        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:







>
>







 







>
>
>





|







 







|


|







 







|




|

|



|




|



|

|




|






|




|











|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
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
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):
................................................................................
    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)

    #### REGEX TRIGGER
    i = s.find(" <<-")
    if i == -1:
        print("# Error: no condition at line " + sLineId)
        return None
    sRegex = s[:i].strip()
................................................................................
    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)
        else:
            if nGroup != len(tGroups):
                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

................................................................................
            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)")
            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
        if not sAction:
            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.")
        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.")
        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.")
        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
....
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
....
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
....
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
....
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
....
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
....
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
....
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
....
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
....
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
.....
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
# 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?|) <<- ~>> *
# crochets
__[s]__  \[…\] <<- ~>> *
__[s]__  \[({w_1})\] @@1
    <<- \1.isdigit() ~>> *
    <<- __else__ ~>> _
__[s]__  \(…\)
    <<- ->> […]                                                                                     # Pour indiquer une troncature de texte, on utilise usuellement des crochets.
................................................................................
    <<- \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)__
    [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.


................................................................................
    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)__
    (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)__
................................................................................
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_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)__
    (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…
................................................................................
    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)__
    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.
................................................................................

__[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)__
    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.

................................................................................
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)__
    (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.
................................................................................
    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)__
    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)__
    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)__
    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)__
    ([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)__
    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)__
    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,$
................................................................................
    <<- 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)__
    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.
................................................................................
    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)__
    ({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.
................................................................................
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
    <<- -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)
    -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.







|







 







|







 







|







 







|


|







 







|







 







|







 







|







 







|



|



|



|



|





|







 







|







 







|







 







|
|

|
|
|







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
....
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
....
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
....
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
....
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
....
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
....
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
....
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
....
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
....
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
.....
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
# 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]__  (?: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.
................................................................................
    <<- \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_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.


................................................................................
    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_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)__
................................................................................
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_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_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…
................................................................................
    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_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.
................................................................................

__[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_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.

................................................................................
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_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.
................................................................................
    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_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_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_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_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_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_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,$
................................................................................
    <<- 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_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.
................................................................................
    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_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.
................................................................................
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_ê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_ê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.