Beskrivelse av programmeringsspr?ket D# (D-sharp).

Her beskrives syntaksen og den statiske semantikken (hva som skal sjekkes av kompilatoren) til spr?ket D#. Den dynamiske semantikken (alts? hva som skal gj?res under utf?relsen) skulle v?re rimelig opplagt, men eventuelle detaljer som er n?dvendige vil vi komme tilbake til i forbindelse med oblig 2.

D# er med vilje lagt opp til ? ha en del likhetstrekk med C (og andre spr?k i samme familien...).

Syntaks

I beskrivelsen under er ikke-terminaler skrevet med store bokstaver, og metasymbolene (i bokas betydning, alts? de som brukes til ? beskrive grammatikken) er : ->, |, (, ), {, }, [, ]. Her betyr {...} gjentakelse null eller flere ganger, og [...] betyr at det kan v?re med eller ikke.

Alt annet, som er skrevet som tette sekvenser er terminalsymboler, og de med sm? bokstaver er reserverte (!) n?kkelord. Merk dog at at alle terminalsymbolene er skrevet i anf?rselstegn for ? skille dem fra de tilsvarende metasymbolene.

Det er noen terminaler som ikke g?r greit fram av syntaksen under, og disse er betegnet NAME, INT_LITERAL, FLOAT_LITERAL og STRING_LITERAL.

NAME

NAME skal starte med bokstav, og deretter v?re en sekvens av siffer, bokstaver og underscore. De kan ikke v?re p? mer enn 16 tegn, og alle er signifikante. Store og sm? bokstaver regnes som forskjellige tegn. Merk alts? at alle n?kkelord skrives med sm? bokstaver, og at de ikke kan brukes som vanlige navn.

INT_LITERAL

INT_LITERAL skal inneholde ett eller flere siffer.

FLOAT_LITERAL

FLOAT_LITERAL skal inneholde ett eller flere siffer, fulgt av et punktum, fulgt av ett eller flere siffer.

STRING_LITERAL

STRING_LITERAL skal best? av en tekststreng innesluttet i anf?rselstegn ("). Strengen kan ikke inneholde linjeskift. Den semantiske "verdien" av en STRING_LITERAL er kun det som er inni anf?rselstegn; selve anf?rselstegnene skal ikke inkluderes.

structs

D# st?tter brukerdefinerte typer kalt "strukter". De tilsvarer struct -konstruksjonen i C og lignende spr?k. I D# defineres de med n?kkelordet "struct" fulgt av en serie variabeldefinisjoner. Variable av strukt-typer kan antas ? ha referanse-semantikk, m.a.o, de oppf?rer seg som pekere. Instanser av strukter kan opprettes med n?kkelordet new. Dette gj?r det mulig ? ha referanser til strukt-typer som attributter til strukter. Den spesielle verdien "null" betegner "ingen struct", som i C# eller Java.  Merk at, i motsetning til C/C++, skal en struct-deklarasjon ikke avsluttes med semikolon. Operatoren . (punktum) brukes for ? aksessere attributter i en struct. Denne operatoren har h?yere presedens enn alle andre operatorene, med unntak av parenteser.

pass-by-reference

D# st?tter s?kalt "pass-by-reference" (selvsagt i tillegg til "vanlig" pass-by-value). Endringer som gj?res i en funksjon med en pass-by-reference parameter vil reflekteres i skopet til den kallende funksjonen (jfr operatoren & i C++ eller "ref" i C#). pass-by-reference markeres i D# med n?kkelordet "ref", som m? brukes b?de i funksjonssignaturen og i funksjonskallet. Et eksempel:

void swap( ref int a, ref int b )
    {
    int tmp = a;
    a = b;
    b = tmp;
    }

    void Main()
    {
    int x = 42;
    int y = 84;
    swap( ref x, ref y );
    }
    

Det er tillatt ? sende struct-attributter by ref (m.a.o., kallet  func( ref a.b ) er tillatt.

(Syntaksen for ref parametre er i stor grad hentet fra C#.)

Eksponensiering

D# st?tter en eksponensieringsoperator ** (som i Fortran). Uttrykket 5**2 betyr 5 opph?yd i andre potens. Merk at **, i motsetning til de fleste andre operatorene, er h?yre-assosiativ. Det inneb?rer at 5 ** 2 ** 3 betyr 5 ** (2 ** 3). Uttrykk med ** evaluerer alltid til en float.

Indre deklarasjoner

I en funksjon kommer alle deklarasjonene f?r den f?rste eksekverbare setningene. Disse deklarasjonene kan inkludere alt som kan deklareres p? ytterste niv?, alts? variable, funksjoner og structer. Det sier seg selv at navnene p? disse funksjonene og structene ikke er tilgjengelige utenfor den funksjonen de er deklarert i (men navnene p? medlemmene i structene er naturligvis tilgjengelig fra det omliggende skop).

Short-circuit evaluation

De logiske operatorene && og || benytter s?kalt short-circuit evaluation. Det betyr at dersom det f?rste uttrykket evaluerer til sann, skal ikke det andre uttrykket evalueres i det hele tatt.

Typer og implisitt typekonvertering

Det er tillatt ? tilegne uttrykk av typen int til variable av typen float. Det motsatte er ikke tilfelle. Det finnes ingen cast-operator. Dersom et aritmetisk uttrykk inneholder en eller flere subuttrykk av typen float, skal hele uttrykket evalueres med flyttallsaritmetikk.

Merk at dette ogs? gjelder i andre sammenhenger der typekonverteringer kan v?re naturlig - dersom en funksjon er definert til ? returnere en float, m? man tillate at uttrykk av typen int brukes.

Det er ingen implisitte konverteringer mellom int og bool - man kan ikke gj?re f.eks if ( 1 ){}.

Standardbibliotek

Programmet har et standardbibliotek med et sett av IO-funksjoner. Dersom ikke annet er angitt har de returtypen void.

read_int()

Leser en int fra standard inn.

read_float()

Leser en float fra standard inn.

read_char()

Leser ett tegn fra standard inn og returnerer ASCII-verdien som en int. Returnerer -1 ved EOF.

read_string()

Leser en string fra standard inn opp til f?rste whitespace.

read_line()

Leser en tekstlinje fra standard inn.

print_int( int i )

Skriver en int til standard ut.

print_float( float f )

Skriver en float til standard ut.

print_str( string s )

Skriver en streng til standard ut.

print_line( string s )

Skriver en streng til standard ut fulgt av et linjeskift.

Kommentarer

Kommentarer i D# starter med // og fortsetter linjen ut(som i C++/Java/C#). Man trenger ikke ? st?tte C's /* */-kommentarer. Merk at det ikke er noen grunn til ? gi kommentarer og whitespace videre til parseren - disse kan trygt fjernes i scanneren.

Grammatikk

Grammatikken som egen fil.

Presedens

Presedens-rekkef?lge (fra lavest til h?yest):

  1. || 
  2. &&
  3. ! (alts? "!a && b" betyr "(!a) && b")
  4. Alle relasjonsoperatorene
  5. + og -
  6. * og /
  7. ** (eksponensiering)
  8. . (punktum, for struct-aksess)

Assosiativitet

Merk at spr?ket ikke st?tter un?r minus (og heller ingen un?r pluss, men det er det vel f? som gr?ter over).

Semantikk (ikke viktig i oblig 1)

Bruksforskomster av navn uten punktum foran bindes p? vanlig m?te til en deklarasjon: Let ut gjennom "blokkene" (alts? funksjoner eller program) som omslutter bruksstedet. Se p? deklarasjonene i hver blokk, og velg den deklarasjonen der du f?rst f?r treff. Om man ikke f?r treff er det en feil i programmet. Her regnes en formell parameter med til de lokale variable i prosedyren.

Spr?ket har fire innebygde typer: "float", "int", "string" og "bool". I tillegg utgj?r hver struct-deklarasjon en ny type. N?r man leter etter en strukt leter man ogs? utover, blokk for blokk, som for andre navn. Se ovenfor.

Alle navn m? v?re deklarert (tekstlig) f?r de brukes (og sjekkingen kan derved naturlig gj?res i ett gjennoml?p).

Semantiske regler som m? sjekkes:

Uttrykk
Funksjoner
Generelt