Simple grammar checker

Spell checking


A text in any language needs first to be spell checked. Spell checking means, that each word will be compared against all correct words of a language. If the word matches any of these, then it is considered to be correct. Since for no language on earth exists a full collection of all possible words, this check is never hundred percent accurate, but in well maintained languages the accuracy is above 99%.

Grammar checking


If all the words are correct, this does not implicate, that the text is grammatically correct and/or understandable. Grammar checkers help to make sure, that the text is nearly perfect. A grammar checker usually checks:

  • Punctuation is correct, i.e. after punctuation space, and none before.

  • Sentences are not too long

  • A new sentence starts with upper case character

  • Identical words follow each other like "and and"

  • The right word is used on the right place like "of cause". This includes the mixing up of words, and use the improper word in a context.

  • The text obeys the grammatic rules of the language

Only to the last check, "The text obeys the grammatic rules of the language" is the usage of a complete word list of the used language necessary. This is a relatively time consuming procedure. For the first four items, a simple perl script can be used, that does those checks in a short time. If all that is done, the last, and time consuming step can be applied, if necessary.

Punctuation correction


The strategy for punctuation is, that a simple perl scripts corrects punctuation errors before testing:

--------------------------------------------------------------------

  open(FILE, $pageName) or die "$!";
     open(FILE1, ">".$pageName."~") or die "$!";
          while ( $mline = < FILE> ) {
         while($mline =~ / ,/gi){
            $mline =~ s/ ,/, /gi;
         }
         while($mline =~ / \./gi){
            $mline =~ s/ \./\. /gi;
         }
         while($mline =~ / :/gi){
            $mline =~ s/ :/: /gi;
         }
         while($mline =~ / ;/gi){
            $mline =~ s/ ;/; /gi;
         }
         while($mline =~ / !/gi){
            $mline =~ s/ !/! /gi;
         }
         while($mline =~ / \?/gi){
            $mline =~ s/ \?/\? /gi;
         }
         while($mline =~ /  /gi){
            $mline =~ s/  / /gi;
         }
         print FILE1 $mline;
            }
    close(FILE);
    close(FILE1);
    # copy corrected file back
       open(FILE, $pageName."~") or die "$!";
      open(FILE1, ">".$pageName) or die "$!";
             while ( $mline = < FILE> ) {
         print FILE1 $mline;
            }
    close(FILE);
    close(FILE1);


--------------------------------------------------------------------

Word mixup-check


For mixed up words a simple set of regular expressions can be set up. The strategy is, that in case of mix-up the more seldom used word will be matched, and flagged, as potential error. If both occur about the same often, then both will be flagged. For sequences the following regular expression can be used:
word1 AND NOT word2, for example of course has to be flagged:

(^| )of cause( |,|:|;)< mix up of 'of cause' and 'of course'

or (of and NOT 'course'):
(^| )of([^ ]| [^c]| c[^o]| co[^u]| cou[^r]| cour[^s]| cours[^e])< mix up of 'of cause' and 'of course'

A sample set of regular expressions for the Hungarian language looks as follows:

#
# Hungarian rules
# format: rule< comment
# '< ' is the separation character between
# rule and comment
#
(^| )alakján( |,|:|;)< alakján és alapján keverése
(^| )az tán( |,|:|;)< az tán és aztán keverése
(^| )egyenlőre( |,|:|;)< egyelőre és egyenlőre keverése
(^| )fegyverzet( |,|:|;)< fegyverzet és fegyverzett keverése
(^| )fűl( |,|:|;)< fül, fűl keverése
(^| )irt( |,|:|;)< irt és írt keverése
(^| )hason ló < hason ló és hasonló keverése
(^| )jelentősség.*? < jelentőség és jelentősség keverése
(^| )kellet( |,|:|;)< kellet és kellett keverése
(^| )keltős.*? < keltős és kettős keverése
(^| )kiadta < kiadta és kiadó keverése
(^| )kicsiket < kicsiket és kicsikét keverése
(^| )kicsikét < kicsiket és kicsikét keverése
(^| )kór.*? < kór és kor keverése
(^| )kölcsönösén( |,|:|;)< kölcsönösen és kölcsönösén keverése
(^| )kűrt.*? < kürt és kürt keverése
(^| )lene( |,|:|;)< lene és lenne keverése
(^| )meg van( |,|:|;)< megvan és meg van keverése
(^| )mellet( |,|:|;)< mellet és mellett keverése
(^| )mindenek([^ ]| [^e]| e[^l]| el[^ő]| elő[^t]| előt[^t])< mindenek és mindennek keverése
(^| )modem.*? < modem és modern keverése
(^| )mér( |,|:|;)< miért és mér keverése
(^| )mért( |,|:|;)< mért és miért keverése
(^| )nem legyen( |,|:|;)< ne legyen helyett nem legyen
(^| )nemzettség.*? < nemzetség helyet nemzettség
(^| )siketül.*? < siketül, sikerül keverése
(^| )szemel( |,|:|;)< szemel, szemmel keverése
(^| )szűkség.*? < szükség és szűkség keverése
(^| )tejes.*? < teljes és tejes keverése
(^| )tolla.*? < tolla és tolta keverése
(^| )tőrök.*? < török és tőrök keverése
(^| )viasza( |,|:|;)< viasza és vissza keverése
(^| )ált( |,|:|;)< ált és állt keverése
(^| )átló.*? < átló és álló keverése
(^| )álló.*? < ált és állt keverése
(^| )áru árú( |,|:|;)< áru és árú keverése
(^| )épen( |,|:|;)< éppen és épen keverése
(^| )őrökké( |,|:|;)< örökké és őrökké keverése
(^| )a (a|á|e|é|í|o|ó|u|ú|ö|ő|ü|ű|Á|É|Í|Ó|Ú|Ő|Ű|Ö|Ü).*? < a után magánhangzóval kezdődő szó
#[^,] (hogy |de |ahogy.*? |aki.*? |ami.*? |amely.*? |hiszen |mert )< hogy előtt vessző
[^(,|.)] (hogy |hiszen |mert )< hogy, hiszen, mert előtt vessző
-----------------------

The perl program that uses the above file, looks:
-----------------------------------

#!/usr/bin/perl -w
#
# perl xml1.pl languagetool_root file_to_be_checked language (hu, de, en)
#

my ( $line1, $oline,$sline, $apos, $cut, $rule, $comment, $i, $mpos); my @array = (); my @rules = (); my @comments = (); $apos = 0; $cut = 0;

# print $ARGV[0].' ools/'.$ARGV[2].'rule.txt', "\n"; open(RULES, $ARGV[0].' ools/'.$ARGV[2].'rule.txt') || die "Can't open ".$ARGV[2]."rule.txt"; while($line1 = < RULES>){ if(substr($line1,0,1) ne '#'){ chop($line1); if(length($line1) > 2){ ($rule, $comment) = split('< ',$line1); push(@rules, $rule); push(@comments, $comment); } } } close RULES;

open(FILE, $ARGV[1]); $apos = 0; while($line1 = < FILE>){ $oline = $line1; $i = 0; foreach $rule (@rules){ $sline = $line1; while ($line1 =~ m/$rule/gi){ $mpos = $apos +$cut + pos($line1)-length($&); if($mpos < 0) {$mpos = 0;} print "", $mpos," ",$apos+$cut+pos($line1)," ",$comments[$i],"\n" ; $cut = $cut + pos($line1); $line1 = substr($line1, pos($line1)); } # line match $line1 = $sline; $i++; $cut = 0; } # rules $apos = $apos + length($oline); $cut = 0; } close(FILE);


------------------------
and the shell script that applies the perl scipt looks:
-------------------------
#
# posi.sh creates sorted error file for coloring KLSpell
# first parameter: languagetool's home directory
# second parameter: pathname of file to be checked
# third parameter: language (en, de or hu)
# result goes into languagetool ools/checkout.txt
# calling example:
#sh posi.sh #/mnt/win_d/hattyu yuk/dtest/python/danielnaber/cvs3/languagetool #/home/en yuk/dtest/qt/examples/richedit2/lang/work/chk.txt
#
# this file will be used by TKLSpell
#
cd $1
base=`basename $2`
perl $1 ools/xml1.pl $1 $2 $3 > mp/1_$base
sort -n mp/1_$base >$1 ools/checkout.txt
rm -f mp/1_$base
--------------------------