Página 1
Linguagens de Programação – Capítulo 3
Descrição da Sintaxe
Sintaxe – Forma das ExpressõesInstruçõesUnidades
Semântica – Significado das ExpressõesInstruçõesUnidades
Exemplo: Comando if do C
Sintaxe:if (<expressão>)
<instrução>
Semântica:“Se o valor de expressão for verdadeiro...”
Sintaxe: mais fácil de descrever que a semântica.Existe uma notação concisa e universalmente aceitapara a descrição da sintaxe, mas não ainda para a semântica
Página 2
Linguagens de Programação – Capítulo 3
Lexemas – Unidades sintáticas
Descrição dada por uma especificação léxica, em nível mais baixo que a descrição sintática
Exemplo: Palavras reservadas, identificadores, literais, operadores...
Tokens
Categorias de lexemas
Às vezes um token tem somente um lexema possível, às vezes “infinitos”
Exemplo: index = 2*count + 17 “index” e “count” são lexemas que pertencem à categoria “identificador”
Página 3
Linguagens de Programação – Capítulo 3
Formas de definir as linguagens, através de:
Reconhecedores de Linguagens
Dispositivos para verificar se certa sentença estána linguagem
Geradores de Linguagens
Dispositivos para gerar sentenças da linguagem
BNF – Backus Naur Form
Notação mais usada para descrever formalmente as linguagens de programação
“Metalinguagem ” ( linguagem usada para descreverlinguagens) para linguagens de programação
Gramática é o conjunto de regras que produz a linguagem
Página 4
Linguagens de Programação – Capítulo 3
BNF
Exemplo: comando “if ” do Pascal
<if_stmt> if <expr_lógica> then <stmt>
<if_stmt> if <expr_lógica> then <stmt>
else<stmt> ou
<if_stmt> if <expr_lógica> then <stmt>| if <expr_lógica> then <stmt>
else<stmt>Exemplo: listas e recursividade
<lista_ident> <ident> | <ident> , <lista_ident>
<ident> <letra> <seq> | <letra>
<seq> <letra> <seq> | <dígito><seq> | <letra> | <dígito>
<letra> A|B|C ... |Z
<dígito> 0|1|2 ... |9
Página 5
Linguagens de Programação – Capítulo 3
Gramática para uma pequena linguagem
<programa> begin <lista_stmt> end
<lista_stmt> <stmt> | <stmt> ; <lista_stmt>
<stmt> <var> := <expressão>
<expressão> <var> + <var> | <var> - <var> | <var>
Exemplo de derivação:<programa> begin <lista_stmt> end
begin <stmt> ; <lista_stmt> end begin <var> := <expressão> ; <lista_stmt> end
begin A := <expressão> ; <lista_stmt> endbegin A := <var> + <var> ; <lista_stmt> endbegin A := B + <var> ; <lista_stmt> endbegin A := B + C ; <lista_stmt> endbegin A := B + C ; <stmt> endbegin A := B + C ; <var> := <expressão> endbegin A := B + C ; B := <expressão> endbegin A := B + C ; B := <var> endbegin A := B + C ; B := C end
<var> A | B | C
Página 6
Linguagens de Programação – Capítulo 3
Gramática para instruções de atribuição
<atribuição> <id> := <expressão>
<id> A | B| C
<expressão> <id> + <expressão>
| <id> * <expressão>
| ( <expressão> ) | <id>
Exemplo: derivar A := B * ( A + C )
<atribuição> <id> := <expressão>A := <expressão> A := <id> * <expressão>A := B * <expressão>A := B * ( <expressão> )A := B * ( <id> + <expressão> )A := B * ( A + <expressão> )A := B * ( A + <id> )A := B * ( A + C )
Página 7
Linguagens de Programação – Capítulo 3
Árvores de Análise ( “Parse Trees” )
<atribuição>
<id> := <expressão>
<id> * <expressão>
( <expressão>
<id> + <expressão>
A
B )
A <id>
C
Exemplo: A := B * ( A + C )
Página 8
Linguagens de Programação – Capítulo 3
Exemplo de Gramática Ambígua
<atribuição> <id> := <expressão>
<id> A | B| C
<expressão> <expressão> + <expressão>
| <expressão> * <expressão>
| ( <expressão> ) | <id>
Exemplo: construir duas árvores diferentes paraA := B * ( A + C )
<atribuição>
<id>:= <expressão>
+ <expressão>
* <expressão>
A
B
C
<id>
A
<expressão>
<expressão><id>
<id>
1º)
Página 9
Linguagens de Programação – Capítulo 3
<atribuição>
<id>:= <expressão>
* <expressão>
+ <expressão>
A
A
B
<id>
C
<expressão>
<expressão> <id>
<id>
2º)
“Consertando” a Gramática
<atribuição> <id> := <expressão>
<id> A | B| C
<expressão> <expressão> + <expressão> | <termo>
<termo> <termo> * <fator> | <fator>
<fator> ( <expressão> ) | <id>
Página 10
Linguagens de Programação – Capítulo 3
<expressão>
Descrição da SintaxeGramática não ambígua para expressões<atribuição> <id> := <expressão>
<id> A | B| C<expressão> <expressão> + <expressão>
| <termo><termo> <termo> * <fator>
| <fator><fator> ( <expressão> )
| <id>Associatividade de operadores de mesma precedência
Operador de adição esquerdo mais baixo que o direito.É a ordem correta sequeremos associatividade à esquerda
<atribuição>
<id>:= <expressão>
+<termo>
+ <termo>
A
A
B
<id>
C
<expressão>
<id>
<id>
<fator>
<fator><termo>
<fator>
Página 11
Linguagens de Programação – Capítulo 3
Regra recursiva à esquerda
LHS aparece no início do RHS ( vide gramática anterior )
Regra recursiva à direita
LHS aparece no final do RHS Exemplo: operador de exponenciação geralmente é
associativo à direita
<fator> <expressão> ^ <fator> | <expressão>
<expressão> ( <expressão> ) | <id>
<id> A | B| C
<fator>
^ <fator>
^ <fator>
AB <id>
C
<expressão>
<expressão><id>
<id> <expressão>
Exemplo: A ^ B ^ C = A ^ ( B C )^
Página 12
Linguagens de Programação – Capítulo 3
Ambigüidade em if – then – else
<if_stmt> if <exp_lógica> then <stmt>| if <exp_lógica> then <stmt> else <stmt>
<stmt> <if_stmt>
Árvore de análise I
<if_stmt>
<exp_lógica> <stmt>thenif else <stmt>
<exp_lógica> <stmt>thenif
<if_stmt>
if <exp> then if <exp>
then <stmt> else <stmt>
Página 13
Linguagens de Programação – Capítulo 3
Árvore de análise II
<if_stmt>
<exp_lógica> <stmt>thenif else <stmt>
<exp_lógica> <stmt>thenif
<if_stmt>
if <exp> then if <exp>
then <stmt> else <stmt>
Página 14
Linguagens de Programação – Capítulo 3
“Consertando” a Gramática
Regra Geral: o else pertence sempre ao then maispróximo e entre um then-else, não pode haver if sem else
<livre> if <exp_lógica> then <stmt> if <exp_lógica> then <coincidente>
else <livre>
É necessário ?Sim!
|
Não é possível fazerif <exp_lógica> then if <exp_lógica> then <algo> else <algo>
Fica obrigatório derivar<stmt> <livre> if <exp_lógica> then
<stmt> if <exp_lógica> then <coincidente>
...
<stmt> <coincidente> | <livre>
<coincidente> if <exp_lógica> then <coincidente> else <coincidente>
| qualquer instrução não if
Página 15
Linguagens de Programação – Capítulo 3
BNF Estendida Extensões não aumentam o poder descritivo da BNF apenas melhoram sua legibilidade e capacidade de escrita
1) Denotar parte opcional dentro de colchetes em RHS
<seleção> if ( <exp_lógica> ) <instrução> [else <instrução>]
2) Uso de chaves em RHS para indicar que o que estácontido nelas pode ser: repetido indefinidamente
omitido completamente
a) <lista_iden> <identificador> {, <identificador>}
b) <comp> begin <stmt> {<stmt>} end
3) Lidar com opções de múltipla escolha
<for_stmt> for <var> := <expressão> (to|downto) <expressão> do <stmt>
não são terminais
Página 16
Linguagens de Programação – Capítulo 3
Comparação entre BNF e EBNF
BNF<expr> <expr> + <termo>
| <expr> - <termo> | <termo>
<termo> <termo> * <fator> | <termo> / <fator> | <fator>
EBNF<expr> <termo> {(+ | -)<termo>}<termo> <fator> {(* | /)<fator>}
Página 17
Linguagens de Programação – Capítulo 3
Grafo Sintático ( grafo de sintaxe)
Exemplo: Instrução if em ADA
<if_stmt> if <condição> then <stmts> {<else_if>} [else <stmts>] end_if
<else_if> elsif <condição> then <stmts>
Legenda:
não-terminais
terminais
if_stmt
end_if
elseelse_if
stmtsthencondiçãoif
stmts
else_if stmtsthencondiçãoelsif
Página 18
Linguagens de Programação – Capítulo 3
void expr ( ){ termo ( ); while ( prox_token == “+” || prox_token == “-” ){ lexical ( ); termo ( ); }}
Parsers – Analisadores sintáticos paralinguagens de programação
yacc: um dos mais usados (yet another compiler compiler)
Parsers: top – down (descendente)
bottom – up (ascendente)
Análise Sintática Descendente Recursiva
Exemplo: <expr> <termo> {(+ | -)<termo>}<termo> <fator> {(* | /)<fator>}<fator> <id> | (<expr>)
Chama uma rotina para cada não terminal
lexical coloca o próximo token de entrada em
prox_token( var global)
Página 19
Linguagens de Programação – Capítulo 3
void termo ( ){ fator ( ); while ( prox_token == “*” || prox_token == “/” ){ lexical ( ); fator ( ); }}
void fator ( ){ if (prox_token == ident ){ lexical ( );
return; } else if (prox_token == “(” ){
lexical ( ); expr( );
if (prox_token ==“)”{ lexical( ); return;
} else error ( );
} else error( );}
Página 20
Linguagens de Programação – Capítulo 3
(A discussão das características que autorizam o uso de parsers descendentes recursivos para uma gramática particular não será feita aqui)
Gramática de atributos Dispositivos para descrever mais detalhes da estrutura das linguagens de programação do que é possível com (a BNF) uma gramática livre de contexto
Existem características da estrutura das linguagens de programação difíceis/impossíveis de descrever comA BNF
Exemplos: “todas as variáveis devem ser declaradas antes de serem referenciadas”
“end de uma subrotina em ADA seguido de um nome deve coincidir com o nome da
subrotina”
Semântica Estática Análise necessária para verificar essas especificações. Pode ser feita em tempo de compilaçãoMais relacionada ainda com a sintaxe
Problema para parsers descendentes recursivos: recursão à esquerda. Ex: < A > < A > + < B >
Página 21
Linguagens de Programação – Capítulo 3
Atributos “Variáveis” associadas a símbolos gramaticais
Funções de computação de atributos Associadas a regras para especificar como os valores dos atributos são computados
Funções Predicadas Símbolo gramatical X
A(X) = S(X) H(X)
Conjunto de atributos
associados a X
Atributos Sintetizados
Atributos Herdados
“Filhos” na árvore de análiseRegra: X0 X1 ... Xn
S(X0) = f ( A(X1),...,A(Xn) )
H(Xj) = f ’ ( A(X0), A(X1),...,A(Xj-1) )
depende dos filhos
depende do pai e irmãos “menores”
1 j n
Página 22
Linguagens de Programação – Capítulo 3
Função predicada: g ( A(X0),..., A(Xn) )
expressão booleana
Se todos os valore de atributos em uma árvore de análise tiverem sido computados ela é totalmente atribuída
Atributos intrínsecos atributos sintetizados de vértices folhas, cujos valores são calculados fora da árvore de análise
Exemplo: Ada Regra sintática: <def_proc> procedure <nome_da_proc>[1] <corpo_da_proc> end <nome_da_proc>[2]
usados para distinguir as 2 ocorrências do mesmo não-
terminal
Regra semântica: <nome_da_proc>[1].string = <nome_da_proc>[2].string
Página 23
Linguagens de Programação – Capítulo 3
Exemplo: Compatibilidade de Tipos
<atribuição>
<var>
A
:=
<var>
A
<var>
B
<expressão>
stringtipo_efetivo
tipo_esperadotipo_efetivo
tipo_efetivo
tipo_efetivo
string string
+
5
4
33
2
1
Legenda
Regra 1Regra 2Regra 3Regra 4
Passos da construção1 2 3 4 5
Página 24
Linguagens de Programação – Capítulo 3
Semântica DinâmicaSemântica propriamente dita, significado das expressões / instruções / unidades do programa
Semântica
Operacional
Axiomática
Denotacional
Semântica Operacional - descreve o significado de um programa através da execução de suas instruções numa máquina ( real ou simulada,virtual ). Alterações no estado da máquina ao executar determinada instrução definem o significado desta
Estado S Estado S’instrução
Estado valores de todos os registros
( células de memória )
Página 25
Linguagens de Programação – Capítulo 3
Qual computador usar ? Hardware de um computador específico interpretador puro de sua linguagem de máquina
Complicado usar umamáquina real específica
Usar um computador de baixo nível, implementadocomo uma simulação de software
Semântica OperacionalDepende de algoritmos, não de
matemática
Tradução para linguagemDe baixo nível
“Rodar” o programa namáquina virtual
Exemplo: Instrução for do C
for ( expr1 ; expr2 ; expr3 ){ ... }
Semântica Operacional
expr1; loop: if expr2 = 0 goto out ... expr3; goto loop; out:
Página 26
Linguagens de Programação – Capítulo 3
Semântica Axiomática - baseia-se na lógica matemática Associada a um método para provar. Correção de programas que mostra a computação descrita por suaespecificação. ( limitada e de aplicação difícil )
Semântica Denotacional – dentre os métodos mais empregados, é o de maior rigor matemático. Baseia-sesolidamente na teoria das funções recursivas.
Idéia: Associar para cada entidade da linguagem um objeto matemático e uma função que os relacione (entidade e objeto )
Há maneiras rigorosas para manipular objetos matemáticos, mas não construções de Linguagens de Programação Os objetos denotam o significado das entidades sintáticas que lhes correspondem
Exemplo: <num_bin> 0 | 1 | <num_bin> 0 | <num_bin> 1
Página 27
Linguagens de Programação – Capítulo 3
<num_bin> 6
<num_bin>
<num_bin> ‘1’
‘1’
‘0’ 0
1
1
3
Árvore para 110 = 6
Função Semântica Mbin – associa os números binários aos inteiros decimais não-negativos
Mbin ( ‘0’ ) = 0Mbin ( ‘1’ ) = 1Mbin ( <num_bin> ‘0’ ) = 2 * Mbin ( <num_bin> ) +
Mbin ( ‘0’ ) Mbin ( <num_bin> ‘1’ ) = 2 * Mbin ( <num_bin> ) +
Mbin ( ‘1’ )Exemplo: <num_dec> 0|1|2| ... |9
| <num_dec> (0|1|2| ... |9 )
Mbin ( ‘0’ ) = 0 ,... , Mbin ( ‘9’ ) = 9Mbin ( <num_dec> ‘0’ ) = 10 * Mbin ( <num_bin> ) + 0 Mbin ( <num_dec> ‘9’ ) = 10 * Mbin ( <num_bin> ) + 9...
Página 28
Linguagens de Programação – Capítulo 3
Estado de um programaS = { <i1 , v1>,...,<in ,vn> }
ij nome da variável j
vj valor da variável j ( pode ser undef )
VARMAP ( i , j ) = vj
Me ( <expr> , s ) = devolve o valor de <expr> no estado s ( Me ( <expr> , s ) {error} )
Ma ( x = E, s ) = devolve o estado do programa após a execução da instrução x = EMs1 ( K, s ) = devolve o estado do programa após a execução da lista de instruções K
lista de instruções
Top Related