languagetool-org / languagetool

Style and Grammar Checker for 25+ Languages
https://languagetool.org
GNU Lesser General Public License v2.1
12.04k stars 1.38k forks source link

[pt] Rewriting of rule ID:IR_CONTRACTION_NOUN #9303

Open marcoagpinto opened 1 year ago

marcoagpinto commented 1 year ago

Heya, @susanaboatto @p-goulart @jaumeortola @maphjo

While removing false positives in this rule, I noticed that I now have the knowledge to join both subrules into just one rule.

I will work on it during the weekend.

There is no reason for it to have redundant code now that I have the knowledge.

❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️

marcoagpinto commented 12 months ago

Heya,

I am going to start again from zero since it gives tons of false positives, and to fix them it requires countless and very complex antipatterns.

There must be an easier way of doing it.

Starting from zero.


        <rule id='IR_CONTRACTION_NOUN_V2' name="Ir + na/no + nome">
            <antipattern>
                <token postag='VMN0000' postag_regexp='no'/>
                <token regexp='yes' spacebefore='no'>&tracos_de_separacao;</token>
                <token regexp='yes' spacebefore='no'>&pronomes_obliquos_sem_a_as_o_os;</token>
                <token regexp='yes' spacebefore='no'>&tracos_de_separacao;</token>
                <token regexp='no' inflected="yes" spacebefore='no'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <example>O peão focar-se-ia no semáforo da estrada.</example>
                <example>As canções de Gitte manter-se-iam nas listas alemãs de discos nas décadas seguintes, apesar de não ter o mesmo sucesso como na década de 1960.</example>
                <example>Jataí e São Pedro de Alcântara transformar-se-iam na atual cidade de Jataizinho; São Jerônimo daria origem a Araporangas.</example>
            </antipattern>
            <antipattern>
                <token regexp='yes'>bom|m(?:au|esmo)</token>
                <token regexp='yes'>caminho|sentido</token>
                <example>Estamos a ir no bom caminho.</example>
                <example>Vamos no mesmo caminho.</example>
                <example>E ver os meus filhos felizes enche-me o coração e é a demonstração de que tudo vai no bom caminho.</example>
            </antipattern>
            <antipattern>
                <token inflected='yes'>ir
                    <exception regexp='yes'>foi|fora|indo</exception></token>
                <token regexp='yes'>n[ao]s?</token>
                <token regexp='yes'>&partes_do_dia;|&expressoes_de_tempo;</token>
                <token postag='RG|CS|CC|SPS00|(SPS00:)?[DP][ADIPRT].+|NC.+|AQ.+' postag_regexp='yes'/>
                <example>Foi aonde eu e meus pais fomos na noite que eles foram...</example>
                <example>Não posso ir na semana que vem.</example>
                <example>Se for no período da manhã, a primeira coisa que você vai dizer é bom dia.</example>
            </antipattern>
            <antipattern>
                <token inflected='yes'>ir
                    <exception regexp='yes'>foi|fora|indo</exception></token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+' postag_regexp='yes'/>
                <token postag='VMP00.+' postag_regexp='yes'/>
                <example>Você deveria ir na posição oposta.</example>
                <example>... "Phacochoerus" inclui duas espécies: "Phacochoerus africanus" e "Phacochoerus aethiopicus", que já foram no passado consideradas uma única espécie, e que ainda são consideradas sinónimos por alguns autores.</example>
            </antipattern>
            <antipattern>
                <token postag='CS|RG' postag_regexp='yes'/>
                <token regexp='yes'>fosse[ms]?</token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+' postag_regexp='yes'/>
                <example>Não o vejo com frequência, mas quando acontece, é como se fosse na faculdade.</example>
                <example>...u os trabalhadores embora, exigindo não ser perturbado e proibindo a entrada de quem quer que fosse na igreja.</example>
            </antipattern>
            <antipattern>
                <token>ainda</token>
                <token postag='Z0.+' postag_regexp='yes'/>
                <token inflected='yes'>ir
                    <exception regexp='yes'>foi|fora|indo</exception></token>
                <token regexp='yes'>n[ao]s?</token>
                <example>Ainda 2018 vai no início…</example>
            </antipattern>
            <antipattern>
                <token postag='UNKNOWN|NP.+|NC.+|AQ.+' postag_regexp='yes'/>
                <token regexp='yes'>foram?</token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+' postag_regexp='yes'/>
                <token regexp='yes'>d[ao]s?|de</token>
                <example>A partida e a chegada foram na Avenida da Europa (Viseu), e pelo meio os participantes tiveram uma subida à Serra do Caramulo.</example>
                <example>Alguns dos primeiros trabalhos de produção de Nottz foram na compilação da "Rawkus Records" no disco "Lyricist Lounge, Volume One", que foi lançado em 1998.</example>
                <example>Seus outros papéis de destaque foram na série de TV de espionagem (2010) e no drama romance Padam Padam (2011).</example>
                <example></example>
            </antipattern>

            <pattern>
                <token inflected='yes'>ir
                    <exception regexp='yes'>foi|fora|indo</exception>
                    <exception scope='previous' regexp='yes'>isso|xxxx</exception>
                </token>
                <marker>
                    <token regexp='yes'>n[ao]s?</token>
                </marker>
                <token min='0' max='1' postag='RG' postag_regexp='no'/>
                <token postag='NC.+|AQ.+' postag_regexp='yes'>
                    <exception regexp='yes'>adros?|almas?|áreas?|braços?|cabeças?|caminhos?|comboios?|contramão|direc?ç(ão|ões)|embalage(m|ns)|encalços?|fígados?|formas?|futuros?|listas?|lugar(es)|malas?|mentes?|metros?|metrôs?|mortes?|mesas?|partes?|postos?|propósitos?|rostos?|sentidos?|simultâneos?|tre(m|ns)|vidas?</exception>
                    <exception regexp='yes'>&dias_semana;|&dias_semana_abrev;|&expressoes_de_tempo;</exception>
                    <exception postag='(AO|Z).+|VMN0000' postag_regexp='yes'/>
                </token>
            </pattern>
            <message>Substitua por <suggestion><match no='2' postag='SPS00:DA0(..)0' postag_replace='SPS00:DA0$10'>a:o</match></suggestion>.</message>
            <example correction="à">Tenho de ir <marker>na</marker> praia.</example>
            <example correction="ao">Tenho de ir <marker>no</marker> ginásio.</example>
            <example>O menor número registrado foi na faixa etária entre 50 a 54 anos…</example>
            <example>Quem estabelece a % de incapacidade é o médico a que vou na sexta.</example>
            <example>Já vou na quarta versão.</example>
            <example>É o que lhe vai na alma.</example>
            <example>Já vou no último capítulo.</example>
            <example>A procissão ainda vai no adro.</example>
            <example>Isto vai no bom caminho.</example>
            <example>Já vai no segundo tempo, e ainda não houve desempate.</example>
            <example>- Vamos nos falar esta noite.</example>
        </rule>
marcoagpinto commented 12 months ago

Maybe a small fix would be to use only the verb “ir” and ignore common entries with the verb “ser”?

@ricardojosehlima

Sorry to disturb you, I have been since last night rewriting this rule, but it is extremely complex.

If I remove common words between verbs “ir” and “ser” will it fix most of the issues?

Is there an easy way?

Thanks!

marcoagpinto commented 12 months ago

I have been redesigning this rule from scratch.

I can't use the verb “ser” as an exception.

Currently, I am trying to create more powerful antipatterns to remove invalid words.

Only after all is removed with antipatterns, I will use static words for sentences that can't be removed with antipatterns.

This will take several days, so I am not sure when it will be ready.

This is the news.

p-goulart commented 11 months ago

@marcoagpinto This is a really tricky case. We already have a much more restrictive rule active, but it's only available for premium accounts. I remember that, in the process of writing it, we had many problems with suppletion, to the point that I needed to restrict matching of the rule to very restrictive contexts. For instance:

            <rule>
                <pattern>
                    <token postag="SENT_START"/>
                    <token postag_regexp="yes" postag="^[CRP].*" min="0" max="-1"/>
                    <token inflected="yes" postag_regexp="yes" postag="VM(I[SM]|S[IF]).+">ir</token>
                    <marker>
                        <token postag_regexp="yes" postag="SP.+">em</token>
                    </marker>
                    <token regexp="yes">\p{Lu}\p{Ll}+</token>
                </pattern>
                <message>O verbo de movimento &quot;ir&quot; exige a preposição &quot;a&quot; ou &quot;para&quot;.</message>
                <suggestion>a</suggestion>
                <suggestion>para</suggestion>
                <example correction="a|para">Fui <marker>em</marker> Varsóvia.</example>
                <!-- example from the original issue -->
                <example correction="a|para">Nunca fui <marker>em</marker> Bonito.</example>
                <example correction="a|para">Eu fui <marker>em</marker> Gdansk.</example>
                <example correction="a|para">Se eu fosse <marker>em</marker> Cuiabá.</example>
                <example correction="a|para">Ele fora <marker>em</marker> Riga já várias vezes antes.</example>
                <example correction="a|para">Se eu for <marker>em</marker> Los Angeles...</example>
                <example>Eu fui médico em Atlântis.</example>
            </rule>

Note how we're only checking for nouns starting with a capital letter. The idea here being that those are the only ones that, when preceded by 'em', are unambiguously referring to places. But this is a far for perfect solution. How about 'fui no ginásio' or 'fui na padaria'? The only reliable way of making this distinction is semantics.


There is no way of accounting systematically for the suppletive ir/ser forms (viz. VMIS, VMIM, VMSI, and VMSF) without some degree of semantic analysis:

foi no ginásio que foi demolido => [ele] foiir.IND.PST.3SG no ginásio que foisubject: 'ginásio' demolido foi no ginásio que foi recriminado => [impersonal] foiser.IND.PST.3SG no ginásio queonde, em que [ele] foi recriminado

I don't think we will ever be 100% satisfied with this rule, so please don't lose any sleep over this.

marcoagpinto commented 11 months ago

@p-goulart

Heya,

Thanks, I spent a few days or a week (can't remember) working on it full days.

But it all had to be done via antipatterns, and some antipatterns would only remove a couple or so of FPs.

I was on the good path, but would take weeks to have it fix most of the issues (countless antipatterns).

I will give it another try in a few weeks, there are other priorities.

If it doesn't become powerful, we could simply give up on it, like it has happened with some rules in the past.

p-goulart commented 11 months ago

If you want to do this, I suggest starting with verbs that *aren't** 'ir' – so other verbs of movement that don't share suppletive forms with 'ser'. Then add 'ser' and start adding antipatterns. Maybe?

marcoagpinto commented 11 months ago

@p-goulart

I became upset with the results from V2 and started from zero.

Before:

Portuguese (Portugal): 430 total matches
Portuguese (Portugal): 811110 total sentences considered
Portuguese (Portugal): ø0.00 rule matches per sentence

0_900000sentences_ALL.txt

After:

Portuguese (Portugal): 201 total matches
Portuguese (Portugal): 811110 total sentences considered
Portuguese (Portugal): ø0.00 rule matches per sentence

41_900000sentences_stable.txt

I was insanely testing APs one by one, but some only would only remove two or three FPs.

Here is the current code:

        <rule id='IR_CONTRACTION_NOUN_V3' name="Ir + na/no + nome">
        <!-- To do: remove verb "mercar" ("mercado") POS? It removes all valid entries with "mercado" -->
            <antipattern>
                <token postag='VMN0000' postag_regexp='no'/>
                <token regexp='yes' spacebefore='no'>&tracos_de_separacao;</token>
                <token regexp='yes' spacebefore='no'>&pronomes_obliquos_sem_a_as_o_os;</token>
                <token regexp='yes' spacebefore='no'>&tracos_de_separacao;</token>
                <token regexp='no' inflected="yes" spacebefore='no'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <example>O peão focar-se-ia no semáforo da estrada.</example>
                <example>As canções de Gitte manter-se-iam nas listas alemãs de discos nas décadas seguintes, apesar de não ter o mesmo sucesso como na década de 1960.</example>
                <example>Jataí e São Pedro de Alcântara transformar-se-iam na atual cidade de Jataizinho; São Jerônimo daria origem a Araporangas.</example>
            </antipattern>
            <antipattern>
                <token regexp='yes'>bom|m(?:au|esmo)</token>
                <token regexp='yes'>caminho|sentido</token>
                <example>Estamos a ir no bom caminho.</example>
                <example>Vamos no mesmo caminho.</example>
                <example>E ver os meus filhos felizes enche-me o coração e é a demonstração de que tudo vai no bom caminho.</example>
            </antipattern>
            <antipattern>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token regexp='yes'>&partes_do_dia;|&expressoes_de_tempo;</token>
                <token postag='RM|RG|CS|CC|SPS00|(SPS00:)?[DP][ADIPRT].+|NC.+|AQ.+|AO.+|Z0.+' postag_regexp='yes'/>
                <example>Foi aonde eu e meus pais fomos na noite que eles foram...</example>
                <example>Não posso ir na semana que vem.</example>
                <example>Se for no período da manhã, a primeira coisa que você vai dizer é bom dia.</example>
            </antipattern>
            <antipattern>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token min="1" max="2" postag='NC.+|AQ.+|NP.+' postag_regexp='yes'>
                    <exception postag='VMP00.+' postag_regexp='yes'/>
                </token>
                <token postag='VMP00.+' postag_regexp='yes'/>
                <example>Você deveria ir na posição oposta.</example>
                <example>... "Phacochoerus" inclui duas espécies: "Phacochoerus africanus" e "Phacochoerus aethiopicus", que já foram no passado consideradas uma única espécie, e que ainda são consideradas sinónimos por alguns autores.</example>
            </antipattern>
            <antipattern>
                <token postag='UNKNOWN|NP.+|NC.+|AQ.+|SENT_START|V.+|PI.+|PP3CN000|_PUNCT' postag_regexp='yes'/>
                <token min="0" max="1" postag='_PUNCT' postag_regexp='no'/>
                <and>
                    <token inflected='yes'>ir</token>
                    <token postag='VMI[MPS][23].+|VMSF.+' postag_regexp='yes'/>
                </and>
                <token regexp='yes'>n[ao]s?</token>
                <token min="1" max="2" postag='NC.+|AQ.+|NP.+' postag_regexp='yes'>
                    <exception postag='SPS00'/>
                </token>
                <token min="0" max="1" postag='_PUNCT' postag_regexp='no'/>
                <token postag='SPS00|SPS00:D[AI].+|SPS00:PP.+|CS|RG|NP.+|NC.+|AQ.+' postag_regexp='yes'>
                    <exception postag='CC'/>
                    <exception scope='next' inflected='yes'>estar</exception>
                </token>
                <example>A partida e a chegada foram na Avenida da Europa (Viseu), e pelo meio os participantes tiveram uma subida à Serra do Caramulo.</example>
                <example>Alguns dos primeiros trabalhos de produção de Nottz foram na compilação da "Rawkus Records" no disco "Lyricist Lounge, Volume One", que foi lançado em 1998.</example>
                <example>Seus outros papéis de destaque foram na série de TV de espionagem (2010) e no drama romance Padam Padam (2011).</example>
                <example>Sua última aparição naquele ano foi na comédia dramática de Rohit Dhawan, "Desi Boyz," ao lado de Akshay Kumar, John Abraham e Chitrangada...</example>
            </antipattern>
            <antipattern>
                <token postag='CS|RG|NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <and>
                    <token inflected='yes'>ir</token>
                    <token postag='VMSI.+' postag_regexp='yes'/>
                </and>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <example>Não o vejo com frequência, mas quando acontece, é como se fosse na faculdade.</example>
                <example>...u os trabalhadores embora, exigindo não ser perturbado e proibindo a entrada de quem quer que fosse na igreja.</example>
            </antipattern>
            <antipattern>
                <token postag='(SPS00:)?PD.+' postag_regexp='yes'/>
                <token min="0" max="1" postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <token min="0" max="1" postag='CS|xxxxxx' postag_regexp='yes'/>
                <token postag='V.+' postag_regexp='yes'/>
                <example>..., NA EVANGELIZAÇÃO DE RUA CASA POR CASA, GERALMENTE SÃO ESQUECIDAS AS CRIANÇAS, COMO QUE ESTAS IRÃO NO FUTURO DESPERTAR INTERESSE NESTA ÁREA TÃO ESQUECIDAS QUASE QUE NA SUA TOTALIDADE PELO POVO DE DEUS....</example>
            </antipattern>
            <antipattern>
                <token postag='CS|SENT_START' postag_regexp='yes'/>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token min="1" max="2" postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <token postag='CS|PR.+' postag_regexp='yes'/>
                <example>Parece que foi no paleolítico que o homem considerou o céu como o lugar onde as histórias dos deuses tomam forma.</example>
            </antipattern>
            <antipattern>
                <token postag='AO.+|DP.+' postag_regexp='yes'/>
                <token min='1' max='2' postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token min='0' max='1' postag='DP.+|RG' postag_regexp='yes'/>
                <token postag='NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <example>[4] Seu primeiro trabalho foi no clube suíço Blue Stars Zurich, na década de 1950, e seu último trabalho aconteceu em 2003, quando e...</example>
                <example>Meu primeiro invento foi na universidade.</example>
                <example>Sabe, meu primeiro beijo foi na série, há quatro anos.</example>
                <example>Seu segundo voo espacial foi na missão STS-132, que transportou o módulo russo de pesquisa Rassvet para instalação na estrutura da ...</example>
            </antipattern>
            <antipattern>
                <token postag='CS|xxxxxxxxxxxxxV.+' postag_regexp='yes'/>
                <token inflected='yes'>ir</token>
                <token regexp='yes'>n[ao]s?</token>
                <token min='1' max='2' postag='NC.+|AQ.+|NP.+' postag_regexp='yes'>
                    <exception postag='SPS00'/>
                </token>
                <token postag='SPS00|SPS00:D[AI].+' postag_regexp='yes'/>
                <token min='0' max='1' postag='D[AI].+|Z0.+' postag_regexp='yes'/>
                <token postag='SPS00|NC.+|AQ.+|NP.+' postag_regexp='yes'/>
                <example>Um de vocês terá que ir no núcleo do reator.</example>
                <example>Não me importa quem você é ou o que você faz, Tem noites que todo mundo tem que ir na parte de trás do congelador e tirar o que tenho aqui embaixo.</example>
                <example>Com isso, iremos personalizar um brinde que irá nas embalagens de uma marca de macarrão instantâneo.</example>
                <example></example>
                <example></example>
                <example></example>
                <example></example>
            </antipattern>

            <pattern>
                <token inflected='yes'>ir
                    <exception scope='previous' regexp='yes'>isso|xxxx</exception>
                </token>
                <marker>
                    <token regexp='yes'>n[ao]s?</token>
                </marker>
                <token postag='NC.+|AQ.+' postag_regexp='yes'>
                    <exception regexp='yes'>almas?|comboios?|direc?ç(ão|ões)|instintos?|malas?|mentes?|metros?|metrôs?|tre(m|ns)|vidas?</exception> <!-- List of words that antipatterns can't deal with -->
<!--
                    <exception regexp='yes'>adros?|áreas?|braços?|cabeças?|caminhos?|contramão|embalage(m|ns)|encalços?|fígados?|formas?|futuros?|listas?|lugar(es)||mortes?|mesas?|partes?|postos?|propósitos?|rostos?|sentidos?|simultâneos?|</exception>

-->
                    <exception regexp='yes'>&dias_semana;|&dias_semana_abrev;|&expressoes_de_tempo;</exception>
                    <exception postag='(AO|Z).+|V.+|SPS00|CC|CS|RG|I|RM|RN|(SPS00:)?[DP][ADIPRT].+|NP.+' postag_regexp='yes'/>

                </token>
            </pattern>
            <message>Substitua por <suggestion><match no='2' postag='SPS00:DA0(..)0' postag_replace='SPS00:DA0$10'>a:o</match></suggestion>.</message>
            <example correction="à">Tenho de ir <marker>na</marker> praia.</example>
            <example correction="ao">Tenho de ir <marker>no</marker> ginásio.</example>
        </rule>
marcoagpinto commented 10 months ago

I have it fully working.

It is the best it can get.

Minor things are the adding of words to the exception list.