200 likes | 338 Views
Avaliador de Expressões. Luiz Carlos d´Oleron (lcadb). O Problema. Modelar (sub-conjunto das) expressões da lógica proposicional (sintaxe e propriedades) Avaliar cadeias de caracteres (String’s) contra as regras de formação de expressões A especificação do projeto está em:
E N D
Avaliador de Expressões Luiz Carlos d´Oleron (lcadb)
O Problema • Modelar (sub-conjunto das) expressões da lógica proposicional (sintaxe e propriedades) • Avaliar cadeias de caracteres (String’s) contra as regras de formação de expressões • A especificação do projeto está em: http://www.cin.ufpe.br/~lcadb/logica/avaliador.html
Definido uma expressão • Cadeia de caracteres formada com o alfabeto: Ω* = {0,1,x,y,z, ),(,.,-,+} • E obedecendo as regras de construção
Regras para EBF - Expressão Bem Formada • Todas expressão atômica é EBF • Se E é uma EBF, então (┐E) também é EBF; • Se E1 e E2 são EBF´s então (E1 □ E2) é também EBF; • Nada mais é uma EBF Obs1: □ : {.,+} Obs2: Esta é só uma pincelada na teoria, todos os detalhes estão nas notas de aula de Ruy
“Exemplinhos” • ‘1’ é EBF • ‘x’ é EBF • ‘(1.x)’ é EBF • ‘1.x’ não é EBF • ‘-(1.x)’ não é EBF • ‘(-(1.x))’ é EBF • ‘((x+1)+z)’ é EBF • ‘(x+1+z)’ não é EBF
Bem vindo ao mundo Virtual • Desafios: • Adaptar o modelo matemático a uma realidade virtual • Para isso usaremos algumas linguagens que não são especializadas para isso: Java, C ou C++
Exemplo: (x + (-y)) Expressao x = new ExpressaoAtomica(‘x’); Expressao y = new ExpressaoAtomica(‘y’); Expressao negY = new Negacao(y); Expressao ou = new ExpressaoOU(x, negY); String e = ou.representacao(); System.out.println(“Altura de ” + e + “ : ” + ou.altura()); System.out.println (“Número de operadores de ” + e + “ : ” + ou.numeroOperadores()); Altura de (x+(-y)) : 2 Número de operadores de (x+(-y)) : 2
Definição recursiva: representacao() //na classe ExpressaoAtomica String representacao(){ return this.simbolo + “”; } //na classe Negacao String representacao(){ return“(-” + this.getE().representacao() + “)”; } //na classe ExpressaoE, bem parecido na //ExpressaoOU String representacao(){ return“(” + this.getE1().representacao() + “.” + this.getE2().representacao() + “)”; }
Definição recursiva: altura () //na classe ExpressaoAtomica int altura(){ return0; } //na classe Negacao int altura(){ return1 + this.getE().altura(); } //na classe ExpressaoBinaria int altura(){ int a1 = this.getE1().altura(); int a2 = this.getE2().altura(); return1 + Math.max(a1,a2); }
Definição recursiva: numeroOperadores () //na classe ExpressaoAtomica int numeroOperadores(){ return0; } //na classe Negacao int numeroOperadores(){ return1 + this.getE().numeroOperadores(); } //na classe ExpressaoBinaria int numeroOperadores(){ int a1 = this.getE1().numeroOperadores(); int a2 = this.getE2().numeroOperadores(); return1 + a1 + a2; }
Definição recursiva: listaSubExpressoes() //na classe ExpressaoAtomica List listaSubExpressoes(){ List retorno = new ArrayList(); //o conjunto de subexpressões de uma expressão //atomica é ela mesma String e = this.representacao(); retorno.add(e); return retorno; } //na classe Negacao List listaSubExpressoes(){ //pega lista de sua sub-expressão List retorno = this.getE().listaSubExpressoes(); //adiciona a si mesma String e = this.representacao(); retorno.add(e); return retorno; }
Definição recursiva: listaSubExpressoes() //na classe ExpressaoBinaria List listaSubExpressoes(){ //pega lista de suas sub-expressões List retorno = this.getE1().listaSubExpressoes(); List temp = this.getE2().listaSubExpressoes(); Object o = null; Iterator i = temp .iterator(); while(i.hasNext()){ o = i.next(); //Só adiciona se não contiver if(!retorno.contains(o)){ retorno.add(o); } } //adiciona a sim mesma String e = this.representacao(); retorno.add(e); return retorno; }
E agora? • Já sabemos modelar as estruturas EBF (a parte mais fácil) • Só falta fazer o computador “ver” uma expressão e dizer se ela é válida ou não...
Solução • As regras de validação EBF são tão poderosas que vamos usá-las de fora para dentro • Usaremos recursão para: • Dada uma expressão φqualquer, identificaremos suas sub-expressões (se existirem), validando recursivamente
Validando expressões • Dado φ • φ é construída com o alfabeto? • Se φ é atômica, é válida • Senão, • Ela possui parênteses em número e ordem corretos? • Se possuir, calcularemos o operador raiz* • Com o operador raiz em mãos, identificamos a(s) sub-expressão (ões) e repetimos o procedimento nela(s)
Exemplo: ((x+1).(-y)) • Construída com o alfabeto ☺ • ((x+1).(-y)) não é atômica • 3x‘(’ por 3x‘)’, começando com ‘(’ e terminando com ‘)’ ☺ • Procurando o op. Raiz > ‘.’ ☺ • Agora repetimos os passos com (x+1) e depois com (-y) • ...
Encontrando o operador raiz • O operador raiz é o operador que fica na raiz da árvore da expressão: • Para encontrá-lo vamos contar
Encontrando o operador raiz • Desconsidere o primeiro ‘(’ e o último ‘)’ • Percorra a expressão e vá contando sempre a diferença ∆ entre o número de ‘(’ e o número de ‘)’ • O primeiro operador (+,- ou .) que você encontrar quando (∆ == 0) é o operador raiz.
É isso aí. O resto são detalhes de implementação. Leiam atentamente a especificação e testem várias vezes seus programas. Mantenham uma lista de expressões para testes. Boa Sorte