[Resolvido] Analisador Léxico e sintático

9 respostas
E

Estou precisando desenvolver um analisador léxico e sintático em JAVA porém ainda não possuo intimidade suficiente com o JAVA para a realização do mesmo.

Alguém poderia me ajudar em como desenvolver esses analisadores?

Obrigado.

9 Respostas

T

http://www.antlr.org/
https://javacc.dev.java.net/

E

Agradeço as informações fornecidas, não teria algo em português, exemplos para me auxiliar melhor. Pois alguns termos em inglês eu me atrapalho.

Mais uma vez obrigado.

M

eu ja usei o javacc, assunto do segundo link que o tingol passou… infelizmente por isso posso afirmar que conteudo bom e em portugeus sobre compiladores é tremendamente raro, sobre compiladores de compiladores é ainda mais raro.

Esse site esta em ingles mais da pra se vira, mesmo que acabe sendo com google translator… la tem exemplos prontos de códigos que geram o analisador lexico e sintatico de linguagens como java, c e sql (ao menos a um certo tempo atras tinha)

da uma olhada la direito…

E

Analisei o JCC porém preciso de algo mais simples, já que se trata de um trabalho de faculdade onde o professor não que algo muito complexo.

Essa é a gramatica que especifica a linguagem:

-> SEQ | PAR
-> begin end
-> , |
-> name (timeout) |

Exemplo de entrada sintaticamente correta

SEQ begin proc (20.5) , PAR begin proc1 (nome), proc1890 (3) end end

O SEQ determina uma lista de processos que devem ser executados sequencialmente.
O PAR uma lista de processos que devem ser executados paralelamente.
O símbolo léxico name pode ser qualquer palavra formada por letras maiúsculas ou minúsculas seguidas ou não de dígitos.
o símbolo léxico timeout representa em segundos e detremina o tempo méximo que o processo pode executar. Caso seja colocado none indica que não possui nenhuma restrição.

É com isso que foi passado que tenho que construir em JAVA um analisador léxico e sintático. Quem puder me ajudar eu agradeceria.

T

Para um analisador léxico, você pode se basear no código do java.io.StreamTokenizer (olhe no JDK, arquivo src.zip, e ache nesse arquivo zip o arquivo java/io/StreamTokenizer.java )

T

Quanto ao analisador sintático, como a gramática é bem bobinha, você pode usar “recursive descent” ( http://en.wikipedia.org/wiki/Recursive_descent_parser ).
O nome é ameaçador, mas na prática é o que você faria se você não conhecesse P*** nenhuma de teoria de compiladores - é bem intuitivo, na verdade. Esse método é particularmente adequado se você quiser fazer as coisas na mão, sem auxílio nenhum de compilador de compiladores.
Mesmo linguagens com gramáticas mais complexas, como o próprio Java, têm compiladores que usam Recursive Descent. Se não me engano, o javac é um compilador desse tipo.

E

Alguém poderia me ajudar a terminar o programa, pois não estou conseguindo o que eu quero!

No botão "Analise Léxica" eu não estou conseguindo fazer com que o mesmo leia a entrada do código e como resposta além dos erros (caso possua algum) listar todos os tokens. (Imagem 1)

No botão "Analise Sintática" ler a entrada do código e como resposta ter a árvore de derivação. (Imagem 2)

Código principal:

package compiladores;

import compiladores.Lexico;
import compiladores.Token;
import compiladores.LexicalError;
import compiladores.Sintatico;
import compiladores.SyntaticError;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class AnalisadorLS extends JFrame {

	private JButton analisadorLexico,analisadorSintatico,fechar;
	private JTextArea codPrograma,tokensGerados,erros;
	private JPanel painel, pBotoes;
	private JScrollPane scroll1, scroll2, scroll3;
	private JLabel lb1,lb2,lb3;
	
	public AnalisadorLS() {
		telaPrograma();
	}
	
	Lexico lexico = new Lexico();
	Sintatico sintatico = new Sintatico();
	
	public void telaPrograma() {
		setSize(540, 580);
		setLayout(null);
		setTitle("Analisador Léxico");
		setResizable(false);
		
		analisadorLexico = new JButton("Analise Léxica");
		analisadorSintatico = new JButton("Analise Sintática");
		fechar = new JButton("Fechar");
		
		lb1 = new JLabel("Entrada de dados");
		lb2 = new JLabel("Resultado da analise");
		lb3 = new JLabel("Erros");
		
		codPrograma = new JTextArea();
		tokensGerados = new JTextArea();
		erros = new JTextArea();
		
		painel = new JPanel(new GridLayout(2,2));
		pBotoes = new JPanel();
				
		analisadorLexico.setSize(10,20);
		analisadorSintatico.setSize(10,20);
		fechar.setSize(10,20);
		
		codPrograma.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		tokensGerados.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		erros.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		
		codPrograma.setWrapStyleWord(true);
		tokensGerados.setWrapStyleWord(true);
		erros.setWrapStyleWord(true);
		
		scroll1 = new JScrollPane(codPrograma);
		scroll2 = new JScrollPane(tokensGerados);
		scroll3 = new JScrollPane(erros);
		
		analisadorLexico.setToolTipText("Executa a analise léxica");
		analisadorSintatico.setToolTipText("Executa a analise sintática");
		fechar.setToolTipText("Fecha a janela");
		
		pBotoes.add(analisadorLexico);
		pBotoes.add(analisadorSintatico);
		pBotoes.add(fechar);
		
		scroll1.setBounds(20, 40, 300, 380);
		scroll2.setBounds(350, 40, 120, 380);
		scroll3.setBounds(20, 450, 450, 50);
		
		pBotoes.setBounds(20, 510, 450, 40);
		
		lb1.setBounds(20, 20, 100, 20);
		lb2.setBounds(350, 20, 120, 20);
		lb3.setBounds(20, 430, 120, 20);
		
		add(scroll1);
		add(scroll2);
		add(scroll3);
		add(pBotoes);
		add(lb1);
		add(lb2);
		add(lb3);
		
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);		
		setLocationRelativeTo(this);
		
		analisadorLexico.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				if(codPrograma.getText().length() == 0){
					JOptionPane.showMessageDialog(null, "O campo 'Entrada de dados' está vazio");
				}else{
					lexico.setInput(codPrograma.getText());
					try
					{
					    Token t = null;
					    while ( (t = lexico.nextToken()) != null ) {
					        tokensGerados.setText(lexico.listaTokens());
					    }
					}
					catch ( LexicalError ev )
					{
					    //erros.getText(ev.getMessage());
					}
					
					
				}
			}
		});
		
		fechar.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				dispose();
			}
		});
	}
	
	public static void main(String[] args) {
		AnalisadorLS executar = new AnalisadorLS();

	}

}

Código Léxico:

package compiladores;

public class Lexico implements Constants
{
    private int position;
    private String input;

    public Lexico()
    {
        this("");
    }

    public Lexico(String input)
    {
        setInput(input);
    }

    public void setInput(String input)
    {
        this.input = input;
        setPosition(0);
    }

    public void setPosition(int pos)
    {
        position = pos;
    }

    public Token nextToken() throws LexicalError
    {
        if ( ! hasInput() )
            return null;

        int start = position;

        int state = 0;
        int lastState = 0;
        int endState = -1;
        int end = -1;

        while (hasInput())
        {
            lastState = state;
            state = nextState(nextChar(), state);

            if (state < 0)
                break;

            else
            {
                if (tokenForState(state) >= 0)
                {
                    endState = state;
                    end = position;
                }
            }
        }
        if (endState < 0 || (endState != state && tokenForState(lastState) == -2))
            throw new LexicalError(SCANNER_ERROR[lastState], start);

        position = end;

        int token = tokenForState(endState);

        if (token == 0)
            return nextToken();
        else
        {
            String lexeme = input.substring(start, end);
            return new Token(token, lexeme, start);
        }
    }

    private int nextState(char c, int state)
    {
        int next = SCANNER_TABLE[state][c];
        return next;
    }

    private int tokenForState(int state)
    {
        if (state < 0 || state >= TOKEN_STATE.length)
            return -1;

        return TOKEN_STATE[state];
    }

    private boolean hasInput()
    {
        return position < input.length();
    }

    private char nextChar()
    {
        if (hasInput())
            return input.charAt(position++);
        else
            return (char) -1;
    }
}

Código do Gerador de erro léxico:

package compiladores;

public class LexicalError extends AnalysisError
{
    public LexicalError(String msg, int position)
	 {
        super(msg, position);
    }

    public LexicalError(String msg)
    {
        super(msg);
    }
}

Código Sintático:

package compiladores;

import java.util.Stack;

public class Sintatico implements Constants
{
    private Stack stack = new Stack();
    private Token currentToken;
    private Token previousToken;
    private Lexico scanner;

    public void parse(Lexico scanner) throws LexicalError, SyntaticError
    {
        this.scanner = scanner;

        stack.clear();
        stack.push(new Integer(0));

        currentToken = scanner.nextToken();

        while ( ! step() )
            ;
    }

    private boolean step() throws LexicalError, SyntaticError
    {
        if (currentToken == null)
        {
            int pos = 0;
            if (previousToken != null)
                pos = previousToken.getPosition()+previousToken.getLexeme().length();

            currentToken = new Token(DOLLAR, "$", pos);
        }

        int token = currentToken.getId();
        int state = ((Integer)stack.peek()).intValue();

        int[] cmd = PARSER_TABLE[state][token-1];

        switch (cmd[0])
        {
            case SHIFT:
                stack.push(new Integer(cmd[1]));
                previousToken = currentToken;
                currentToken = scanner.nextToken();
                return false;

            case REDUCE:
                int[] prod = PRODUCTIONS[cmd[1]];

                for (int i=0; i<prod[1]; i++)
                    stack.pop();

                int oldState = ((Integer)stack.peek()).intValue();
                stack.push(new Integer(PARSER_TABLE[oldState][prod[0]-1][1]));
                return false;

            case ACTION:
                int action = FIRST_SEMANTIC_ACTION + cmd[1] - 1;
                stack.push(new Integer(PARSER_TABLE[state][action][1]));
                return false;

            case ACCEPT:
                return true;

            case ERROR:
                throw new SyntaticError(PARSER_ERROR[state], currentToken.getPosition());
        }
        return false;
    }

}

Código do erro sintático:

package compiladores;

public class SyntaticError extends AnalysisError
{
    public SyntaticError(String msg, int position)
	 {
        super(msg, position);
    }

    public SyntaticError(String msg)
    {
        super(msg);
    }
}

Quem puder me ajudar eu agradeço, já estou há uns três dias tentando e não saio do lugar!



E

Caso alguém precise de mais alguma informação para me ajudar a terminar esse programa é só perguntar.

Obrigado!

A

eu gostaria que voce postasse o seu codigo final,
por curiosidade minha mesmo!

grato.

Criado 26 de maio de 2009
Ultima resposta 22 de mai. de 2013
Respostas 9
Participantes 4