Detta är en artikel i serien ”Antik datateknik”.
Jag kommer i denna artikel att visa hur jag enkelt kan skapa en svenskspråkig variant av programmeringsspråket C, språket kallar jag sv och kompilatorn blir då csv. Notera att avsikten med denna övning är att illustrera hur enkelt det vore att erbjuda en nationell nybörejarplattform för unga programmerare. För att verifiera programspråket sv skriver jag ett program som läser in en textsträng och sänder resultatet som morsekod. Morsekoden visas också i textform. Följande steg blir att undersöka vilka förändringar jag behöver göra i koden för att programmet skall fungera på min emulerade minidator PDP11/70 som kör en gammal BSD Unix 2.11 från början av 1990-talet. Unix utvecklades i tiden på minidatorn PDP11 som klarade av att hatera flera användare på olika terminaler allt detta på en maskin med 4 MB (4 miljoner byte) minne. En modern hemdator har typiskt 2000 gånger mera minne … eller ännu mer.
Kompilering av ett program skrivet i sv görs på någon sekund. Jag kompilerar morsesändaren smorse.sv dock utan filtyp eftersom mitt kompileringsskript förenklas en aning om jag inte behöver kontrollera filtypen utan kan anta att användaren vet vad hen gör.
./csv smorse
Källkod:smorse.sv
Översättaren är definierad i swe.lex
Kompilerar översätteren swe.lex till c-kod
Kompilerar lex analysatorn till körbar maskinkod: sv
Översätter sv-programmet smorse.sv till c-kod: smorse.c
C-kod finns nu i smorse.c
Kompilerar nu till körbar maskinkod!
The executable is: smorse.run
Jag kan nu köra programmet med smorse.run

Texten nedan visar hur ”kompilatorn” för språket sv är konstruerad. Jag skriver därefter programmet smorse i språket sv för att verifiera att kompileringen fungerar. Notera att programmet på min Linux-dator genererar hörbar morsekod. PDP11 har inte ljudstöd varför jag tänker generera ett simulerat magnetband som huvuddatorn kan sända som ljud.
En elev som lär sig att programmera kommer att stöta på flera samtidiga utmaningar. Vid programmering dyker det upp nya begrepp såsom ”variabel”, ”fil”, ”adress” och många andra begrepp som inte är bekanta från vardagslivet. Eleven lär sig också ett nytt språk, mycket enkelt dock, som beskriver logiken i programmet. Det språk som ligger under de flesta programmeringsspråk idag är engelska. Om vi börjar undervisa tex. en 10-12 årig elev programmering så kan engelskan som sådan vara ett visst problem som kan göra det svårare för eleven att komma över den första tröskeln in i programmeringens värld.
En enkel lösning på problemet programmering på ett främmande språk är naturligtvis att vi i inledningsaskedet skulle låta eleverna programmera på svenska/finska/norska/estniska för att därefter då grunderna finns gå över till engelska som idag är en de facto standard.
Skulle programmering på t.ex. svenska kräva våldsamma ekonomiska resurser? Är inte utveckling av ett nytt programmeringsspråk samt kompilator för det ”nya” språket extremt dyrt? Svaret är att en enkel tvåstegskompilator kan skrivas i ungefär hundra rader kod … inte dyrt alltså!
Om någon läsare är intresserad av att experimentera med språket sv eller modifiera det för något annat språk så kan det löna sig att ta kontakt via en kommentar så skickar jag alla filerna som ett paket med epost. Jag gör inte dessa förfrågningar synliga. Programlistningar på vebben tenderar att vara opålitliga vilket kan leda till onödig felsökning om man kopierar koden direkt från skärmen.
Språket ”sv” samt kompilatorn ”csv”
Min emulerade PDP11/70 minidator kör idag på mitt arbetsbord och jag måste således hitta på något vettigt leksaksprojekt. Jag kör BSD Unix v2.11 på PDP11:an vilket betyder att jag har tillgång till i princip samma programmeringsverktyg som på min huvuddator d.v.s. en kompilator för språket ”c” (kompilatorn heter cc) samt verktyget lex (lex har jag använt mycket sällan).
Ett trevligt miniprojekt kunde då vara att skapa ett svenskt programmeringsspråk som strukturellt är identiskt med programmeringsspråket ”c” under Unix/Linux. Tanken är att det skall vara möjligt att koda helt i ”sv” eller koda i en hybridmiljö där det är möjligt att använda ”c” direkt utan att programmets funktion påverkas. Tanken är att översätta ”sv” till normalt ”c” som därefter kompileras till maskinspråk som vilket normalt c-program som helst.
Fördelen med att använda c som mellanliggande språk är naturligtvis at jag inte behöver skriva den egentliga kompilatorn och maskinkodsgeneratorn (jag har för många år sedan skrivit ett komplett programmeringsspråk ”sil=simple language). Problemet är alltså att skriva en översättare från
språket sv till språket c.
Unix ger tillgång till två klassiska verktyg för att skapa kompilatorer
lex (lexical analyzer) och yacc (yacc=yet another compiler compiler). Jag har aldrig tidigare aktivt använt någondera. Programmet ”lex” kan enkelt sköta översättningen från sv till c d.v.s. jag behöver inte yacc eftersom min kompilator redan finns under förutsättning att det program lex producerar förmår att skapa kompilerbar c-kod.
Jag definierar ett antal ”REGLER” i lex som beskriver hur t.ex. ett nyckelord, en kommentar, en textsträng o.s.v. definieras. Då en regel passar in på källtexten skriver mitt genererade analysatorprogram ut motsvarande element för språket c.
Då jag skriver min översättare från sv till c i lex blir programmets längd ungefär hundra rader kod d.v.s. programmet är väldigt litet och överskådligt. Mitt sv-språk är i detta skede ett subset av språket c men redan i nedanstående form kan man skriva riktiga program i sv. Språket kan enkelt utvidgas genom att modifiera filen swe.lex. Då jag använder lex för att kompilera min definition av sv blir resultatet ett c-program som heter lex.yy.c . Jag kompilerar därefter lex.yy.c till ett körbart program sv som sköter översättningen av en källkodsfil i sv till motsvarande c-program.
Lex-program för översättning av sv till c
Filen swe.lex kan enkelt modofieras så att en större del av c-språket stöds. Notera att jag har skrivit swe.lex så att resulterande c-filen som ett sv-program översätts till har exakt samma antal rader som källkoden i sv. Detta betyder att då jag kompilerar mitt sv program så stämmer radnumren för felmeddelanden för både sv och c.
Min definition av sv-språket ser ut på följande sätt:
%{ /* A lexical analyzer for the computer language "sv". This is a simple translation */ /* of the "c" language into swedish. The corresponding "compiler" translates a */ /* sv-source into c-language that can be compiled using an ordinary c-compiler */ /* need this for the call to atof() below */ #include <math.h> /* need this for printf(), fopen() and stdin below */ #include <stdio.h> %} WHITESPACE [ \t\n]+ DIGIT [0-9] ID [a-zA-Z][a-zA-Z0-9]* CHAR [a-zåäö][A-ZÅÄÖ][0-9][\ ][!?][\n] COMMENT \/\/.*[\n] STR1 \".[\\]*\" APP [\"] LPAR [(] RPAR [)] LWAV [{] RWAV [}] TERMINATOR [;] EXCL [!] AE [Ä] ae [ä] Aring [Å] aring [å] COMMA [,] %% {DIGIT}+ printf("%d",atoi(yytext)); {DIGIT}+"."{DIGIT}* printf("%s", yytext); {STR1} printf("%s",yytext); {LPAR} printf("%s",yytext); {RPAR} printf("%s",yytext); {LWAV} printf("%s",yytext); {RWAV} printf("%s",yytext); {EXCL} printf("!"); {COMMA} printf(","); #inkludera printf("#include"); #definiera printf("#define"); program printf("\nmain"); funktion printf(" "); resultat printf("return "); alternativ printf("switch"); valt printf("case "); bryt printf("break"); om printf("if "); medan printf("while"); upprepa printf("for"); annars printf("else "); skrivf printf("printf"); skrivr printf("printf"); fskrivf printf("fprintf"); hämtarad printf("getline"); hämta printf("get"); sätt printf("put"); läs printf("read"); läsrd printf("readln"); dröj printf("delay"); heltal printf("int "); tecken printf("char "); byte printf("byte "); sanningsvärde printf("boolean "); register printf("int"); bitmask printf("int"); likamed printf("=="); mindre_än printf("<"); mindre_än_eller_likamed printf("<="); större_än printf(">"); större_än_eller_likamed printf(">="); och printf("&&"); binär_och printf("&"); and printf("&"); or printf("|"); xor printf("^"); binär_exclusiv_och printf("^\n"); vflytta printf("<<"); hflytta printf(">>"); storlek_t printf("size_t"); \<\< printf("<<"); \>\> printf(">>"); = printf("="); \< printf("<"); \> printf(">"); \. printf("."); \&\& printf("&&"); \& printf("&"); {ID} printf("%s", yytext); {TERMINATOR} printf("%s",yytext); {COMMENT} printf("%s",yytext); {WHITESPACE} printf("%s",yytext); "+"|"-"|"*"|"/" printf("%s", yytext); "{"[^}\n]*"}" /* eat up one-line comments */ %% int main(int argc, char *argv[]) { ++argv, --argc; /* skip over program name */ if (argc > 0) yyin = fopen(argv[0], "r"); else yyin = stdin; yylex(); return(0); }
Verifiering av språket ”sv”
Ett enkelt sätt att visa att det nya språket ”fungerar” är naturligtvis att skriva ett riktigt program i
programspråket sv. Jag byggde för kanske tjugo år sedan några led-ficklampor med några barnhemsbarn där vi använde en liten mikroprocessor som programmerades i mitt språk ”sil” (simple language) för Microchips processor 16F84. Ficklamporna programmerades så att de olika barnens ficklampor kunde blinka ägarens namn i morsekod.
Nedan visar jag hur man kan skriva ett program i språket sv som läser in en textrad från användaren och
”sänder” texten som morsekod till skärmen men också som morseljud via datorns högtalare. Jag kommer att flytta programmet till PDP11 och något modifiera det så att PDP11 som saknar högtalare i stället skickar ett magnetband till huvuddatorn för sändning, detta beskrivs eventuellt i en senare artikel.
Morsesändare skriven i sv
En morseöversättare gör man enklast så att man tabellerar tecknen ”A-Z”, ”a-z” samt siffrorna 0-9 samt deras motsvarande teckenkoder. För en specifik bokstav vill vi alltså ha en översättarfunktion skrivMorse() av ungefär följande typ (ti=’*’ och taa=’-‘):
heltal skrivMorse(tecken c){
heltal i;
tecken morse[16];
alternativ (c){
valt ‘a’: strcpy(morse, ”-”); bryt;
valt ‘b’: strcpy(morse,”-”); bryt;
valt ‘c’: strcpy(morse,”–”); bryt;
valt ‘d’: strcpy(morse,”-”); bryt;
valt ‘e’: strcpy(morse,”*”); bryt;
…
}
skrivf(”Morsekod:%s\n”,morse);
…
Som indata till vår funktion ”skrivMorse” ges ett tecken/en bokstav ”c” vid anrop till funktionen. Resultatet av översättningen finns efter exekvering nu i variabeln ”morse”. Jag antar att funktionen är ganska läslig även för personer som inte kan programmera. Nyckelordet ”bryt” betyder att rätt alternativ hittades och exekveringen fortsätter vid ”skrivf(…). Om vi vill översätta bokstaven ”s” till morse så anropar vi vår funktion med:
skrivMorse(‘s’);
Resultatet skulle bli Morsekod:***
Vi börjar vårt egentliga program med att låta programmet be om en text att sända samt läsa in en textrad som innehåller texten. Funktionen skrivf() skriver ut text som kan formatteras för heltal, flyttal etc. Vi kan göra detta med:
skrivf(”Skriv text att sända som morse:”);
l=hämtaRad(&line,&len,stdin);
Kommandot ”hämtaRad” använder biblioteksfunktionen ”getline” som finns definierad i biblioteket stdio.h. Vi måste då komma ihåg att deklarera att vi använder biblioteket stdio.h . Vi inkluderar ett standardbibliotek med:
#inkludera <stdio.h>
Vårt program har nu ungefär följande utseende och det utför inte ännu något vettigt :
#inkludera <stdio.h>
#inkludera <stdlib.h>
#inkludera <string.h>
heltal skrivMorse(tecken c){
heltal i;
char morse[16];
alternativ (c){
valt ‘a’: strcpy(morse, ”-”); bryt;
valt ‘b’: strcpy(morse,”-**”); bryt;
… fler definitioner av morsekoder …
}
}
heltal program(){
heltal l=0;
storlek_t len=0;
tecken *rad=NULL;
skrivf(”Skriv text att sända som morse:”);
l=hämtarad(&rad,&len,stdin);
// Skriv ut den lästa raden för att verifiera att inläsningen lyckades
skrivf(”Inläst rad:%s\n”,rad);
}
Variablerna l, len och *rad behövs för anropet till hämtarad().
Då vi skriver in vår text som skall skickas så vill vi gärna hantera texten ordvis d.v.s. vi skickar ett ord i taget och genererar en standardiserad paus mellan orden. För att splittra up vår textsträng i separata ord inkluderar vi biblioteket string (#inkludera <string.h> se ovan). String-biblioteket har en användbar funktion strtok() som splittrar upp den text vi ger som funktionsparameter i en tabell med separata textsträngar (ordsträngar) separerade med mellanslag ‘ ‘. Råtexten bryts alltså vid mellanslag. Jag splittrar upp den ingående råtexten genast då jag deklarerar ordtabellen som jag kallar ett_ord:
tecken *ett_ord = strtok(rad,” ”);
Om jag har matat in texten ”Lasse skickar morse” så kommer ett_ord efter anrop att innehålla textsträngar som jag kommer åt med:
ett_ord[0] = ”Lasse”
ett_ord[1] = ”skickar”
ett_ord[2] = ”morse”
Vi kan nu skriva en ny funktion som vi kallar skicka_text_som_ord(”någon text …”) .
heltal skicka_text_som_ord(tecken rad[]){
heltal i;
tecken *ett_ord = strtok(rad,” ”);
medan (ett_ord != NULL){
skrivf(”Ord=%s\n”,ett_ord);
upprepa(i=0; i<strlen(ett_ord);i++){
// Skriv ett tecken i nuvarande ord
skrivMorse(ett_ord[i]);
system(teckenpaus);
skrivf(”\n”);
}
skrivf(”\n”);
ett_ord = strtok(NULL, ” ”);
}
}
Efter att vi splittrade upp råtexten i ord så tar vi ett ord i taget och splittrar upp det i bokstäver som skickas för konvertering till morse.
Vi går igenom alla orden i vår råtext med:
medan (ett_ord != NULL){
skrivf(”Ord=%s\n”,ett_ord);
…
}
Motsvarande konstruktion i språket c är ”while(ett_ord != NULL){ … }” .
Vi skickar vidare orden för sändning så länge som ett_ord inte är tomt (NULL).
Vi lägger nu till en slinga för att skicka iväg varje ord bokstav för bokstav för översättning till morse och sändning. Slingan har följande utseende:
upprepa(i=0; i<strlen(ett_ord);i++){
// Skriv ett tecken i nuvarande ord
skrivMorse(ett_ord[i]);
system(teckenpaus);
skrivf("\n");
}
Vi använder konstruktionen ”upprepa” som motsvarar c-språkets ”for” slinga.
Slingan går igenom ordsträngen ett_ord bokstav för bokstav tills vi har nått den fulla längden på strängen ett_ord.
Slingan stegar alltså igenom ett_ord på följande sätt:
i=0 ett_ord[i] = ‘L’ som skickas till skrivMorse(‘L’)
i=1 ett_ord[i] = ‘a’ som skickas till skrivMorse(‘a’)
i=2 ett_ord[i] = ‘s’ som skickas till skrivMorse(‘s’)
i=3 ett_ord[i] = ‘s’ som skickas till skrivMorse(‘s’)
i=4 ett_ord[i] = ‘e’ som skickas till skrivMorse(‘e’)
Efter att vi har skickat ett helt ord så håller vi paus genom att anropa operativsystemets funktion sleep.
Vi låter systemet sova i 0.7 sekunder mellan ord. Sovtiden mellan bokstäver är 0.1 sekunder.
Vi spelar upp ”tit” och ”taa” under Linux så att jag med hjälp av programmet ”Audacity” genererade en ton med frekvensen 880 Hz. Från denna ton klippte jag två stumpar 0.1 repektive 0.3 sekunder långa som jag sparade som ljudfilerna 0_1.wav samt 0_3.wav . Jag kan spela upp en wavfil under Linux med hjälp av programmet ”aplay”.
Programmet i dess helhet (under linux i detta skede) har då följande utseende:
// Morse // Programspråket "sv" är språket "c" med svenska kommando-ord. // Språket översätts till standard "c" som sedan kompileras till maskinspråk // för att köras. // Språket "sv" är egentligen ett experiment med Unixverktyget "lex" som // har konstruerats för att känna igen ord och strukturer i en text. // Strukturer som hittas skulle normalt skickas vidare till programmet "yacc" // (yet another compiler compiler = en annan kompilator kompilator). // Eftersom jag översätter språket "sv" till "c" så behöver jag inte // någon kompilator eftersom denna redan finns och likaså behöver jag inte // någon kodgenerator som skulle generera maskinspråk eftersom även den redan // finns. Notera att jag kan använda c-språk direkt om motsvarande // sv-konstruktion inte har definierats. // Notera att endast en delmängd av SV-C har skrivits. // Vill man ha en mera fullständig // motsvarighet så måste filen swe.lex utvidgas med nya nyckelord. // Jag kör för närvarande en emulerad minidator PDP11/70 från 1970-talet. // Operativsystemet är BSD Unix 2.11. // Detta är ett experiment i att skriva ett enkelt svenskt // programmeringsspråk som är körbart på denna urgamla dator. // // Lars Silen 2022 // Detta är öppen källkod som fritt får distribueras // Författaren tar inget ansvar för eventuella fel i genererad kod #inkludera <stdio.h> #inkludera <stdlib.h> #inkludera <string.h> // Definiera tidslängden på olika element i Morse tecken teckenpaus[] = "sleep 0.1"; tecken ordpaus[] = "sleep 0.7"; heltal skrivMorse(tecken c){ heltal i; char morse[16]; alternativ (c){ valt 'a': strcpy(morse, "*-"); bryt; valt 'b': strcpy(morse,"-***"); bryt; valt 'c': strcpy(morse,"-*-*"); bryt; valt 'd': strcpy(morse,"-**"); bryt; valt 'e': strcpy(morse,"*"); bryt; valt 'f': strcpy(morse,"**-*"); bryt; valt 'g': strcpy(morse,"--*"); bryt; valt 'h': strcpy(morse,"****"); bryt; valt 'i': strcpy(morse,"**"); bryt; valt 'j': strcpy(morse,"*---"); bryt; valt 'k': strcpy(morse,"-*-"); bryt; valt 'l': strcpy(morse,"*-**"); bryt; valt 'm': strcpy(morse,"--"); bryt; valt 'n': strcpy(morse,"-*"); bryt; valt 'o': strcpy(morse,"---"); bryt; valt 'p': strcpy(morse,"*--*"); bryt; valt 'q': strcpy(morse,"--*-"); bryt; valt 'r': strcpy(morse,"*-*"); bryt; valt 's': strcpy(morse,"***"); bryt; valt 't': strcpy(morse,"-"); bryt; valt 'u': strcpy(morse,"**-"); bryt; valt 'v': strcpy(morse,"***-"); bryt; valt 'w': strcpy(morse,"*--"); bryt; valt 'x': strcpy(morse,"-**-"); bryt; valt 'y': strcpy(morse,"-*--"); bryt; valt 'z': strcpy(morse,"--**"); bryt; // Lägg till ÅÄÖ här om du behöver dem valt 'A': strcpy(morse, "*-"); bryt; valt 'B': strcpy(morse,"-***"); bryt; valt 'C': strcpy(morse,"-*-*"); bryt; valt 'D': strcpy(morse,"-**"); bryt; valt 'E': strcpy(morse,"*"); bryt; valt 'F': strcpy(morse,"**-*"); bryt; valt 'G': strcpy(morse,"--*"); bryt; valt 'H': strcpy(morse,"****"); bryt; valt 'I': strcpy(morse,"**"); bryt; valt 'J': strcpy(morse,"*---"); bryt; valt 'K': strcpy(morse,"-*-"); bryt; valt 'L': strcpy(morse,"*-**"); bryt; valt 'M': strcpy(morse,"--"); bryt; valt 'N': strcpy(morse,"-*"); bryt; valt 'O': strcpy(morse,"---"); bryt; valt 'P': strcpy(morse,"*--*"); bryt; valt 'Q': strcpy(morse,"--*-"); bryt; valt 'R': strcpy(morse,"*-*"); bryt; valt 'S': strcpy(morse,"***"); bryt; valt 'T': strcpy(morse,"-"); bryt; valt 'U': strcpy(morse,"**-"); bryt; valt 'V': strcpy(morse,"***-"); bryt; valt 'W': strcpy(morse,"*--"); bryt; valt 'X': strcpy(morse,"-**-"); bryt; valt 'Y': strcpy(morse,"-*--"); bryt; valt 'Z': strcpy(morse,"--**"); bryt; // Lägg till åäö här om du behöver dem valt '1': strcpy(morse,"*----"); bryt; valt '2': strcpy(morse,"**---"); bryt; valt '3': strcpy(morse,"***--"); bryt; valt '4': strcpy(morse,"****-"); bryt; valt '5': strcpy(morse,"*****"); bryt; valt '6': strcpy(morse,"-****"); bryt; valt '7': strcpy(morse,"--***"); bryt; valt '8': strcpy(morse,"---**"); bryt; valt '9': strcpy(morse,"----*"); bryt; valt '0': strcpy(morse,"-----"); bryt; // Lägg till skiljetecken etc här } // Skriv bokstaven som sänds (finns som variabelparametern "c" vid anropet) skrivf("%c ",c); skrivf("%s ",morse); // Generera ljud upprepa(i=0; i<strlen(morse);i++){ om (morse[i] == '*'){ skrivf("ti "); system("aplay -q 0_1.wav >/dev/null"); } annars { skrivf("taa "); system("aplay -q 0_3.wav >/dev/null"); } // skrivf("\n"); } } heltal skicka_text_som_ord(tecken rad[]){ heltal i; tecken *ett_ord = strtok(rad," "); medan (ett_ord != NULL){ skrivf("Ord=%s\n",ett_ord); upprepa(i=0; i<strlen(ett_ord);i++){ // Skriv ett tecken i nuvarande ord skrivMorse(ett_ord[i]); system(teckenpaus); skrivf("\n"); } skrivf("\n"); ett_ord = strtok(NULL, " "); } } heltal program(){ heltal l=0; storlek_t len=0; tecken *rad=NULL; skrivf("Skriv text att sända som morse:"); l=hämtarad(&rad,&len,stdin); skicka_text_som_ord(rad); }
Den genererade c-koden är strukturellt identisk med sv-programmets kod d.v.s. vi gör en ord för ord översättning. Detta betyder att c-kompilatorn ger felmeddelanden som pekar till rätt rad också i sv källkoden. Min editor bör naturligtvis konfigureras så att den visar radnummer för att felsökning skall vara effektiv.
Översättaren bör sannolikt expanderas med ytterligare c-konstruktioner. Det är oklart i hur hög utsträckning det är värt att översätta funktioner i bibliotek men exemplet ”hämtaRad” visar att detta naturligtvis är möjligt. Det är naturligtvis också möjligt att översätta namnen på standardbiblioteken på samma sätt men knappast vettigt eftersom målet är att eleven också bekantar sig med c-språket och dess bibliotek.
Oversättarprogram komplett:
#!/bin/bash # Name=csv # Detta är en kompilator för programspråket "sv" som är en svensk översätytning av språket "c". # Språket "sv" kan enkelt utvidgas genom att modifiera filen "swe.lex". # Användning: ./csv program # Notera att källkoden antas vara program.sv . # Resultatet blir det körbara programmet program.run # # En textfil som är en översättning till språket "c" genereras som program.c . # Lars Silen 2022 # Detta är fri källkod som fritt får användas och modifieras på egen risk. echo "Källkod:"$1.sv echo "Översättaren är definierad i swe.lex" echo "Kompilerar översätteren swe.lex till c-kod" lex swe.lex echo "Kompilerar lex analysatorn till körbar maskinkod: sv" gcc lex.yy.c -ll -o sv echo "Översätter sv-programmet " $1.sv " till c-kod: " $1.c ./sv $1.sv >$1.c echo "C-kod finns nu i " $1.c echo "Kompilerar nu till körbar maskinkod!" gcc $1.c -o $1.run echo "The executable is:" $1.run
Notera att skriptet kompilerar om swe.lex varje gång. Användaren kan alltså enkelt lägga till
nya definitioner som blir en del av språket. Om användaren uppfattar att språkdefinitionen är stabil så kan man naturligtvis lämna bort raderna lex swe.lex samt gcc lex.yy.c -ll -o sv , tidsvinsten blir dock marginell.
Kommentera