Skip to content

scanner lexico document

Muriel S edited this page Aug 17, 2019 · 4 revisions

documentação

Essas bibliotecas (em azul) permitem executar a aplicação. Recomenda-se a instalação Java SE Development Kit em conjunto com algum ambiente de Desenvolvimento (IDE) que execute a linguagem JAVA.

Java Development Kit v.8.0 GSON 2.8.0

características do parser

Esse repositório contém um analisador léxico com as seguintes características:

  palavras reservadas: while, do
  operadores: <, =, +
  terminador: ;
  identificadores: i, j
  constantes: sequência de números
  números: 0 ... 9

Por meio da entrada de um arquivo texto (qualquer nome e qualquer extensão), o scanner processa (analisa) e gera na saída um arquivo JSON, contendo a tabela de tokens, a tabela de símbolos e um possível erro encontrado durante a análise.

Por que usar esse repositório?

Vantagens

  • É Simples e funcional,
  • Tem interface gráfica,
  • Permite adição de novas palavras reservadas ou identificadores via interface gráfica,
  • Pode utilizar um código-fonte com diversas linhas (o código não precisa está em uma linha somente),
  • Gera os arquivos JSON e as tabelas (na interface-gráfica) durante sua execução,
  • E o mais importante: FOI FEITO COM ❤.

processo criação do parser

processo criativo
  1. A primeira coisa feita foi definir a linguagem de programação que seria utilizada. Nesse caso, optou-se pela linguagem de programação JAVA, pois ela permitia um fácil construção da interface-gráfica, é popular e a equipe estava familiarizada.
  2. Após a definição da linguagem, criou-se o repositório compartilhado no Github para que todo o desenvolvimento ocorresse de forma compartilhada entre a equipe.
  3. Enfim, a etapa mais importante, O DESENVOLVIMENTO. A primeira coisa definida foi a construção da interface-gráfica que ia compor a aplicação. Após isso ocorria-se a construção dos método. Primeiro definia-se qual método ia ser construído (ex. Método que cria o arquivo JSON). Depois definia-se que subsídios internos e externos poderiam ser utilizados para construir o método (ex. Bibliotecas, pacotes e etc). Ao fim, o código era construído. Esse processo era cíclico até todos os métodos necessários estarem construídos e interligados.

descrição estrutural do parser

O principal método do código, que realiza a detecção dos tokens, cria tabelas e chama outros métodos secundários.

public void analisar(String codigofonte, int numLinha){
        ...
}

Aqui é onde é realizado uma parte muito importante do método. Ocorre-se a leitura de cada caractere da linha de código e definindo o mapa com todas as palavras e suas respectivas posições na lista.

public void analisar(String codigofonte, int numLinha){
        ...
        Map<Integer,String> dicionarioCode = new TreeMap<>();
        for (int i = 0; codigofonte.length() > i; i++){     
            if(codigofonte.substring(i, i+1).equals(" ") || listaTerminadores.contains(codigofonte.substring(i, i+1).charAt(0))){
                dicionarioCode.put(inicioWord, word);
                word = "";
                inicioWord = i + 1;
                if (listaTerminadores.contains(codigofonte.substring(i, i+1).charAt(0)))
                    dicionarioCode.put(inicioWord,codigofonte.substring(i, i+1));
            }
            else{
                word = word + codigofonte.substring(i, i+1);
            }
        }        
               ...

}

Nessa etapa (abaixo) cada palavra mapeada é verificada para ver se ela pertence ao vocabulário definido (em características do parser). Uma vez verificada, ela é adicionada a tabela(interface-gráfica) com suas devidas informações. Caso ocorra um erro ele também é captado e armazenado em variável. Aqui também é criado objetos do tipo Token.

public void analisar(String codigofonte, int numLinha){
               ...
Set<Integer> chaves = dicionarioCode.keySet();
	for (int chave : chaves){  
            if(isPalavraReservada(dicionarioCode.get(chave))){
                Token t = new Token(dicionarioCode.get(chave), "palavra reservada", dicionarioCode.get(chave).length(), "(" +numLinha+" , "+ chave + ")");
                criarJSON(t);
                linha = new String[]{dicionarioCode.get(chave)+"", "palavra reservada"+"", dicionarioCode.get(chave).length()
        +"","(" +numLinha+" , "+ chave + ")"};
                modelo.addRow(linha);
            }
            else if(isOperador(dicionarioCode.get(chave))){
                               ...
            }
            else if(isIdentificador(dicionarioCode.get(chave))){                    
                              ...
            }
            else if(isConstante(dicionarioCode.get(chave))){
                               ...
            }
            else if(isTerminador(dicionarioCode.get(chave))){
                              ...
            }
            else{
                erro = "Não foi possivel achar nenhum contexto para " + dicionarioCode.get(chave)+ ", esse elemento está na posição: " + "(" +numLinha+" , "+ chave + ")";
                JOptionPane.showMessageDialog(null, erro);
                break;
            }     
	}
}

Aqui (abaixo) é criado os JSON a medida que os tokens detectado é verificado e válido. O método utiliza a biblioteca GSON para construção desses arquivos. Os objetos de JSON criados são armazenados em uma lista.

public void criarJSON(Token t){
        Gson gson = new GsonBuilder().disableHtmlEscaping().create();
        String JSON = gson.toJson(t);
        listaJSONTokens.add(JSON);
    }

Essa função (abaixo) gerá (write) o arquivo .json com as listas de todas as informações da tabela de tokens e tabela de índices e erro [caso ocorra].

public void imprimirSaida(ArrayList<String> tokens, ArrayList<String> simbolos, String erro){
        String saida = "\"tokens\":{";
        for (String s : tokens){
            saida = saida + "\n\t" + s + ",";
        }
        saida = saida + "\n},\n \"simbolos\":{";
        
        for (String s : simbolos){
            saida = saida + "\n\t" + s + ",";
        }
        saida = saida + "\n}";
        if(!erro.isEmpty())
            saida = saida + ",\n\"erros\":{\n\t\"erro\": \"" + erro + "\"\n}";
        FileWriter arquivo;
		try {
			arquivo = new FileWriter(new File("scannerLexico.json"));
			arquivo.write(saida);
			arquivo.close();
               } 
               catch (FileNotFoundException e) {
                          ...
               }
        }
    }

funcionamento

Com a ferramenta em execução, selecione um arquivo com código-fonte (exemplos de arquivo no link ao lado). Por exemplo:

  1. [Entrada] File.py:

    while i < 100 do i = i + j;

  2. [Processamento]

processando código

  1. [Saída] file.json:

Tabela de Tokens

Token Identificação Tamanho Posição
while palavra reservada 5 (0,0)
i [identificador, 1] 1 (0,6)
< operador 1 (0,8)
100 [constante, 2] 3 (0,10)
do palavra reservada 2 (0,14)
i [identificador, 1] 1 (0,17)
= operador 1 (0,19)
i [identificador, 1] 1 (0,21)
+ operador 1 (0,23)
j [identificador, 3] 1 (0,25)
; terminador 1 (0,27)

Tabela de Símbolos

Índice Símbolo
1 i
2 100
3 j