
En ĉi tiu enskribo, mi pli-malpli priskribas tiel, kiel interne funkcias
Lingvoilo,
la gramatika kontrolilo por Esperanto kaj por multaj aliaj lingvoj.
Mi esperas, ke tiuj klarigoj eble instigos aliulojn por kontribui
al la plibonigo de Lingvoilo en Esperanto, aŭ eble en aliaj lingvoj.
Lingvoilo estas verkita en la programlingvo Ĝavao (Java).
Gramatikaj reguloj estas priskribitaj en XML-dosieroj.
Kontrolado de enira teksto procedas en pluraj sinsekvaj fazoj.
1. Tranĉado de teksto en frazoj.
Unue, la enira teksto estas tranĉita en frazoj. Eblus simple
tranĉi tekston en frazoj kiam ajn la programo trovas punktosignon, krisignon,
demandosignon (ktp.). Tiuj signoj ja dislimas frazojn. Sed tiu simpla
metodo ofte mistranĉus frazojn, kiam ekzemple frazo enhavus mallongigon
kiel «t.e.» (tio estas). Kvankam tiu mallongigo enhavas punktojn, ĝi ne
devus tranĉi tekston en multaj frazoj! La fraztranĉilo de Lingvoilo
estas do pli inteligenta ol tio. Por bone tranĉi frazojn, Lingvoilo uzas
SRX.
SRX estas normo por precize tranĉi tekston. Oni povas agordi la fraztranĉilon
per reguloj en XML-dosiero (languagetool/src/resource/segment.srx)
kun ŝablonoj, kiu priskribas, kie tranĉi aŭ ne tranĉi frazojn. Ekzemple,
por netranĉi frazojn ĉe oftaj mallongigoj, kiuj uzas punkton, la dosiero
de SRX enhavas tian regulon:
<!-- Esperanto abbreviations (see http://eo.lernu.net/lernado/gramatiko/demandoj/mallongigoj.php) -->
<rule break="no">
<beforebreak>\b(div|[Ee]kz|h|[Ii]nkl|p|[Rr]ed|[Rr]im|ktp)\.\s</beforebreak>
<afterbreak>\p{Ll}</afterbreak>
</rule>
Kaj la ĉi-suba regulo indikas male, kie eblas tranĉi frazojn (tio estas nur
fragmento de la pli ampleksa SRX-dosiero):
<rule break="yes">
<beforebreak>[\.!?…]['|"|«|\)|\]|\}]?\s+</beforebreak>
<afterbreak></afterbreak>
</rule>
2. Tranĉado de frazoj en vortoj
Post tranĉado de enira tekston en frazoj, Lingvoilo devas tranĉi
frazojn en vortoj. Tio estas sufiĉe simpla afero: spacetoj kaj iuj interpunkciosignoj
dislimas vortojn en la frazoj. Estas speciala traktado por la
apostrofo, kiu povas fariĝi parto de vorto (l’, dank' al, …) en
Esperanto.
La Ĝavao-kodofonto por tranĉi frazojn en vortoj de la Esperanta
versio de Lingvoilo estas languagetool/src/java/org/languagetool/tokenizers/eo/EsperantoWordTokenizer.java
3. Aldono de gramatikaj etikedoj al vortoj
La programo poste aldonas etikedojn al ĉiuj vortoj de la frazoj.
Tiuj etikedoj priskribas gramatikajn ecojn de la vortoj. Mi elektis
kelkajn etikedojn taŭgajn por gramatika kontrolilo kaj listigis ilin
en la dokumento
languagetool/src/resources/eo/etikedoj.txt
(helpa dosiero). Etikedoj indikas ekzemple, ĉu vorto estas o-vorto (substantivo),
a-vorto (adjektivo) verbo, rolmontrilo (prepozicio), tabelvorto, nombro, ĉu vorto estas
ununombra aŭ multenombra (pluralo), ĉu vorto havas akuzativon aŭ ne, ktp.
Ekzemple, la frazo «La domo malbelegas.» enhavas 3 vortojn.
Eblas vidi la gramatikajn etikedojn, kiujn Lingvolilo donas al
ĉiu vorto pere de la komanda opcio -v:
$ echo "La domoj malbelegas." | java -jar languagetool/dist/LanguageTool.jar -c utf-8 -l eo -v
Expected text language: Esperanto
Working on STDIN...
259 rules activated for language Esperanto
<S> La[la/D] domoj[domo/O nak pl] malbelegas[malbelegi/V nt as].[</S>]<P/>
En la supra ekzemplo:
- la vorto «La» havas etikedon «D», ĉar la vorto estas difinilo.
- La vorto «domoj» havas etikedon «O nak pl», ĉar ĝi
estas O-vorto (substantivo), neakuzativa, kaj plurala.
- La vorto «malbelegas» havas la etikedon «V nt as», ĉar ĝi estas verbo,
netransitiva, kaj ĝi estas as-verbo (estanta tempo).
Rimarku ankaŭ, ke Lingvoilo ne nur donas gramatikajn etikedojn, sed
ankaŭ
normalan radikon de ĉiuj vortoj. T.e., la normala radiko de «domoj»
estas «domo», la normala radiko de «malbelegas» estas «melbelegi».
Ni vidu poste, kial utilas tion scii.
Por multaj lingvoj, kiel la angla, la franca (ktp.), oni bezonas vortaron
por trovi etikedon de vortoj. Sed en Esperanto pli facilas, ĉar eblas
doni etikedon al preskaŭ ĉiuj vortoj nur dank’ al la regula finaĵo de
vortoj. Nu, malgranda vortaro estas tamen bezonata por la kelketaj
vortoj kiuj havas neregulan finaĵon (ĉefe pronomoj, tabelvortoj, nombroj, ktp.).
La dosiero
languagetool/src/resource/eo/manual-tagger.txt
listigas la vortojn kun neregulaj finaĵoj kaj donas iliajn etikedojn.
La programo ankaŭ bezonas vortareton por scii, ĉu verbo estas transitiva
aŭ netransitiva. Eblas aŭtomate trovi transitivecon de verboj sen
helpa vortaro nur por la -iĝ kaj -ig vortoj. Sed eĉ
por tiuj -iĝ/-ig verboj, oni devas tamen atenti pri strangaĵo:
la verbo
memmortigi estas netransitiva, kvankam ĝi havas la finaĵon -ig.
Mi kreis liston de transitivaj kaj netransitivaj verboj. Tiuj verboj
estas listigitaj en la dosieroj
languagetool/src/rules/eo/verb-tr.txt
(transitivaj verboj) kaj
languagetool/src/rules/eo/verb-ntr.txt
(netransitivaj verboj). Kelkaj verboj povas esti ambaŭ transitivaj
kaj netransitivaj, kaj tiuj verboj tiam aperas en ambaŭ dosieroj.
Farinte tiun liston, mi konsciis, ke transitiveco estas iom nebula
afero en Esperanto, kaj diversaj vortaroj donas malsamajn
transitivecojn por kelkaj verboj. Por iuj verboj, vortaroj
eĉ ne indikas transitivecon.
Ĉar en Esperanto eblas aldoni plurajn prefiksojn kaj sufiksojn
al vortoj, ne vere eblas listigi ĉiujn validajn verbojn. La
programo scias, ke iuj afiksoj neniam ŝanĝas transitivecon
(mal-, mis-, ek-, re-, fi-, ne-, -ad, -aĉ, -eg, -et). Do se
la vortaro indikas, ke la verbo «beli» estas netransitiva, la
programo bone trovos, ke la verbo «malbelegas» (mal-bel-eg-as)
estas ankaŭ netransitiva, êc se tiu verbo ne estas listigita en
vortaro. Por nekonata verbo kiel «malbelegas»,
la programo trovas ĝian radikon «beli». Ĉar «beli» estas listigita
kiel netransitiva verbo, Lingvoilo ĝuste donas netransitivan etikedon
al la vorto «malbelegas». La programo devas serĉi en la vortaro
antaŭ ol forigi prefikson/sufikson, ĉar kelkaj verboj havas
falsajn afiksojn (ekz.: «respond/i» kaj ne «re-spond/i»).
Estas ankaŭ alia listo de vortoj por ne fuŝe doni etikedon de
participoj (-at, -ant, vortoj). Tiu vortlisto estas bezonata
por ne doni etikedon de participo al vortoj kiel elefant-o
(kaj ne elef-ant-to!). Tiu listo de vortoj, kiu aspektas kiel
participoj, sed ne estas participoj estas en la dosiero
languagetool/src/rules/eo/root-ant-at.txt
La dosiero
languagetool/src/java/org/languagetool/tagging/eo/EsperantoTagger.java
enhavas la Ĝavao-fontkodon por aldoni etikedojn al vortoj.
4. Kongruo kun gramatikaj reguloj
Por atentigi pri gramatikaj eraroj, Lingvoilo listigas ŝablonojn
de oftaj eraroj. Tiu ŝablonoj estas difinitaj en la XML-dosiero
languagetool/src/rules/eo/grammar.xml.
Tiu XML-dosiero estas vere la kerno de la programo.
Kiam ajn frazo kongruas kun erarŝablono, la programo atentigas
pri eraro en la frazo. Estas multaj erarŝablonoj en Lingvoilo,
kaj la nombro de erarŝablonoj kreskadas por trovi pliajn erarojn
en Esperanta teksto.
Mi ne priskribos ĉi tie ĉiujn eblaĵojn por skribado de gramatikaj
XML-dosieroj de Lingvoilo. Por pli amplaksaj informoj,
vidu la retejon de LanguageTool.
Ni unue rigardu tre simplan gramatikan ŝablonon en la dosiero
languagetool/src/rules/eo/grammar.xml:
<rule id="ANSTATAUX_OL" name="anstataŭ + ol (anstataŭ)">
<pattern>
<token>anstataŭ</token>
<token>ol</token>
</pattern>
<message>Uzu <suggestion>\1</suggestion> (sen «ol»).</message>
<example type="incorrect">Li rezignis <marker>anstataŭ ol</marker> lerni la lingvon.</example>
<example type="correct">Li rezignis anstataŭ lerni la lingvon.</example>
</rule>
Tiu regulo estas unu el la plej simplaj gramatikaj reguloj en Lingvoilo.
Kion faras tiu regulo? Kiam ajn la sinsekvaj vortoj «anstataŭ ol»
aperas en frazo, Lingvoilo atentigas pri eraro, klarigas kial estas
eraro, kaj donas sugeston por korekti la eraron.
La ŝablono de la eraro estas ene de <pattern> … </pattern>
La ekzemplojn en la regulo helpas la programiston por klarigi tion, kion faras
la regulo. Tiuj ekzemploj (
<example … >) ne nur helpas komprenigi la
regulon, sed ili estas ankaŭ uzataj por aŭtomate testi la programon.
Alivorte, kiam oni lanĉas
ant test en komanda linio, la programo
kontrolas, ke ĉiu ekzemplaj frazoj kun
type="incorrect" ja
kaŭzas gramatikan eraron, kaj ĉiuj ekzemplaj frazoj kun
type="correct"
ja ne kaŭzas gramatikan eraron. La aŭtomata testado estas tre grava,
ĉar facilas fuŝi dum kreado de XML-reguloj! Kaj la ekzemploj tiam
plej ofte trovas cimojn.
Jen kiel Lingvoilo atentigas, se oni lanĉas Lingvoilon en komanda linio
kun erara frazo, kiu kongruas kun la ĉi-supra regulo:
$ echo "Li ludis anstataŭ ol studi." | java -jar languagetool/dist/LanguageTool.jar -c utf-8 -l eo -v
Expected text language: Esperanto
Working on STDIN...
259 rules activated for language Esperanto
<S> Li[li/R nak np] ludis[ludi/V tn is] anstataŭ[anstataŭ/P kak] ol[ol/_] studi[studi/V tr i].[</S>]<P/>
1.) Line 1, column 10, Rule ID: ANSTATAUX_OL[1]
Message: Uzu 'anstataŭ' (sen «ol»).
Suggestion: anstataŭ
Li ludis anstataŭ ol studi.
^^^^^^^^^^^
Time: 80ms for 1 sentences (12.5 sentences/sec)
Ni nun vidu alian (ankoraŭ simplan) regulon, kiu montras alian gravan eblon
en la XML-reguloj:
<rule id="MALGRAUX_V" name="malgraŭ + verbo">
<pattern>
<token>malgraŭ</token>
<token postag="V .*" postag_regexp="yes"/>
</pattern>
<message>Anstataŭ «\1 \2», oni uzas participon kun e-finaĵo, aŭ «kvankam», aŭ «\1 tio, ke + plenan subfrazon».</message>
<example type="incorrect"><marker>Malgraŭ fali</marker>, li batalis.</example>
<example type="correct">Malgraŭ tio, ke li falis, li batalis.</example>
<example type="correct">Kvankam li falfis, li batalis.</example>
</rule>
Ĉi tie, la dua ĵeteno en la ŝablono estas priskribita pere de
ĝia gramatika etikedo (postag) anstataŭ pere de vorto. Vorto,
por kiu ĝia gramatika etikedo kongruas kun "V .*" estas
verbo. Do tiu regulo atentigas pri eraro, kiam ajn estas verbo
post la vorto «malgraŭ». Rimarku, ke oni povas flekseble priskribi
tiun etikedon per regula esprimo.
Lingvoilo atentigas jene pri la eraro:
$ echo "Malgraŭ fali, li batalis." | java -jar languagetool/dist/LanguageTool.jar -c utf-8 -l eo -v
Expected text language: Esperanto
Working on STDIN...
259 rules activated for language Esperanto
<S> Malgraŭ[malgraŭ/P sak] fali[fali/V nt i],[,] li[li/R nak np] batalis[batali/V nt is].[</S>]<P/>
1.) Line 1, column 1, Rule ID: MALGRAUX_V[1]
Message: Anstataŭ «Malgraŭ fali», oni uzas participon kun e-finaĵo, aŭ «kvankam», aŭ «Malgraŭ tio, ke + plenan subfrazon».
Malgraŭ fali, li batalis.
^^^^^^^^^^^^
Time: 65ms for 1 sentences (15.4 sentences/sec)
Ni nun vidu iom pli malsimplan regulon, kiu montras aliajn eblaĵojn:
<rule id="LITERO_LETERO" name="Litero (Letero)">
<pattern mark_from="1">
<token skip="2" inflected="yes" regexp="yes">.*(adres|send|redakt|leg|ricev)i</token>
<token inflected="yes">litero
<exception scope="previous" regexp="yes">((mal)?(grand|et)aj?n)|(ĉin|japan)aj?n?</exception></token>
</pattern>
<message>Ĉu vi intencis <suggestion><match no="2" regexp_match="(.).(.*)" regexp_replace="$1e$2"/></suggestion> anstataŭ «\2»?</message>
<example type="incorrect">Mi dissendis la <marker>literon</marker>.</example>
<example type="correct">Mi dissendis la <marker>leteron</marker>.</example>
<example type="correct">Mi ne povas legi etajn literojn.</example>
</rule>
Tiu regulo atentigas pri verŝajna konfuzo inter la vortoj
«litero» kaj «letero» laŭ la kunteksto.
Ĉar en tiu regulo tute ne gravas, ĉu la unua vorto estas «sendi»,
aŭ «sendis», «sendos» (ktp.), pro tio la regulo kongruas kun la norma
radiko de la vorto uzante inflected="yes" anstataŭ kun la vorto mem.
Rimarku ankaŭ aliajn aferojn en tiu regulo:
- Regula esprimo (.*(adres|send|redakt|leg|ricev)i)
povas esti ankaŭ uzata por la vorto (dank’ al regexp="yes").
- Inteligenta substituo en la mesaĝo eblas dank’ al <match …>.
Tio ebligas la programon por bone korekti ŝanĝante «litero» en «letero»,
«literoj» en «leteroj», ktp.
- Uzo de skip="2" signifas, ke povas esti inter 0 kaj 2 aliaj vortoj
inter la verbo «adresi/sendi/redakti/legi/ricevi» kaj la vorto litero/literoj/literojn
en la kontrolenda teksto.
- Uzo de escepto en ŝablono: la regulo atentigas pri misuzo de la
vorto «litero» apud la verbo sendi/skribi (ktp.) krom tiam, kiam la vorto ĝuste antaŭ
la vorto «litero» estas io kiel «eta/ĉina/japana» (ktp.)
Tiu escepto esta por eviti neverajn
erarojn en frazo kiel «Mi ne povas legi etajn literojn.», kie la vorto
«litero» sufiĉe verŝajnas sen esti erara. Kompreneble, estas heŭristiko ĉi tie.
Plej verŝajne ekzistas frazoj, kie la programo atentigos
pri ĝusta frazo. Tamen, estas sufiĉe neverŝajna, kaj oni povas aldoni pliajn
esceptojn laŭ bezone por eviti neverajn erarojn.
Jen, kiel Lingvoilo atentigas en komanda linio pri tiu regulo:
$ echo "Mi ne ricevis vian literon." | java -jar languagetool/dist/LanguageTool.jar -c utf-8 -l eo -v
Expected text language: Esperanto
Working on STDIN...
259 rules activated for language Esperanto
<S> Mi[mi/R nak np] ne[ne/_] ricevis[ricevi/V tr is] vian[via/A akz np] literon[litero/O akz np].[</S>]<P/>
1.) Line 1, column 20, Rule ID: LITERO_LETERO[1]
Message: Ĉu vi intencis 'leteron' anstataŭ «literon»?
Suggestion: leteron
Mi ne ricevis vian literon.
^^^^^^^
Time: 72ms for 1 sentences (13.9 sentences/sec)
Eblas ankaŭ difini gramatikajn regulojn en Ĝavao anstataŭ XML,
sed ĝis nun, la Esperanta kontrolilo ne bezonis tiajn regulojn.
Vi nun scias preskaŭ ĉion pri Lingvoilo. La metodo de Lingvoilo certe
havas limojn, ĉar la programo ne vere analizas la gramatikan strukturon
de la frazoj. Tamen, kun sufiĉe da erarŝablonoj, la programo certe fariĝas
utila, sen troaj malveraj atentigoj.