Ybadoo - Soluções em Software Livre
Tutoriais
Compiladores

Apresente a implementação da Análise Recursiva Preditiva sobre a gramática a seguir.

G = ({E, T, F}, {x, &, v, ~, (, )}, P, E)
P = {EEvT | T
TT&F | F
F → (E) | ~F | x}

 

Eliminação de Recursividade à Esquerda:

G = ({E, E₁, T, T₁, F}, {x, &, v, ~, (, )}, P, E)
P = {ETE₁
E₁ → vTE₁ | ε
TFT₁
T₁ → &FT₁ | ε
F → (E) | ~F | x}

Fatoração à Esquerda:

G = ({E, E₁, T, T₁, F}, {x, &, v, ~, (, )}, P, E)
P = {ETE₁
E₁ → vTE₁ | ε
TFT₁
T₁ → &FT₁ | ε
F → (E) | ~F | x}

Conjuntos FIRST(α) e FOLLOW(A):

FIRST(E)  = {x, ~, (}
FIRST(E₁) = {v, ε}
FIRST(T)  = {x, ~, (}
FIRST(T₁) = {&, ε}
FIRST(F)  = {x, ~, (}
FOLLOW(E)  = {), $}
FOLLOW(E₁) = {), $}
FOLLOW(T)  = {v, ), $}
FOLLOW(T₁) = {v, ), $}
FOLLOW(F)  = {&, v, ), $}
Compiler.java

Arquivo Compiler.java

/*************************************************************************
* Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br) *
* Ybadoo - Solucoes em Software Livre (ybadoo.com.br) *
* *
* Permission is granted to copy, distribute and/or modify this document *
* under the terms of the GNU Free Documentation License, Version 1.3 or *
* any later version published by the Free Software Foundation; with no *
* Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A *
* A copy of the license is included in the section entitled "GNU Free *
* Documentation License". *
* *
* Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic) *
* OpenJDK Version "1.8.0_121" *
* OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode) *
*************************************************************************/
package com.ybadoo.tutoriais.cmp.tutorial03.exercicio70;

/**
* Classe responsavel pela analise recursiva preditiva
*/
public class Compiler
{
/**
* Token atual
*/
private int index;

/**
* Lista dos tokens
*/
private String tokens;

/**
* Apresentar a mensagem de erro
*
* @param estado estado onde o erro ocorreu
* @param validos tokens validos
*/
private void error(final char estado, final char ... validos)
{
System.out.print("q" + estado + " ");

boolean first = true;

for (char valido: validos)
{
if (first)
{
first = false;
}
else
{
System.out.print(" ou ");
}

System.out.print("'" + valido + "'");
}

System.out.print(" - '");

for (int i = index; i < tokens.length(); i++)
{
System.out.print(tokens.charAt(i));
}

System.out.print("'\n");
}

/**
* Retornar o token em analise
*
* @return token em analise
*/
private char getToken()
{
if (index < tokens.length())
{
return tokens.charAt(index);
}

return '$';
}

/**
* Pular para o proximo token
*/
private void nextToken(final char estado)
{
System.out.print("q" + estado + " '" + tokens.charAt(index) + "' - '");

index = index + 1;

for (int i = index; i < tokens.length(); i++)
{
System.out.print(tokens.charAt(i));
}

System.out.print("'\n");
}

/**
* Funcao responsavel pela validacao da regra A → CB
*
* @return true caso a regra esteja correta, false caso contrario
*/
private boolean qA()
{
if ('x' == getToken() || '~' == getToken() || '(' == getToken())
{
return qC() && qB();
}

error('A', 'x', '~', '(');

return false;
}

/**
* Funcao responsavel pela validacao da regra B → vCB | ε
*
* @return true caso a regra esteja correta, false caso contrario
*/
private boolean qB()
{
if ('v' == getToken())
{
nextToken('B');

return qC() && qB();
}

if (')' == getToken() || '$' == getToken())
{
return true;
}

error('B', 'v', ')', '$');

return false;
}

/**
* Funcao responsavel pela validacao da regra C → ED
*
* @return true caso a regra esteja correta, false caso contrario
*/
private boolean qC()
{
if ('x' == getToken() || '~' == getToken() || '(' == getToken())
{
return qE() && qD();
}

error('C', 'x', '~', '(');

return false;
}

/**
* Funcao responsavel pela validacao da regra D → &ED | ε
*
* @return true caso a regra esteja correta, false caso contrario
*/
private boolean qD()
{
if ('&' == getToken())
{
nextToken('D');

return qE() && qD();
}

if ('v' == getToken() || ')' == getToken() || '$' == getToken())
{
return true;
}

error('D', 'v', '&', ')', '$');

return false;
}

/**
* Funcao responsavel pela validacao da regra E → (A) | ~E | x}
*
* @return true caso a regra esteja correta, false caso contrario
*/
private boolean qE()
{
if ('(' == getToken())
{
nextToken('E');

if (qA())
{
if (')' == getToken())
{
nextToken('E');

return true;
}
else
{
error('E', ')');

return false;
}
}
else
{
return false;
}
}

if ('~' == getToken())
{
nextToken('E');

return qE();
}

if ('x' == getToken())
{
nextToken('E');

return true;
}

error('E', '(', '~', 'x');

return false;
}

/**
* Realizar a analise recursiva preditiva
*
* @param source codigo-fonte
* @return true caso o codigo-fonte esteja correto, false caso contrario
*/
public boolean parse(final String source)
{
tokens = source + '$';

index = 0;

return qA() && '$' == getToken();
}

/**
* Metodo principal da linguagem de programacao Java
*
* @param args argumentos da linha de comando (nao utilizado)
*/
public static void main(String[] args)
{
final Compiler compiler = new Compiler();

if (compiler.parse("x&(x~x)"))
{
System.out.println("Análise concluída com sucesso!");
}
else
{
System.out.println("Análise concluída com erro!");
}
}
}