Sie sind Professor für Informatik und unterrichten die Programmiersprache C. Ein Prinzip, das Sie den Schülern vermitteln möchten, ist die Modularität . Leider haben frühere Klassen die Nachricht nicht erhalten und Aufgaben mit dem gesamten Programm eingereicht main()
. Daher haben Sie für dieses Semester strenge Modularitätsrichtlinien herausgegeben, nach denen die Studierenden benotet werden.
Eine Teilmenge der C-Grammatik und Regeln für "wohlgeformte" Übersetzungseinheiten sind unten definiert. Code, der diesen Regeln folgt, sollte C89 gültig sein, WENN kein Bezeichner verwendet wird, der ein Schlüsselwort ist.
Aufgabe
Sie erhalten als Eingabe eine Zeichenfolge, die angeblich C-Code enthält. Sie können davon ausgehen, dass diese Zeichenfolge nur Leerzeichen, Zeilenumbrüche und Zeichen enthält abcdefghijklmnopqrstuvwxyz123456789(){},+-*/%;=
.
Ihr Code muss die Anzahl der Punkte ausgeben, die die Aufgabe des Schülers gemäß der folgenden Rubrik erhalten soll:
- Die Eingabe ist
translation-unit
laut Grammatik nicht gültig : 0 Punkte - Die Eingabe folgt der Grammatik, ist jedoch gemäß den folgenden Regeln nicht "wohlgeformt": 1 Punkt
- Die Eingabe ist eine wohlgeformte Übersetzungseinheit, jedoch nicht vollständig modular: 2 Punkte
- Der Eingang ist eine vollständig modulare, wohlgeformte Übersetzungseinheit: 3 Punkte
Token-Definitionen
identifier
: Beliebige Folge von 1 oder mehr englischen Kleinbuchstaben. Wenn ein Bezeichner ein reserviertes C89-Wort 1 ist , können Sie optional 0 zurückgeben, anstatt das Ergebnis, das reservierte Wörter ignoriert hätte. Sie müssen nicht konsequent sein, um die Verwendung reservierter Wörter als Bezeichner zu erkennen. Sie können sie in einigen Fällen markieren und in anderen passieren lassen.integer-literal
: Eine Folge von 1 oder mehr der Ziffern 1-9 (denken Sie daran, dass das Zeichen0
garantiert nicht in der Eingabe erscheint)- Andere gültige Token werden in der Grammatik wörtlich definiert.
- Ein Zeichen muss genau dann zu einem Token gehören, wenn es kein Leerzeichen ist.
- Zwei aufeinanderfolgende alphanumerische Zeichen müssen Teil desselben Tokens sein.
EBNF-Grammatik
var-expr = identifier
literal-expr = integer-literal
binary-op = "+" | "-" | "*" | "/" | "%"
binary-expr = expr binary-op expr
paren-expr = "(" expr ")"
call-expr = identifier "(" [ expr ( "," expr )* ] ")"
expr = var-expr | literal-expr | binary-expr | paren-expr | call-expr
assign-stmt = var-expr "=" expr ";"
if-stmt = "if" "(" expr ")" assign-stmt
return-stmt = "return" expr ";"
function-body = ( assign-stmt | if-stmt )* return-stmt
argument-list = [ identifier ( "," identifier )* ]
function-definition = identifier "(" argument-list ")" "{" function-body "}"
translation-unit = function-definition*
Gut geformte Programmanforderungen
- Keine zwei Funktionsdefinitionen dürfen denselben Funktionsnamen haben.
- Keine zwei Bezeichner in einem
argument-list
dürfen identisch sein. - Kein Bezeichner in a
argument-list
darf mit einem Funktionsnamen identisch sein (ob von afunction-definition
oder acall-expr
). - Die Kennung in a
var-expr
muss in den umschließenden Funktionen enthalten seinargument-list
. - Für eine gegebene Funktion müssen alle
call-expr
s undfunction-definition
(falls vorhanden) in der Anzahl der Argumente übereinstimmen.
Voll modular
- Nicht mehr als 1 Binäroperator pro Funktion
- Nicht mehr als 1 Zuweisungsanweisung pro Funktion
- Nicht mehr als 1 Funktionsaufruf pro Funktion
Beispiele (eines pro Zeile)
Punktzahl 0
}}}}}
return 2;
f() { return -1; }
f() {}
f(x,) { return 1; }
f(x) { return 1 }
f(x) { returnx; }
f(x) { return1; }
f() { g(); return 1;}
f() { if(1) return 5; }
f(x) { if(1) if(1) x = 2; return x; }
f(x, y) { x = y = 2; return x; }
Punktzahl 1
f(){ return 1; } f(){ return 1; }
g(x, x) { return 1; }
g(f) { return 1; } f() { return 1; }
f(x) { x = write(); x = write(1); return 1; }
f() { return f(f); }
f() { return 1; } g() { return f(234567); }
f() { return(x); }
f() { j = 7; return 5; }
Punktzahl 2
f(x,y,zzzzz) { return x + y + zzzzz; }
f(x,a,b) { if(a) x = foo(); if(b) x = bar(); return x; }
f(j) { return g(h( i() / j, i() ), 1) ; }
Punktzahl 3
mod(x, y) { return ((x % y)); }
f() { return f(); }
f(c) { if(c) c = g(c) + 2; return c; }
fib(i){return bb(i,0,1);}aa(i,a,b){return bb(i,b,a+b);}bb(i,a,b){if(i)a=aa(i-1,a,b);return a;}
Punktzahl 0 oder 1
h(auto, auto) { return 1; }
Punktzahl 0 oder 3
if() { return 1; }
1 Reservierte Wortliste:auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
write
es einmal ohne Argument und einmal mit einem Argument aufgerufen wurde?