fredag 16 juli 2010

PP3 del II

(flyttat från siderespector)

Hackade en del på min ersättare till PP3, men hamnade i de klassiska språksvårigheterna: om man vill göra en parser för ett flexibelt kartspråk måste man ha en parser med lookahead. Nu hade jag skapat en simpel UTF-8-variant av de i C vanligt förekommande primitiva funktionerna fgetc och ungetc, vilket är ett kuggproblem: man läser in snuttar från en till sex st 8-bitars char men funktionerna producerar en 32-bitars int som representerar ett utökat tecken drygt täckande in fulla Unicode. En ungetc måste man göra om man läser in ett tecken som man inte tänker sig att använda i den nuvarande operationen: om man till exempel håller på att samla ihop tecken till ett ord bestående av bokstäver allena, låt oss säga "Ανδρομέδη", och vi samlar ihop tecken till och med "η" och därefter finner ".", då vill vi använda hela "Ανδρομέδη" till ordet - dock ej "." - men vi vill heller inte bara kasta bort ".", eftersom den används i texten som en annan senare tecken-grupp bestående av ett tecken. Således måste vi lägga tillbaka tecknet, men i min UTF-8-klon av ungetc kan jag inte utnyttja min fil att skriva tillbaka på eftersom man i C-filer endast kan skriva tillbaka ett enda 8-bitars-tecken, och sannerligen inte en till sex 8-bitars-tecken. Om jag nu förresten har ett 32-bitars så vill jag hellre spara undan denna, inte backa tillbaka ett större antal 8-bitars-tecken och i min första version av ungetc använde jag helt enkelt en variabel att spara undan på. Det gick alldeles utmärkt ett tag tills jag med hjälp av dessa ville bygga en ordläsarfunktion fgetw med vilken man kan läsa hela ord åt gången och på samma sätt som ovan göra en motsvarande tillbakaskrivningsfunktion ungetw! Då måste jag ge alldeles för många argument till dessa fgetw och ungetw, en för att spara undan ett 32-bitars-tecken, en för att spara undan ett helt ord. Det är sådant som gör att man relativt snabbt kör fast i quick-n-dirty-programmering. Jag fick göra en helt ny typ av fil i form av en struct där det finns både återsparningsplatser för ett 32-bitars-tecken och ett helt ord. Det ser ut sålunda:
typedef struct _token_file_S {
    /* specialized token file allowing token get and unget */
    FILE *tok_file;
    uchar uchar_lah;
    token *tok_lah;
} token_file;
men detta strider, i viss mån mot den allmänna Unix-principen KISS, Keep It Simple and Stupid. Dessutom är det en osund tanke att både ha sparningsplats för enstaka 32-bitars-tecken och hela ord i samma filtyp! Ett "rent och vackert" program skall i stället ha
typedef struct _utf8_file_S {
    /* specialized token file allowing token getuc and ungetuc */
    FILE *_file;
    uchar uchar_lah;
} utf8_file;
med sina "metoder" och
typedef struct _token_file_S {
    /* specialized token file allowing token getw and ungetw */
    utf8_file *tok_file;
    token *tok_lah;
} token_file;
med sina "metoder" - vilket dubblerar antalet funktioner och filstructar, men gör koden "återanvändbar" - ren och klar och tyvärr oöverskådlig.

Inga kommentarer: