(Deitel, 2003) A linguagem de programação SIMPLE é uma linguagem simples, mas ainda poderosa e de alto nível, semelhante às versões iniciais da conhecida linguagem de programação BASIC. Cada instrução da linguagem de programação SIMPLE consiste em um número de linha e um comando da linguagem. Os números de linha devem aparecer em ordem crescente. Cada comando inicia com uma das seguintes palavras reservadas da linguagem de programação SIMPLE: rem
, input
, let
, print
, goto
, if/goto
ou end
. Considere o programa escrito na linguagem de programação SIMPLE a seguir.
10 input n
15 if n <= 0 goto 65
20 let y = 0
25 let k = 0
30 if k >= n goto 75
35 let a = 2 * k
40 let b = a + 1
45 let y = y + b
50 print y
55 let k = k + 1
60 goto 30
65 let y = -1
70 print y
75 end
Caso a entrada fornecida pelo usuário seja 5, o programa apresentará como resposta:
a. 1 2 3 4 5
b. 1 2 4 8 16
c. 1 3 5 7 9
d. 1 3 6 10 15
e. 1 4 9 16 25
(Price, 2005) A construção de analisadores descendentes é auxiliada por duas funções, denominadas FIRST e FOLLOW, associadas a uma gramática G. Durante a análise descendente, as funções FIRST e FOLLOW permitem escolher qual produção deverá ser aplicada, com base no próximo símbolo de entrada. Considerando a gramática livre de contexto G, analise as assertivas a seguir:
G = ({S, A, B, C}, {a, b, d, g, h}, P, S)
P = {S → ACB | Cbb | Ba
A → da | BC
B → g | ε
C → h | ε}
Quais das assertivas apresentadas estão corretas?
a. apenas as assertivas I e II.
b. apenas as assertivas I e III.
c. apenas as assertivas II e III.
d. apenas as assertivas II e IV.
e. apenas as assertivas III e IV.
(Sebesta, 2000) O escopo de uma variável é a faixa de comandos em que a mesma é visível, ou seja, onde a variável pode ser referenciada por aquele comando. No escopo estático (ou léxico) o escopo de uma variável é determinado através da estrutura textual do programa, enquanto que no escopo dinâmico, o escopo de uma variável é determinado através da linha de execução do programa, sendo dependente, portanto da ordem de execução das rotinas.
public class Test {
private int x, y, z;
public void sub1() { int x, y, c; }
public void sub2() { int x, b, c; }
public void sub3() { int a, b, z; }
public void sub4() { int a, y, z; }
public static void main(String[] args) { int a, b, c; }
}
Supondo que o pseudoprograma apresentado utilize o escopo dinâmico, considere as assertivas a seguir:
main
chama sub1
; sub1
chama sub3
e sub3
chama sub2
, as variáveis visíveis durante a execução da última função chamada são y
de sub1
, x
, b
e c
de sub2
, a
de sub3
e z
de Test
.main
chama sub3
; sub3
chama sub4
e sub4
chama sub1
, as variáveis visíveis durante a execução da última função chamada são x
, y
e c
de sub1
, b
de sub3
e a
e z
de sub4
.main
chama sub2
; sub2
chama sub1
e sub1
chama sub4
, as variáveis visíveis durante a execução da última função chamada são x
e c
de sub1
, b
de sub2
, y
e z
de sub4
e a
de main
.main
chama sub1
; sub1
chama sub2
e sub2
chama sub3
, as variáveis visíveis durante a execução da última função chamada são y
de sub1
, x
e c
de sub2
, a
, b
e z
de sub3
.Quais das assertivas apresentadas estão corretas?
a. apenas as assertivas I e II.
b. apenas as assertivas I e III.
c. apenas as assertivas I e IV.
d. apenas as assertivas II e III.
e. apenas as assertivas II e IV.
(Ramos, 2009) Analise as assertivas apresentadas a seguir:
Quais das assertivas apresentadas estão corretas?
a. apenas as assertivas I e II.
b. apenas as assertivas I e III.
c. apenas as assertivas II e III.
d. apenas as assertivas II e IV.
e. apenas as assertivas III e IV.
(Ricarte, 2008) Os analisadores sintáticos preditivos, ou seja, os analisadores de descida recursiva que não precisam de retrocesso, podem ser construídos para uma classe de gramáticas chamada LL(1). O primeiro L em LL(1) significa que a cadeia de entrada é lida da esquerda para a direita, o segundo L representa uma derivação mais à esquerda e o 1 pelo uso de um símbolo à frente na entrada utilizado em cada passo para tomar as decisões quanto à ação de análise. Apresente a tabela M de análise para a gramática livre de contexto G, reapresentada a seguir:
G = ({D, T, L, X}, {a, b, c, int, real, char, ',', ;}, P, D)
P = {D → TL; | TL;D
T → int | real | char
L → X | X,L
X → a | b | c}
Eliminação de Recursividade à Esquerda e da Fatoração à Esquerda
G = ({A, B, C, D, E, F}, {a, b, c, int, real, char, ',', ;}, P, A)
P = {A → CD;B
B → A | ε
C → int | real | char
D → FE
E → ,D | ε
F → a | b | c}
Conjuntos FIRST(α) e FOLLOW(A)
FIRST(A) = {int, real, char}
FIRST(B) = {int, real, char, ε}
FIRST(C) = {int, real, char}
FIRST(D) = {a, b, c}
FIRST(E) = {',', ε}
FIRST(F) = {a, b, c}
FOLLOW(A) = {$}
FOLLOW(B) = {$}
FOLLOW(C) = {a, b, c}
FOLLOW(D) = {;}
FOLLOW(E) = {;}
FOLLOW(F) = {',', ;}
Tabela de Análise Preditiva
a | b | c | int | real | char | , | ; | $ | |
---|---|---|---|---|---|---|---|---|---|
A | A → CD;B | A → CD;B | A → CD;B | ||||||
B | B → A | B → A | B → A | B → ε | |||||
C | C → int | C → real | C → char | ||||||
D | D → FE | D → FE | D → FE | ||||||
E | E → ,D | E → ε | |||||||
F | F → a | F → b | F → c |
(Ricarte, 2008) Um analisador sintático preditivo sem recursão pode ser construído mantendo uma pilha explicitamente, em vez de implicitamente, via chamadas recursivas. O analisador é dirigido por um programa que considera X, o símbolo no topo da pilha, e a, o símbolo corrente da entrada. Se X é um não-terminal, o analisador escolhe uma produção-X consultando a entrada M[X, a] da tabela M de análise. Por outro lado, ele tenta fazer um casamento entre o terminal X no topo da pilha e o símbolo corrente a da entrada. Apresente a sequência de movimentos para o reconhecimento da entrada int a, b; real c;, considerando a tabela M obtida na Questão 05.
Pilha | Entrada | Derivação |
---|---|---|
$ A | int a, b; real c; $ | A → CD;B |
$ B ; D C | int a, b; real c; $ | C → int |
$ B ; D int | int a, b; real c; $ | |
$ B ; D | a, b; real c; $ | D → FE |
$ B ; E F | a, b; real c; $ | F → a |
$ B ; E a | a, b; real c; $ | |
$ B ; E | , b; real c; $ | E → ,D |
$ B ; D , | , b; real c; $ | |
$ B ; D | b; real c; $ | D → FE |
$ B ; E F | b; real c; $ | F → b |
$ B ; E b | b; real c; $ | |
$ B ; E | ; real c; $ | E → ε |
$ B ; | ; real c; $ | |
$ B | real c; $ | B → A |
$ A | real c; $ | A → CD;B |
$ B ; D C | real c; $ | C → real |
$ B ; D real | real c; $ | |
$ B ; D | c; $ | D → FE |
$ B ; E F | c; $ | F → c |
$ B ; E c | c; $ | |
$ B ; E | ; $ | E → ε |
$ B ; | ; $ | |
$ B | $ | B → ε |
$ | $ | aceita |
(Price, 2005) Analisadores de precedência de operadores operam sobre a classe das gramáticas de operadores, ou seja, gramáticas que os não-terminais aparecem sempre separados por símbolos terminais e que as produções não derivam a palavra vazia. A análise de precedência de operadores é bastante eficiente e é aplicada, principalmente, no reconhecimento de expressões, como expressões aritméticas e lógicas. Considerando a tabela de precedência de operadores apresentada a seguir, apresente a sequência de movimentos para o reconhecimento da entrada "x";"x".
G = ({A, B, C}, {x, ;, "}, P, A)
P = {A → B | B;A
B → "C"
C → x}
x | ; | " | $ | |
---|---|---|---|---|
x | > | > | > | |
; | < | > | < | > |
" | < | > | < | > |
$ | < | < | < | aceita |
Pilha | Relação | Entrada | Ação | Handle |
---|---|---|---|---|
$ | < | "x";"x"$ | empilha " | |
$ " | < | x";"x"$ | empilha x | |
$ " x | > | ";"x"$ | reduz | C → x |
$ " A | < | ";"x"$ | empilha " | |
$ " A " | > | ;"x"$ | reduz | B → "C" |
$ A | < | ;"x"$ | empilha ; | |
$ A ; | < | "x"$ | empilha " | |
$ A ; " | < | x"$ | empilha x | |
$ A ; " x | > | "$ | reduz | C → x |
$ A ; " A | < | "$ | empilha " | |
$ A ; " A " | > | $ | reduz | B → "C" |
$ A ; A | > | $ | reduz | A → B;A |
$ A | aceita | $ |
Para o desenvolvimento do compilador para a linguagem de programação SIMPLE, é necessário a elaboração de sua gramática livre de contexto, que servirá de base para a implementação do analisador sintático (descendente ou ascendente). Apresente a gramática livre de contexto, empregada por você, no desenvolvimento do analisar sintático da linguagem de programação SIMPLE. Lembre-se de reconhecer todas as regras sintáticas requeridas pela linguagem.
G = ({PROGRAM, COMMAND, EXPRESSION, OPERATOR, CONDITIONAL, RELATIONAL, ITEM, INTEGER, LABEL, DIGIT, VARIABLE}, {lf, etf, +, -, /, *, =, !, <, >, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z}, P, PROGRAM)
P = { PROGRAM → PROGRAM LABEL COMMAND lf | LABEL COMMAND lf | lf | etf
COMMAND → input VARIABLE | print VARIABLE | rem | if CONDITIONAL goto LABEL | let VARIABLE = EXPRESSION | goto LABEL | end
EXPRESSION → ITEM OPERATOR ITEM | ITEM
OPERATOR → + | - | / | *
CONDITIONAL → ITEM RELATIONAL ITEM
RELATIONAL → == | != | > | < | >= | <=
ITEM → VARIABLE | INTEGER
INTEGER → - LABEL | LABEL
LABEL → LABEL DIGIT | DIGIT
DIGIT → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
VARIABLE → a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z }