scanner lexico document - murielsouza/scanner-lexico-de-codigo GitHub Wiki
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.
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?
- É 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 ❤.
- 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.
- 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.
- 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.
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) {
...
}
}
}
Com a ferramenta em execução, selecione um arquivo com código-fonte (exemplos de arquivo no link ao lado). Por exemplo:
-
[Entrada] File.py:
while i < 100 do i = i + j;
-
[Processamento]
- [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 |