© LES/PUC-Rio Padrão de Projeto Interpreter Kleinner Farias.
Transcript of © LES/PUC-Rio Padrão de Projeto Interpreter Kleinner Farias.
© LES/PUC-Rio
Padrão de Projeto InterpreterKleinner Farias
© LES/PUC-Rio
Agenda
• Propósito/Intenção
• Motivação
• Exemplo
• Aplicabilidade
• Estrutura
• Participantes
• Conseqüências
• Implementação
© LES/PUC-Rio
Intenção
• Afinal, qual é o propósito do Interpreter? - Dada uma linguagem, definir uma representação para a sua
gramática juntamente com um interpretador que usa representação para interpretar sentenças da linguagem.
• Interpreter descreve como definir uma gramática para linguagens simples, representar sentenças e interpretar estas sentenças.
© LES/PUC-Rio
Motivação
• Quando devemos usar o padrão Interpreter?
- Se um tipo específico de problema ocorre com freqüência suficiente,
pode valer a pena expressar instâncias do problema como sentenças de uma linguagem simples.
• Alguns Problemas:Como irei trabalhar com
patterns of strings?
Como irei fazer pesquisa de caracteres?
Use o Padrão Interpreter.
Algorítmos de busca podem interpretar uma expressão regular que especifica um conjunto
de cadeias a serem encontrados.
© LES/PUC-Rio
Motivação
• O Interpreter analisa o problema dividindo-o em pequenos pedaços, e então coloca os pedaços de volta juntos, como uma sentença numa linguagem simples.
• Pattern matching – pesquisar cadeias de caracteres que correspondem a um determinado padrão.
• Pattern of strings – expressões regulares
• Match – algoritmo de busca
© LES/PUC-Rio
Exemplo
BooleanExp ::= VariableExp | Constant | OrExp | AndExp | NotExp | '(' BooleanExp ')'
AndExp ::= BooleanExp 'and' BooleanExp
OrExp ::= BooleanExp 'or' BooleanExp
NotExp ::= BooleanExp 'not' BooleanExp
Constant ::= 'true' | 'false'
VariableExp ::= 'A' | 'B' | ... | 'Z‘
• Onde temos:- Símbolos não-terminais: BooleanExp, AndExp, OrExp, NotExp.- Símbolos terminais: Constant, VariableExp
© LES/PUC-Rio
Aplicabilidade
• Quando houver uma linguagem para interpretar e seja possível representar sentenças da linguagem como árvores sintéticas abstratas.
• Quando ele funciona melhor?
- A gramática é simples.
- A eficiência não é uma preocupação crítica.
© LES/PUC-Rio
Estrutura
© LES/PUC-Rio
Participantes
• AbstractExpression – declara uma operação que será comum a todos os nós na árvore sintática abstrata.
• TerminalExpression – implementa operações definidas na AbstractExpression
• NonTerminalExpression- para cada regra da gramática é necessário um NonTerminalExpression.- mantém variáveis de instância do tipo AbstratctExpression.- implementa uma operação Interpret.
• Context - contém informação que é global para o interpretador.
• Client – contrói ou recebe um árvore sintática.
© LES/PUC-Rio
Conseqüências
• Facilidade de mudar e estender gramática – usa classe para representar regras da gramática.
• Implementar a gramática também é fácil – os “nodos” da árvore são implementados de uma maneira similar.
• Gramáticas complexas são difíceis de manter – para cada regra da gramática é definido uma classe.
• Acrescentando novas formas de interpretar expressões – torna mais fácil resolver uma expressão de uma nova maneira.
© LES/PUC-Rio
Implementação
• Criação da árvore sintática abstrata – o padrão não define como criar a árvore sintática abstrata.
• Compartilhando símbolos terminais com o padrão FlyWeight – compartilhamento de símbolos terminais usando o padrão FlyWeight.
• Flexibilidade – as classes podem ser alteras e modificadas facilmente.
© LES/PUC-Rio
Implementação
© LES/PUC-Rio
Implementação
public class Context { private Hashtable context = new Hashtable();
public void assign(String name, boolean val) { context.put(name, new Boolean(val)); } public boolean lookUp(String name) { return ((Boolean)context.get(name)).booleanValue(); } public Context() { }}
public interface BooleanExp { public abstract boolean evaluate( Context c ); public abstract BooleanExp replace(String var, BooleanExp exp); public abstract BooleanExp copy();}
© LES/PUC-Rio
Implementação
public class AndExp implements BooleanExp { private BooleanExp operand1; private BooleanExp operand2; public andExp (BooleanExp oper1, BooleanExp oper2) { operand1 = oper1; operand2 = oper2; }
public boolean evaluate(Context c) { return operand1.Evaluate(c) && operand2.Evaluate(c); }
public BooleanExp copy() { return new AndExp(operand1.Copy(), operand2.Copy()); }
public BooleanExp replace(String var, BooleanExp exp) { return new AndExp( operand1.Replace(var, exp), operand2.Replace(var, exp) ); }}
© LES/PUC-Rio
Implementação
public class VariableExp implements BooleanExp { private String name; public VariableExp(String _name) { name = _name; }
public boolean evaluate(Context c) { return c.LookUp(name); }
public BooleanExp copy() { return new VariableExp(name); }
public BooleanExp replace(String var, BooleanExp exp) { if(var.equals(name)) { return exp.Copy(); } else { return new VariableExp(name); } } }
© LES/PUC-Rio
Implementação
public class Test { public static void main(String[] args) { // Test : // (true and x) or (y and (not x)) Context context = new Context(); VariableExp x = new VariableExp("X"); VariableExp y = new VariableExp("Y"); VariableExp bTure = new VariableExp("true"); VariableExp bFalse = new VariableExp("false");
context.Assign("true", true); context.Assign("false", false); context.Assign("X", true); context.Assign("Y", true); BooleanExp expression = new orExp( new AndExp(bTure, x), new AndExp(y, new NotExp(x)) ); boolean result = expression.evaluate(context); System.out.println("The result is:" + result); }}