1 mai Mekaanisen Aritmetiikan Ideaali LKTT 2007 (per I-III) 2. LOKAKUUTA 2007, VERSIO 10 Kielen määrittely annetaan laajennetulla BNF-notaatiolla, joka on seuraava. <nimi> ::= määrittely määrittelee välisymbolin nimi a1 a2 a1 jota välittömästi seuraa a2 a1 a2 a1 tai a2 [ a ] a tai ei mitään { a } nolla tai useampia kertoja a ( a1 a2 ) a3 kaarisulut määräävät vaikutusalueen (esimerkissä a1 tai a2 ja heti perään a3) Kun <nimi> esiintyy operaattorin ::= oikealla puolella, on sen merkitys täsmälleen sama kuin määrittely. 1. Perusrakenteita 1.1. Kommentti on merkkijono, joka a) alkaa -- ja päättyy rivin loppuun, tai b) alkaa merkeillä (* ja loppuu merkkeihin *) (voi siis olla useampirivinen). 1.2. Alkioiden (non-terminaalit) välissä saa olla tyhjiä merkkejä: välilyönti, rivinvaihto tai tabulaattori. 1.3. digit ::= 0 1... 9 1.4. integer ::= digit { digit } 1.5. scale_factor ::= ( E e ) [ + - ] integer 1.6. float ::= integer. integer [ scale_factor ] 1.7. number ::= integer float 1.8. letter ::= a... z A... Z ö Ö ä Ä 1.9. ident ::= letter { letter digit _ } 1.10. ident_list ::= ident {, ident } 1.11. full_ident ::= ident [ [ expression_list ] ] 1.12. qualident ::= { full_ident. } full_ident mai.tex 1 Rev: 10, October 2, 2007
2 1.13. designator ::= qualident 1.14. single_character ::= ascii merkki 32-255 1.15. character ::= single_character \ single_character 1.16. char_constant ::= character 1.17. string_constant ::= { character } 1.18. Kielen varatut sanat (tunnistetaan pienellä kirjoitettuna): and begin case constant div do else elsif end eval exit external for foreach function if import in internal is loop map mod module not of or out pointer procedure record requires return stack then type use vector while with Näiden lisäksi varattuja sanoja ovat myös kaikki kielen tietotyyppien nimet: boolean, char, double, integer, string sekä sisäisten funktioiden ja proseduurien nimet: chr, convert, dispose, len, isempty, new, ord, pop, print, println, push, read, readln, osoittimiin liittyvät nimet val, nil sekä vakiot true, false. 2. Kielen syntaksi 2.1. Käännösyksikkö 2.1.1. compilation ::= module { module } 2.1.2. module ::= module ident is [ import_part ] declaration_part procedure_part [ begin statement_sequence ] end module ident. 2.2. Moduulin pääosat 2.2.1. import_part ::= import ident_list ; 2.2.2. declaration_part ::= { type_declaration ; variable_declaration ; } 2.2.3. procedure_part ::= { procedure_declaration ; function_declaration ; } mai.tex 2 Rev: 10, October 2, 2007
3 2.3. Peruslauseita 2.3.1. boolean_exp ::= expression 2.3.2. statement ::= assignment procedure_call if_statement loop_statement while_statement iterate_statement case_statement eval expression exit [ boolean_exp ] return [ expression ] 2.3.3. statement_sequence ::= [ use declaration_part with ] statement ; { statement ; } 2.3.4. assignment ::= designator := expression 2.3.5. procedure_call ::= qualident [ actual_parameters ] 2.3.6. if_statement ::= if boolean_exp then statement_sequence { elsif boolean_exp then statement_sequence } [ else statement_sequence ] end if 2.3.7. loop_statement ::= loop statement_sequence end loop 2.3.8. while_statement ::= while boolean_exp loop_statement do loop_statement while boolean_exp 2.3.9. iterate_statement ::= for ident in range loop_statement foreach ident in expression loop_statement 2.3.10. range ::= expression.. expression 2.3.11. case_statement ::= case expression of case_branch { ; case_branch } end case 2.3.12. case_branch ::= expression_list : statement_sequence. 2.4. Funktiot ja proseduurit 2.4.1. fp_section ::= [ in ] [ out ] ident_list : type 2.4.2. formal_parameters ::= ( fp_section { ; fp_section } ) 2.4.3. procedure_heading ::= procedure ident [ formal_parameters ] 2.4.4. procedure_body ::= statement_sequence end [ ident ] 2.4.5. procedure_declaration ::= procedure_heading is procedure_body mai.tex 3 Rev: 10, October 2, 2007
4 2.4.6. function_heading ::= function ident [ formal_parameters ] return type 2.4.7. function_declaration ::= function_heading is procedure_body 2.4.8. actual_parameters ::= ( [ expression_list ] ) 2.4.9. function_call ::= qualident actual_parameters 2.5. Tyypit ja muuttujat 2.5.1. type ::= qualident [ pointer ] 2.5.2. record_type ::= record ident : type { ; ident : type } end 2.5.3. vector_type ::= vector [ range {, range } ] of type 2.5.4. map_type ::= map of type, type 2.5.5. stack_type ::= stack of type 2.5.6. type_declaration ::= type ident = ( type record_type vector_type map_type stack_type ) 2.5.7. map_val ::= factor : expression 2.5.8. map_init ::= { map_val {, map_val } } 2.5.9. vector_init ::= [ expression_list ] 2.5.10. initialization ::= expression vector_init map_init 2.5.11. variable_declaration ::= ident_list : type [ := initialization ] constant ident := initialization 2.6. Lausekkeet 2.6.1. primary ::= number char_constant string_constant qualident function_call ( expression ) 2.6.2. prefix_op ::= + - not & 2.6.3. factor ::= [ prefix_op ] primary 2.6.4. mult_op ::= * / div mod 2.6.5. term ::= factor { mult_op factor } 2.6.6. add_op ::= + - 2.6.7. simple_expression ::= term { add_op term } mai.tex 4 Rev: 10, October 2, 2007
5 2.6.8. relation_op ::= = # = = 2.6.9. relation ::= simple_expression [ relation_op simple_expression ] 2.6.10. expression ::= relation { and relation } relation { or relation } 2.6.11. expression_list ::= expression {, expression } 2.7. Import-moduulin rakenne 2.7.1. import_module ::= ident external [ requires_part ] import_declaration_part import_procedure_part end. 2.7.2. requires_part ::= requires ident_list ; 2.7.3. import_type_declaration ::= type_declaration 2.7.4. import_variable_declaration ::= ident : [ constant ] type internal string_constant 2.7.5. import_declaration_part ::= { import_variable_declaration ; import_type_declaration ; } 2.7.6. import_procedure_part ::= { procedure_heading internal string_constant ; function_heading internal string_constant ; } mai.tex 5 Rev: 10, October 2, 2007
6 3. Tietotyypit 3.1. boolean : totuusarvot true ja false. 3.2. char : ascii-merkki (8 bittinen). 3.3. integer : etumerkillinen kokonaisluku, joka on yhteensopiva saman ympäristön C-kielisen int -tietotyypin kanssa (esim. 32 bittinen). 3.4. double : liukuluku, joka on yhteensopiva saman ympäristön C-kielisen double -tietotyypin kanssa (esim. 64 bittinen). 3.5. string : merkkijono (kuten C-kielessä eli ascii-merkit ja viimeisenä tavuna nolla). Merkkijonoa voi indeksoida, jolloin saatu yksittäinen merkki on tyyppiä char. 3.6. vector : Samaa tietotyyppiä sisältävä 1 N ulotteinen taulukko. 3.7. map : Assosiatiivinen taulukko. 3.8. stack : Pino, jota käsitellään aliohjelmilla push, pop ja isempty. 4. Semantiikkaa (tämä ei ole täydellinen luettelo, tarkista WWW-sivulta) 4.1. Leksikaalit 4.1.1. Merkkiliteraalien ja merkkijonojen yhteydessä voidaan käyttää merkintää \x, joka tarkoittaa merkkiä x itse tai erikoismerkintää jostain ohjauskoodista. Tällä tavoin saadaan kirjattua esim. merkkijonon sisään lainausmerkki. Ainakin seuraavien symbolien on toimittava: \n rivinvaihto (kuten C-kielessä) \t tabulaattori \0 nolla (merkkijonon lopetusmerkki) \ merkki itse (heittomerkki) \" merkki itse (lainausmerkki) \\ merkki itse (takakenoviiva) 4.1.2. Merkkijonon sisällä esiintyvät kommenttimerkit eivät aloita tai lopeta kommenttia. 4.1.3. Kielen varattu sana ei saa esiintyä muussa kuin syntaksin määräämässä merkityksessä. Varattu sana ei siis voi olla esim. moduulin, muuttujan tai tietotyypin nimenä. 4.1.4. qualident tarkoittaa pisteillä toisistaan eroteltuja nimiä (esim. moduuli.funktionimi ). mai.tex 6 Rev: 10, October 2, 2007
7 4.1.5. Nimien peittyminen on sallittua (eli jos esim. funktion parametrina on muuttuja i ja funktion rungossa for-silmukan silmukkamuuttuja on i, niin silmukan sisällä i-tarkoittaa silmukkamuuttujaa ja edellisen tason muuttujaan ei pystytä viittaamaan). 4.2. Moduulit 4.2.1. Määrittelyn lopussa oleva ident on sama kuin moduulin nimi. 4.2.2. Import-moduuli ei esiinny yksinään käännösyksikkönä, vaan se luetaan erillisestä tiedostosta import -lauseen seurauksena. 4.2.3. Import-moduulin requires -osassa luetellut moduulit otetaan automaattisesti mukaan käännökseen ( monuulinimi.o ) ja niiden alustuskoodi suoritetaan. 4.2.4. Ohjelmakoodi lähtee suoritukseen Main-nimisen moduulin alustuskoodista. Kaikki muut moduulit ovat käännösyksiköitä, joista tuotetaan esittelytiedosto ja objektitiedosto. 4.2.5. Esittelytiedosto tuotetaan nimelle moduulinimi.maidef 4.2.6. Kaikkien import-moduulina käyttöön otettujen moduulien alustuskoodit on suoritettava ennen Main:n käynnistymistä. 4.2.7. Jokaisen moduulin ohjelmakoodissa on globaali rutiini assemblernimellä moduulinimi$init, joka suorittaa moduulin alustuksen. 4.2.8. Import-moduulien internal -määreet (merkkijono) kertovat rakenteista käytettävän nimen assembler-tasolla. 4.3. Lauseet 4.3.1. for ja foreach -silmukan silmukkamuuttuja on näkyvissä ainoastaan silmukan sisällä. 4.3.2. Silmukkamuuttujaan ei saa sijoittaa. 4.3.3. Pinolle suoritettu foreach käy läpi pinon kaikki alkiot (suunnassa pinon päältä pohjalle ). 4.3.4. Map-taulukolle suoritettu foreach käy läpi taulukon kaikki avaimet type T = map of string, integer; puhelinluettelo : T := { "jyke": 12345, "bitti": 45612 }; -- tulosta kaikki numerot foreach nimi in puhelinluettelo loop println( nimi, ":", puhelinluettelo[nimi] ); end loop; mai.tex 7 Rev: 10, October 2, 2007
8 4.3.5. Taulukolle suoritettu foreach on määritelty vain yksiulotteisille taulukoille. 4.3.6. exit boolean_exp poistuu sisimmästä silmukasta jos ehtolauseen arvo on true. 4.3.7. exit -lause voi esiintyä ainoastaan silmukkarakenteen sisällä. 4.3.8. eval suorittaa lausekkeen ja hukkaa sen arvon (käytetään lähinnä silloin, jos halutaan kutsua funktiota ilman, että sen paluuarvolla on merkitystä). 4.3.9. use... with luo uuden näkyvyysalueen, jossa määritellyt tyypit ja muuttujat ovat voimassa seuraavaan lohkon sulkevaan rakenteeseen. 4.4. Tietotyypit 4.4.1. Tietotyypeillä on rakenne-ekvivalenssi. 4.4.2. Automaattisia tyyppimuunnoksia tietotyyppien välillä ei ole olemassa. 4.4.3. Osoittimilla on erityinen tyhjä arvo nil, joka on tyyppiyhteensopiva kaikkien osoitintietotyyppien kanssa. 4.4.4. record -tyyppi saa sisältää osoittimen samaa tietotyyppiä oleviin alkioihin. type IntList = record x : integer; next : IntList pointer end; 4.4.5. Jos osoitinta käytettäessä on yksikäsitteistä, että tarkoitetaan osoittimen päässä olevaa arvoa, toiminta tehdään automaattisesti. Jos käyttötilanne ei ole selkeä, kerrotaan varatulla sanalla val tilanteet joissa halutaan käyttää osoittimen päässä olevaa arvoa. nimi osoitin osoitin.val osoitin.nimi merkitys osoittimen arvo osoittimen osoittama arvo osoittimen päässä olevan recordin kenttä (jolle tehdään tulkinta uudelleen) a, b : IntList; p, q : IntList pointer; p := nil; -- sijoitetaan osoitinmuuttujaan tyhjä arvo mai.tex 8 Rev: 10, October 2, 2007
9 p := &a; q := &b; q.next := nil; q.x := 42; -- tiedetään kohteen olevan muuttuja p.val := q.val; -- q:n osoittama record kopioidaan -- p:n osoittamaan paikkaan p.next := q; p.next.x := 1; -- muuttujan b kenttä x p.next.next := nil; p.next.next.val := b; -- semanttisesti oikein, -- viittaus nil:n läpi p := q; -- osoitin q muuttujaan p 4.4.6. Eri tietotyyppien oletusalkuarvot ovat: false, a, 0, 0.0, "mai", nil. 4.5. Lausekkeet 4.5.1. # on erisuuruusoperaattori. 4.5.2. boolean_exp on lauseke, jonka laskettu lopputulos on tietotyyppiä boolean. 4.5.3. Peruslaskutoimitukset toimivat totutulla tavalla tietotyypeillä integer ja double. 4.5.4. Perustietotyyppien välillä ei ole automaattisia tyyppimuunnoksia. (Erityisesti integer ja double eivät ole yhteensopivia.) 4.5.5. mod ja div toimivat vain kokonaisluvuilla integer ja toteuttavat ehdot x = (x div y) y + (x mod y) 0 (x mod y) < y tai y < (x mod y) 0 4.5.6. Merkkijonoilla string katenointi ( + ) tuottaa uuden merkkijonon, joka on yhdistelmä laskun termeistä. 4.5.7. Operaattori & antaa muuttujaan viittaavan osoittimen. 4.5.8. Osoittimien arvoilla toimivat yhtä- ja erisuuruusvertailut. 4.5.9. and ja or noudattavat oikosulkuevaluointia (ketjutetun lausekkeen laskeminen lopetetaan heti kun sen lopputulos on tiedossa). 4.6. Muuttujat 4.6.1. constant -muuttujien tietotyyppi määräytyy määrittelyn alustuslausekkeen tietotyypin mukaan. 4.7. Funktiot ja proseduurit 4.7.1. Aliohjelmaa (procedure) saa kutsua vain lauseessa. mai.tex 9 Rev: 10, October 2, 2007
10 4.7.2. Funktiota saa kutsua vain lausekkeessa (erillisenä lauseena kutsu tehdään eval -lauseen avulla). 4.7.3. Funktiot ja proseduurit ovat ylimääriteltyjä siten, että nimen lisäksi tarvitaan parametrien lukumäärä ja tietotyypit tunnistamaan aliohjelma. Sisäisiä funktioita ei saa ylimääritellä. 4.7.4. Funktion ja proseduurin määrittelyn lopussa oleva ident on oltava sama kuin ko. aliohjelman nimi (koodin selkeyteen tähtäävä syntaksi). 4.7.5. Parametrimääreiden toiminta: Määre <tyhjä> in out in out Käyttö sijoituksessa Luku ja kirjoitus. Kuten paikallinen muuttuja (arvoparametri). Vain luku. Vakioparametrimuuttuja. Vain kirjoitus. Viitepaluuarvo. Luku ja kirjoitus. Kuten viiteparametri. 4.7.6. Arvon palauttaminen return -lauseella proseduurista on virhe. 4.7.7. Tyhjä return -lause funktiossa on virhe. mai.tex 10 Rev: 10, October 2, 2007
11 4.7.8. Kielen sisäiset funktiot Nimi len(x) Argumentin tyyppi string, vector, stack Tulostyyppi integer Toiminta x:n pituus (alkioiden lukumäärä, jossa merkkijonoilla ei ole mukana loppunollaa) ord(x) char integer x:n järjestysnumero chr(x) 0 char x:s ascii-merkki integer 255 pop(p) pino arvo Palauttaa pinon päällimmäisen alkion ja samalla poistaa ko. alkion pinosta. Jos pino on tyhjä, niin toiminta on määrittelemätön isempty(p) pino boolean Palauttaa true jos pino on tyhjä, muutoin false convert(x,t) X T Palauttaa arvon joka on tietotyyppiä T ja jonka arvo on x 4.7.9. convert -funktion tulee ymmärtää vähintään muunnokset Muunnos convert(d, integer) convert(i, double) Toiminta Palauttaa suurimman kokonaisluvun joka on d Palauttaa liukuluvun, jonka arvo on i mai.tex 11 Rev: 10, October 2, 2007
12 4.7.10. Kielen sisäiset proseduurit read(m,s) readln(m,s) muuttuja ja boolean status muuttuja ja boolean status Nimi Argumentin Toiminta tyyppi new(p) osoitinmuuttuja dynaaminen muistinvaraus, johon mahtuu osoittimen tietotyyppiä oleva alkio, osoitinmuuttuja osoittaa varattuun lohkoon dispose(p) osoitinmuuttuja poistaa osoittimen päässä olevan alkion käytöstä ja asettaa parametrina olevan osoittimen arvoksi nil. print(a,b,...) luettelo dataa tulostaa parametrit println(a,b,...) luettelo dataa toimii kuten print, mutta tulostaa viimeisenä rivinvaihdon lukee käyttäjältä merkkejä, jotka muunnetaan parametrin m arvoksi. s on true on muunnos onnistui. (Toteutusvinkki: scanf()) lukee käyttäjältä rivin merkkejä, jotka muunnetaan parametrin m arvoksi. s on true on muunnos onnistui. Myös rivinvaihtomerkki luetaan pois syötteestä. push(p,x) pino ja arvo laittaa pinon p päällimmäiseksi uuden arvon x (joka on pinon tyyppiä). 4.7.11. integer, double ja string tietotyyppien parametrinvälityksen on oltava yhteensopiva C-kielestä tuotetun koodin kanssa (C:n vastaavat tietotyypit int, double ja char*). Tämä takaa sen, että mai-ohjelmat voivat käyttää C-kielellä tehtyjä kirjastoja. 4.7.12. Osoitintyypeille määritellyt new ja dispose varaavat ja vapauttavat dynaamista muistia. Molemmat ottavat yhden osoitintyyppisen argumentin. Lause new(p); varaa p:n osoittaman tyypin tarvitseman määrän dynaamista muistia, ja lause dispose(p); vapauttaa p:n osoittaman muistin. Lauseen new(p) suorittamimai.tex 12 Rev: 10, October 2, 2007
13 sen jälkeen p sisältää varatun muistilohkon osoitteen (tai nil jos muistinvaraus epäonnistui). mai.tex 13 Rev: 10, October 2, 2007
14 5. Käyttöliittymä 5.1. Kääntäjää ajetaan komennolla maic 5.2. Kääntäjän on ymmärrettävä seuraavat komentoriviparametrit -h tulostaa käyttöohjeen. tiedosto(t) luettelo lähdekooditiedostoja. -o btiedosto valmis binääri tulee nimelle btiedosto (oletuksena mai.out). -S käännös tuottaa tiedostoon moduulinimi.s käännöksen assembler muodossa. -llib linkittää mukaan kirjaston lib, joka on yhteensopiva C-kirjaston kanssa (esim. libcurses). -Lpath hakemisto, josta kirjastoja, moduuleja ja import-esittelyitä etsitään (jos tarvitaan useampia hakemistoja, niin valitsin annetaan useamman kerran). Työskentelyhakemisto on aina mukana etsinnässä. -Xstring asettaa päälle toteuttajien oman laajennuksen kääntäjässä. Esimerkkinä vaikkapa -Xgs ottaa käyttöön roskienkeruun tuotetussa binäärissä tai -Xjava tuottaa suoritettavan koodin javan tavukoodina. 5.3. Kääntäjä osaa ottaa itse automaattisesti mukaan kaikki tarvitsemansa apukirjastot ilman että käyttäjän tarvitsee niitä luetella -l ja -L vipusilla. Omat apukirjastot tulee sijoittaa hakemistoon, joka on kerrottu kääntäjän käännösvaiheessa Makefilen PREFIX-muuttujalla (katso tarkemmin työn palautusohjeista WWW-sivuilla). 5.4. Vinkki: tätä kaikkea ei ole tarvis nysvätä itse, vaan osan ominaisuuksista voi toteuttaa käyttämällä hyväksi valmiita työkaluja (llvm-gcc ja llvm-sovelluskehyksen työkalut). Sopivilla parametreilla ja vipusilla kirjastojen linkitys mukaan yms. saa toteutettua helposti. mai.tex 14 Rev: 10, October 2, 2007