Recursive descent analysis

1. The purpose of the experiment:

Compile and debug the recursive descent analysis program according to a certain grammar to analyze any input symbol string. The purpose of this experiment is to deepen the understanding of recursive descent analysis.

2. Pre-experiment reminder

1. The function of recursive descent analysis method

The function of the lexical analyzer is to use the recursive calls between functions to simulate the top-down construction of the syntax tree.

2. The premise of the recursive descent analysis method

Modification of grammar: eliminate ambiguity, eliminate left recursion, extract left factor, judge whether it is LL (1) grammar,

3. Experimental design ideas and algorithms of recursive descent analysis method

Construct a recursive process for each non-terminal symbol U of G, which may be named U.

The right side of U’s production indicates the code structure of this process:

(1) If it is a terminal symbol, compare it with the forward-looking symbol,

If there is a match, move forward one symbol; otherwise, an error occurs.

(2) If it is a non-terminal symbol, call the procedure corresponding to this non-terminal symbol. When there are multiple productions in the right part of A, it can be realized by selection structure.

Specifically:

(1) For each non-terminal symbol U→X1| X2|...| Xn, the processing method is as follows:

U ()

{

Read(ch);//Current symbol

If ch in First(X1) calls the subroutine of X1;

else if ch in First(X2) call the subroutine of X2;

else error()

}

(2) The processing architecture for each right part X1→Y1 Y 2...Y n is as follows:

Call the subroutine of Y1;

Call the subroutine of Y 2;

Call the subroutine of Y n

(3) If the right part is empty, it will not be processed.

(4) For each symbol Yi in the right part

① If Yi is a terminal symbol:

if(Yi= = current symbol)

{

Read(ch);//

return;

}

else error()

② If Yi is a non-terminal symbol, directly call the corresponding sub-procedure Yi()

3. Experimental process and guidance:

(1) Preparation:

1. Read the relevant chapters of the textbook,

2. Consider the design plan;

3. Design the module structure, test data, and initially prepare the program.

(2) Procedure requirements:

Program input/output example:

For the following grammar, use the recursive descent analysis method to analyze any input symbol string:

(1)E→TG

(2) G → + TG | -TG

(3)G→ε

(4)T→FS

(5) S → * FS | / FS

(6)S→ε

(7)F→(E)

(8)F→i

The output format is as follows:

(1) Recursive descent analysis program, prepared by: name, student number, class

(2) Input the symbol string ending with # (including +— /()i#): input the symbol string at this position, for example: i+i i#

(3) Output result: i+i*i# is a legal symbol string

Remarks: The input symbol string such as i+i*# requires the output to be an "illegal symbol string".

Note: 1. Operators (+-*/), delimiters (brackets), characters i, terminator # are allowed in expressions;

2. If you encounter an incorrect expression, you should output an error message (the more detailed the information, the better);

3. For students who have the ability to learn, you can output the derivation process in detail, that is, list the productions used in each step in detail.

(3) Program ideas (for reference only):

0. Definition part: define constants, variables, and data structures.

1. Initialization: Input the input symbol string from the file into the character buffer.

2. Use the recursive descent analysis method to analyze, write a function for each non-terminal symbol, and call the function of the grammar start symbol in the main function.

(4) Practice the purpose and ideas of the experiment:

The program began to become more complicated. It requires the use of programming language knowledge and a lot of programming skills. The recursive descent analysis method is a more practical analysis method. Through this exercise, the software development ability can be greatly improved. Through practice, master the method of calling each other between functions.

(2) In order to design a good program, pay attention to the following things:

1. Module design: Divide the program into a number of reasonable modules (functions), and each module does the same thing.

2. Write (draw) the design plan: module relationship diagrams, flowcharts, global variables, function interfaces, etc.

3. Pay attention to the programming style when programming: the use of blank lines, the use of comments, the use of indentation, etc.

 

Fourth, the experimental process

Experiment code

 

#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();
    }

}


Note: The file suffix is ​​.cpp

5. Experimental results

 

 

Guess you like

Origin blog.csdn.net/qq_41371349/article/details/104951610