Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Compiladores - Apostilas - Informática Part3, Notas de estudo de Informática

Apostilas de Informática sobre Compiladores, Linguagens e suas Representações, Tipos, Especificação de uma linguagem, Tipos de Compilação, Sistemas de Interpretação Híbridos, Construção de Compiladores.

Tipologia: Notas de estudo

2013

Compartilhado em 27/08/2013

Garoto
Garoto 🇪🇸

4.6

(121)

1 / 19

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
-43-
S ::= ASB | BSA | SS | aS | ε
A ::= ABS | B
B ::= BSSA | A
Neste momento SP = {a, S}. Agora Q := , e assim a repetição do algoritmo termina com SP = {a,
S}, os únicos símbolos produtivos.
Para simplificar a gramática, os símbolos improdutivos podem ser removidos, bem como todas as
produções de P que contenham estes símbolos. Assim, a gramática simplificada para o exemplo
seria:
S ::= SS | aS | ε
Dicas para a eliminação de símbolos inúteis :
1º Todo T (terminal) é produtivo;
2º Marcar todos os T (terminais);
3º Marcar todos os NT (não-terminais) que possuem produções totalmente marcadas;
4º Marcar nas outras produções os NT que já foram marcados;
5º Eliminar os estados e as produções não marcadas.
Obs : Se o inicial for inútil, a linguagem (L) é vazia.
Obs II : Quando inútil, o símbolo não encaminha a finalização de uma sentença.
O segundo tipo de símbolos inúteis são aqueles que jamais são gerados a partir de S. Estes
símbolos, chamados de inalcançáveis, são eliminados pelo seguinte algoritmo:
Algoritmo: Eliminação de Símbolos Inalcançáveis
Entrada : Uma GLC G=(N,T,P,S)
Saída : Uma GLC G’=(N’,T,P’,S), sem símbolos inalcançáveis.
SA := {S}
M := {S} “o conjunto de símbolos marcados”.
Repita
M := {X | X NT e X SA e existe uma produção Y ::= αXβ e Y SA};
SA := SA M;
Até M = ;
N’= SA N;
T’= SA T;
P’:= {p | pP e todos os símbolos de p pertencem a SA};
Para exemplificar, seja G :
S ::= aS | SB | SS | ε
A ::= ASB | c
B ::= b
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13

Pré-visualização parcial do texto

Baixe Compiladores - Apostilas - Informática Part3 e outras Notas de estudo em PDF para Informática, somente na Docsity!

S ::= ASB | BSA | SS | aS | ε

A ::= ABS | B

B ::= BSSA | A

Neste momento SP = {a, S}. Agora Q := ∅, e assim a repetição do algoritmo termina com SP = {a,

S}, os únicos símbolos produtivos.

Para simplificar a gramática, os símbolos improdutivos podem ser removidos, bem como todas as

produções de P que contenham estes símbolos. Assim, a gramática simplificada para o exemplo

seria:

S ::= SS | aS | ε

 Dicas para a eliminação de símbolos inúteis :

1º Todo T (terminal) é produtivo;

2º Marcar todos os T (terminais);

3º Marcar todos os NT (não-terminais) que possuem produções totalmente marcadas;

4º Marcar nas outras produções os NT que já foram marcados;

5º Eliminar os estados e as produções não marcadas.

Obs : Se o inicial for inútil, a linguagem (L) é vazia.

Obs II : Quando inútil, o símbolo não encaminha a finalização de uma sentença.

O segundo tipo de símbolos inúteis são aqueles que jamais são gerados a partir de S. Estes

símbolos, chamados de inalcançáveis, são eliminados pelo seguinte algoritmo:

Algoritmo: Eliminação de Símbolos Inalcançáveis

Entrada : Uma GLC G=(N,T,P,S)

Saída : Uma GLC G’=(N’,T,P’,S), sem símbolos inalcançáveis.

SA := {S}

M := {S} “o conjunto de símbolos marcados”.

Repita

M := {X | X ∈ N∪T e X ∉ SA e existe uma produção Y ::= αXβ e Y ∈ SA};

SA := SA ∪ M;

Até M = ∅;

N’= SA ∩ N;

T’= SA ∩ T;

P’:= {p | p∈P e todos os símbolos de p pertencem a SA};

Para exemplificar, seja G :

S ::= aS | SB | SS | ε

A ::= ASB | c

B ::= b

Inicialmente, SA = {S} e M = {S}. Assim, se obtém :

S ::= aS | SB | SS | ε

e a e B são os únicos símbolos recém marcados que não estão em SA. Assim, a M é atribuído o

conjunto {a, B} e a SA é atribuído {S, a, B}. Em seguida se obtém :

B ::= b

e assim M passa a ser igual a {b} e SA igual a {S, a, B, b}. Já que M não contém não-terminais, a

execução do laço deixará M = ∅ e SA não será alterado. Assim, S, a, B e b são alcançáveis e A e

c são inalcançáveis e suas produções podem ser eliminadas da gramática, resultando :

S ::= aS | SB | SS | ε

B ::= b

 Dicas para a eliminação de símbolos inalcançáveis :

Os símbolos inalcançáveis são aqueles que partindo do inicial S, não são alcançados por n

transições.

5.6.2 εεεε - Produções

Conforme foi dito anteriormente, uma GLC pode ter produções do tipo A ::= εεεε. Mas toda GLC

pode ser transformada em uma GLC equivalente sem este tipo de produções (chamadas

εεεε -produções ), com exceção da produção S ::= εε εε, se esta existir (ou seja, a cadeia vazia pertence

à linguagem). Assim procedendo, é possível mostrar que toda GLC pode obedecer à restrição

das GSC (tipo 1). É o método da eliminação de εεεε -produções , da qual se tratará agora.

A exclusão de εεεε -produções pode determinar modificações diversas nas produções da gramática.

O algoritmo é dividido em três etapas, como segue :

a) Variáveis que constituem produções vazias. Considera, inicialmente, todas as variáveis que

geram diretamente ε (ex: A →→→→ εεεε). A seguir, sucessivamente são determinadas as variáveis que

indiretamente geram ε (ex: B →→→→ A );

b) Exclusão de produções vazias. Inicialmente, são consideradas todas as produções não-

vazias. A seguir, cada produção cujo lado direito possui uma variável que gera a palavra vazia,

determina uma produção adicional, sem esta variável;

c) Inclusão de geração da palavra vazia, se necessário. Se a palavra vazia pertence à

linguagem, então é incluída uma produção para gerar a palavra vazia.

O método consiste em determinar, para cada variável A em N , se A →→→→ * εεεε. Se isto for verdade, se

diz que a variável A é anulável. Pode-se assim substituir cada produção da forma

B ::= X 1 X 2 ...Xn por todas as produções formadas pela retirada de uma ou mais variáveis Xi

anuláveis.

Inicialmente temos E = { εεεε }.

Quando o laço é executado pela primeira vez, Q = {C} , e se obtém :

S ::= aS|SS|bA A::=BC B::=CC|ab|aAbC C::= ε

Como Q não é vazio, temos E = {ε, C} e uma segunda iteração, que deixa Q = {B}, e obtém-se :

S::=aS|SS|bA A::=BC B::=CC|ab|aAbC C::= ε

Novamente Q não é vazio, temos E = {ε, B, C}, e numa nova iteração, que faz Q = {A}

S::=aS|SS|bA A::=BC B::=CC|ab|aAbC C::= ε

O símbolo A é acrescentado a E , que passa a ser E = { εεεε , A, B, C}. Na próxima iteração não são

acrescentados símbolos a Q , terminando assim o algoritmo, e temos que os ε-não-terminais em G

são A , B e C.

Para eliminar os ε-não-terminais de uma GLC , pode-se usar o seguinte algoritmo, que elimina ε-

não-terminais sem introduzir novos. A estratégia é baseada na seguinte idéia: Seja A um ε-não-

terminal em G. Então ele é dividido conceitualmente em dois não-terminais A’ e A”, tal que A’

gera todas as cadeias não-vazias e A ” gera apenasεε εε. Agora, do lado direito de cada produção

onde A aparece uma vez, por exemplo B ::= αααα A ββββ, é trocado por duas produções B ::= αααα A’ ββββ e

B ::= αα αα A” ββββ. Já que A” só gera εεεε, ele pode ser trocado por εεεε (ou seja, eliminado), deixando

B ::= ααααββββ. Depois disso, pode-se usar A em lugar de A’. A produção final fica: B ::= ααααββββ | αααα A ββββ,

onde A não é mais um ε-não-terminal. Se B ::= αα αα A ββ ββ A γγγγ, então são obtidas quatro combinações

possíveis pelas trocas de A por εεεε ( α A β A γ , α A βγ , αβ A γ , αβγ ) e assim por diante.

Algoritmo: Eliminar Todos os εεεε -não-terminais

Entrada : Uma GLC G=(N,T,P,S)

Saída : Uma GLC G=(N’,T,P’,S’) ε-livre.

Construa o conjunto E

P’ := {p | p ∈ P e p não é ε-produção }

Repita

Se P’ tem uma produção da forma A ::= αBβ, tal que B ∈ E, αβ (N∪T)*^ e αβ ≠ ε, então

inclua a produção A ::= αβ em P’;

Até que nenhuma nova produção possa ser adicionada a P’;

Se S ∈ E, então

Adicione a P’as produções S’ ::= S | ε;

N’ := N ∪ {S’};

Senão

S’ := S;

N’ := N;

Fim Se

 Dica : Como eliminar as εεεε -produções.

1º Se o símbolo inicial S possui ε-produção, cria a seguinte regra : S’::= S / ε

2º Riscar as ε-produções de todas as regras

3º marcar os NT (não-terminais) que possuem ε-produções indiretas, ou seja, muda para um

estado onde tenha ε-produções.

4º Onde houver NT marcados, fazer novas combinações, criando novas produções.

5.6.3 Produções Unitárias

Uma produção na forma A →→→→ B não adiciona informação alguma em termos de geração de

palavras, a não ser que a variável A pode ser substituída por B. Neste caso, se B →→→→ αααα, então a

produção A →→→→ B pode ser substituída por A →→→→ αααα.

Uma produção da forma A ::= αα αα em uma GLC G=(N,T,P,S) é chamada de produção unitária se α

é um não-terminal. Um caso especial de produção unitária é a produção A ::= A , também

chamada produção circular. Tal produção pode ser removida imediatamente sem afetar a

capacidade de geração da gramática. O algoritmo para eliminar produções unitárias assume que

as produções circulares já tenham sido eliminadas anteriormente. Essa eliminação é trivial, pois a

identificação de produções circulares é bastante simples.

Algoritmo: Eliminar Produções Unitárias

Entrada : Uma GLC G=(N,T,P,S) sem produções circulares.

Saída : Uma GLC G=(N,T,P’,S) sem produções unitárias.

Para toda A ∈ N faça:

NA := {B | A →* B, com B ∈ N};

Fim Para

P’ := ∅;

Para toda produção B ::= α ∈ P faça:

Se B ::= α não é uma produção unitária, então:

P’ := P’ ∪ {A ::= α | B ∈ NA};

Fim Se

Fim Para

Podem surgir símbolos inalcançáveis depois da aplicação deste algoritmo. Isso se deve ao fato de

que o símbolo é substituído por suas produções, e se o mesmo aparecer somente em produções

unitárias, o mesmo irá desaparecer do lado direito das produções. Para exemplificar, aplique o

algoritmo na seguinte gramática:

S ::= aB | aA | A // substitui A pelas suas produções

B ::= aA | B | A // idem com A e B

A ::= C | aaa // idem com C

C ::= ε | cBc

Observação : Depois de eliminar produções unitárias deve-se eliminar produções inalcançáveis,

e transformar a GLC em GLC ε -livre se necessário.

5.6.4 Fatoração

Uma GLC está fatorada se ela é determinística, ou seja, se ela não possui produções para um

mesmo não-terminal no lado esquerdo cujo lado direito inicie com a mesma cadeia de símbolos

ou com símbolos que derivam seqüências que iniciem com a mesma cadeia de símbolos. De

acordo com esta definição, a seguinte gramática é não-determinística:

S ::= aSB | aSA

A ::= a

B ::= b

fonte do

não-determinismo

5.6.5 Eliminação de Recursão à Esquerda

Um não-terminal A , em uma GLC G=(N,T,P,S) é recursivo se A →→→→αααα A ββββ, para

αααα e ββββ ∈∈∈∈ (N ∪∪∪∪ T)*.

Se α = ε, então A é recursivo à esquerda ; se β = ε, então A é recursivo à direita. Esta

recursividade pode ser direta ou indireta.

Uma gramática com pelo menos um não-terminal recursivo à esquerda ou à direita é uma

gramática recursiva à esquerda ou à direita , respectivamente.

Uma GLC G=(N,T,P,S) possui recursão à esquerda direta se P contém pelo menos uma

produção da forma A ::= A αααα.

Uma GLC G=(N,T,P,S) possui recursão à esquerda indireta se existe em G uma derivação da

forma A →→→→ n^ A ββββ, para algum n ≥≥≥≥ 2.

Para eliminar as recursões diretas à esquerda nas produções :

A::=Aα 1 |Aα 2 |...|Aαn|...|β 1 |β 2 |...|βm

onde nenhum ββββ i começa com A , deve-se substituir estas produções pelas seguintes :

A ::= β 1 A’|β 2 A’|...|βmA’

A’::= α 1 A’|α 2 A’|...|αnA’|ε

onde A’ é um novo não-terminal.

A seguir é apresentado um algoritmo para eliminar recursões diretas e indiretas à esquerda :

Algoritmo: Eliminar Recursões à Esquerda

Entrada : Uma GLC G=(N,T,P,S).

Saída : Uma GLC G=(N’,T,P’,S) sem recursão à esquerda.

N’ := N;

P’ := P;

Ordene os não-terminais de N’ em uma ordem qualquer (por exemplo, A 1 , A 2 , A 3 , ..., An);

Para i de 1 até n, faça:

Para j de 1 até i-1 faça

Substitua as produções de P’ da forma Ai ::= Ajγ por produções da forma

Ai ::= δ 1 γ | δ 2 γ | ... | δkγ, onde δ 1 , δ 2 , ... δk são os lados direitos das produções

com lado esquerdo Aj, ou seja, Aj ::= δ 1 | δ 2 | ... | δk.

Fim Para;

Elimine as recursões diretas das produções de P’com lado esquerdo Ai;

Fim Para;

Note que este algoritmo já elimina as recursões à esquerda diretas e indiretas.

 Dica : Eliminação de recursão à esquerda.

1º Detectar recursão à esquerda

2º Eliminar a recursão, mantendo as não recursivas na mesma regra com X’ no final de cada

produção

3º Criar um estado ‘X’ com produções formadas pelas produções recursivas mais ‘X’ no final de

cada produção. Adicionar no final a produção ε

4º Verificar se não existem recursões indiretas

5.7 TIPOS ESPECIAIS DE GLC

  • A seguir serão identificados alguns tipos especiais de GLC :

a) Gramática Própria: Uma GLC é própria se :

a.1) Não possui produções cíclicas (ver definição seguinte);

a.2) É ε-livre;

a.3) Não possui símbolos inúteis.

b) Gramática Sem Ciclos: G = (N,T,P,S) é uma GLC sem ciclos (ou livre de ciclos) se não existe

em G nenhuma derivação da forma A →

A, para todo A ∈ N.

c) Gramática Reduzida: Uma GLC G=(N,T,P,S) é uma GLC reduzida se :

c.1) L(G) não é vazia;

c.2) Se A ::= α ∈ P então A ≠ α

c.3) G não possui símbolos inúteis

d) Gramática de Operadores: Uma GLC G=(N,T,P,S) é de operadores se ela não possui

produções cujo lado direito contenha não-terminais consecutivos.

e) Gramática Unicamente Inversível: Uma GLC reduzida é unicamente inversível se ela não

possui produções com lados direitos iguais.

f) Gramática Linear: Uma GLC G=(N,T,P,S) é linear se todas as suas produções forem da forma

A ::= xBw | x, onde A e B pertencem a N, e x e w pertencem a T

g) Forma Normal de Chomsky: Uma GLC está na forma normal de Chomsky se ela é ε-livre, e

todas as suas produções (exceto, possivelmente, S ::= ε) são da forma:

g.1) A ::= BC, com A, B e C ∈ N, ou

g.2) A ::= a; com A ∈ N e a ∈ T.

h) Forma Normal de Greinbach: Uma GLC está na forma normal de Greinbach se ela é ε-livre e

todas as suas produções (exceto, possivelmente, S ::= ε) são da forma A ::= aα tal que

a ∈ T, α ∈ N*^ e A ∈ N.

O algoritmo genérico do cálculo do conjunto FIRST para uma cadeia qualquer é recursivo e utiliza

as definições para os casos especiais acima.

Algoritmo: Cálculo do Conjunto First de uma Cadeia

Entrada: Uma cadeia de símbolos X ∈∈∈∈ (N ∪∪∪∪ T)* de uma gramática G=(N,T,P,S).

Uma tabela TABFIRST com o conjunto FIRST de cada não-terminal de G.

Saída: O conjunto FIRST(X), denotado por F.

Se X = εεεε então:

F := {εεεε}.

Senão se X ∈∈∈∈ T então:

F = {X}

Senão se X ∈∈∈∈ N então:

Sejam X ::= αααα 1 | αααα 2 | ... | ααααn as produções com lado esquerdo X, então

F := FIRST(αααα 1 ) ∪∪∪∪ FIRST(αααα 2 ) ∪∪∪∪...∪∪∪∪ FIRST(ααααn);

Senão

i := 0;

F := ∅;

Repita:

i := i+1;

Xi := o i-ésimo símbolo da cadeia X;

F := F ∪∪∪∪ TABFIRST(Xi) - {εεεε};

Se X = εεεε então:

F := F ∪∪∪∪ {εεεε};

Fim Se

Até X ∈∈∈∈ T ou X = εεεε ou (X ∈∈∈∈ N e εεεε ∉∉∉∉ TABFIRST(X))

Fim Se

Para determinar o conjunto FIRST de cada um dos não-terminais de uma gramática, procede-se

como segue:

Crie uma tabela TABFIRST cujas linhas são rotuladas com os não-terminais da gramática e com

uma coluna rotulada como “FIRST”, que irá conter os símbolos pertencentes ao FIRST de cada não-

terminal. Inicialize cada uma das posições desta tabela com ∅ (conjunto vazio).

Para cada um dos não-terminais, calcule o seu conjunto FIRST utilizando o algoritmo acima. Repita

o passo 2 até que não ocorra mais nenhuma modificação na tabela.

Para exemplificar, considere a gramática:

S ::= ABS|aA

A ::= ε|a

B ::= Bb|cd

Inicialmente constrói-se a tabela:

N FIRST

S ∅

A ∅

B ∅

Calculando o FIRST de S pelo algoritmo acima, faz-se FIRST(S) = FIRST(ABS) ∪∪∪∪ FIRST(aA).

Como FIRST(A) = ∅∅∅∅, na tabela, então FIRST(S) inicialmente é ∅∅∅∅ ∪∪∪∪ {a}. A tabela fica:

N FIRST

S {a}

A ∅

B ∅

Calculando o FIRST(A) temos {εεεε, a}. Então a tabela fica:

N FIRST

S {a}

A {ε, a}

B ∅

Calculando o FIRST(B) temos FIRST(B) = FIRST(Bb) ∪ FIRST(cd) = ∅ ∪ {c}. A tabela fica:

N FIRST

S {a}

A {ε, a}

B {c}

Como a tabela foi modificada, o passo 2 deve ser repetido. Desta vez, ao calcular o FIRST de S

teremos: FIRST(S) = FIRST(ABS) ∪∪∪∪ FIRST(aA) = {a} ∪∪∪∪ FIRST(BS) ∪∪∪∪ {a} = {a}∪∪∪∪{c}∪∪∪∪{a} = {a,

c}. Logo a tabela fica:

N FIRST

S {a, c}

A {ε, a}

B {c}

O cálculo do FIRST de A e B não modifica a tabela. Mas como houve uma modificação no cálculo

do FIRST de S, o passo 2 deve ser novamente executado. Como desta vez não haverá

modificações, a última tabela será de fato a definitiva.

5.9.2 Conjunto Follow

FOLLOW(A) é definido para todo A ∈∈∈∈ N como sendo o conjunto de símbolos terminais que

podem aparecer imediatamente após A em alguma forma sentencial de G. A seguir, é definido um

algoritmo que constrói o FOLLOW de todos os não-terminais simultaneamente.

O tabela FOLLOW dos não-terminais da gramática é inicializada como:

N FOLLOW

S {$}

A ∅

B ∅

Para o primeiro passo, temos as ocorrências de Y ::= XXX em S ::= ABS e B ::= Bb, assim:

FOLLOW(A) = FOLLOW(A) ∪∪∪∪ FIRST(BS) = ∅∅∅∅ ∪∪∪∪ {c} = {c}

FOLLOW(B) = FOLLOW(B) ∪∪∪∪ FIRST(S) = ∅∅∅∅ ∪∪∪∪ {a, c} = {a, c}

FOLLOW(B) = FOLLOW(B) ∪∪∪∪ FIRST(b) = {a, c} ∪∪∪∪ {b} = {a, b, c}

Temos então a tabela FOLLOW intermediária:

N FOLLOW

S {$}

A {c}

B {a, b, c}

No segundo passo, as produções são analisadas da esquerda para a direita. A produção S ::= ABS

faz com que:

FOLLOW(S) = FOLLOW(S) ∪∪∪∪ FOLLOW(S) = {$}

Como εεεε ∉∉∉∉ FIRST(S), a segunda regra termina para esta produção. Para a produção

S ::= aA, temos:

FOLLOW(A) ::= FOLLOW(A) ∪∪∪∪ FOLLOW(S) = {c, $}

Como εεεε ∈∈∈∈ FIRST(A), o símbolo a esquerda de A é analisado. Como é um terminal (a), o algoritmo

pára. Já que não há mais produções que tenham não-terminais a direita, o cálculo da tabela

FOLLOW termina. A tabela final fica:

N FOLLOW

S {$}

A {c, $}

B {a, b, c}

Lista de Exercícios de Simplificação de GLC’s

1 – Eliminação de símbolos inúteis ou improdutivos :

a)

S ::= ASB | BSA | SS | aS | ε A ::= ABS | B B ::= BSSA | A

b) A ::= aBa | cB | cC | aD B ::= aCb | aD | ab | ε C ::= ab | cBd | aA D ::= aD | dE | aD E ::= Ead | aD | ED

c) S ::= aA A ::= a | bB B ::= b | dD C ::= cC | c D ::= dD

d) S ::= aCD | ab | bB | aaS B ::= bbB | Daa | a C ::= aCa | BCb | Ecab E ::= ab | Ea | Ba D ::= abB | ab | DD

e) S ::= Abc | aBc A ::= aAb | AB | Abc | CD B ::= bBc | bC | Bc C ::= cCc | cC | CD D ::= bbD | Dbc | DD E ::= bEc | EC | cc

f) S ::= 0A1 | 1B0 | C A ::= 1A0 | AC B ::= 0D1 | 01 C ::= 1A | 0C D ::= 1B0 | 10

g) S ::= EE | E + E | (E) A ::= id | id * E | id + E | (id) E ::= BS | A+E | AE | A B ::= id + B | id*E

h) S ::= aAc | aBc | ac A ::= aEd | aAb | ab B ::= BaD | aBb | a C ::= aCd | af D ::= aDd | aD E ::= aEa | af

i) S ::= aAb | aCd | ab A ::= aAb | aA B ::= ad | aBC C ::= aSa | aa

i) P ::= KL | bKLe K ::= cK | TV T ::= tT | ε

V ::= vV | ε L ::= LC | C C ::= P | com | ε

4 – Produções Unitárias :

a) S ::= bS | A A ::= aA | a

b) S ::= aSb | A A ::= aA | B B ::= bBc | bc

c) S ::= 1S0 | 0A00 | A | B A ::= 0 | BC | C | S B ::= A | 01 | 0S0 | 1 C ::= 1 | 01 | 0S D ::= D | 01 | ab

d) S ::= 1A0 | 0B1 | B A ::= 1B0 | C | 01 B ::= 10B | 01C | D C ::= 10 | 01 | 0C D ::= 1D0 | 10 | C

e) S ::= aA | aB | A A ::= bC | Bd | B B ::= aCd | aC | A C ::= aC | S

f) S ::= aSa | FbD A ::= aA | CA | ε B ::= bB | FE C ::= cCb | AcA D ::= Dd | fF | c E ::= BC | eE | EB F ::= fF | Dd

5 – Fatoração :

a) c ::= V = exp | id (E) V ::= id [E] | id E ::= exp + E | exp

b) S ::= bcD | Bcd B ::= bB | b D ::= dD |d

c) S ::= aA | aB A ::= aA | a B ::= b

d) S ::= Ab | ab | baA A ::= aab | b

e) S ::= Abc | bBC | bCD A ::= aBC | aDC B ::= dCc | dc C ::= Acd | cd D ::= aBC | abc | aC

f) S ::= 1A0 | 1B A ::= 1A0 | 100 B ::= C10 | C C ::= 11C | 11D D ::= 10 | 11

g) S ::= 10D | 11C | 0B B ::= 1CD | 101B | 01 C ::= 101C | 1B0 | 00 D ::= 00B | 011D | 110

h) S ::= aBd | acD | bC B ::= bDc | bCd | ad D ::= cdD | caB C ::= cbB | adD

i) S ::= bcD | Bcd B ::= bB | b D ::= dD | d

j) C ::= V=exp | id(E) V ::= id[E] | id E ::= exp,E | exp

6 – Eliminação de recursão à esquerda :

a) A ::= Abc | Acd | cdB | c B ::= Bc | dd

b) S ::= Aab | Bc | ScAb A ::= Sac | BaA | ab B ::= Ac | aBb | ab

c) A ::= Ac | bd | cd B ::= ac | Bd | Ac

d) S ::= Aa | Bb | Sac A ::= Sab | ab B ::= a | Ba

e) S ::= A0 | 0B1 | 11C

BIBLIOGRAFIA

AHO, A.V.; SETHI, R.; ULLMAN, J.D. Compiladores: princípios, técnicas e ferramentas. Rio

de Janeiro/RJ: LTC, 1995. 344 p.

FURTADO, O.J.V. Linguagens formais e compiladores: notas de aula. Florianópolis/SC: INE-

UFSC, 1992. 77 p.

HOPCROFT, J. E.; ULLMAN, J. D. Introduction to automata theory, languages and

computation. Reading: Addison-Wesley, 1979. 418 p.

JOSÉ NETO, J. Introdução à compilação. Rio de Janeiro/RJ: LTC, 1987. 222 p.

MARTINS, Joyce. Linguagens Formais e Compiladores. Universidade do Vale do Itajaí – Notas

de Aula. São José/SC.

MENEZES, P. F. B. Linguagens Formais e Autômatos. Porto Alegre/RS: II-UFRGS, Sagra

Luzzatto, 1997. 168 p.

PRICE, A.M.A.; EDELWEISS, N. Introdução às linguagens formais. Porto Alegre/RS: II-

UFRGS, 1989. 60 p.

WAZLAWICK, R.S. Linguagens formais e compiladores: notas de aula. Florianópolis/SC: INE-

UFSC, 1992. 83 p.

ZILLER, R.M. Aplicação de autômatos finitos. In: SEMANA TECNOLÓGICA, 1., Florianópolis,

1997. Anais. Biguaçu, UNIVALI, 1997. p.51-71.