Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Flavio Rodrigues
ITUIUTABA - MG 2013
Flavio Rodrigues
Trabalho de aproveitamento do Curso de Engenharia de Computao da Fundao Educacional de Ituiutaba-FEIT e Universidade do Estado de Minas Gerais UEMG como pr-requisito para obteno parcial de crditos na disciplina de compiladores sob orientao da Prof. Dr. Mnica Rocha.
ITUIUTABA - MG 2013
Resumo
Este trabalho traz as fazes de desenvolvimento e gerao de um analisador lxico, sendo este o objeto de estudo. Para tal desenvolvimento, foi escolhido o Software Gerador de Analisadores Lxicos e Sintticos (GALS), sendo este uma ferramenta eficaz para gerao de analisadores lxicos e analisadores sintticos e com proposito didtico auxiliando na construo de Compiladores.
Introduo
Analisadores Lxicos e Sintticos so importantes partes de um compilador. Sua construo sem a utilizao de ferramentas de auxlio pode levar a erros no projeto, alm de ser um trabalho desnecessrio. Existem hoje diversas ferramentas comerciais semelhantes, porm a maioria delas gera apenas ou o Analisador Lxico ou o Sinttico, o que obriga o usurio a conhecer duas ferramentas distintas e leva a incompatibilidades no momento da utilizao em conjunto dos analisadores gerados. Muitas ferramentas geram analisadores segundo uma nica tcnica de anlise sinttica, o que limita seu valor didtico. Praticamente todas geram analisadores em apenas uma linguagem objeto, diminuindo sua flexibilidade. Outro fator agravante o fato de serem ferramentas de cdigo fechado, o que impede que se possa provar formalmente o analisador gerado, j que no se tem acesso a seu cdigo fonte. Tambm existem ferramentas livres (gratuitas e de cdigo aberto) para esta tarefa. A maioria apresenta as mesmas limitaes citadas acima. Mas, por se tratarem de software, livre tm a vantagem de poderem ter seu cdigo-fonte analisado, verificando-se assim se o que fazem realmente aquilo que se prope a fazer. O GALS tenta superar estes problemas e se tornar uma ferramenta prtica e verstil, com aplicabilidade tanto como ferramenta didtica como para uso profissional, promovendo assim o uso das tcnicas formais de anlise.
Para toda produo X ::= Y pertencente gramtica, |X| <= |Y| (o tamanho de X menor que o tamanho de Y)
Tipo 2 (Gramticas Livres de Contexto): Possui a restrio das gramticas tipo 1, e suas produes devem ser da forma A ::= Y, com A N, e Y (N T)*
Tipo 3 (Gramticas Regulares): Alm das restries das gramticas tipo2, as tipo 3 s podem ter produes das formas: A ::= aB, com A e B N, e a T, ou A ::= a, com A N, e a T. Vale a pena notar que em gramticas tipo 2 e 3, produes do tipo A ::= so
permitidas, mesmo que elas quebrem a regra das gramticas tipo 1 (o tamanho de e 0, que menor que o tamanho do lado esquerdo da produo). Isto possvel graas a um teorema que prova que para toda gramtica tipo 2 ou tipo 3 com este tipo de produo, pode-se escrever uma equivalente sem este tipo de produo.
(conjunto vazio) denotando o conjunto (cadeia de caracteres vazia) denotando o conjunto {} (literal) a em denotando o conjunto {a}
(concatenao) RS denotando o conjunto { | em R e em S }. Por exemplo, {"ab", "c"}{"d", "ef"} = {"abd", "abef", "cd", "cef"}.
(alternncia) R|S denotando o conjunto unio de R e S. Usa-se os smbolos , + ou para alternncia ao invs da barra vertical. Por exemplo, {"ab", "c"}{"dv", "ef"} = {"ab", "c", "dv", "ef"}
Exemplos
a|b* denota {, a, b, bb, bbb, ...} (a|b)* denota o conjunto de todas as cadeias de caracteres que contm os smbols a e b, incluindo a cadeia vazia: {, a, b, aa, ab, ba, bb, aaa, ...} ab*(c|) denota o conjunto de cadeias de caracteres comeando com a, ento com zero ou mais bs e opcionalmente com um c: {a, ac, ab, abc, abb, ...}
A definio formal de expresses regulares concisa e evita a utilizao dos quantificadores redundantes ? e +, que podem ser expressados respectivamente por (a|) e aa*. Por vezes o operador de complemento ~ adicionado; ~R denota o conjunto das cadeias de caracteres de * que no esto em R. Esse operador redundante, e pode ser expressado usando outros operadores, apesar da computao para tal representao ser complexa.
Nesta interface so definidos aspectos lxicos e sintticos de uma forma conjunta. Porm, dependendo da escolha que se faa, para gerar apenas o analisador lxico ou o sinttico, o ambiente rearranjado de modo adequado.
Os seguintes menus esto disponveis para o usurio: Arquivo Permite operaes bsicas, como abrir, salvar e criar novos arquivos, alm de importar especificaes sintticas do GAS. Ferramentas Possibilita modificar opes, verificar erros, simular os analisadores e gerar o cdigo dos analisadores lxico e sinttico. Documentao Exibe as tabelas de anlise. Ajuda Ajuda para o usurio.
Tokens
Numero Letra ID ABRECOLCH FECHACOLCH VIRGULA ATRIB ABREPAR FECHAPAR NEGACAO ADICAO SUB MENOR MAIOR BIT_OU MULT DIV MOD BIT_E PONTOVIRGULA Num
Expresses Regulares
[0-9] [a-zA-Z] ({Numero}+({Letra}{Letra}{Letra}){Numero}+) ["["] ["]"] [","] ["="] ["("] [")"] ["!"] ["+"] ["-"] ["<"] [">"] [|] [*] [/] [%] [&] [;] [({Numero}+)]
A imagem abaixo define onde e como devem ser escritas as expresses regulares:
Tm-se aqui duas definies regulares: Numero e Letra. Estas definies no influem em nada no analisador gerado, apenas facilitam a vida do usurio no sentido de que ele no precisa ficar repetindo uma expresso regular complexa na posterior definio dos tokens.
2.5 Tokens
3. Simulao
Abaixo segue a imagem com a simulao proposta no software GALS:
Atravs da imagem pode notar a forma que cada um dos tokens so implementados. Ao simular observa-se que o analisador lxico implementado est funcionando corretamente, pois ele separa cada um dos tokens informando o seu lexema e a posio que este lexema assume no simulador.
Concluses
Este trabalho foi importante para o entendimento da forma que um analisador lxico trabalha as formas de implementao e principalmente a principal funcionalidade deste analisador. A tutorial apresentado no menu ajuda do GALS auxiliou juntamente com a matria aplicada em sala de aula uma implementao de um analisador lxico.
ANEXO A
Cdigos fonte SyntaticError public class SyntaticError extends AnalysisError { public SyntaticError(String msg, int position) { super(msg, position); } public SyntaticError(String msg) { super(msg); } } Cdigos fonte LexicalError public class LexicalError extends AnalysisError { public LexicalError(String msg, int position) { super(msg, position); } public LexicalError(String msg) { super(msg); } } Cdigos fonte SemanticError public class SemanticError extends AnalysisError { public SemanticError(String msg, int position) { super(msg, position); } public SemanticError(String msg) { super(msg); } }
Cdigos fonte Lexico public class Lexico implements Constants { private int position; private String input; public Lexico() { this(new java.io.StringReader("")); } public Lexico(java.io.Reader input) { setInput(input); } public void setInput(java.io.Reader input) { StringBuffer bfr = new StringBuffer(); try { int c = input.read(); while (c != -1) { bfr.append((char)c); c = input.read(); } this.input = bfr.toString(); } catch (java.io.IOException e) { e.printStackTrace(); } 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; } } Cdigo Fonte Token public class Token { private int id; private String lexeme; private int position; public Token(int id, String lexeme, int position) { this.id = id; this.lexeme = lexeme; this.position = position; } public final int getId() { return id; } public final String getLexeme() { return lexeme; }
public final int getPosition() { return position; } public String toString() { return id+" ( "+lexeme+" ) @ "+position; }; } Cdigo fonte Constantes public interface Constants extends ScannerConstants { int EPSILON = 0; int DOLLAR = 1; int t_Num = 2; int t_Letra = 3; int t_ID = 4; int t_ABRECOLCH = 5; int t_FECHACOLCH = 6; int t_VIRGULA = 7; int t_ATRIB = 8; int t_ABREPAR = 9; int t_FECHAPAR = 10; int t_NEGACAO = 11; int t_ADICAO = 12; int t_SUB = 13; int t_MENOR = 14; int t_MAIOR = 15; int t_BIT_OU = 16; int t_MULT = 17; int t_DIV = 18; int t_MOD = 19; int t_BIT_E = 20; int t_PONTOVIRGULA = 21; }