15. Modo intérprete

Dado un idioma, defina una representación de su gramática y defina un intérprete que use esa representación para interpretar oraciones en el idioma.

Diagrama de clase

Ejemplo de código

1.	class Context {}  
2.	abstract class Expression {  
3.	    public abstract Object interpreter(Context ctx);  
4.	}  
5.	class TerminalExpression extends Expression {  
6.	    public Object interpreter(Context ctx){  
7.	        return null;  
8.	    }  
9.	}  
10.	class NonterminalExpression extends Expression {  
11.	    public NonterminalExpression(Expression...expressions){  
12.	          
13.	    }  
14.	    public Object interpreter(Context ctx){  
15.	        return null;  
16.	    }  
17.	}  
18.	public class Client {  
19.	    public static void main(String[] args){  
20.	        String expression = "";  
21.	        char[] charArray = expression.toCharArray();  
22.	        Context ctx = new Context();  
23.	        Stack<Expression> stack = new Stack<Expression>();  
24.	        for(int i=0;i<charArray.length;i++){  
25.	            //进行语法判断,递归调用  
26.	        }  
27.	        Expression exp = stack.pop();  
28.	        exp.interpreter(ctx);  
29.	    }  
30.	}  

La parte del código de la recursividad gramatical debe implementarse de acuerdo con la situación específica, por lo que no se refleja en el código. Las expresiones abstractas son la clave para generar conjuntos gramaticales. Cada expresión de símbolo no terminal interpreta una unidad gramatical mínima y luego combina de forma recursiva estas unidades gramaticales en una gramática completa. Este es el modo de intérprete.

Estructura del modo analizador

  1. Intérprete abstracto: declara una interfaz abstracta (o clase abstracta) que todas las expresiones concretas deben implementar. La interfaz es principalmente un método interpret (), que se denomina operación de interpretación. La tarea de interpretación específica se completa con sus diversas clases de implementación, y los intérpretes específicos son completados respectivamente por el intérprete terminal TerminalExpression y el intérprete no terminal NonterminalExpression.
  2. Expresión terminal: realiza la operación de interpretación asociada con los elementos de la gramática. Normalmente, solo hay una expresión terminal en un modo de intérprete, pero hay varias instancias correspondientes a diferentes símbolos terminales. El símbolo terminal es la mitad de la unidad de operación en la gramática. Por ejemplo, hay una fórmula simple R = R1 + R2, en la que R1 y R2 son símbolos terminales, y el intérprete correspondiente que analiza R1 y R2 es expresión terminal.                                
  3. Expresión de símbolo no terminal: cada regla de la gramática corresponde a una expresión de símbolo no terminal. Las expresiones de símbolo no terminal son generalmente operadores u otras palabras clave en la gramática. Por ejemplo, en la fórmula R = R1 + R2, + no es Símbolo terminal, el intérprete que analiza + es una expresión de símbolo no terminal. Las expresiones de símbolos no terminales aumentan según la complejidad de la lógica En principio, cada regla gramatical corresponde a una expresión de símbolos no terminales.
  4. Rol ambiental: La tarea de este rol es generalmente almacenar el valor específico correspondiente a cada símbolo terminal en la gramática, como R = R1 + R2, asignamos 100 a R1 y 200 a R2. Esta información debe almacenarse en el rol ambiental, en muchos casos es suficiente utilizar Map para actuar como rol ambiental.

Ventajas y desventajas del modo intérprete

El intérprete es una sencilla herramienta de análisis gramatical. Su ventaja más significativa es su extensibilidad. Para modificar las reglas gramaticales, solo es necesario modificar los símbolos no terminales correspondientes. Si expande la gramática, solo necesita agregar símbolos no terminales.

Sin embargo, el modo de intérprete provocará la expansión de clases. Cada gramática necesita producir una expresión de símbolo no terminal. Cuando las reglas gramaticales son más complicadas, se pueden generar una gran cantidad de archivos de clases, lo que trae muchos problemas para el mantenimiento. Al mismo tiempo, debido al método de llamada recursiva, cada expresión no terminal solo se preocupa por las expresiones relacionadas consigo misma, y ​​cada expresión necesita conocer el resultado final, que debe ser recursivo, ya sea un lenguaje orientado a objetos o un lenguaje orientado a procesos. , No se recomienda la recursividad. Debido al uso de una gran cantidad de bucles y recursividad, la eficiencia es un problema que no se puede ignorar. Especialmente cuando se usa para explicar una gramática compleja y extensa, la eficiencia es insoportable.

Escenarios de uso del modo de intérprete

El modo de intérprete se puede utilizar en las siguientes situaciones:

  1. Existe una regla gramatical simple, como una declaración SQL. Si necesitamos realizar una conversión rm basada en la declaración SQL, podemos usar el modo de intérprete para interpretar la declaración.
  2. Algunos problemas recurrentes, como las cuatro operaciones aritméticas de suma, resta, multiplicación y división, pero la fórmula es diferente cada vez, a veces es a + bc * d, a veces a * b + cd, etc., etc., la fórmula cambia constantemente, pero siempre se suma Reste, multiplique y divida los cuatro no terminales para conectar, luego podemos usar el modo de intérprete.

 

Supongo que te gusta

Origin blog.csdn.net/sinat_37138973/article/details/88636537
Recomendado
Clasificación