Análisis de descenso recursivo

1. El propósito del experimento:

Compile y depure el programa de análisis de descenso recursivo de acuerdo con una determinada gramática para analizar cualquier cadena de símbolo de entrada. El propósito de este experimento es profundizar la comprensión del análisis de descenso recursivo.

2. Recordatorio previo al experimento

1. La función del método de análisis de descenso recursivo

La función del analizador léxico es utilizar las llamadas recursivas entre funciones para simular la construcción descendente del árbol de sintaxis.

2. La premisa del método de análisis de descenso recursivo

Modificación de la gramática: eliminar la ambigüedad, eliminar la recursividad a la izquierda, extraer el factor de la izquierda, determinar si es gramática LL (1),

3. Las ideas de diseño experimental y los algoritmos del método de análisis de descenso recursivo.

Construya un proceso recursivo para cada símbolo no terminal U de G, que puede llamarse U.

El lado derecho de la producción de U indica la estructura del código de este proceso:

(1) Si es un símbolo terminal, compárelo con el símbolo prospectivo,

Si hay una coincidencia, avance un símbolo; de lo contrario, se producirá un error.

(2) Si es un símbolo no terminal, llame al procedimiento correspondiente a este símbolo no terminal. Cuando hay varias producciones en la parte derecha de A, se puede realizar mediante la estructura de selección.

Específicamente:

(1) Para cada símbolo no terminal U → X1 | X2 | ... | Xn, el método de procesamiento es el siguiente:

U ()

{

Read (ch); // Símbolo actual

Si ch in First (X1) llama a la subrutina de X1;

de lo contrario, si ch en First (X2) llama a la subrutina de X2;

...

más error ()

}

(2) La arquitectura de procesamiento para cada parte derecha X1 → Y1 Y 2 ... Y n es la siguiente:

Llame a la subrutina de Y1;

Llame a la subrutina de Y 2;

...

Llame a la subrutina de Y n

(3) Si la parte derecha está vacía, no se procesará.

(4) Para cada símbolo Yi en la parte derecha

① Si Yi es un símbolo de terminal:

si (Yi = = símbolo actual)

{

Leer (ch); //

regreso;

}

más error ()

② Si Yi es un símbolo no terminal, llame directamente al subprocedimiento correspondiente Yi ()

3. Proceso experimental y orientación:

(1) Preparación:

1. Lea los capítulos relevantes del libro de texto,

2. Considere el plan de diseño;

3. Diseñe la estructura del módulo, pruebe los datos y prepare inicialmente el programa.

(2) Requisitos de procedimiento:

Ejemplo de entrada / salida de programa:

Para la siguiente gramática, use el método de análisis de descenso recursivo para analizar cualquier cadena de símbolo de entrada:

(1) E → TG

(2) G → + TG | -TG

(3) G → ε

(4) T → FS

(5) S → * FS | / FS

(6) S → ε

(7) F → (E)

(8) F → i

El formato de salida es el siguiente:

(1) Programa de análisis de descenso recursivo, preparado por: nombre, número de alumno, clase

(2) Ingrese la cadena de símbolos que termina con # (incluyendo + - / () i #): ingrese la cadena de símbolos en esta posición, por ejemplo: i + i i #

(3) Resultado de salida: i + i * i # es una cadena de símbolo legal

Observaciones: La cadena de símbolo de entrada, como i + i * #, requiere que la salida sea una "cadena de símbolo ilegal".

Nota: 1. Los operadores (+ - * /), los separadores (corchetes), los caracteres i y el terminador # están permitidos en las expresiones;

2. Si encuentra una expresión incorrecta, debe mostrar un mensaje de error (cuanto más detallada sea la información, mejor);

3. Para los estudiantes que tienen la capacidad de aprender, puede generar el proceso de derivación en detalle, es decir, enumerar en detalle las producciones utilizadas en cada paso.

(3) Ideas del programa (solo como referencia):

0. Parte de definición: define constantes, variables y estructuras de datos.

1. Inicialización: Ingrese la cadena del símbolo de entrada del archivo en el búfer de caracteres.

2. Utilice el método de análisis de descenso recursivo para analizar, escribir una función para cada símbolo no terminal y llamar a la función del símbolo de inicio gramatical en la función principal.

(4) Practique el propósito y las ideas del experimento:

El programa comienza a complicarse y requiere el uso de conocimientos de lenguaje de programación y muchas habilidades de programación. El método de análisis de descenso recursivo es un método de análisis más práctico. A través de este ejercicio, las capacidades de desarrollo de software se pueden mejorar enormemente. A través de la práctica, domine el método de llamarse entre funciones.

(2) Para diseñar un buen programa, preste atención a lo siguiente:

1. Diseño del módulo: divida el programa en varios módulos (funciones) razonables, y cada módulo hace lo mismo.

2. Escriba (dibuje) el plan de diseño: diagramas de relación de módulos, diagramas de flujo, variables globales, interfaces de función, etc.

3. Preste atención al estilo de programación al programar: el uso de líneas en blanco, el uso de comentarios, el uso de sangrías, etc.

 

Cuarto, el proceso experimental

Código de experimento

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 255
bool flag=true;
char src[LEN];
int i;
void E();
void T();
void G();
void F();
void S();

int main(){
    printf("编制人:周江峰,20161209719,计科1601\n");
    printf("请输入字符串(以#结束):");
    
    scanf("%s",&src);

    i=0;
    E();
    if(src[i]=='#'&&flag==true){
        printf("语句合法");
    }else
    {printf("不合法");} 
    return 0;
}

void E(){
    printf("E=>TG");
    T();
    G();
    
}

void T(){
    printf("T=>FS");
    F();
    S();
}
void G(){
    if(src[i]=='+'){
        i++;
        printf("G->+TG");
        T();
        G();
    }else if(src[i]=='-'){
        printf("G->-TG");
        i++;
        T();
        G();
    }
    
}

void F(){
    if(src[i]=='('){
        i++;
        E();
        if(src[i]==')')
        {   i++;
            printf("F->(E)");}
        else flag=false;
        }
    else if(src[i]=='i')
    {   printf("F->i");
        i++;}
    
    
    else flag=false;
}

void S(){
    
    if(src[i]=='*'){
        i++;
        F();
        S();
    }else if(src[i]=='/'){
        i++;
        F();
        S();
    }

}


Nota: el sufijo del archivo es .cpp

5. Resultados experimentales

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_41371349/article/details/104951610
Recomendado
Clasificación