Escolar Documentos
Profissional Documentos
Cultura Documentos
1 Introdução
(. . . )
2 Linguagens legais
É fácil ver que as palavras de PARBAL devem ter a mesma quantidade de abre parênteses e
fecha parênteses — (essa é a parte BAL da linguagem)
é preciso que que todo fecha parênteses corresponda a um abre parênteses que apareceu antes.
E observamos também que só pode haver um fecha parênteses em correspondência com um abre parênteses.
Quer dizer, se a gente vai contando os abre e fecha parênteses, o fecha parênteses nunca deve passar
à frente na contagem.
Agora que a gente viu isso, é bem fácil construir o autômato de pilha que reconhece PARBAL
)[(,e]
e[e, ] e[ ,e]
([e,(]
E que a leitura de um fecha parênteses só pode ocorrer se existe algum abre parênteses na pilha.
1
É isso o que garante a propriedade acima.
Finalmente, o marcador de pilha vazia (⊥) inserido no inı́cio da computação, só pode ser removido
no final se a palavra tem a mesma quantidade de abre parênteses e fecha parênteses.
Exemplos
a. PAROP
4 + 7 ∗ 5 ⇒ +∗
2 ∗ (4 + 7 + 1) ∗ 5 ⇒ ∗(++)∗
Mas para simplificar as coisas, nós também vamos aceitar coisas como
(+∗)(+)
Para obter um autômato de pilha que reconhece PAROP nós vamos fazer duas modificações no
autômato que foi contruı́do no exemplo anterior
*[e,*]
+[e,+]
([e,(]
e[e, ] e e[ ,e]
) e[(,e] e[+,e]
e[*,e]
e[+,e]
e[*,e] e[+,e]
e[*,e]
2
b. EXPR
( ( 18 + 5 ) ∗ 2 )
( ( 5 + 7 ) ∗ ( 15 + 2 ) )
E isso significa que nós vamos ter que verificar uma condição adicional.
Quer dizer, as palavras de EXPR devem satisfazer o seguinte
7 + 2 ∗ 5 + 1
Daı́ que, o que nós esperamos encontrar é uma alternação: operando, operaç~
ao, operando,
operaç~
ao, ....
E a ideia é que nós podemos empilhar tudo isso, e verificar a alternação na hora do desempil-
hamento.
Certo.
Mas ainda existe uma pequena dificuldade.
Quer dizer, às vezes o operando é uma expressão entre parênteses
3 ∗ (2 + 1 + 4) + 1
Daı́ que, se a leitura da expressão não deixar nada na pilha, então nós não vamos ver uma
alternação
3 ∗ + 1
3 ∗ X + 1
X ∗ X + X
3
0..9
0..9 ( [e, ( ]
e[e, X] +[e, +]
∗[e, ∗]
e[e, ⊥] e[X, e] e[⊥, e]
) e[(, X] e[+, e]
e[X, e]
e[X, e] e[∗, e]
e[+, e]
e[X, e]
e[∗, e]
c. REG
As expressões regulares são semelhantes às expressões aritméticas, com a sua estrutura de
parênteses balanceados e a operação binária de união (∪).
Para lidar com essas novidades, nós vamos utilizar a variável E (i.e., expressão), e as seguintes
regras
bba −→ E
E∗ −→ E
EE −→ E
(E ∪ . . . ∪ E) −→ E
4
a, b
a, b e[EE, E]
e[e, E] ( [e, ( ]
∗[E, E]
e[e, ⊥] e[E, e] e[⊥, e]
e[∪, e] e[E, e]
d. LOOP
A linguagem LOOP é uma linguagem de programação muito simples que possui apenas dois tipos
de instrução
Z <-- Y - X;
LOOP Z
X <-- X + 1;
Y <-- Y - 1;
ENDLOOP
Note que a coisa funciona porque na situação emq em Z vale zero ou um número negativo, o
programa não entra no laço.
Certo.
Agora imagine que um programa em LOOP é uma palavra — (i.e., uma sequência de caracteres)
Daı́, a gente pode definir a linguagem
5
Por exemplo, o programa acima é uma palavra de ProgLOOP.
Mas o seguinte programa não é
LOOP X
Y <-- X + * 41;
ENDLOOP
LOOP Y
ENDLOOP
LOOP Z
A tarefa agora é
Bom, é bem fácil ver que os termos LOOP e ENDLOOP fazem o papel de abre-parênteses e
fecha-parênteses.
E nós podemos reutilizar o autômato que reconhece EXPR para verificar se os comandos de
atribuição são válidos.
Daı́, a coisa fica assim
←
MEXPR
X, Y, ...
e[e, ⊥] e[C, e] e[⊥, e]
e[C, e]