あなたは、Cプログラミング言語を教えるコンピューターサイエンスの教授です。学生に伝えたい原則の1つはモジュール性です。残念ながら、過去のクラスはメッセージを受信しない傾向があり、プログラム全体を使用して課題を提出していましたmain()
。したがって、この学期では、学生を採点するための厳格なモジュール化ガイドラインを発行しました。
Cの文法のサブセットと「整形式」の翻訳単位の規則を以下に定義します。これらの規則に従うコードは、キーワードである識別子が使用されない限り、有効なC89である必要があります。
仕事
Cコードを含むとされる文字列を入力として受け取ります。この文字列には、スペース、改行、および文字のみが含まれていると想定できますabcdefghijklmnopqrstuvwxyz123456789(){},+-*/%;=
。
コードは、次のルーブリックに従って、学生の課題が受け取るポイント数を出力する必要があります。
translation-unit
文法により、入力は無効です:0ポイント- 入力は文法に従いますが、以下のルールに従って「整形式」ではありません:1ポイント
- 入力は整形式の翻訳単位ですが、完全にモジュール化されていません:2ポイント
- 入力は完全にモジュール化された整形式の翻訳単位です:3ポイント
トークンの定義
identifier
:1つ以上の英小文字のシーケンス。識別子がC89予約語1の場合、結果が予約語を無視していたであろうものの代わりに、オプションで0を返すことができます。予約語の識別子としての使用を検出することに一貫性がある必要はありません。場合によってはフラグを立てて、他のインスタンスに渡すこともできます。integer-literal
:1桁以上の数字1から9のシーケンス(文字0
が入力に表示されないことが保証されていることを思い出してください)- 他の有効なトークンは文法で文字通り定義されています。
- 文字が空白でない場合に限り、文字はトークンに属している必要があります。
- 2つの連続した英数字は、同じトークンの一部である必要があります。
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*
適切なプログラム要件
- 2つの関数定義が同じ関数名を持つことはできません。
- 内の2つの識別子
argument-list
が同一であってはなりません。 - 内の識別子は、
argument-list
関数名と同じであってはなりません(afunction-definition
またはa からcall-expr
)。 - 内の識別子は
var-expr
、囲んでいる関数のに含まれている必要がありますargument-list
。 - 特定の関数では、すべて
call-expr
のとfunction-definition
(存在する場合)は引数の数が一致している必要があります。
完全にモジュール式
- 関数ごとに1つ以下の2項演算子
- 関数ごとに1つ以下の代入ステートメント
- 関数ごとに1つ以下の関数呼び出し
例(1行に1つ)
スコア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; }
スコア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; }
スコア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) ; }
スコア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;}
スコア0または1
h(auto, auto) { return 1; }
スコア0または3
if() { return 1; }
1 予約語リスト: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
引数なしで1回、引数1つで1回呼び出されたため、整形式ではありませんか?