Grammalecte  Check-in [e0ce6b10d7]

Overview
Comment:[core][graphspell][fx][cli] lexicographer: update
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | cli | core | fx | graphspell | salxg
Files: files | file ages | folders
SHA3-256: e0ce6b10d774d48acf58859b526b54bac1d377ee8022394eaeb344a1244dbe0b
User & Date: olr on 2020-09-10 12:17:59
Other Links: branch diff | manifest | tags
Context
2020-09-10
13:15
[graphspell][fx] lexicographer update: same code for Python and JavaScript (remove deprecated code) Closed-Leaf check-in: 891500b92a user: olr tags: fx, graphspell, salxg
12:17
[core][graphspell][fx][cli] lexicographer: update check-in: e0ce6b10d7 user: olr tags: cli, core, fx, graphspell, salxg
2020-09-07
09:48
[graphspell][fx] lexicographer: update check-in: f614419de2 user: olr tags: fx, graphspell, salxg
Changes

Modified gc_core/js/lang_core/gc_engine.js from [bd80498a18] to [1ef4c7eeea].

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
                if (bFullInfo) {
                    this.lTokens0 = Array.from(this.lTokens);
                    // the list of tokens is duplicated, to keep tokens from being deleted when analysis
                }
                this.parseText(this.sSentence, this.sSentence0, false, iStart, sCountry, dOpt, bShowRuleId, bDebug, bContext);
                if (bFullInfo) {
                    for (let oToken of this.lTokens0) {
                        if (oToken["sType"] == "WORD") {
                            oToken["bValidToken"] = gc_engine.oSpellChecker.isValidToken(oToken["sValue"]);
                        }
                        if (!oToken.hasOwnProperty("lMorph")) {
                            oToken["lMorph"] = gc_engine.oSpellChecker.getMorph(oToken["sValue"]);
                        }
                        gc_engine.oSpellChecker.setLabelsOnToken(oToken);
                    }
                    lSentences.push({
                        "nStart": iStart,
                        "nEnd": iEnd,
                        "sSentence": this.sSentence0,
                        "lTokens": this.lTokens0,







<
<
<
<
<
<







223
224
225
226
227
228
229






230
231
232
233
234
235
236
                if (bFullInfo) {
                    this.lTokens0 = Array.from(this.lTokens);
                    // the list of tokens is duplicated, to keep tokens from being deleted when analysis
                }
                this.parseText(this.sSentence, this.sSentence0, false, iStart, sCountry, dOpt, bShowRuleId, bDebug, bContext);
                if (bFullInfo) {
                    for (let oToken of this.lTokens0) {






                        gc_engine.oSpellChecker.setLabelsOnToken(oToken);
                    }
                    lSentences.push({
                        "nStart": iStart,
                        "nEnd": iEnd,
                        "sSentence": this.sSentence0,
                        "lTokens": this.lTokens0,

Modified gc_core/py/lang_core/gc_engine.py from [a0179d3d20] to [3958209087].

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
                    self.lTokens = list(_oTokenizer.genTokens(self.sSentence, True))
                    self.dTokenPos = { dToken["nStart"]: dToken  for dToken in self.lTokens  if dToken["sType"] != "INFO" }
                    if bFullInfo:
                        self.lTokens0 = list(self.lTokens)  # the list of tokens is duplicated, to keep tokens from being deleted when analysis
                    self.parseText(self.sSentence, self.sSentence0, False, iStart, sCountry, dOpt, bShowRuleId, bDebug, bContext)
                    if bFullInfo:
                        for dToken in self.lTokens0:
                            if dToken["sType"] == "WORD":
                                dToken["bValidToken"] = _oSpellChecker.isValidToken(dToken["sValue"])
                            if "lMorph" not in dToken:
                                dToken["lMorph"] = _oSpellChecker.getMorph(dToken["sValue"])
                            _oSpellChecker.setLabelsOnToken(dToken)
                        lSentences.append({
                            "nStart": iStart,
                            "nEnd": iEnd,
                            "sSentence": self.sSentence0,
                            "lTokens": self.lTokens0,
                            "lGrammarErrors": list(self.dSentenceError.values())







<
<
<
<







284
285
286
287
288
289
290




291
292
293
294
295
296
297
                    self.lTokens = list(_oTokenizer.genTokens(self.sSentence, True))
                    self.dTokenPos = { dToken["nStart"]: dToken  for dToken in self.lTokens  if dToken["sType"] != "INFO" }
                    if bFullInfo:
                        self.lTokens0 = list(self.lTokens)  # the list of tokens is duplicated, to keep tokens from being deleted when analysis
                    self.parseText(self.sSentence, self.sSentence0, False, iStart, sCountry, dOpt, bShowRuleId, bDebug, bContext)
                    if bFullInfo:
                        for dToken in self.lTokens0:




                            _oSpellChecker.setLabelsOnToken(dToken)
                        lSentences.append({
                            "nStart": iStart,
                            "nEnd": iEnd,
                            "sSentence": self.sSentence0,
                            "lTokens": self.lTokens0,
                            "lGrammarErrors": list(self.dSentenceError.values())

Modified gc_lang/fr/webext/content_scripts/panel_gc.js from [cb02a4a038] to [6fa57d1aea].

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
...
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
                    xSentenceBlock.appendChild(oGrammalecte.createNode("p", {className: "grammalecte_lxg_paragraph_sentence", textContent: oSentence.sSentence}));
                    let xTokenList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
                    for (let oToken of oSentence.lTokens) {
                        if (oToken["sType"] != "INFO" && !oToken.hasOwnProperty("bMerged")) {
                            if (oToken["sType"] == "WORD" && !oToken["bValidToken"]) {
                                oToken["sType"] = "UNKNOWN_WORD";
                            }
                            xTokenList.appendChild(this._createTokenBlock2(oToken));
                        }
                    }
                    xSentenceBlock.appendChild(xTokenList);
                    this.xLxgResultZone.appendChild(xSentenceBlock);
                }
            }
        }
        catch (e) {
            showError(e);
        }
        this.stopWaitIcon();
    }

    _createTokenBlock2 (oToken) {
        let xTokenBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"});
        // token description
        xTokenBlock.appendChild(this._createTokenDescr2(oToken));
        return xTokenBlock;
    }

    _createTokenDescr2 (oToken) {
        try {
            let xTokenDescr = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_descr"});
            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
            if (oToken.aLabels) {
                if (oToken.aLabels.length < 2) {
                    // one morphology only
                    xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: oToken.aLabels[0]}));
                } else {
                    // several morphology
                    let xMorphList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"});
                    for (let sLabel of oToken.aLabels) {
                        xMorphList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
                    }
                    xTokenDescr.appendChild(xMorphList);
                }
            } else {
                xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: "étiquettes non décrites : [" + oToken.lMorph + "]" }));
            }
            // other labels description
            if (oToken.aOtherLabels) {
                let xSubBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_subblock"});
                for (let sLabel of oToken.aOtherLabels) {
                    xSubBlock.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_other_tags", textContent: "• " + sLabel}));
                }
                xTokenDescr.appendChild(xSubBlock);
            }
            return xTokenDescr;
        }
        catch (e) {
            showError(e);
        }
    }

    //  Lexical analysis

    getListOfTokens () {
        if (!this.bOpened || this.bWorking) {
            return;
        }
................................................................................
        catch (e) {
            showError(e);
        }
    }

    _createTokenBlock (oToken) {
        let xTokenBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"});

        xTokenBlock.appendChild(this._createTokenDescr(oToken));
        if (oToken.aSubElem) {


            let xSubBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_subblock"});
            for (let oSubElem of oToken.aSubElem) {


                xSubBlock.appendChild(this._createTokenDescr(oSubElem));

            }
            xTokenBlock.appendChild(xSubBlock);
        }
        return xTokenBlock;
    }

    _createTokenDescr (oToken) {
        try {
            let xTokenDescr = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_descr"});
            if (oToken.sType == "LOCP") {
                xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_also", textContent: "possiblement › "}));
            }
            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
            if (oToken.aLabel.length === 1) {


                xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: oToken.aLabel[0]}));
            } else {

                let xMorphList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"});
                for (let sLabel of oToken.aLabel) {
                    xMorphList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
                }
                xTokenDescr.appendChild(xMorphList);



            }
            return xTokenDescr;
        }
        catch (e) {
            showError(e);
        }
    }







|













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







 







>

<
>
>

<
>
>
|
>









<
<
<


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







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
...
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
                    xSentenceBlock.appendChild(oGrammalecte.createNode("p", {className: "grammalecte_lxg_paragraph_sentence", textContent: oSentence.sSentence}));
                    let xTokenList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
                    for (let oToken of oSentence.lTokens) {
                        if (oToken["sType"] != "INFO" && !oToken.hasOwnProperty("bMerged")) {
                            if (oToken["sType"] == "WORD" && !oToken["bValidToken"]) {
                                oToken["sType"] = "UNKNOWN_WORD";
                            }
                            xTokenList.appendChild(this._createTokenBlock(oToken));
                        }
                    }
                    xSentenceBlock.appendChild(xTokenList);
                    this.xLxgResultZone.appendChild(xSentenceBlock);
                }
            }
        }
        catch (e) {
            showError(e);
        }
        this.stopWaitIcon();
    }











































    //  Lexical analysis

    getListOfTokens () {
        if (!this.bOpened || this.bWorking) {
            return;
        }
................................................................................
        catch (e) {
            showError(e);
        }
    }

    _createTokenBlock (oToken) {
        let xTokenBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"});
        // token description
        xTokenBlock.appendChild(this._createTokenDescr(oToken));

        // subtokens
        if (oToken.hasOwnProperty("lSubTokens")) {
            let xSubBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_subblock"});

            for (let oSubToken of oToken["lSubTokens"]) {
                if (oSubToken["sValue"] != "") {
                    xSubBlock.appendChild(this._createTokenDescr(oSubToken));
                }
            }
            xTokenBlock.appendChild(xSubBlock);
        }
        return xTokenBlock;
    }

    _createTokenDescr (oToken) {
        try {
            let xTokenDescr = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_descr"});



            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
            xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
            if (oToken.aLabels) {
                if (oToken.aLabels.length < 2) {
                    // one morphology only
                    xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: oToken.aLabels[0]}));
                } else {
                    // several morphology
                    let xMorphList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"});
                    for (let sLabel of oToken.aLabels) {
                        xMorphList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
                    }
                    xTokenDescr.appendChild(xMorphList);
                }
            } else {
                xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: "étiquettes non décrites : [" + oToken.lMorph + "]" }));
            }
            return xTokenDescr;
        }
        catch (e) {
            showError(e);
        }
    }

Modified gc_lang/fr/webext/content_scripts/panel_lxg.css from [e1c944551d] to [b335aa8c9f].

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

div.grammalecte_lxg_token_block  {
    margin: 4px 0;
}
div.grammalecte_lxg_token_subblock {
    margin: 2px 0 2px 20px;
    padding: 5px;
    border-left: 4px solid hsl(150, 30%, 70%);
    background-color: hsl(210, 10%, 90%);
    border-radius: 2px;
}
div.grammalecte_lxg_token_descr {
    margin: 1px;
    padding: 1px;
}
div.grammalecte_lxg_token {
    display: inline-block;







|
|
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

div.grammalecte_lxg_token_block  {
    margin: 4px 0;
}
div.grammalecte_lxg_token_subblock {
    margin: 2px 0 2px 20px;
    padding: 5px;
    border-left: 4px solid hsl(210, 50%, 80%);
    background-color: hsl(210, 50%, 94%);
    border-radius: 3px;
}
div.grammalecte_lxg_token_descr {
    margin: 1px;
    padding: 1px;
}
div.grammalecte_lxg_token {
    display: inline-block;

Modified grammalecte-cli.py from [65f33ab4b5] to [4b02966a37].

351
352
353
354
355
356
357






358
359
360
361
362
363
364
                            echo("  {0[nStart]:>3}:{0[nEnd]:<3} {1} {0[sType]:<14} {2} {0[sValue]:<16} {3}".format(dToken, \
                                                                                                        "×" if dToken.get("bToRemove", False) else " ",
                                                                                                        "!" if dToken["sType"] == "WORD" and not dToken.get("bValidToken", False) else " ",
                                                                                                        " ".join(dToken.get("aTags", "")) ) )
                            if "lMorph" in dToken:
                                for sMorph, sLabel in zip(dToken["lMorph"], dToken["aLabels"]):
                                    echo("            {0:40}  {1}".format(sMorph, sLabel))






                        #echo(txt.getReadableErrors(dSentence["lGrammarErrors"], xArgs.width))
            else:
                for sParagraph in txt.getParagraph(sText):
                    if xArgs.textformatter:
                        sParagraph = oTextFormatter.formatText(sParagraph)
                    sRes, _ = oGrammarChecker.getParagraphWithErrors(sParagraph, bEmptyIfNoErrors=xArgs.only_when_errors, nWidth=xArgs.width, bDebug=xArgs.debug)
                    if sRes:







>
>
>
>
>
>







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
                            echo("  {0[nStart]:>3}:{0[nEnd]:<3} {1} {0[sType]:<14} {2} {0[sValue]:<16} {3}".format(dToken, \
                                                                                                        "×" if dToken.get("bToRemove", False) else " ",
                                                                                                        "!" if dToken["sType"] == "WORD" and not dToken.get("bValidToken", False) else " ",
                                                                                                        " ".join(dToken.get("aTags", "")) ) )
                            if "lMorph" in dToken:
                                for sMorph, sLabel in zip(dToken["lMorph"], dToken["aLabels"]):
                                    echo("            {0:40}  {1}".format(sMorph, sLabel))
                            if "lSubTokens" in dToken:
                                for dSubToken in dToken["lSubTokens"]:
                                    if dSubToken["sValue"]:
                                        echo("              · {0:20}".format(dSubToken["sValue"]))
                                        for sMorph, sLabel in zip(dSubToken["lMorph"], dSubToken["aLabels"]):
                                            echo("                {0:40}  {1}".format(sMorph, sLabel))
                        #echo(txt.getReadableErrors(dSentence["lGrammarErrors"], xArgs.width))
            else:
                for sParagraph in txt.getParagraph(sText):
                    if xArgs.textformatter:
                        sParagraph = oTextFormatter.formatText(sParagraph)
                    sRes, _ = oGrammarChecker.getParagraphWithErrors(sParagraph, bEmptyIfNoErrors=xArgs.only_when_errors, nWidth=xArgs.width, bDebug=xArgs.debug)
                    if sRes:

Modified graphspell-js/ibdawg.js from [25fa8fe973] to [858a3af6e6].

311
312
313
314
315
316
317



318
319
320
321
322
323
324
            }
        }
        return Boolean(this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask);
    }

    getMorph (sWord) {
        // retrieves morphologies list, different casing allowed



        sWord = str_transform.spellingNormalization(sWord);
        let l = this.morph(sWord);
        if (sWord[0].gl_isUpperCase()) {
            l.push(...this.morph(sWord.toLowerCase()));
            if (sWord.gl_isUpperCase() && sWord.length > 1) {
                l.push(...this.morph(sWord.gl_toCapitalize()));
            }







>
>
>







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
            }
        }
        return Boolean(this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask);
    }

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

Modified graphspell-js/lexgraph_fr.js from [94bb3a1779] to [841b4146b0].

419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
...
438
439
440
441
442
443
444



445
446
447
448
449
450
451
...
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
...
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
        // préfixe élidé
        let m = /^([ldmtsnjcç]|lorsqu|presqu|jusqu|puisqu|quoiqu|quelqu|qu)[’'‘`ʼ]([a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]+)/i.exec(sWord);
        if (m) {
            sPrefix = m[1] + "’";
            sWord = m[2];
        }
        // mots composés
        m = /^([a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]+)(-(?:(?: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|ce))$/i.exec(sWord);
        if (m) {
            sWord = m[1];
            sSuffix = m[2];
        }
        // split word in 3 parts: prefix, root, suffix
        return [sPrefix, sWord, sSuffix];
    },
................................................................................
        if (this.dValues.has(sWord)) {
            return this.dValues.get(sWord);
        }
        return "";
    },

    readableMorph: function (sMorph) {



        let sRes = "";
        sMorph = sMorph.replace(/:V([0-3][ea_])[itpqnmr_eaxz]+/, ":V$1");
        let m;
        while ((m = this._zTag.exec(sMorph)) !== null) {
            if (this.dTag.has(m[0])) {
                sRes += this.dTag.get(m[0])[0];
            } else {
................................................................................
                case 'WORD':
                    if (oToken.hasOwnProperty("lMorph")  &&  oToken["lMorph"].length > 0) {
                        // with morphology
                        oToken["aLabels"] = [];
                        for (let sMorph of oToken["lMorph"]) {
                            oToken["aLabels"].push(this.readableMorph(sMorph));
                        }
                        if (oToken.hasOwnProperty("sTags")) {
                            let aTags = [];
                            for (let sTag of oToken["sTags"]) {
                                if (this.dValues.has(sTag)) {
                                    aTags.push(this.dValues.get(sTag))
                                }
                            }
                            if (aTags.length > 0) {
                                oToken["aOtherLabels"] = aTags;
                            }
                        }
                    } else {
                        // no morphology, guessing
                        if (oToken["sValue"].gl_count("-") > 4) {
                            oToken["aLabels"] = ["élément complexe indéterminé"];
                        }
                        else if (m = this._zPartDemForm.exec(oToken["sValue"])) {
                            // mots avec particules démonstratives
................................................................................
                        else if (m = this._zInterroVerb.exec(oToken["sValue"])) {
                            // formes interrogatives
                            oToken["aLabels"] = ["forme verbale interrogative"];
                        }
                        else {
                            oToken["aLabels"] = ["mot inconnu du dictionnaire"];
                        }













                    }
                    break;
                default:
                    oToken["aLabels"] = ["token de nature inconnue"];
            }
        } catch (e) {
            console.error(e);
        }
    },

    getInfoForToken: function (oToken) {
        // Token: .sType, .sValue, .nStart, .nEnd
        // return a object {sType, sValue, aLabel}
        let m = null;
        try {
            switch (oToken.sType) {
                case 'PUNC':
                case 'SIGN':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: [this.dValues.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 'TAG':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["étiquette (hashtag)"]
                    };
                    break;
                case 'HTML':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabel: ["balise HTML"]
                    };
                    break;
                case 'PSEUDOHTML':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["balise pseudo-HTML"]
                    };
                    break;
                case 'HTMLENTITY':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["entité caractère XML/HTML"]
                    };
                    break;
                case 'HOUR':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["heure"]
                    };
                    break;
                case 'WORD_ELIDED':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: [this.dValues.gl_get(oToken.sValue.toLowerCase(), "préfixe élidé inconnu")]
                    };
                    break;
                case 'WORD_ORDINAL':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["nombre ordinal"]
                    };
                    break;
                case 'FOLDERUNIX':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabel: ["dossier UNIX (et dérivés)"]
                    };
                    break;
                case 'FOLDERWIN':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabel: ["dossier Windows"]
                    };
                    break;
                case 'WORD_ACRONYM':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["Sigle ou acronyme"]
                    };
                    break;
                case 'WORD':
                    if (oToken.sValue.gl_count("-") > 4) {
                        return {
                            sType: "COMPLEX",
                            sValue: oToken.sValue,
                            aLabel: ["élément complexe indéterminé"]
                        };
                    } else if (m = this._zPartDemForm.exec(oToken.sValue)) {
                        // mots avec particules démonstratives
                        if (this._aPartDemExceptList.has(m[1].toLowerCase())) {
                            return {
                                sType: "WORD",
                                sValue: oToken.sValue,
                                aLabel: this._getMorph(oToken.sValue)
                            };
                        }
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabel: ["mot avec particule démonstrative"],
                            aSubElem: [
                                { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (m = this._zImperatifVerb.exec(oToken.sValue)) {
                        // formes interrogatives
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabel: ["forme verbale impérative"],
                            aSubElem: [
                                { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (m = this._zInterroVerb.exec(oToken.sValue)) {
                        // formes interrogatives
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabel: ["forme verbale interrogative"],
                            aSubElem: [
                                { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (this.oSpellChecker.isValidToken(oToken.sValue)) {
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabel: this._getMorph(oToken.sValue)
                        };
                    } else {
                        return {
                            sType: "UNKNOWN_WORD",
                            sValue: oToken.sValue,
                            aLabel: ["mot inconnu du dictionnaire"]
                        };
                    }
                    break;
                default:
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabel: ["token inconnu"]
                    }
            }
        } catch (e) {
            console.error(e);
        }
        return null;
    },







|







 







>
>
>







 







<
<
<
<
<
<
<
<
<
<
<







 







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












|








|






|






|






|






|






|






|






|






|






|






|






|






|







|







|





|
|
|
|







|
|
|
|







|
|
|
|






|





|







|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
512
513
514
515
516
517
518











519
520
521
522
523
524
525
...
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
        // préfixe élidé
        let m = /^([ldmtsnjcç]|lorsqu|presqu|jusqu|puisqu|quoiqu|quelqu|qu)[’'‘`ʼ]([a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st-]+)/i.exec(sWord);
        if (m) {
            sPrefix = m[1] + "’";
            sWord = m[2];
        }
        // mots composés
        m = /^([a-zA-Zà-öÀ-Ö0-9_ø-ÿØ-ßĀ-ʯfi-st]+)(-(?:(?: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|ce))$/i.exec(sWord);
        if (m) {
            sWord = m[1];
            sSuffix = m[2];
        }
        // split word in 3 parts: prefix, root, suffix
        return [sPrefix, sWord, sSuffix];
    },
................................................................................
        if (this.dValues.has(sWord)) {
            return this.dValues.get(sWord);
        }
        return "";
    },

    readableMorph: function (sMorph) {
        if (!sMorph) {
            return " mot inconnu";
        }
        let sRes = "";
        sMorph = sMorph.replace(/:V([0-3][ea_])[itpqnmr_eaxz]+/, ":V$1");
        let m;
        while ((m = this._zTag.exec(sMorph)) !== null) {
            if (this.dTag.has(m[0])) {
                sRes += this.dTag.get(m[0])[0];
            } else {
................................................................................
                case 'WORD':
                    if (oToken.hasOwnProperty("lMorph")  &&  oToken["lMorph"].length > 0) {
                        // with morphology
                        oToken["aLabels"] = [];
                        for (let sMorph of oToken["lMorph"]) {
                            oToken["aLabels"].push(this.readableMorph(sMorph));
                        }











                    } else {
                        // no morphology, guessing
                        if (oToken["sValue"].gl_count("-") > 4) {
                            oToken["aLabels"] = ["élément complexe indéterminé"];
                        }
                        else if (m = this._zPartDemForm.exec(oToken["sValue"])) {
                            // mots avec particules démonstratives
................................................................................
                        else if (m = this._zInterroVerb.exec(oToken["sValue"])) {
                            // formes interrogatives
                            oToken["aLabels"] = ["forme verbale interrogative"];
                        }
                        else {
                            oToken["aLabels"] = ["mot inconnu du dictionnaire"];
                        }
                    }
                    if (oToken.hasOwnProperty("lSubTokens")) {
                        for (let oSubToken of oToken["lSubTokens"]) {
                            if (oSubToken["sValue"]) {
                                if (this.dValues.has(oSubToken["sValue"])) {
                                    oSubToken["lMorph"] = [ "" ];
                                    oSubToken["aLabels"] = [ this.dValues.get(oSubToken["sValue"]) ];
                                }
                                else {
                                    oSubToken["aLabels"] = oSubToken["lMorph"].map((sMorph) => this.readableMorph(sMorph));
                                }
                            }
                        }
                    }
                    break;
                default:
                    oToken["aLabels"] = ["token de nature inconnue"];
            }
        } catch (e) {
            console.error(e);
        }
    },

    getInfoForToken: function (oToken) {
        // Token: .sType, .sValue, .nStart, .nEnd
        // return a object {sType, sValue, aLabels}
        let m = null;
        try {
            switch (oToken.sType) {
                case 'PUNC':
                case 'SIGN':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: [this.dValues.gl_get(oToken.sValue, "caractère indéterminé")]
                    };
                    break;
                case 'NUM':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["nombre"]
                    };
                    break;
                case 'LINK':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabels: ["hyperlien"]
                    };
                    break;
                case 'TAG':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["étiquette (hashtag)"]
                    };
                    break;
                case 'HTML':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabels: ["balise HTML"]
                    };
                    break;
                case 'PSEUDOHTML':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["balise pseudo-HTML"]
                    };
                    break;
                case 'HTMLENTITY':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["entité caractère XML/HTML"]
                    };
                    break;
                case 'HOUR':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["heure"]
                    };
                    break;
                case 'WORD_ELIDED':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: [this.dValues.gl_get(oToken.sValue.toLowerCase(), "préfixe élidé inconnu")]
                    };
                    break;
                case 'WORD_ORDINAL':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["nombre ordinal"]
                    };
                    break;
                case 'FOLDERUNIX':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabels: ["dossier UNIX (et dérivés)"]
                    };
                    break;
                case 'FOLDERWIN':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue.slice(0, 40) + "…",
                        aLabels: ["dossier Windows"]
                    };
                    break;
                case 'WORD_ACRONYM':
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["Sigle ou acronyme"]
                    };
                    break;
                case 'WORD':
                    if (oToken.sValue.gl_count("-") > 4) {
                        return {
                            sType: "COMPLEX",
                            sValue: oToken.sValue,
                            aLabels: ["élément complexe indéterminé"]
                        };
                    } else if (m = this._zPartDemForm.exec(oToken.sValue)) {
                        // mots avec particules démonstratives
                        if (this._aPartDemExceptList.has(m[1].toLowerCase())) {
                            return {
                                sType: "WORD",
                                sValue: oToken.sValue,
                                aLabels: this._getMorph(oToken.sValue)
                            };
                        }
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabels: ["mot avec particule démonstrative"],
                            lSubTokens: [
                                { sType: oToken.sType, sValue: m[1], aLabels: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabels: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (m = this._zImperatifVerb.exec(oToken.sValue)) {
                        // formes interrogatives
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabels: ["forme verbale impérative"],
                            lSubTokens: [
                                { sType: oToken.sType, sValue: m[1], aLabels: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabels: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (m = this._zInterroVerb.exec(oToken.sValue)) {
                        // formes interrogatives
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabels: ["forme verbale interrogative"],
                            lSubTokens: [
                                { sType: oToken.sType, sValue: m[1], aLabels: this._getMorph(m[1]) },
                                { sType: oToken.sType, sValue: m[2], aLabels: [ this._formatSuffix(m[2]) ] }
                            ]
                        };
                    } else if (this.oSpellChecker.isValidToken(oToken.sValue)) {
                        return {
                            sType: oToken.sType,
                            sValue: oToken.sValue,
                            aLabels: this._getMorph(oToken.sValue)
                        };
                    } else {
                        return {
                            sType: "UNKNOWN_WORD",
                            sValue: oToken.sValue,
                            aLabels: ["mot inconnu du dictionnaire"]
                        };
                    }
                    break;
                default:
                    return {
                        sType: oToken.sType,
                        sValue: oToken.sValue,
                        aLabels: ["token inconnu"]
                    }
            }
        } catch (e) {
            console.error(e);
        }
        return null;
    },

Modified graphspell-js/spellchecker.js from [851f1e59f5] to [a94325f4c6].

171
172
173
174
175
176
177














178
179
180
181
182
183
184
        }
        return this.lexicographer.formatTags(sMorph);
    }

    setLabelsOnToken (oToken) {
        if (!this.lexicographer) {
            return;














        }
        this.lexicographer.setLabelsOnToken(oToken);
    }


    // Storage








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







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
        }
        return this.lexicographer.formatTags(sMorph);
    }

    setLabelsOnToken (oToken) {
        if (!this.lexicographer) {
            return;
        }
        if (!oToken.hasOwnProperty("lMorph")) {
            oToken["lMorph"] = this.getMorph(oToken["sValue"]);
        }
        if (oToken["sType"] == "WORD") {
            oToken["bValidToken"] = this.isValidToken(oToken["sValue"]);
            let [sPrefix, sStem, sSuffix] = this.lexicographer.split(oToken["sValue"]);
            if (sStem != oToken["sValue"]) {
                oToken["lSubTokens"] = [
                    { "sType": "WORD", "sValue": sPrefix, "lMorph": this.getMorph(sPrefix) },
                    { "sType": "WORD", "sValue": sStem,   "lMorph": this.getMorph(sStem)   },
                    { "sType": "WORD", "sValue": sSuffix, "lMorph": this.getMorph(sSuffix) }
                ];
            }
        }
        this.lexicographer.setLabelsOnToken(oToken);
    }


    // Storage

Modified graphspell/ibdawg.py from [01e0cc9f3f] to [2c4cbe4f53].

296
297
298
299
300
301
302


303
304
305
306
307
308
309
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr is 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"


        sWord = st.spellingNormalization(sWord)
        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







>
>







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
            iAddr = self._lookupArcNode(self.dChar[c], iAddr)
            if iAddr is 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"
        if not sWord:
            return []
        sWord = st.spellingNormalization(sWord)
        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

Modified graphspell/lexgraph_fr.py from [ef96895529] to [60d5043aa3].

397
398
399
400
401
402
403


404
405
406
407
408
409
410
...
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
    if sWord in _dValues:
        return _dValues[sWord]
    return ""


def readableMorph (sMorph):
    "returns string: readable tags"


    sRes = ""
    sMorph = re.sub("(?<=V[0123][ea_])[itpqnmr_eaxz]+", "", sMorph)
    for m in _zTag.finditer(sMorph):
        if m.group(0) in _dTAGS:
            sRes += _dTAGS[m.group(0)][0]
        else:
            sRes += " [" + m.group(0) + "]?"
................................................................................
            dToken["aLabels"] = ["sigle ou acronyme"]
        elif dToken["sType"] == 'WORD':
            if "lMorph" in dToken and dToken["lMorph"]:
                # with morphology
                dToken["aLabels"] = []
                for sMorph in dToken["lMorph"]:
                    dToken["aLabels"].append(readableMorph(sMorph))
                if "sTags" in dToken:
                    aTags = []
                    for sTag in dToken["sTags"]:
                        if sTag in _dValues:
                            aTags.append(_dValues[sTag])
                    if aTags:
                        dToken["aOtherLabels"] = aTags
            else:
                # no morphology, guessing
                if dToken["sValue"].count("-") > 4:
                    dToken["aLabels"] = ["élément complexe indéterminé"]
                elif _zPartDemForm.search(dToken["sValue"]):
                    # mots avec particules démonstratives
                    dToken["aLabels"] = ["mot avec particule démonstrative"]
                elif _zImperatifVerb.search(dToken["sValue"]):
                    # formes interrogatives
                    dToken["aLabels"] = ["forme verbale impérative"]
                elif _zInterroVerb.search(dToken["sValue"]):
                    # formes interrogatives
                    dToken["aLabels"] = ["forme verbale interrogative"]










        else:
            dToken["aLabels"] = ["token de nature inconnue"]
    except:
        return


# Other functions

def filterSugg (aSugg):
    "exclude suggestions"
    return filter(lambda sSugg: not sSugg.endswith(("è", "È")), aSugg)







>
>







 







<
<
<
<
<
<
<













>
>
>
>
>
>
>
>
>
>











397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
...
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
    if sWord in _dValues:
        return _dValues[sWord]
    return ""


def readableMorph (sMorph):
    "returns string: readable tags"
    if not sMorph:
        return "mot inconnu"
    sRes = ""
    sMorph = re.sub("(?<=V[0123][ea_])[itpqnmr_eaxz]+", "", sMorph)
    for m in _zTag.finditer(sMorph):
        if m.group(0) in _dTAGS:
            sRes += _dTAGS[m.group(0)][0]
        else:
            sRes += " [" + m.group(0) + "]?"
................................................................................
            dToken["aLabels"] = ["sigle ou acronyme"]
        elif dToken["sType"] == 'WORD':
            if "lMorph" in dToken and dToken["lMorph"]:
                # with morphology
                dToken["aLabels"] = []
                for sMorph in dToken["lMorph"]:
                    dToken["aLabels"].append(readableMorph(sMorph))







            else:
                # no morphology, guessing
                if dToken["sValue"].count("-") > 4:
                    dToken["aLabels"] = ["élément complexe indéterminé"]
                elif _zPartDemForm.search(dToken["sValue"]):
                    # mots avec particules démonstratives
                    dToken["aLabels"] = ["mot avec particule démonstrative"]
                elif _zImperatifVerb.search(dToken["sValue"]):
                    # formes interrogatives
                    dToken["aLabels"] = ["forme verbale impérative"]
                elif _zInterroVerb.search(dToken["sValue"]):
                    # formes interrogatives
                    dToken["aLabels"] = ["forme verbale interrogative"]
                else:
                    dToken["aLabels"] = ["mot inconnu du dictionnaire"]
            if "lSubTokens" in dToken:
                for dSubToken in dToken["lSubTokens"]:
                    if dSubToken["sValue"]:
                        if dSubToken["sValue"] in _dValues:
                            dSubToken["lMorph"] = [ "" ]
                            dSubToken["aLabels"] = [ _dValues[dSubToken["sValue"]] ]
                        else:
                            dSubToken["aLabels"] = [ readableMorph(sMorph)  for sMorph in dSubToken["lMorph"] ]
        else:
            dToken["aLabels"] = ["token de nature inconnue"]
    except:
        return


# Other functions

def filterSugg (aSugg):
    "exclude suggestions"
    return filter(lambda sSugg: not sSugg.endswith(("è", "È")), aSugg)

Modified graphspell/spellchecker.py from [a872642ccf] to [0ef2e9e17a].

131
132
133
134
135
136
137











138
139
140
141
142
143
144
        if not self.lexicographer:
            return ""
        return self.lexicographer.readableMorph(sMorph)

    def setLabelsOnToken (self, dToken):
        if not self.lexicographer:
            return











        self.lexicographer.setLabelsOnToken(dToken)


    # Storage

    def activateStorage (self):
        "store all lemmas and morphologies retrieved from the word graph"







>
>
>
>
>
>
>
>
>
>
>







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
        if not self.lexicographer:
            return ""
        return self.lexicographer.readableMorph(sMorph)

    def setLabelsOnToken (self, dToken):
        if not self.lexicographer:
            return
        if "lMorph" not in dToken:
            dToken["lMorph"] = self.getMorph(dToken["sValue"])
        if dToken["sType"] == "WORD":
            dToken["bValidToken"] = self.isValidToken(dToken["sValue"])
            sPrefix, sStem, sSuffix = self.lexicographer.split(dToken["sValue"])
            if sStem != dToken["sValue"]:
                dToken["lSubTokens"] = [
                    { "sType": "WORD", "sValue": sPrefix, "lMorph": self.getMorph(sPrefix) },
                    { "sType": "WORD", "sValue": sStem,   "lMorph": self.getMorph(sStem)   },
                    { "sType": "WORD", "sValue": sSuffix, "lMorph": self.getMorph(sSuffix) }
                ]
        self.lexicographer.setLabelsOnToken(dToken)


    # Storage

    def activateStorage (self):
        "store all lemmas and morphologies retrieved from the word graph"