Você é um professor de ciência da computação que ensina a linguagem de programação C. Um princípio que você procura transmitir aos alunos é a modularidade . Infelizmente, as aulas anteriores tendem a não receber a mensagem, enviando tarefas com todo o programa main()
. Portanto, para este semestre, você emitiu diretrizes rígidas de modularidade nas quais os alunos serão classificados.
Um subconjunto da gramática C e regras para a unidade de tradução "bem formada" são definidas abaixo. O código que segue essas regras deve ser válido C89, a menos que um identificador que seja uma palavra-chave seja usado.
Tarefa
Você receberá como entrada uma string supostamente contendo o código C. Você pode assumir que essa sequência contém apenas espaços, novas linhas e os caracteres abcdefghijklmnopqrstuvwxyz123456789(){},+-*/%;=
.
Seu código deve gerar o número de pontos que a tarefa do aluno deve receber de acordo com a seguinte rubrica:
- A entrada não é válida de
translation-unit
acordo com a gramática: 0 pontos - A entrada segue a gramática, mas não é "bem formada" de acordo com as regras abaixo: 1 ponto
- Input é uma unidade de tradução bem formada, mas não totalmente modular: 2 pontos
- Input é uma unidade de tradução bem formada totalmente modular: 3 pontos
Definições de token
identifier
: Qualquer sequência de 1 ou mais letras minúsculas em inglês. Se um identificador for uma palavra reservada C89 1 , você pode, opcionalmente, retornar 0 em vez de qualquer resultado que estivesse ignorando palavras reservadas. Você não precisa ser consistente em detectar o uso de palavras reservadas como identificadores; você pode sinalizá-los em alguns casos e deixá-los passar em outros.integer-literal
: Uma sequência de 1 ou mais dos dígitos de 1 a 9 (lembre-se de que o caractere0
é garantido para não aparecer na entrada)- Outros tokens válidos são definidos literalmente na gramática.
- Um caractere deve pertencer a um token se, e somente se, não for um espaço em branco.
- Dois caracteres alfanuméricos consecutivos devem fazer parte do mesmo token.
Gramática 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*
Requisitos de programa bem formados
- Duas definições de função não podem ter o mesmo nome de função.
- Não há dois identificadores em um
argument-list
podem ser idênticos. - Nenhum identificador em um
argument-list
pode ser idêntico ao nome de uma função (seja de afunction-definition
ou acall-expr
). - O identificador em a
var-expr
deve ser incluído nas funções anexasargument-list
. - Para uma determinada função, todos
call-expr
osfunction-definition
se (se houver) devem concordar em número de argumentos.
Totalmente modular
- Não mais que 1 operador binário por função
- Não mais que 1 declaração de atribuição por função
- Não mais que 1 chamada de função por função
Exemplos (um por linha)
Pontuação 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; }
Pontuação 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; }
Pontuação 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) ; }
Pontuação 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;}
Pontuação 0 ou 1
h(auto, auto) { return 1; }
Pontuação 0 ou 3
if() { return 1; }
1 Lista de palavras reservadas: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
foi chamado uma vez sem argumento e uma vez com um argumento?