Capítulo 5 Análise sintática
|
|
|
- Sônia Palha Benevides
- 7 Há anos
- Visualizações:
Transcrição
1 Capítulo 5 1. Objetivo 2. Estratégias gerais de parsing 3. descendente (top-down) 3.1. Analisador sintático com retrocesso (backtracking) 3.2. Analisador sintático predicativo recursivo 3.3. Analisador sintático predicativo não recursivo Parser LL 3.4. Construção de tabelas sintáticas predicativas (Tabelas Oráculo) 4. ascendente (bottom-up) 4.1. Parser por transição-redução (método geral) 4.2. Parser LR 4.3. Parser SLR 4.4. Parser LALR 1/183
2 Objetivo Objetivo 2/183
3 Objetivo Gramática da linguagem árvore de sintaxe Sequência de símbolos PARSER Aceitação ou Erro Dado - uma gramática livre do contexto G - uma sequência a de símbolos terminais (frase) pretende-se - verificar se a é uma frase válida de L(G) - reconhecer a forma da frase (identificar as produções de G). 3/183
4 Objetivo Em cada momento do processo, a a a a em que: a sequência já percorrida a próximo símbolo a analisar (token) a sequência por analisar a é uma frase de L(G) se e só se * S a 4/183
5 Objetivo Em cada momento do processo, - ou existe uma derivação * S m a d, onde m com m T* e d (S T)* a. { Fase de possível aceitação } - ou não existe nenhuma derivação que aceite a a. { ERRO: não é frase de L(G) } 5/183
6 Estratégias gerais de parsing Estratégias gerais de parsing 6/183
7 Estratégias gerais de parsing Existem duas estratégias gerais de parsing: - reconhecimento descendente ( top-down ) - reconhecimento ascendente ( bottom-up ). Reconhecimento descendente ( Top-Down ) - A árvore é construída da raiz para as folhas - Em cada vértice (com um símbolo não terminal A): - selecionar uma produção com A à esquerda e construir os vértices filhos de A com os símbolos à direita nessa produção; - selecionar o vértice onde continuar. - Termina quando todas as folhas são símbolos terminais. - A aceitação é obtida se a sequência a for esgotada. - As decisões são tomadas por observação de a, chamado lookahead símbolo. 7/183
8 Estratégias gerais de parsing Reconhecimento ascendente ( Bottom-up ) - A árvore é construída das folhas para a raiz. - Os símbolos de a são associados até se reconhecer o lado direito de uma produção. - A aceitação é obtida se, esgotada a sequência a, o símbolo inicial estiver na raiz da árvore. 8/183
9 descendente (top-down) descendente (top-down) 9/183
10 descendente (top-down) Dada uma frase a, a análise descendente pode ser vista como uma tentativa de se, - encontrar uma derivação mais à esquerda para a, - construir uma árvore gramatical para a a partir da raiz, criando os nós em pré-ordem. Desta forma, - a frase a é percorrida da esquerda para a direita, - vão-se identificando derivações esquerdas, - enquanto a árvore de sintaxe vai sendo construída. 10/183
11 descendente (top-down) 1. descendente com retrocesso (backtracking) O reconhecimento é feito por expansão de regras sintáticas, substituindo - símbolos não-terminais do lado esquerdo de produções, - pelos símbolos do lado direito das produções. Depois, a expansão das regras sintáticas é confirmada - por emparelhamento - dos símbolos da frase de entrada (a) - com os símbolos terminais das regras sintáticas. - se não emparelhar, então terá que haver retrocesso no processo ( backtracking ). O retrocesso ( backtrack ) é resultado da existência de várias produções com o mesmo símbolo no lado esquerdo. 11/183
12 descendente (top-down) Algoritmo: Entrada: Uma gramática G e uma frase a Saída: Árvore de derivação 1. Criar um nó com o símbolo inicial da gramática. 2. Substituir o símbolo não-terminal situado mais à esquerda da árvore de derivação pelos símbolos do lado direito da produção cujo lado esquerdo é o símbolo substituído. Este passo termina quando o primeiro símbolo da produção for um símbolo terminal. 3. Se o primeiro símbolo ainda não processado de a não emparelhar com o primeiro símbolo da produção selecionada no passo anterior, recuar para o passo 2 e pesquisar outra alternativa ( backtrack ); se não existir outra alternativa, o algoritmo termina sem sucesso. 4. Emparelhar, da esquerda para a direita, os símbolos de a com os símbolos terminais nas folhas da árvore de derivação, até que aconteça uma das três hipóteses: - o emparelhamento de símbolos falha terminar sem sucesso; - é detetada na folha da árvore um símbolo não-terminal regressar ao passo 2; - todos os símbolos de a foram emparelhados e todas as folhas da árvore contêm apenas símbolos terminais que foram emparelhados com símbolos de a terminar com sucesso. 12/183
13 descendente (top-down) Vantagens: - simplicidade de implementação do algoritmo que lhe está associado. 13/183
14 descendente (top-down) Desvantagens: - Não aceita gramáticas recursivas à esquerda; por ex., numa entrada com, o analisador entra em ciclo infinito de expansão duma produção recursiva à esquerda - A ordem da escolha das alternativas determina a linguagem aceite pelo analisador; por ex., a frase aa é aceite pelo analisador se for expandida em primeiro a produção S B, o que não acontece se a primeira produção a ser expandida for S aa, pois o primeiro símbolo da entrada, a, emparelha com o primeiro símbolo terminal da produção S aa, mas o segundo símbolo de entrada, a, não pode ser derivado a partir de A. - Em caso de entrada com, não é possível identificar as causas de, pois não há distinção entre retrocesso por e por necessidade de pesquisa de alternativas - A operação de retrocesso é muito demorada, degradando o desempenho ( performance ) da análise sintática. 14/183
15 descendente (top-down) 2. Analisador sintático predicativo recursivo Definição: Um Parser recursivo-descendente diz-se profético (ou predicativo) quando: - a análise do a, ou lookahead, determina univocamente a produção a utilizar; - a execução de um procedimento simula a sequência de símbolos do lado direito dessa produção. Um Parser predicativo é caracterizado por tomar sempre decisões irrevogáveis, isto é, sem backtracking. Para se construir um analisador predicativo, é preciso: - dado o lookahead a (a = a) e o símbolo não terminal A a ser expandido, - conhecer qual das alternativas da produção A b1 b2 bn é a única que deriva uma cadeia que começa por a. 15/183
16 descendente (top-down) Ou seja, a alternativa adequada precisa ser detetável examinando-se apenas o primeiro símbolo da cadeia que a mesma deriva. Algoritmo: {XÎT} Reconhecer_X: Se (X = a ) Então avançar (a) { reconhecimento parcial } Senão ERRO {XÎS} Reconhecer_X: { em função de a, escolher uma produção p : X X1 X2... Xn } Reconhecer_X1 Reconhecer_X2... Reconhecer_Xn 16/183
17 descendente (top-down) Partindo do símbolo inicial (S) e do início de a: Parser_RD: Avançar (a); Reconhecer_S ; Se ( a = e) Então RECONHECIMENTO Senão ERRO Para a construção de um Parser predicativo é necessário estabelecer um método que, - conhecidos o lookahead (a ) e o símbolo a reconhecer, - determine univocamente a produção a utilizar. Uma das formas é utilizar uma tabela sintática (Tabela Oráculo), M[X,a] = p, que significa: a produção p será aplicada se pretender-se expandir o símbolo não terminal X e o lookahead for um símbolo terminal a (a = a). 17/183
18 descendente (top-down) Pretende-se elaborar um Parser predicativo que seja: - independente da gramática; - constituído por uma única função, onde o símbolo é passado como parâmetro; - eficiente; Reconhecer(X): Se (X Î T) Então Se (X = a ) Então Da_Simbolo (a ) Senão ERRO Senão np Oráculo(X, a ) Se (np ¹ ERRO) Então Para cada Y Î Produção[np] Reconhecer (Y) Senão ERRO 18/183
19 descendente (top-down) - ainda é recursivo; - mas é mais cómodo e mais independente da linguagem: a informação relativa à linguagem está guardada em duas estruturas de dados. Otimização da Função Oráculo: ORÁCULO : (S È T) x T (X, a ) { skip, np, } ação Se (X Î T e X = a ) Então ação = skip { o reconhecedor léxico reconhece um símbolo terminal } * Se (X Î T e X ¹ a ) ou (X Î S e $ p : X a ) Então ação = * Se (X Î S e $1 p : X a ) Então p ação = np 19/183
20 descendente (top-down) Nota: * * Se (X Î S e $ p', p'' : X a e X a ) Então p' p'' Situação de conflito Reconhecer (X): ação ORÁCULO (X, a ) Caso (ação) Seja : ERRO skip : Da_Simbolo(a ) np : Para (" Y Î Produção[np]) Fazer Reconhecer (Y) Em cada momento continua a haver apenas dois casos possíveis: - ERRO - Possível reconhecimento. 20/183
21 Analisador sintático predicativo não recursivo Analisador sintático predicativo não recursivo 21/183
22 Analisador sintático predicativo não recursivo Pode-se construir um analisador predicativo usando uma pilha (sem recursividade). Um analisador sintático predicativo não recursivo é composto por: - uma frase de entrada, - uma pilha, - uma tabela sintática, e - um fluxo de saída. Frase de entrada Pilha X Y Z $ a + b $ Programa de Análise Sintática Predicativa Saída Tabela Sintática M 22/183
23 Analisador sintático predicativo não recursivo A frase de entrada é seguida por um $ à direita (indica o fim da sequência de símbolos) A pilha Z: - contém uma sequência de símbolos gramaticais, - com $ a indicar o fundo da pilha; - inicialmente, a pilha contém o símbolo inicial da gramática acima de $. A tabela sintática é um array bidimensional M[A, a] onde, - A é um símbolo não terminal, terminal ou $, - a é um símbolo terminal ou $. O analisador sintático é um programa que se comporta da seguinte forma: - considera o símbolo do topo da pilha X e o lookahead a (estes dois símbolos determinam a ação do analisador). 23/183
24 Analisador sintático predicativo não recursivo Existem três possibilidades: 1. Se X = $, o analisador pára a análise com sucesso, se a = $. 2. Se X = a (a é terminal), o analisador sintático remove X da pilha e avança o apontador da entrada para o próximo símbolo (próximo lookahead), a = a. 3. Se X é um não terminal, o programa consulta a entrada M[X, a] da tabela sintática M, que será uma produção-x (X a) da gramática ou ERRO. Por ex., se M[X,a] = { X U V W } substitui-se X no topo da pilha por W V U (com U no topo); se M[X, a] = chama-se uma rotina de recuperação de s. Algoritmo: predicativa não recursiva Entrada: Uma frase a e uma tabela sintática M para a gramática G = (S, T, P, S). Saída: Uma derivação mais à esquerda (se a L(G)) ou uma indicação de. Método: Introduzir os símbolos $ e S na pilha Z (S é o símbolo inicial de G) ¾ Topo(Z) = S a = primeiro símbolo de a 24/183
25 Analisador sintático predicativo não recursivo Repetir Se (Topo(Z) Î T) Então Se (Topo(Z) = a ) Então Pop(Z) Da_Simbolo(a ) Senão ERRO Senão Se (Topo(Z) Î S) Então Se M[Topo(Z), a ] = { X Y1Y2 Yn } Então Pop(Z) Para i desde n até 1 Fazer Push(Z, Yi) Senão ERRO Até (Topo(Z) = $) 25/183
26 Analisador sintático predicativo não recursivo Resumindo, temos que sendo a : sequência de símbolos terminais já analisados Z : sequência de símbolos terminais e não terminais a reconhecer, mantém-se invariante: * S a Z no início : a = e e Z = S e no fim : a = a e Z = e { se tudo correr bem } Deste modo: - não é necessário construir a árvore de derivação - nem guardar a - Z funciona como uma pilha, - portanto, é possível construir um algoritmo iterativo. 26/183
27 Analisador sintático predicativo não recursivo A este analisador sintático dá-se o nome de Parser LL (scan input from Left to right and construct Leftmost derivation). Falta apenas incluir uma ação de aceitação: Ação = { skip, np,, ac }. A aceitação ocorre quando: (Z = $) e (a = $) pois não há símbolo para reconhecer nem falta analisar nenhum símbolo. 27/183
28 Analisador sintático predicativo não recursivo ParserLL (algoritmo LL): Push(Z, $) Push(Z, S) Da_Simbolo(a ) Repetir Acção Oráculo(Topo(Z), a ); Pop(Z); Caso Acção Seja : Erro; ac : ; skip : Da_Simbolo(a ); np : Para i desde n até 1 Fazer { X Y1Y2 Yn } Push(Z, Yi); Até Ação = ac; 28/183
29 Construção de tabelas sintáticas predicativas (Tabelas Oráculo) Construção de tabelas sintáticas predicativas (Tabelas Oráculo) 29/183
30 Construção de tabelas sintáticas predicativas (Tabelas Oráculo) A ideia subjacente ao algoritmo associado à construção destas tabelas é a seguinte: - suponha-se que A a é uma produção e que a Î First(a); - logo, o analisador sintático irá expandir A através de a quando o símbolo de entrada corrente (lookahead) for a (a = a). A única complicação ocorre quando a = e ou a e. Neste caso, deve-se expandir A de novo através de a se: - a Î Follow(A) ou - $ (na entrada) foi atingido e $ Î Follow(A). 30/183
31 Construção de tabelas sintáticas predicativas (Tabelas Oráculo) Algoritmo: Entrada : Gramática G Saída : Tabela Oráculo M[X, Y] em que, X (S T { $ }) e Y (T { $ }) Descrição do método: 1. Para cada produção A a de G, executar os passos 2 e Para cada símbolo terminal a Î First(a), fazer M[A, a] = A a. 3. Se e Î First(a), então para cada b Î Follow(A), fazer M[A, b] = A a. Se e Î First(a) e $ Î Follow(A), fazer M[A, $] = A a. 4. Fazer a cada entrada da tabela M do tipo M[x, x] = SKIP, em que x T. 5. Fazer à entrada da tabela M, M[$, $] = AC. 6. Fazer a cada entrada indefinida da tabela M, M[k, j] = ERRO. Os passos 2 e 3 podem ser substituídos pelo seguinte único passo: 2-3. Para cada símbolo terminal a Î Lookhead(A a), fazer M[A, a] = A a. 31/183
32 Exemplo de um analisador sintático predicativo não recursivo Exemplo de um analisador sintático predicativo não recursivo 32/183
33 Exemplo de um analisador sintático predicativo não recursivo Considere a seguinte gramática G = (Σ, T, P, S), em que Σ = { S, A, B, C, D }, T = { a, b, c, d, e, f }, P= { 1) S DC; 2) A a; 3) A Cb; 4) B e; 5) B c; 6) B da; 7) C e; 8) C f; 9) D AB } 33/183
34 Exemplo de um analisador sintático predicativo não recursivo First (a) = { a } Follow (S) = { $ } First (b) = { b } Follow (A) = { c, d, e, f } First (c) = { c } Follow (B) = { e, f } First (d) = { d } Follow (C) = { $, b } First (e) = { e } Follow (D) = { e, f } First (f) = { f } First (S) = { a, e, f } First (A) = { a, e, f } First (B) = { ε, c, d } First (C) = { e, f } First (D) = { a, e, f } 34/183
35 Exemplo de um analisador sintático predicativo não recursivo 1) S DC First(S DC) = First(D) = { a, e, f } (e First(D)) M[S, a] = M[S, e] = M[S, f] = 1 Oráculo S $ a b 1 c d e f 1 1 A B C D $ a b c d e f 35/183
36 Exemplo de um analisador sintático predicativo não recursivo 2) A a First(A a) = First(a) = { a } M[A, a] = 2 Oráculo $ a S 1 A 2 b c d e f 1 1 B C D $ a b c d e f 36/183
37 Exemplo de um analisador sintático predicativo não recursivo 3) A Cb First(A Cb) = First(C) = { e, f } (e First(C)) M[A, e] = M[A, f] = 3 Oráculo $ a b c d e f S A B C D $ a b c d e f 37/183
38 Exemplo de um analisador sintático predicativo não recursivo 4) B e Como e First(e), M[B, x] = 4, para x Follow(B) = { e, f } M[B, e] = M[B, f] = 4 Oráculo $ a b c d e f S A B C D $ a b c d e f 38/183
39 Exemplo de um analisador sintático predicativo não recursivo 5) B c First(B c) = First(c) = { c } M[B, c] = 5 Oráculo $ a b c d e f S A B 5 C D $ a b c d e f 39/183
40 Exemplo de um analisador sintático predicativo não recursivo 6) B da First(B da) = First(d) = { d } M[B, d] = 6 Oráculo $ a b c d e f S A B 5 6 C D $ a b c d e f 40/183
41 Exemplo de um analisador sintático predicativo não recursivo 7) C e First(C e) = First(e) = { e } M[C, e] = 7 Oráculo $ a b c d e f S A B C D $ a b c d e f 41/183
42 Exemplo de um analisador sintático predicativo não recursivo 8) C f First(C f) = First(f) = { f } M[C, f] = 8 Oráculo $ a b c d e f S A B C 5 6 D $ a b c d e f 42/183
43 Exemplo de um analisador sintático predicativo não recursivo 9) D AB First(D AB) = First(A) = { a, e, f } (e First(A)) M[D, a] = M[D, e] = M[D, f] = 9 Oráculo $ a b c d e f S A B 5 C D 9 6 $ a b c d e f 43/183
44 Exemplo de um analisador sintático predicativo não recursivo M[x, x] = SKIP, para x T Oráculo $ a M[$, $] = AC b c d e f S A B 5 6 C D $ a b c 9 AC SKIP SKIP SKIP d e f SKIP SKIP SKIP 44/183
45 Exemplo de um analisador sintático predicativo não recursivo M[X, Y] = E (Erro), para as entradas vazias Oráculo $ a b c d e f S E 1 E E E 1 1 A E 2 E E E 3 3 B E E E C E E E E E 7 8 D E 9 E E E 9 9 $ AC E E E E E E a E SKIP E E E E E b E E SKIP E E E E c E E E SKIP E E E d E E E E SKIP E E e E E E E E SKIP E f E E E E E E SKIP 45/183
46 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Push(Z, $) Push(Z, S) S $ Oraculo(Topo(Z), a ) = Oraculo(S, e) = 1 46/183
47 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, C) Push(Z, D) D C $ Oraculo(Topo(Z), a ) = Oraculo(D, e) = 9 47/183
48 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, B) Push(Z, A) A B C $ Oraculo(Topo(Z), a ) = Oraculo(A, e) = 3 48/183
49 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, b) Push(Z, C) C b B C $ Oraculo(Topo(Z), a ) = Oraculo(C, e) = 7 49/183
50 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, e) e b B C $ Oraculo(Topo(Z), a ) = Oraculo(e, e) = SKIP 50/183
51 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Da_Simbolo(a ) b B C $ Oraculo(Topo(Z), a ) = Oraculo(b, b) = SKIP 51/183
52 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, e) Da_Simbolo(a ) B C $ Oraculo(Topo(Z), a ) = Oraculo(B, d) = 6 52/183
53 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, A) Push(Z, d) d A C $ Oraculo(Topo(Z), a ) = Oraculo(d, d) = SKIP 53/183
54 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Da_Simbolo(a ) A C $ Oraculo(Topo(Z), a ) = Oraculo(A, f) = 3 54/183
55 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, b) Push(Z, C) C b C $ Oraculo(Topo(Z), a ) = Oraculo(C, f) = 8 55/183
56 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, f) f b C $ Oraculo(Topo(Z), a ) = Oraculo(f, f) = SKIP 56/183
57 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Da_Simbolo(a ) b C $ Oraculo(Topo(Z), a ) = Oraculo(b, b) = SKIP 57/183
58 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Da_Simbolo(a ) C $ Oraculo(Topo(Z), a ) = Oraculo(C, e) = 7 58/183
59 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Push(Z, e) e $ Oraculo(Topo(Z), a ) = Oraculo(e, e) = SKIP 59/183
60 Exemplo de um analisador sintático predicativo não recursivo ebdfbe$ Pop(Z) Da_Simbolo(a ) $ Oraculo(Topo(Z), a ) = Oraculo($, $) = AC FIM. A frase pertence à linguagem gerada pela gramática G, L(G). 60/183
61 Análise Sintática Ascendente (bottom-up) 61/183
62 1. Princípios gerais O objetivo da análise sintática ascendente é a construção da árvore de derivação, a partir das folhas, em direção à raiz. A árvore de derivação é construída percorrendo a sequência a de símbolos de entrada (frase) da esquerda para a direita (e armazenada numa string s): esta operação é designada por deslocamento ( shift ) da posição do analisador sintático. Quando é detetada uma sequência de símbolos gramaticais idêntica ao lado direito de uma produção, esses símbolos são substituídos pelo símbolo não-terminal do lado esquerdo da produção: esta operação é designada por redução ( reduce ). 62/183
63 Exemplo: Considere-se a gramática com as seguintes 6 produções : 1) S A B c 2) S B A c 3) A a 4) A a A 5) B b 6) B b B A frase abbc pode ser reduzida até ao símbolo inicial da gramática S em 4 etapas: SÞABcÞAbBcÞAbbcÞabbc Etapa Sequência de Símbolos Gramaticais Regra Gramatical Reduzida 1 abbc 3 2 Abbc 5 3 AbBc 6 4 ABc 1 5 S O procedimento corresponde a uma sequência de derivação à direita. 63/183
64 2. Método geral: parser por transição-redução s = m b e p : A b s=ma Redução de b em A pela produção p Cada redução corresponde a uma subida de nível na árvore de derivação. p:a XY Z A m X Y Z depois disso, se : s = m A = f d A e p : B d A s=fb B A f d X Y Z Sequência reconhecida: ao atingir a raiz da árvore (s = S) não restam símbolos em a. 64/183
65 Um parser bottom-up é caracterizado por dois tipos de operações básicas: Redução: s=mb s=ma Transição: s = m a e Avançar( a ) No início do processo: s = e e a = a No fim do processo: s = S e a = e { Aceitação } Num parser top-down : No início do processo: s = S e a = a No fim do processo: s = e e a = e { Aceitação } 65/183
66 Em qualquer momento de parsing bottom-up : - Ou existe uma derivação: S s a b { estado possível de aceitação } - Ou não existe nenhuma derivação a efetuar: estado de. Assumindo (por enquanto) que todas as decisões podem ser tomadas apenas em função dos valores de S e de a, define-se: ORÁCULO : (T È S)* x T { shift, reduce, ac, } (s, a ) ação 66/183
67 Parser_Trans_Red: Inicializar(s) ; Da_Simbolo(a ) ; Repetir ação ORÁCULO(s, a ) ; Caso ação Seja : ERRO ; ac: ; shift: s s a ; Da_Simbolo(a ) ; reduce: s s - b ; { p : A b } s sa; Até ac ; 67/183
68 Exemplo: Dada a gramática G com as seguintes produções: p1 : E E + E p2 : E E * E p3 : E ( E ) p4 : E id analisar a expressão: a + (b * c) $ 68/183
69 p1 : E E + E p2 : E E * E s a a a +(b*c)$ p3 : E ( E ) p4 : E id Ação Shift E 69/183
70 p1 : E E + E p2 : E E * E s a a a a +(b*c)$ + (b*c)$ p3 : E ( E ) p4 : E id Ação Shift Reduce p4 70/183
71 p1 : E E + E p2 : E E * E s a a p3 : E ( E ) Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift p4 : E id Shift 71/183
72 p1 : E E + E p2 : E E * E s a a p3 : E ( E ) Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift p4 : E id Shift 72/183
73 p1 : E E + E p2 : E E * E s a a p3 : E ( E ) Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift p4 : E id Shift 73/183
74 p1 : E E + E p2 : E E * E s a a p3 : E ( E ) p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Shift Reduce p4 74/183
75 p1 : E E + E p2 : E E * E s a a p3 : E ( E ) p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift Shift 75/183
76 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift Shift 76/183
77 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Shift Reduce p4 77/183
78 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Reduce p4 E + (E * E ) $ Reduce p2 Shift 78/183
79 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Reduce p4 E + (E * E ) $ Reduce p2 E+(E ) $ Shift Shift 79/183
80 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Reduce p4 E + (E * E ) $ Reduce p2 E+(E ) $ Shift E+(E) $ e Reduce p3 Shift 80/183
81 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Reduce p4 E + (E * E ) $ Reduce p2 E+(E ) $ Shift E+(E) $ e Reduce p3 E+E $ e Reduce p1 Shift 81/183
82 p1 : E E + E p2 : E E * E s a p3 : E ( E ) a p4 : E id Ação a +(b*c)$ a + (b*c)$ Reduce p4 E + (b*c)$ Shift E+ ( b*c)$ Shift E+( b *c)$ Shift E+(b * c)$ Reduce p4 E+(E * c)$ Shift E+(E* c )$ Shift E+(E*c ) $ Reduce p4 E + (E * E ) $ Reduce p2 E+(E ) $ Shift E+(E) $ e Reduce p3 E+E $ e Reduce p1 E $ e ac Shift 82/183
83 3. Parser LR Os analisadores sintáticos LR apresentam diversas vantagens: - Reconhecem praticamente todos os construtores de linguagens de programação estruturadas em blocos, expressas em gramáticas independentes do contexto. - São mais gerais que outros analisadores sintáticos e revelam o mesmo grau de eficiência. - Podem detetar cedo s sintáticos, quando tal é possível, ao pesquisar a entrada da esquerda para a direita. Maior inconveniente destes analisadores: - a complexidade da sua implementação. No entanto, a existência de ferramentas que geram automaticamente analisadores sintáticos (tal como o YACC) eliminou este problema. 83/183
84 O analisador sintático LR: Left-scan, leitura da frase da esquerda para a direita, Rightmost derivation, derivação da direita para a esquerda, - pesquisa os elementos da frase da esquerda para a direita (tal como os analisadores descendentes) e - constrói uma derivação à direita, invertida. 84/183
85 Arquitetura do analisador sintático LR Entrada Pilha Frase$ Reconhecedor Saída Ações Saltos 85/183
86 Tabelas do analisador sintático LR As duas tabelas do analisador sintático ascendente LR são designadas por: - tabela de ações ( actions ) e - tabela de saltos ( goto ). A tabela de ações A[estado, entrada] é indexada pelo estado e pelo símbolo de entrada (terminal), e possui um dos quatro valores : 1. Desloca s ( shift ), na qual s é um estado. 2. Reduz n ( reduce ), na qual n é a referência a uma produção X a. 3. Aceita ( accept ). 4. Erro. 86/183
87 A tabela de saltos G[estado, símbolo]: - é indexada pelo estado e pelo símbolo não-terminal, - possui, nalgumas células, uma indicação da referência a um estado. A construção das tabelas pode ser efetuada utilizando três metodologias distintas: 1. SLR ( Simple LR ) é o método mais simples, mas também o menos poderoso, porque não é possível construir as tabelas para algumas gramáticas. 2. LR canónico é o método mais poderoso e, em simultâneo, o mais complexo, sendo aquele que mais memória necessita para armazenar a tabela. 3. LALR ( LookAhead LR ) este método é um compromisso entre os métodos SLR e LR canónico, e funciona para a maior parte das linguagens de programação. 87/183
88 Reconhecimento de uma frase Um parser LR implementa o autómato determinístico de pilha, capaz de reconhecer uma dada gramática do tipo LR(k), onde: - os estados do autómato representam valores da string s - cada transição: s s a corresponde à determinação do próximo estado, em função do atual e de a T - cada redução: s s b determina o estado anterior quando do atual se retira b (S T)*, s sa determina o próximo estado em função do atual e de A S - transições são implementadas por uma tabela chamada Oráculo_T ou Ação: Oráculo_T : Q T { shift, reduce, ac, } (Q P) (q, a ) ( ação, q np ) 88/183
89 - os estados anteriores são recuperados se, numa pilha F de estados forem efetuados Pop s em número igual ao dos símbolos em β - mudanças de estado por redução são implementadas por um Oráculo_S ou Goto: Oráculo_S : Q S Q (q, A) q 89/183
90 Algoritmo: Proc Parser_LR: Inicializar(F) ; Da_Simbolo(a ) ; Repetir acção Oráculo_T(Topo(F), a ) ; Caso ação Seja : ERRO ; ac: ; shift: q ação.estado ; Push(F, q) ; Da_Simbolo(a ) ; reduce: np ação.num_prod ; (A, nsd) Prod[np] ; Para i desde 1 até nsd Fazer Pop(F) ; q Oráculo_S(Topo(F), A) ; Push(F, q) ; Até ac ; 90/183
91 - Como associar estados a valores de s? - Como construir os Oráculos? - Será sempre possível? Cada passo do processo LR é caracterizado por : ( s, a ) CONFIGURAÇÃO LR Cada decisão é tomada em função de: A d.b produção em reconhecimento e ponto (.) de decisão; w o prefixo de s, com s = w d; m o contexto direito de A. 91/183
92 Ao conjunto destes três elementos chama-se: Item LR [ w, A d. b, m ] Uma configuração ( s, a ) satisfaz a condição não- LR se : * bm a A cada configuração não-, está associado um e um só item LR. No início : (e, a) [ e, Z. S $, e ] No fim : (S, $) [ e, Z S. $, e ] 92/183
93 Só existem três formas de itens LR (a que correspondem três tipos de ações): 1) [ ω, A d. a b, m ] a que corresponde a transição: (wd, a r ) (wd a, r) s 2) [ ω, A d. B b, m ] a ação a tomar depende de B, e virá a ser tomada em função de [ wd, B.g, bm ] 3) [ w, A d. e, m ] a que corresponde a redução (wd, m) (w A, m) r A cada configuração (s, a ) está associado um item [ w, A d. b, m ] que determina de forma única a ação a executar, sendo necessário verificar que a é derivável de b m. 93/183
94 Construção do autómato Para um dado item LR [ w, A d. b, m ] chama-se item LR(k) a [ A d. b, First(k, m) ] Os estados de um autómato LR(k) são constituídos por itens LR(k). Num autómato LR(0) os estados são [ A d. b ]. Exemplo: Construir o autómato não determinístico LR(0) para a gramática G com as seguintes produções: 1) Z S $ 2) S a 3) S b A A 4) A ε 5) A A a 94/183
95 95/183
96 96/183
97 97/183
98 98/183
99 99/183
100 100/183
101 101/183
102 102/183
103 103/183
104 104/183
105 105/183
106 106/183
107 107/183
108 108/183
109 109/183
110 110/183
111 Algoritmo para construir o autómato determinístico: Alfabeto : S T Estado inicial : [ Z. S $, e ] Cada estado é formado por : - Um item LR(k) : [ A d. b, n ] - Pelo seu fecho, isto é, todos os itens da forma [ B. g, m ] sempre que b = B r, com m = First(k, r n) - E pelo fecho de cada um desses itens. A função de transição : D = Q (T S) Q para cada item LR(k) associado ao estado q [ A d. B r, n ] B T S D (q, B) = q com q = [ A d B. r, n ] Exemplo: construir o autómato determinístico LR(0) para a gramática G anterior. 111/183
112 112/183
113 113/183
114 114/183
115 115/183
116 116/183
117 117/183
118 118/183
119 119/183
120 120/183
121 121/183
122 122/183
123 123/183
124 124/183
125 125/183
126 126/183
127 NOTAS: - Uma redução corresponde a recuar no grafo (com o conhecimento da produção). { redução por S baa } - Num parser LR(0), a redução é feita qualquer que seja o a ; basta que tenha acabado o reconhecimento da produção atual. 127/183
128 - Neste parser LR(0) podem ocorrer duas situações de conflito : { redução por A e } { redução por S baa } { redução por A Aa } Por exemplo, ao estado 5 estão associados: [ A e, m ] e [ A A.a, a ] Se a First(m) é impossível decidir: redução por A e, ou transição para [ A Aa., a ]. Para fazer o reconhecimento basta conhecer: - A identificação (número) de cada estado; - Transições ou reduções definidas para esse estado. 128/183
129 A partir do autómato determinístico A constroem-se as Tabelas Oráculo, da seguinte forma: - q Q, X S Oráculo_S (q, X) = sq', se (q, q')x A Oráculo_S (q, X) =, caso contrário - q Q, t T Oráculo_T (q, t) = sq', se (q, q')t A Oráculo_T (q, t) = rp, se [ A a., n ] : t First(k, n) Oráculo_T (q, t) =, caso contrário q [ Z S.$, e ] e t = $ Oráculo_T (q, t) = AC 129/183
130 Tabela Oráculo (exemplo anterior): a a b $ S A 1 s3 s4 s2 2 AC t 3 r2 r2 r2 a 4 r4 r4 r4 s5 d 5 s7/r4 r4 r4 s6 6 s7/r3 r3 r3 7 r5 r5 r5 e s o s Oráculo_T Oráculo_S { 2 conflitos redução/transição não é LR(0) } 130/183
131 Construir o autómato determinístico LR(1) para a mesma gramática: First(S) = { a, b } First(A) = { a, e } Follow(S) = { $ } Follow(A) = { a, $ } 131/183
132 1 [ Z.S$, ] 132/183
133 1 [ Z.S$, ] [ S.a, $ ] First($e) = { $ } [ S. b A A, $ ] First($e) = { $ } 133/183
134 1 [ Z.S$, ] S 2 [ Z S. $, ] AC ( = $) [ S.a, $ ] [ S.bAA, $ ] 134/183
135 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC ( = $) [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) 135/183
136 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 4 [ S b.aa, $ ] 136/183
137 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 4 [ S b.aa, $ ] [ A., a/$ ] First(A$) = { a, $ } [ A. A a, a/$ ] First(A$) = { a, $ } red#4 ( = a/$) 137/183
138 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] A [ S ba.a, $ ] [ A A. a, a/$ ] [ A., a/$ ] [ A. A a, a/$ ] red#4 ( = a/$) 138/183
139 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] [ A A. a, a/$ ] red#4 [ A., $ ] ( = $) [ A. A a, $ ] First($) = { $ } First($) = { $ } red#4 ( = a/$) 139/183
140 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] red#4 ( = a/$) A [ S ba.a, $ ] [ A A. a, a/$ ] red#4 [ A., $ ] ( = $) [ A. A a, $ ] First($) = { $ } red#4 ( = a) [ A., a ] First(a$) = { a } [ A.Aa, a ] First(a$) = { a } First($) = { $ } 140/183
141 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] [ A A. a, a/$ ] red#4 [ A., a/$ ] ( = a/$) [ A. A a, a/$ ] red#4 ( = a/$) 141/183
142 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] [ A A. a, a/$ ] red#4 [ A., a/$ ] ( = a/$) [ A. A a, a/$ ] red#4 ( = a/$) a 6 [ A A a., a/$ ] red#5 ( = a/$) 142/183
143 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] [ A A. a, a/$ ] red#4 [ A., a/$ ] ( = a/$) [ A. A a, a/$ ] red#4 ( = a/$) A 7 [ S b A A., $ ] [ A A. a, a/$ ] red#3 ( = $) a 6 [ A A a., a/$ ] red#5 ( = a/$) 143/183
144 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] 7 A [ A A. a, a/$ ] red#4 [ A., a/$ ] ( = a/$) [ A. A a, a/$ ] red#4 ( = a/$) [ S b A A., $ ] [ A A. a, a/$ ] red#3 ( = $) a a 6 [ A A a., a/$ ] red#5 ( = a/$) 144/183
145 1 [ Z.S$, ] S 2 a 3 [ Z S. $, ] AC [ S.a, $ ] [ S.bAA, $ ] [ S a., $ ] red#2 ( = $) b 5 4 [ S b.aa, $ ] [ A., a/$ ] [ A. A a, a/$ ] A [ S ba.a, $ ] 7 A [ A A. a, a/$ ] red#4 [ A., a/$ ] ( = a/$) [ A. A a, a/$ ] red#4 ( = a/$) [ S b A A., $ ] [ A A. a, a/$ ] red#3 ( = $) a a 6 [ A A a., a/$ ] red#5 ( = a/$) Os Follow's são apenas utilizados para decidir quando devem ser feitas reduções. 145/183
146 Tabela Oráculo LR(1) (exemplo anterior): a a b $ S A 1 s3 s4 s2 e 2 AC s 3 r2 4 r4 r4 s5 5 s6 r4 s7 o 6 r5 r5 s 7 s8 r3 8 r5 t a d Oráculo_T Oráculo_S { não existem conflitos é LR(1) } 146/183
147 Conflito redução/transição Resumindo e concluindo: - Um item LR(k) da forma [ A a.xb, m ] determina uma transição por X - Um item LR(k) da forma [ A a., m ] determina uma redução por A a para todo o a First(k, m). As possíveis situações de conflito são - Conflito redução-transição ao mesmo estado estão associados 2 itens LR(k) da forma: [ A a.ab, m ] e [ B d., n ], com a First(k, n) 147/183
148 - Conflito redução-redução ao mesmo estado estão associados 2 itens LR(k) da forma: [ A a., m ] e [ B b., n ] com First(k, m) First(k, n). - Uma dada gramática satisfaz a condição LR(k) se não provocar conflitos em nenhum dos estados. 148/183
149 Exercício: Verificar se a gramática não-ambígua de expressões é LR(0) ou LR(1). Produções: p1: Z S $ p2: S E p3: E E + T p4: E T p5: T ( E ) p6: T id 149/183
150 { conflito redução/transição no estado 5 não é LR(0) } 150/183
151 Construção do autómato LR(1): First(S) = First(E) = First(T) = { (, id } Follow(S) = { $ } Follow(E) = Follow(T) = { +, ), $ } 151/183
152 - As transições possíveis a partir do estado 1 são: - (Action) símbolos terminais :First(S) ou First(E) ou First(T) = { (, id } - (Goto) símbolos não-terminais: S, E, T - Não ocorrem reduções no estado 1 - First(k, rn) servem apenas para identificar reduções 152/183
153 153/183
154 Observações - O autómato LR(0) contem informação insuficiente para resolver os conflitos que surgem na maioria das linguagens. - As exigências de memória destes autómatos são aceitáveis. - O autómato LR(1) contem informação suficiente para resolver os conflitos na maioria das linguagens. - A memória necessária neste autómatos é impraticável. - No entanto, existem soluções de compromisso, como sejam: SLR(1) e LALR(1). 154/183
155 4. Parser SLR(1) Simple LR(1) - Os seus estados são basicamente os mesmos que os do autómato LR(0) - A certos items é associada informação necessária para identificar reduções - A cada item LR(0) da forma: [ A a. ] é associado o Follow(A) Haverá redução por A a se a Follow(A) - O correspondente item LR(1) seria: [ A a., m ], com m Follow(A), mas não todo o Follow(A). 155/183
156 Exemplo: Verificar se a gramática G = ( { S, A }, { a, b, c }, S, P ) é SLR(1), em que P contém as seguintes produções: p0: Z S$ p1: S Sb p2: S baa p3: A asc p4: A asb p5: A a Follow(S) = { $, b, c } Follow(A) = { a } Serão resolvidos os dois conflitos LR(0): No estado 6 : conflito redução/transição No estado 10: conflito redução/redução 156/183
157 157/183
158 158/183
159 Tabela Oráculo SLR(1): a a b c $ S A 1 s3 s2 2 s4 AC e 3 s6 s5 s 4 r1 r1 r1 5 s7 6 r5 s3 s8 o 7 r2 r2 r2 s 8 s10 s9 9 r3 10 r4 r1 r1 r1 t a d Oráculo_T Oráculo_S 159/183
160 Conclusão: O método SLR(1) resolve conflitos LR(0) quando Conflito redução-transição: quando a Ï Follow(B) [ A a.ab ] [ B d. ] Conflito redução-redução: quando Follow(A) Follow(B) = Æ [ A a. ] [ B b. ] 160/183
161 5. Parser LALR(1) LookAhead LR(1) - Ainda os mesmos estados que os autómatos LR(0). - Com mais informação associada a cada item - Cada item LR(0) da forma [ A a. ] do estado q é substituído por [ A a., n ], onde n = L (q, A a. ) - Cada item LR(0) da forma [ A a. X b ] do estado q é substituído por [ A a. X b, n ], onde n = L (q, A a. X b ) - Deste modo, a redução num estado com o item [ A a., n ] só será efetuada se a Î n. 161/183
162 - O método LALR(1) resolve conflitos LR(0) quando: Conflito redução-transição: [ A a.ab ] [ B d. ] resolvido quando a Ï L(q, B d) Conflito redução-redução: [ A a. ] [ B b. ] resolvido quando L(q, A a) Ç L(q, B b) = Æ 162/183
163 Cálculo dos L() LALR(1): Regra 1: Propagação por transição de estados : L(q, A ax. b ) = È L(q, A a. X b ) [A a. X b ] Î q Uma transição de q para q pelo símbolo X, propaga o L() do item [A a. X b ] para o item [A a X. b ]. Regra 2: Concatenação por cálculo do fecho [A a. B r ] [B.d ] L(q, B. d ) = È First(r L(q, A a. B r )) [A a. B r ] Î q O L() de cada item do fecho de [A a. B r ] obtém-se concatenando r com L(q, A a. B r ) e calculando o First da cadeia obtida. 163/183
164 Regra 3: Estado inicial q0 e estado final qf L(q0, Z. S $ ) = { e } L(qf, Z S. $ ) = { $ } As regras são aplicadas por travessias iterativas do autómato. 164/183
165 Exemplo: Verificar se a gramática G = ( { S, L, R }, { id, =, * }, S, P ) é LALR(1), em que P contém as seguintes produções: p0: Z S$ (não faz parte de G) p1: S L=R p2: S R p3: L *R p4: L id p5: R L O método LALR(1) vai eliminar o conflito redução/transição no estado 4, que ocorreria por LR(0) e SLR(1). 165/183
166 LR(0) com conflito redução/transição no estado 4: 166/183
167 SLR(1) com conflito redução/transição no estado 4: 167/183
168 LALR(1): 168/183
169 LALR(1): 169/183
170 LALR(1): 170/183
171 LALR(1): 171/183
172 LALR(1): 172/183
173 LALR(1): 173/183
174 LALR(1): 174/183
175 LALR(1): 175/183
176 LALR(1): 176/183
177 LALR(1): 177/183
178 Tabela Oráculo LALR(1): a id = * $ S L R 1 s5 s6 s2 s4 s3 2 AC e 3 r2 s 4 s7 r5 5 r4 r4 6 s5 s6 s9 s10 o 7 s5 s6 s9 s8 s 8 r1 9 r5 r5 10 r3 r3 t a d Oráculo_T Oráculo_S 178/183
179 Relação entre LL(k), LR(k), SLR(k) e LALR(k): - LL(k) é o parser mais simples e, consequentemente, o com mais problemas, pos nem todas as gramáticas podem ser tratadas com este parser (as recursivas) - As fraquezas do parser LL(k) são superadas pelo parser LR(k) - O parser SLR(1) LR(1) simples; aumenta o poder de análise do LR(0) - O parser LR(1) aumenta o poder de análise do SLR(1), pois ajuda a resolver conflitos redução-redução e redução-transição - O parser LALR(1) aumenta o poder de análise de LR(1); diminui o AFD e a tabela de parsing do LR(1) 179/183
180 Construção do AFD LALR(1) a partir do AFD LR(1): Seja a gramática com as seguintes produções: A (A) A a 180/183
181 LR(1): 181/183
182 LALR(1): (Fazer também o LALR(1) a partir do LR(0) e verificar se são iguais) 182/183
183 Otimização das Tabelas de Parsing: - São geralmente matrizes esparsas - Tentativas de compactação /183
Compiladores Analisador Sintático. Prof. Antonio Felicio Netto Ciência da Computação
Compiladores Analisador Sintático Prof. Antonio Felicio Netto [email protected] Ciência da Computação 1 Análise Sintática - A Análise Sintática constitui a segunda fase de um tradutor de uma
Compiladores - Análise Ascendente
Compiladores - Análise Ascendente Fabio Mascarenhas - 2013.1 http://www.dcc.ufrj.br/~fabiom/comp Análise Descendente vs. Ascendente As técnicas de análise que vimos até agora (recursiva com retrocesso,
Compiladores - Análise Ascendente
Compiladores - Análise Ascendente Fabio Mascarenhas - 2013.2 http://www.dcc.ufrj.br/~fabiom/comp Análise Descendente vs. Ascendente As técnicas de análise que vimos até agora (recursiva com retrocesso,
INE5318 Construção de Compiladores. AULA 4: Análise Sintática
INE5318 Construção de Compiladores AULA 4: Análise Sintática Ricardo Azambuja Silveira INE CTC UFSC E Mail: [email protected] URL: www.inf.ufsc.br/~silveira Definições preliminares Parser (Analisador
Reduce: reduz o que está imediatamente à esquerda do foco usando uma produção
Shift e reduce Shift: move o foco uma posição à direita A B C x y z A B C x y z é uma ação shift Reduce: reduz o que está imediatamente à esquerda do foco usando uma produção Se A x y é uma produção, então
Construção de Compiladores Aula 16 - Análise Sintática
Construção de Compiladores Aula 16 - Análise Sintática Bruno Müller Junior Departamento de Informática UFPR 25 de Setembro de 2014 1 Introdução Hierarquia de Chomsky Reconhecedores Linguagens Livres de
Análise sintática. Prof. Thiago A. S. Pardo. Análise sintática ascendente
Análise sintática Função, interação com o compilador Análise descendente e ascendente Especificação e reconhecimento de cadeias de tokens válidas Implementação Tratamento de erros Prof. Thiago A. S. Pardo
V Análise Sintática. V.1.1 Gramáticas Livres de Contexto Definições de GLC
V Análise Sintática V.1 Fundamentos Teóricos V.1.1 G.L.C V.1.2 Teoria de Parsing V.2 Especificação Sintática de Ling. de Prog. V.3 - Implementação de PARSER s V.4 - Especificação Sintática da Linguagem
COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Análise sintática Parte 02 Prof. [email protected] Data Conteúdo 23/09/2013 3. Análise Sintática: 3.1 analisadores
Compiladores. Exemplo. Caraterísticas de Gramáticas. A αβ 1 αβ 2. A αx X β 1 β 2. Lembrando... Gramáticas Livres de Contexto
Compiladores Análise sintática (2) Análise Top-Down Lembrando... Gramáticas Livres de Contexto Análise sintática = parsing. Baseada em GLCs Gramática: S A B Top-Down Bottom-Up S AB cb ccbb ccbca S AB A
Compiladores. Top-Down x Bottom Up. Plano da aula. Redução exemplo 1. Redução exemplo 1. Lembrando: construir a tabela de análise LL(1) A Abc b B d
Compiladores Análise sintática ) Análise ascendente Autômatos Empilhar/Reduzir Lembrando: construir a tabela de análise LL) Como fazer? Re-escrever gramática para satisfazer condições de LL) Calcular conjuntos
Analisadores Sintáticos LR
FACULDADE ANGLO AMERICANO FOZ DO IGUAÇU Curso de Ciência da Computação 7º Periodo Disciplina: Compiladores Prof. Erinaldo Sanches Nascimento Analisadores Sintáticos LR SLR LR Canônicos LALR Analisadores
Análise Sintática (Cap. 04) Análise Sintática Ascendente Analisador Sintático LR
Análise Sintática (Cap. 04) Análise Sintática Ascendente Analisador Sintático LR Análise Sintática LR Analisadores sintáticos LR(k): L, verificação da entrada da esquerda para direita R, constrói a derivação
Análise Sintática Bottom-up
MAB 471 2011.2 Análise Sintática Bottom-up http://www.dcc.ufrj.br/~fabiom/comp Recapitulando parsers top-down Constróem árvore sintática da raiz até as folhas Recursão à esquerda faz parsers entrarem em
Compiladores - Análise SLR
Compiladores - Análise SLR Fabio Mascarenhas - 2013.1 http://www.dcc.ufrj.br/~fabiom/comp Um exemplo que funciona Todo estado com um item de redução e algum outro item causa conflito LR(0)! A técnica LR(0)
Análise Sintática I. Eduardo Ferreira dos Santos. Abril, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 42
Análise Sintática I Eduardo Ferreira dos Santos Ciência da Computação Centro Universitário de Brasília UniCEUB Abril, 2017 1 / 42 Sumário 1 Introdução 2 Derivações 3 Ambiguidade 4 Análise sintática descendente
Compiladores Aula 6. Celso Olivete Júnior.
Aula 6 Celso Olivete Júnior [email protected] Na aula passada Analisadores Sintáticos Descendentes ASD com retrocesso ASD preditivo recursivo não-recursivo 2 ASD Preditivo Recursivo Projeto Parte 2
Compiladores. Análise Sintática
Compiladores Análise Sintática Análise Sintática Vejamos um exemplo, seja a seguinte instrução de atribuição: posicao = inicial + incremento * 60 Na análise sintática tenta-se construir uma frase correta
INE5317 Linguagens Formais e Compiladores AULA 9: Propriedades e Reconhecimento das Linguagens Livres do Contexto
INE5317 Linguagens Formais e Compiladores AULA 9: Propriedades e Reconhecimento das Linguagens Livres do Contexto baseado em material produzido pelo prof Paulo Bauth Menezes e pelo prof Olinto José Varela
BNF (Backus-Naur Form) Gramática Livres de Contexto / Estruturas Recursivas
Sintae => Usualmente Gramática Livre do Conteto (GLC) BNF (Backus-Naur Form) Gramática Livres de Conteto / struturas Recursivas comando => IF epressao THN epressao LS epressao epressao => (epressao) OR
Análise Sintática II. Eduardo Ferreira dos Santos. Outubro, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 34
Análise Sintática II Eduardo Ferreira dos Santos Ciência da Computação Centro Universitário de Brasília UniCEUB Outubro, 2016 1 / 34 Sumário 1 Introdução 2 Ambiguidade 3 Análise sintática descendente 4
Análise sintática. Análise sintática ascendente. Parte-se dos símbolos terminais em direção ao símbolo inicial da gramática. Derivação mais à direita
Análise sintática Função, interação com o compilador Análise descendente e ascendente Especificação e reconhecimento de cadeias de tokens válidas Implementação Tratamento de erros Prof. Thiago A. S. Pardo
Análise Sintática LL(1)
FACULDADE ANGLO AMERICANO FOZ DO IGUAÇU Curso de Ciência da Computação 7º Periodo Disciplina: Compiladores Prof. Erinaldo Sanches Nascimento Análise Sintática LL(1) Análise Sintática Descendente Introdução
Análise Sintática - Final
MAB 471 2011.2 Análise Sintática - Final http://www.dcc.ufrj.br/~fabiom/comp LR(k ) vs LL(k ) Encontrando o próximo passo em uma derivação LR(k) Cada redução na análise detectável com o contexto esquerdo
Compiladores - Análise LL(1)
Compiladores - Análise LL(1) Fabio Mascarenhas - 2013.1 http://www.dcc.ufrj.br/~fabiom/comp Gramáticas LL(1) Uma gramática é LL(1) se toda predição pode ser feita examinando um único token à frente Muitas
Análise Sintática (Cap. 04) Análise Sintática Descendente
(Cap. 04) Análise Sintática Descendente Análise Sintática Análise sintática descendente Constrói a árvore de derivação de cima para baixo, da raíz para as folhas, criando os nós da árvore em pré ordem
Análise sintática. Análise sintática. Top-down ou descendente. Com retrocesso: por tentativa e erro. Preditiva: para gramáticas LL(1) 09/04/2012
Análise sintática Função, interação com o compilador Análise descendente e ascendente Especificação e reconhecimento de cadeias de tokens válidas Implementação Tratamento de erros Prof. Thiago A. S. Pardo
Problemas decidíveis para LICs
Problemas decidíveis para LICs Dada uma gramática independente de contexto G, L(G) =? Dada uma gramática independente de contexto G, L(G) é finita? Dada uma gramática independente de contexto G, L(G) é
Linguagens Formais e Autômatos P. Blauth Menezes
Linguagens Formais e Autômatos P. Blauth Menezes [email protected] Departamento de Informática Teórica Instituto de Informática / UFRGS Linguagens Formais e Autômatos - P. Blauth Menezes 1 Linguagens
Compilação: Erros. Detecção de Erros: * Analisadores Top-Down - Preditivo Tabular (LL) - Feito a mão. * Analisadores Botton-Up: - Shift-Reduce (SLR)
Compilação: Erros Detecção de Erros: * Analisadores Top-Down - Preditivo Tabular (LL) - Feito a mão * Analisadores Botton-Up: - Shift-Reduce (SLR) * Erros no Lex * Erros no Yacc * Erros na Definição da
COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Análise sintática Parte 05 Prof. [email protected] Data Conteúdo 23/09/2013 3. Análise Sintática: 3.1 analisadores
Tokens, Padroes e Lexemas
O Papel do Analisador Lexico A analise lexica e a primeira fase de um compilador e tem por objetivo fazer a leitura do programa fonte, caracter a caracter, e traduzi-lo para uma sequencia de símbolos lexicos
Construção de Compiladores Aula 18 - Análise Sintática Ascendente
Construção de Compiladores Aula 18 - Análise Sintática Ascendente Bruno Müller Junior Departamento de Informática UFPR 10 de Novembro de 2014 Bruno Müller 5 Implementação Junior Departamento de Informática
Análise sintática. Análise sintática ascendente. Bottom-up, ascendente ou redutiva. Analisadores de precedência de operadores Analisadores LR
Análise sintática Função, interação com o compilador Análise descendente e ascendente Especificação e reconhecimento de cadeias de tokens válidas Implementação Tratamento de erros Prof. Thiago A. S. Pardo
Análise Sintática. Fabiano Baldo
Compiladores Análise Sintática Fabiano Baldo Gramáticas Livre de Contexto (GLC) É utilizada na especificação formal lda sintaxe de uma linguagem de programação. É um conjunto de produções ou regras gramaticais
Linguagens Livres de Contexto
Universidade Católica de Pelotas Centro Politécnico Bacharelado em Ciência da Computação 364018 Linguagens Formais e Autômatos TEXTO 4 Linguagens Livres de Contexto Prof. Luiz A M Palazzo Maio de 2011
Concurso Público para provimento de cargo efetivo de Docentes. Edital 20/2015 CIÊNCIA DA COMPUTAÇÃO II Campus Rio Pomba
Questão 01 No processo de construção de compiladores, é essencial compreender e manipular as expressões regulares e suas equivalências. Dentro desse contexto, seja o alfabeto = {a, b, c, d, e} e a seguinte
Parsing Preditivo. Antes de ser abordado o Parsing Preditivo, será apresentado o Analisador Sintático Descendente Recursivo.
UPE Caruaru Sistemas de Informação Disciplina: Compiladores Prof.: Paulemir G. Campos Parsing Preditivo Antes de ser abordado o Parsing Preditivo, será apresentado o Analisador Sintático Descendente Recursivo.
Compiladores. Análise lexical. Plano da aula. Motivação para análise lexical. Vocabulário básico. Estrutura de um compilador
Estrutura de um compilador programa fonte Compiladores Análise lexical () Expressões Regulares analisador léxico analisador sintático analisador semântico análise gerador de código intermediário otimizador
Linguagens e Programação Gramáticas. Paulo Proença
Linguagens e Programação Gramáticas Gramáticas Ferramenta para a descrição e análise de linguagens; Baseada num conjunto de regras que especificam o modo de construção das frases válidas na linguagem;
Análise Sintática II: Analisadores Descendentes Preditivos
Análise Sintática II: Analisadores Descendentes Preditivos Exercícios LL(1) = Left to right, Left-most derivation, 1 símbolo look-ahead 1. LL(1): definição 2. Para toda produção A -> α β Se β =>* λ, então
COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Análise sintática Parte 04 Prof. [email protected] Data Conteúdo 23/09/2013 3. Análise Sintática: 3.1 analisadores
Gramáticas Livres de Contexto Parte 1
Universidade Estadual de Feira de Santana Engenharia de Computação Gramáticas Livres de Contexto Parte 1 EXA 817 Compiladores Prof. Matheus Giovanni Pires O papel do Analisador Sintático É responsável
IV Gramáticas Livres de Contexto
IV Gramáticas Livres de Contexto Introdução Definições de GLC 1 G = (Vn, Vt, P, S) onde P = {A α A Vn α (Vn Vt) + } 2 GLC ε - LIVRE : S ε pode pertencer a P, desde que: S seja o símbolo inicial de G S
Capítulo 9: Linguagens sensíveis ao contexto e autômatos linearmente limitados.
Capítulo 9: Linguagens sensíveis ao contexto e autômatos linearmente limitados. José Lucas Rangel 9.1 - Introdução. Como já vimos anteriormente, a classe das linguagens sensíveis ao contexto (lsc) é uma
Linguagens Livres do Contexto. Adaptado de H. Brandão
Linguagens Livres do Contexto Adaptado de H. Brandão Linguagens Livres do Contexto Para as LLC, temos as Gramáticas Livres do Contexto; Linguagens Livres do Contexto Para as LLC, temos as Gramáticas Livres
Compiladores Aula 4. Celso Olivete Júnior.
Aula 4 Celso Olivete Júnior [email protected] Na aula de hoje... Revisão: gramáticas Relações em uma gramática: Cabeça, Último, Primeiro (First) e Seguinte (Follow) Capítulo 4 (seção 4.4.2) do livro
COMPILADORES. Revisão Linguagens formais Parte 02. Prof. Geovane Griesang
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Revisão Linguagens formais Parte 02 Prof. [email protected] Legenda: = sigma (somatório) = delta ε = epsilon λ =
Análise Bottom-Up. Compiladores. Parsing LR. Tabela Ações/Transições. Análise LR. Construindo tabelas LR
Análise Bottom-Up Compiladores Análise sintática 5) Gramáticas SLR), LR) e LALR String Entrada -> Símbolo Inicial Regras aplicadas em reverso adiar decisões mais poderoso Noção de handle, redução, uso
Analisadores Ascendentes ou Empilha-Reduz. Mais um exemplo... Mais um exemplo... Top-Down x Bottom Up. Conteúdo da aula. Analisadores Ascendentes
Conteúdo da aula Analisadores Ascendentes ou mpilha-reduz Marcelo Johann Analisadores Ascendentes uncionamento Analisadores de Precedência de Operadores Analisadores LR(k) SLR - Simple LR (estudaremos
Teoria da Computação Gramáticas, Linguagens Algébricas e Autómatos de Pilha
Teoria da Computação Gramáticas, Linguagens Algébricas e Autómatos de Pilha Simão Melo de Sousa 12 de Outubro de 2011 Conteúdo 1 Gramáticas e Definições básicas 1 2 Gramáticas e Linguagens 4 2.1 Gramáticas
Análise Sintática. Análise Sintática. Tipos de Analisadores Gramáticais: PARSERS
Análise Sintática Tipos de Analisadores Gramáticais: PARSERS * Analisadores TOP-DOWN: Árvore de derivação começa pela raiz indo para as folhas => Análise Descendente Tipo LL(1): Left to right / Leftmost
Vantagens de uma Gramática. Sintaxe de uma Linguagem. Analisador Sintático - Parser. Papel do Analisador Sintático. Tiposde Parsers para Gramáticas
Sintaxe de uma Linguagem Cada LP possui regras que descrevem a estrutura sintática dos programas. specificada através de uma gramática livre de contexto, BNF (Backus-Naur Form). 1 Vantagens de uma Gramática
Compiladores. Bruno Lopes. Bruno Lopes Compiladores 1 / 12. Instituto de C
ompiladores Análise Sintática Bruno Lopes Bruno Lopes ompiladores 1 / 12 Front-end Lida com a linguagem de entrada Teste de pertinência: código fonte linguagem fonte? Programa está bem formado? Sintaticamente?
UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO. Prof.ª Danielle Casillo
UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO CURSO: CIÊNCIA DA COMPUTAÇÃO Prof.ª Danielle Casillo Diferencia-se das máquinas de Turing e Post principalmente pelo fato de possuir a memória de entrada separada
Linguagens Formais. Aula 01 - Conceitos Básicos. Prof. Othon Batista Mestre em Informática
Linguagens Formais Aula 01 - Conceitos Básicos Prof. Othon Batista Mestre em Informática Sumário Introdução à Linguagem Alfabeto Cadeias de Símbolos, Palavras Tamanho de Palavra Prefixo, Sufixo ou Subpalavra
Apresentação. !! Familiarização com os métodos de construção de compiladores de linguagens e com as técnicas de compilação mais habituais.
Apresentação Universidade dos Açores Departamento de Matemática www.uac.pt/~hguerra/!! Aquisição de conceitos sobre a definição de linguagens de programação.!! Familiarização com os métodos de construção
Linguagens Livres de Contexto
Linguagens Livres de Contexto 1 Roteiro Gramáticas livres de contexto Representação de linguagens livres de contexto Formas normais para gramáticas livres de contexto Gramáticas ambíguas Autômatos de Pilha
Análise Sintática. Eduardo Ferreira dos Santos. Outubro, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 18
Análise Sintática Eduardo Ferreira dos Santos Ciência da Computação Centro Universitário de Brasília UniCEUB Outubro, 2016 1 / 18 Sumário 1 Introdução 2 Derivações 2 / 18 1 Introdução 2 Derivações 3 /
LINGUAGENS FORMAIS E AUTÔMATOS. Prova 2-10/06/ Prof. Marcus Ramos
LINGUAGENS FORMAIS E AUTÔMATOS Prova 2-10/06/2011 - Prof. Marcus Ramos NOME: _ Colocar seu nome no espaço acima; A prova pode ser feita à lápis ou caneta; A duração é de três horas; As questões da parte
LINGUAGEM LIVRE DE CONTEXTO GRAMÁTICA LIVRE DE CONTEXTO
LINGUAGEM LIVRE DE CONTEXTO As Linguagens Livres de Contexto é um reconhecedor de linguagens, capaz de aceitar palavras corretas (cadeia, sentenças) da linguagem. Por exemplo, os autômatos. Um gerador
COMPILADORES. Revisão Linguagens formais Parte 01. Geovane Griesang
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Revisão Linguagens formais Parte 01 [email protected] Legenda: = sigma (somatório) = delta ε = épsilon λ = lambda
Curso de Engenharia de Computação - UTFPR Teoria da Computação - Prof. Celso Kaestner Lista de exercícios
Curso de Engenharia de Computação - UTFPR Teoria da Computação - Prof. Celso Kaestner Lista de exercícios 1. Escreva a expressão regular para as seguintes linguagens sobre o alfabeto {0, 1}: strings começando
Como construir um compilador utilizando ferramentas Java
Como construir um compilador utilizando ferramentas Java p. 1/2 Como construir um compilador utilizando ferramentas Java Aula 6 Análise Sintática Prof. Márcio Delamaro [email protected] Como construir
Como construir um compilador utilizando ferramentas Java
Como construir um compilador utilizando ferramentas Java p. 1/2 Como construir um compilador utilizando ferramentas Java Aula 4 Análise Léxica Prof. Márcio Delamaro [email protected] Como construir
Linguagens Livres de Contexto
Linguagens Livres de Contexto 1 Roteiro Gramáticas livres de contexto Representação de linguagens livres de contexto Formas normais para gramáticas livres de contexto Gramáticas ambíguas Autômatos de Pilha
Um Compilador Simples. Definição de uma Linguagem. Estrutura de Vanguarda. Gramática Livre de Contexto. Exemplo 1
Definição de uma Linguagem Linguagem= sintaxe + semântica Especificação da sintaxe: gramática livre de contexto, BNF (Backus-Naur Form) Especificação Semântica: informal (textual), operacional, denotacional,
Folha 4.1 Análise sintática descendente
1. Dada a seguinte gramática G = (Σ, T, P, S), onde : Σ = { S, A, B } T = { a, b, c } S a b A c A A a S b S c B B a B b S b) Verifique que G é do tipo LL(1). c) Construa a tabela sintática predicativa
Conceitos de Análise Sintática
Conceitos de Análise Sintática Pro.f. Marcus Ramos UNIVASF Atualizado em 28 de outubro de 2016 The Theory of Parsing, Translation and Compiling Volume I: Parsing Alfred V. Aho Jeffrey D. Ullman Prentice
COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática
Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES Análise sintática Parte 01 Prof. [email protected] Continuação... Próxima aula 2 Análise léxica x Análise sintática
A. (Autómatos finitos determinísticos e não determinísticos AFD e AFND)
DEP. INFORMÁTICA - UNIVERSIDADE DA BEIRA INTERIOR Teoria da Computação Eng. Informática 1º Semestre Exame 1ª chamada - Resolução 2h + 30min 31/Jan/2011 Pergunta A.1 A.2 A.3 B.1 B.2 B.3a B.3b C.1 C.2 D.1
Função, interação com o compilador Especificação e reconhecimento de tokens Implementação Tratamento de erros. Prof. Thiago A. S.
Análise léxica Função, interação com o compilador Especificação e reconhecimento de tokens Implementação Tratamento de erros Prof. Thiago A. S. Pardo 1 Estrutura geral de um compilador programa-fonte analisador
Linguagens Formais e Problemas de Decisão
Linguagens Formais e Problemas de Decisão Mário S. Alvim ([email protected]) Fundamentos de Teoria da Computação (FTC) DCC-UFMG (2018/02) Mário S. Alvim ([email protected]) Linguagens Formais e Problemas
Compiladores. Capítulo 3: Análise Sintática Introdução
Compiladores Capítulo 3: Análise Sintática 3.1 - Introdução O problema da análise sintática para uma dada gramática livre de contexto, consiste em descobrir, para uma cadeia x qualquer, se a cadeia pertence
