Ange antalet tal: 5 Ange tal nummer 1: 10 Ange tal nummer 2: 20 Ange tal nummer 3: 10 Ange tal nummer 4: -4 Ange tal nummer 5: 100 Genomsnitt: 27.200000 |
Programmet, som visas nedan, är tyvärr inte helt korrekt, och när vi försöker bygga och köra det får vi de angivna fel- och varningsmeddelandena. I vilka av kompilatorns faser, eller vid andra tidpunkter, upptäcks vart och ett av de olika felen och varningarna?
(Man kan behöva åtgärda en del av felen för att komma vidare och få de andra felen.)
Programmet | Meddelanden | Lösningsförslag |
---|---|---|
#include <stdio.h> int start(void) { int antal; printf("Ange antalet tal: "); scanf("%d", &antalet); Int summa = 0; for (int i = 0; i < antal; ++i) { int talet = "0" printf("Ange tal nummer %d: ", i + 1); scanf("%d", talet); summa += 3talet; } printf("Genomsnitt: %f\n", 1.0 * summa div antal); } |
(1) undefined reference to "main" (2) error: "antalet" undeclared (3) error: unknown type name "Int" (4) warning: "antal" is used uninitialized (5) warning: initialization of "int" from "char *" (6) error: expected "," or ";" before "printf" (7) Segmentation fault (core dumped) (8) error: invalid suffix "talet" on integer constant (9) error: expected ")" before "div" (10) warning: control reaches end of non-void function |
länkaren semantisk analys semantisk analys optimering, semantisk analys...? semantisk analys parser programkörning scanner parser semantisk analys |
if (x * y == z * t * t) { x = y; while (z < t) { x = y * z * t; y = z * t; } x = y; } else { z = t; } t = x; |
Översätt ovanstående programavsnitt till två av följande tre typer av mellankod. (Skulle du svara på alla tre, räknas den med högst poäng bort.)
a) ett abstrakt syntaxträd (genom att rita upp trädet!)
Lösningsförslag:
b) postfixkod för en stackmaskin
Lösningsförslag:
rvalue x rvalue y * rvalue z rvalue t * rvalue t * == gofalse ELSE-START lvalue x rvalue y = label WHILE-START: rvalue z rvalue t < gofalse AFTER-WHILE lvalue x rvalue y rvalue z * rvalue t * = lvalue y rvalue z rvalue t * = jump WHILE-START label AFTER-WHILE: lvalue x rvalue y = goto AFTER-IF label ELSE-START: lvalue z rvalue t = label AFTER-IF: lvalue t rvalue x =
c) treadresskod
Lösningsförslag:
temp1 = x * y temp2 = z * t temp3 = temp2 * t if temp1 != temp3 goto ELSE-START x = y label WHILE-START: if z >= t goto AFTER-WHILE temp4 = y * z x = temp4 * t y = z * t goto WHILE-START label AFTER-WHILE: x = y goto AFTER-IF label ELSE-START: z = t label AFTER-IF: t = x
Lösningsförslag: Semikolon, kommatecken, textsträng samt nyckelorden klass, elev, i och klart.
b) Det kan hända att en eller flera av terminalerna inte har fixa lexem, utan kan se ut på olika sätt. Skriv i så fall reguljära uttryck som beskriver hur de får se ut.
Lösningsförslag: Textsträng, med det reguljära uttrycket \"[^"]\"
Lösningsförslag: Här är en Flex-fil (skola.l):
%{ #include "skola.tab.h" %} %% [\n\t ] { /* Ignorera whitespace, inklusive radslut */ } "," { return KOMMATECKEN; } ";" { return SEMIKOLON; } \"[^"]*\" { return TEXTSTRANG; } "klass" { return KLASS; } "elev" { return ELEV; } "i" { return I; } "klart" { return KLART; } . { fprintf(stderr, "[Ignorerar felaktigt tecken: '%c']\n", *yytext); } %%
Lösningsförslag:
inmatning -> kommandlista klartkommando
kommandolista -> kommando kommandolista
kommandolista -> tomt
kommando -> klasskommando
kommando -> elevkommando
klasskommando -> klass textsträng semikolon
elevkommando -> elev elevlista i klass textsträng semikolon
elevkommando -> elev elevlista semikolon
elevlista -> textsträng
elevlista -> textsträng kommatecken elevlista
klartkommando -> klart semikolon
tomt markerar en tom produktion.
elev "Anna Alm" i klass "3b"; elev "Bob Berg", "Conny C Cornström III", "Napoleon"; klart; |
Lösningsförslag:
Lösningsförslag:
Grammatiken i lösningsförslaget till uppgift 5 ovan har två FIRST()-konflikter, så vi behöver först vänsterfaktorisera. Produktionerna för elevkommando:
elevkommando -> elev elevlista i klass textsträng semikolon
elevkommando -> elev elevlista semikolon
blir i stället:
elevkommando -> elev elevlista elevkommandorest
elevkommandorest -> i klass textsträng semikolon
elevkommandorest -> semikolon
Produktionerna för elevlista:
elevlista -> textsträng
elevlista -> textsträng kommatecken elevlista
blir i stället:
elevlista -> textsträng elevlisterest
elevlisterest -> kommatecken elevlista
elevlisterest -> empty
Som en komplett grammatik:
inmatning -> kommandlista klartkommando
kommandolista -> kommando kommandolista
kommandolista -> tomt
kommando -> klasskommando
kommando -> elevkommando
klasskommando -> klass textsträng semikolon
elevkommando -> elev elevlista elevkommandorest
elevkommandorest -> i klass textsträng semikolon
elevkommandorest -> semikolon
elevlista -> textsträng elevlisterest
elevlisterest -> kommatecken elevlista
elevlisterest -> empty
klartkommando -> klart semikolon
En nedladdningsbar komplett fil finns här: skolparser.c
void inmatning(void) { kommandolista(); klartkommando(); } void kommandolista(void) { if (lookahead == ELEV || lookahead == KLASS) { kommando(); kommandolista(); } else { /* Ingenting */ } } void kommando(void) { if (lookahead == KLASS) { klasskommando(); } else if (lookahead == ELEV) { elevkommando(); } else { error(); } } void klasskommando(void) { match(KLASS); match(TEXTSTRANG); match(SEMIKOLON); } void elevkommando(void) { match(ELEV); elevlista(); elevkommandorest(); } void elevkommandorest(void) { if (lookahead == I) { match(I); match(KLASS); match(TEXTSTRANG); match(SEMIKOLON); } else if (lookahead == SEMIKOLON) { match(SEMIKOLON); } } void elevlista(void) { match(TEXTSTRANG); elevlisterest(); } void elevlisterest(void) { if (lookahead == KOMMATECKEN) { match(KOMMATECKEN); elevlista(); } else { /* Ingenting */ } } void klartkommando(void) { match(KLART); match(SEMIKOLON); } void parse() { lookahead = scan(); inmatning(); printf("Ok.\n"); }