Bạn là giáo sư khoa học máy tính giảng dạy ngôn ngữ lập trình C. Một nguyên tắc bạn tìm cách truyền đạt cho sinh viên là tính mô đun . Thật không may, các lớp học trước đây có xu hướng không nhận được tin nhắn, gửi bài tập với toàn bộ chương trình bên trong main()
. Do đó, trong học kỳ này, bạn đã ban hành các hướng dẫn mô đun nghiêm ngặt theo đó học sinh sẽ được xếp loại.
Một tập hợp con của ngữ pháp C và các quy tắc cho đơn vị dịch "được hình thành tốt" được định nghĩa dưới đây. Mã tuân theo các quy tắc này phải hợp lệ C89, KHÔNG GIỚI HẠN một mã định danh là từ khóa được sử dụng.
Bài tập
Bạn sẽ nhận được đầu vào là một chuỗi có chứa mã C. Bạn có thể cho rằng chuỗi này chỉ chứa khoảng trắng, dòng mới và ký tự abcdefghijklmnopqrstuvwxyz123456789(){},+-*/%;=
.
Mã của bạn phải xuất số điểm mà bài tập của học sinh sẽ nhận được theo phiếu tự đánh giá sau:
- Đầu vào không hợp lệ
translation-unit
theo ngữ pháp: 0 điểm - Đầu vào tuân theo ngữ pháp nhưng không được "hình thành tốt" theo các quy tắc dưới đây: 1 điểm
- Đầu vào là một đơn vị dịch được hình thành tốt nhưng không đầy đủ mô-đun: 2 điểm
- Đầu vào là một đơn vị dịch thuật được hình thành đầy đủ mô-đun: 3 điểm
Định nghĩa mã thông báo
identifier
: Bất kỳ chuỗi từ 1 hoặc nhiều chữ cái tiếng Anh viết thường. Nếu số nhận dạng là từ dành riêng 1 C89 , bạn có thể tùy ý trả về 0 thay vì bất kỳ kết quả nào có thể đã bỏ qua các từ dành riêng. Bạn không nhất quán về việc phát hiện việc sử dụng các từ dành riêng làm định danh; bạn có thể gắn cờ chúng trong một số trường hợp và để chúng vượt qua trong những trường hợp khác.integer-literal
: Một chuỗi gồm 1 hoặc nhiều chữ số 1-9 (nhắc lại rằng ký tự0
được đảm bảo không xuất hiện trong đầu vào)- Các mã thông báo hợp lệ khác được định nghĩa theo nghĩa đen trong ngữ pháp.
- Một ký tự phải thuộc về một mã thông báo khi và chỉ khi nó không phải là khoảng trắng.
- Hai ký tự chữ và số liên tiếp phải là một phần của cùng một mã thông báo.
Ngữ pháp EBNF
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*
Yêu cầu chương trình tốt
- Không có hai định nghĩa hàm có thể có cùng tên hàm.
- Không có hai định danh trong một
argument-list
có thể giống hệt nhau. - Không có định danh trong một
argument-list
có thể giống hệt với tên hàm (cho dù từ afunction-definition
hoặc acall-expr
). - Mã định danh trong
var-expr
phải được bao gồm trong hàm kèm theoargument-list
. - Đối với một hàm đã cho, tất cả
call-expr
s vàfunction-definition
(nếu có) phải đồng ý về số lượng đối số.
Mô-đun đầy đủ
- Không quá 1 toán tử nhị phân cho mỗi hàm
- Không quá 1 câu lệnh gán cho mỗi hàm
- Không quá 1 chức năng gọi cho mỗi chức năng
Ví dụ (một trên mỗi dòng)
Điểm 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; }
Điểm 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; }
Điểm 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) ; }
Điểm 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;}
Điểm 0 hoặc 1
h(auto, auto) { return 1; }
Điểm 0 hoặc 3
if() { return 1; }
1 danh sách từ dành riêng: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
được gọi một lần không có đối số và một lần với một đối số?