Compilation principle experiment (lexical analysis / LL analysis method / generation and calculation of inverse Polish formula / operator priority analysis method / LR analysis method)

Posted by AngelicS on Mon, 03 Jan 2022 18:51:27 +0100

1, Lexical analysis

1.1 experimental requirements

Prepare a word reading process, and identify each word with independent meaning from the input source program, namely basic reserved word, identifier, constant, operator and separator. The internal code of each word and the value of the word symbol are output.

Save the sample code in file 1 Txt, the program reads the file for lexical analysis. The example code is:

#include "math.h"
main()
{
float a,b,y1,y2;
int c,d,e;
a=3.1415926;
b=25.0;
scanf("%d,%d",&c,&d);
y1=cos(a/3);
y2=sqrt(b);
e=d+(-1);
if(c>d&&c>0)  e=c;
printf("y1=%f,y2=%f,e=%d,c=%x\n",y1,y2,e,c);  }

1.2 experimental code

#include<iostream>
using namespace std;
#define MAX 32
#define maxchar 200
/*
*Identifier: 1
*Reserved word | keyword: 2
*Constant: 3
*Operator | operator: 4
*Separator: 5
*/
char ch = ' ';
char* keyWord[MAX] = { "auto","short","int","long","float","double","char","struct","union","enum","typedef","const",
	"unsigned","signed","extern","register","static","volatile","void","else","switch","case","for","do","while","goto",
	"continue","break","default","sizeof","return","if"};
char token[maxchar];//Defines the character to get
//Determine whether it is a keyword
bool isKey(char* token)
{
    for (int i = 0; i < MAX; i++)
    {
        if (strcmp(token, keyWord[i]) == 0)
            return true;
    }
    return false;
}
//Determine whether it is a letter
bool isLetter(char letter)
{
    if ((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z'))
        return true;
    else
        return false;
}
//Judge whether it is a number
bool isDigit(char digit)
{
    if (digit >= '0' && digit <= '9')
        return true;
    else
        return false;
}
//Lexical analysis function
void analyze(FILE* fpin)
{//The fgetc function means to get the next character, and EOF means to read to the end of the file
    while ((ch = fgetc(fpin)) != EOF) {
        if (ch == ' ' || ch == '\t' || ch == '\n') {}  //Remove spaces and carriage returns
        else if (isLetter(ch)) {//Judgment keywords and identifiers
            char token[maxchar] = { '\0' };
            int i = 0;
            while (isLetter(ch) || isDigit(ch)) {
                token[i] = ch;
                i++;
                ch = fgetc(fpin);
            }
            //Fallback a pointer
            fseek(fpin, -1L, SEEK_CUR);
            if (isKey(token)) {
                //keyword
                cout << '(' << token << ',' << "   2" << ')' << "keyword" << endl;
            }
            else {
                //identifier 
                cout << '(' << token << ',' << "   1" << ')' << "identifier " << endl;
            }
        }
        else if (isDigit(ch) )//Judge whether it is a number
        {
            int i = 0;
            char token[maxchar] = { '\0' };
            while (isDigit(ch) || (ch == '.' && isDigit(fgetc(fpin))))//Integer or decimal (read one more digit)
            {
                if (ch == '.')fseek(fpin, -1L, SEEK_CUR);
                token[i] = ch;
                i++;
                ch = fgetc(fpin);
            }
            fseek(fpin, -1L, SEEK_CUR);
            cout << '(' << token << ',' << "   3" << ')' << "constant" << endl;
        }
        else switch (ch) {
        //operator
        case '+': {
            ch = fgetc(fpin);
            if (ch == '+')
                cout << '(' << "++" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "+" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '-': {
            ch = fgetc(fpin);
            if (ch == '-')
                cout << '(' << "--" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "-" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '&': {
            ch = fgetc(fpin);
            if (ch == '&')
                cout << '(' << "&&" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "&" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '|': {
            ch = fgetc(fpin);
            if (ch == '|')
                cout << '(' << "||" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "|" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '=': {
            ch = fgetc(fpin);
            if (ch == '=')cout << '(' << "==" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "=" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case ':': {
            ch = fgetc(fpin);
            if (ch == '=')cout << '(' << ":=" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << ":" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '>': {
            ch = fgetc(fpin);
            if (ch == '=')cout << '(' << ">=" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << ">" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
        case '<': {
            ch = fgetc(fpin);
            if (ch == '=')cout << '(' << "<=" << ',' << "   4" << ')' << "operator" << endl;
            else {
                cout << '(' << "<" << ',' << "   4" << ')' << "operator" << endl;
                fseek(fpin, -1L, SEEK_CUR);
            }
        }break;
	    case '*':cout << '(' << ch << ',' << "   4" << ')' << "operator" << endl; break;
        case '%':cout << '(' << ch << ',' << "   4" << ')' << "operator" << endl; break;
        case '/':cout << '(' << ch << ',' << "   4" << ')' << "operator" << endl; break;
        //Delimiter
        case '"':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '(':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case ')':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '[':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case ']':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case ';':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '{':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '}':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case ',':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '.':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        case '#': cout < <' ('< ch < <', '< "5" <') '< "delimiter" < < endl; break;
        case '\\':cout << '(' << ch << ',' << "   5" << ')' << "Delimiter" << endl; break;
        }
    }
}

1.3 experimental results




2, LL(1) analytical method

2.1 experimental requirements

The purpose of this experiment is to deepen the understanding of predictive analysis LL (1) analysis method.
Simple requirements: at least use LL (1) analysis method to analyze any input symbol string for the following known grammars
1)E->TG
2)G->+TG
3)G->ε
4)T->FS
5)S->*FS
6)S->ε
7)F->(E)
8)F->I
High requirements:
1. Manual input grammar
2. Displays the Follow set of non terminators for the grammar
3. Displays an optional collection of rules
3. Structural prediction analysis table
4. Analyze any input symbol string

2.2 experimental code

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char A[20];/*Analysis stack*/
char B[20];/*Residual string*/
char v1[20] = { 'i','+','*','(',')','#' };/* Terminator*/
char v2[20] = { 'E','G','T','S','F' };/*Non Terminator   */

int j = 0, b = 0, top = 0, l, m, n;/*l Is the input string length */
char ch, x;/*x Is the top character of the current stack*/
int k = 1, flag = 0, finish = 0;

typedef struct type/*Production type definition      */
{
	char origin;/*Uppercase character  */
	char array[5];/*Production right character */
	int length;/*Number of characters      */
}type;




void print()/*Output analysis stack  */
{
	int a;                 /*Pointer*/
	for (a = 0; a <= top + 1; a++)
		printf("%c", A[a]);
	printf("\t\t");
}

void print1()/*Output remaining string*/
{
	int j;
	for (j = 0; j < b; j++)
		printf(" ");
	for (j = b; j <= l; j++)
		printf("%c", B[j]);
	printf("\t\t\t");
}


int main() {
	type e, t, g, g1, s, s1, f, f1, cha;/*Structure variable  */
	type C[10][10];/*Forecast analysis table
		 */
		 /*Assign grammar production to structure*/
	e.origin = 'E';
	strcpy_s(e.array, "TG");
	e.length = 2;/*Change length assignment*/
	t.origin = 'T';
	strcpy_s(t.array, "FS");
	t.length = 2;/*Change length assignment*/
	g.origin = 'G';
	strcpy_s(g.array, "+TG");
	g.length = 3;/*Change length assignment*/
	g1.origin = 'G';
	g1.array[0] = '^';
	g1.array[1] = '\0';/*Change string end flag*/
	g1.length = 1;/*Change length assignment*/
	s.origin = 'S';
	strcpy_s(s.array, "*FS");
	s.length = 3;/*Change length assignment*/
	s1.origin = 'S';
	s1.array[0] = '^';
	s1.array[1] = '\0';/*Change string end flag*/
	s1.length = 1;/*Change length assignment*/
	f.origin = 'F';
	strcpy_s(f.array, "(E)");
	f.length = 3;/*Change length assignment*/
	f1.origin = 'F';
	f1.array[0] = 'i';
	f1.array[1] = '\0';/*Change string end flag*/
	f1.length = 1;/*Change length assignment*/

	for (m = 0; m <= 4; m++)/*Initialize analysis table*/
		for (n = 0; n <= 5; n++)
			C[m][n].origin = 'N';/*Empty all*/
   /*Fill analysis table*/
	C[0][0] = e; C[0][3] = e;
	C[1][1] = g; C[1][4] = g1; C[1][5] = g1;
	C[2][0] = t; C[2][3] = t;
	C[3][1] = s1; C[3][2] = s; C[3][4] = C[3][5] = s1;
	C[4][0] = f1; C[4][3] = f;
	printf("The characters that can be entered are\'i\',\'+\',\'*\',\'(\',\')\',\'#\'Note: take the first\'#\'end as string: \ n "");
	do/*Read in analysis string*/ {
		scanf_s("%c", &ch);
		if ((ch != 'i') && (ch != '+') && (ch != '*') && (ch != '(') && (ch != ')') && (ch != '#'))
		{
			printf("Error!Illegal character in input string!\n");
			exit(1);
		}
		B[j] = ch;
		j++;
	} while (ch != '#');
	printf("The process of string analysis is as follows:\n");
	l = j;/*Analysis string length*/
	ch = B[0];/*Current analysis character*/
	A[top] = '#'; A[++top] = 'E';/*'#','E'Enter the stack*/
	printf("step\t\t Analysis stack\t\t Remaining characters\t\t Production used \n");
	/*The derivation process is as follows*/
	do
	{
		x = A[top--];/*x Is the top character of the current stack*/
		printf("%d", k++);/*Step No*/
		printf("\t\t");
		for (j = 0; j <= 5; j++)/*Determine whether it is a terminator*/
			if (x == v1[j])
			{
				flag = 1;
				break;
			}
		if (flag == 1)/*If Terminator*/
		{
			if (x == '#')
			{
				if (ch == '#')
				{


					finish = 1;/*End tag*/
					print();/*Align on last successful change*/
					print1();


					printf("acc!\n");/*accept */
					printf("The input string conforms to the grammar!\n");
					getchar();
					getchar();
					exit(1);
				}
				else
				{
					print();
					print1();
					printf("Error!\n");
					printf("The current analysis stack is#, but there are still characters in the remaining string that do not match. \n");
					printf("The input string does not conform to the grammar!\n");
					getchar();
					getchar();
					exit(0);
				}
			}
			if (x == ch)
			{
				print();
				print1();
				printf("%c matching\n", ch);
				ch = B[++b];/*Next input character*/
				flag = 0;/*Recovery tag*/
			}
			else
			{
				if (ch == '#')
				{
					print();
					print1();
					printf("Error!\n");
					printf("The remaining string is#, but there are still characters unmatched in the analysis stack. \n");
					printf("The input string does not conform to the grammar!\n");
					getchar();
					getchar();
					exit(0);
				}
				else
				{
					print();
					print1();
					printf("Error!%c Matching error\n", ch);/*Output error Terminator*/
					printf("Does not match the current input character!\n");
					printf("The input string does not conform to the grammar!\n");
					getchar();
					getchar();
					exit(1);
				}
			}
		}
		else/*Non terminator processing*/
		{
			for (j = 0; j <= 4; j++)
				if (x == v2[j])
				{
					m = j;/*Line number*/
					break;
				}
			for (j = 0; j <= 5; j++)
				if (ch == v1[j])
				{
					n = j;/*Column number*/
					break;
				}
			cha = C[m][n];/*Production of recording application*/
			if (cha.origin != 'N')
			{
				print();
				print1();
				printf("%c->", cha.origin);
				for (j = 0; j < cha.length; j++)
					printf("%c", cha.array[j]);
				printf("\n");
				for (j = (cha.length - 1); j >= 0; j--)
				{
					A[++top] = cha.array[j];
					if (A[top] == '^')/*If it is empty, it will not be stacked*/
						top--;
				}
			}
			else
			{
				print();
				print1();
				printf("Error!\n");
				printf("The current stack top element is a non terminator, but the corresponding production of the current input character cannot be found!\n");
				printf("The input string does not conform to the grammar!\n");
				getchar();
				getchar();
				exit(0);
			}
		}
	} while (true);
	return 0;
}

2.3 experimental results

3, Generation and calculation of inverse wave

3.1 experimental requirements

Convert the arithmetic expression represented by infix into the arithmetic expression represented by inverse Polish, and calculate the value of the arithmetic expression represented by inverse Polish.

3.2 experimental code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
const int StackSize = 30;//Stack size
char result[100];//It is used to store the conversion results for easy output, and spaces can be added
char num;//Count the result array
 
//Define stack structure
typedef struct Stack
{
	char data[StackSize];
	int top;
}StackType;
//Out of stack
char Pop(StackType *p)
{
	if(p->top == -1) //Whether the stack is empty is determined when the stack is out of the stack
	{
		printf("Stack empty\n");
		exit(0);//exit(0) means to exit the program normally, and exit(1) means to exit the program due to abnormal operation;
	}
    return p->data[p->top--];//After the stack top element returns, subtract the stack top pointer by one
	
}
//Enter the stack
void Push(StackType *p, char dat)
{
	if(p->top == StackSize -1)//Enter the stack to judge whether the stack is full
	{
		printf("Stack full\n");
		exit(0);
	}
	p->data[++p->top] = dat;//Add one to the top of the stack pointer to put dat on the stack
}
//Get the data at the top of the stack
char GetTop(StackType *p)
{
	if(p->top != -1)
		return p->data[p->top];
	return 0;
}
//Determine whether it is an operator or an operand
 bool isNumber(char op)
 {
	 switch(op)
	 { 	
		case ' ':
		case '(':
		case ')':
		case '+':    	
		case '-':    	
		case '*':    	
		case '/':
		case '#': 		 return 0;// Returns 0 if op is an operator
		default :       return 1;//Returns 1 if op is an operand
	}
 }
//Gets the priority of the operator, 1 is the highest, and the priority is counted
 int priority(char ch)
 {
	int value= 10; //Set the initial value of value to minimize the priority of spaces
	switch(ch)
	{
		case '*':	value = 2;	break;
		case '/':	value = 2;	break;
		case '+':	value = 3;  break;
		case '-':	value = 3;	break;
		case '(':
		case ')':	value = 4;	break;//When the left bracket is encountered, all symbols will be stacked until the right bracket is encountered
		case '#':	value = 5;	break;//'#' has the lowest priority among operators
		default:  break;
	}
	return value;
 }
//Solving inverse Polish principal function
void NiBoLan(char arr[])
{
	StackType* pStack = new StackType;
	pStack->top = -1;//Initialization stack is empty
	char ch;//ch represents the operator
	for(int i=0;arr[i] != '\0';i++)//'\ 0', which is a null character. The flag to judge whether a string ends is to see whether '\ 0' is encountered. If '\ 0', it indicates the end of the string
	{
		if(isNumber(arr[i]))
		{
			result[num++] = arr[i];//If arr[i] is an operand, it is placed in the result array and output later
		}
		else//If arr[i] is not an object, it is an operator
		{
			
			//First, judge whether the stack is empty. If the stack is empty, enter the stack  
			if(pStack->top==-1 || arr[i] == '(')
			{
				Push(pStack, arr[i]);
				continue;
			}
			if(arr[i] == '#')//End symbol (the first entry is' # 'break, and continue to cycle to judge the next symbol)
				break;
			if(arr[i] == ')')//When the closing parenthesis') 'is read, it is out of the stack
			{
				result[num++] = ' ';
				while((ch = Pop(pStack)) != '(' )//Start out of the stack until the left bracket '(' is encountered at the top of the stack
				{
					result[num++] = ch;
				}
				continue;
			}
			result[num++] = ' ';
			ch = priority(GetTop(pStack)) - priority(arr[i]);//Compare priorities and obtain the results after priority comparison. However, when ch > 0, the operator priority is greater than the top of the stack, = 0 is equal, and < 0 is less than
			//The priority is greater than the top of the stack (the smaller the value, the greater the priority; for example, the top of the stack is + and its value is 3, * its value is 2, but * priority is higher than + but ch = 3-2 = 1 > 0
			if(ch > 0)
			{
				//Stack with high priority
				Push(pStack, arr[i]);
			}
			//Priority is less than or equal to the top of the stack
			else if(ch <= 0)
			{
				//It should be out of the stack, and then judge the priority. If it is not empty, continue to judge the priority, and then put arr[i] into the stack
				while( priority(arr[i]) >= priority(GetTop(pStack)))//When the priority of this operator is less than or equal to the top of the stack, it is always output
				{
					result[num++] = Pop(pStack);
					result[num++] = ' ';
				}
				Push(pStack, arr[i]);							
			}
		}
	}
	while(GetTop(pStack) != '#'/ / perfection in the previous operation, all the elements in the stack may not be out of the stack
	{
		result[num++] = ' ';
		result[num++] = Pop(pStack);
	}
	for(int i=0;i<num;i++) //Traverse the result array and output
		printf("%c",result[i]);
}
//Calculates the value of the suffix expression
int Calculate(char arr[])
{
	int i, cal[100],top=-1;
	memset(cal,0,sizeof(cal));//The memset function means to empty the stack
	for(i=0;i<num;i++)
	{
		if(isNumber(arr[i]))//Judge whether it is an operator, return 1, no, what comes in can only be numbers
		{
			//Simulation stack
			top++;
			while(arr[i] != ' ')//Get an integer and merge it into the stack
			{
				cal[top] = cal[top]*10 + arr[i++]-48;
			}
		}
		else
		{
			switch(arr[i])
			{
				//Simulated out of stack
				case '+':	cal[top-1] = cal[top-1] + cal[top]; cal[top--] = 0; break;
				case '-':	cal[top-1] = cal[top-1] - cal[top]; cal[top--] = 0; break;
				case '*':	cal[top-1] = cal[top-1] * cal[top]; cal[top--] = 0; break;
				case '/':	cal[top-1] = cal[top-1] / cal[top]; cal[top--] = 0; break;
				default: break;
			}
		}
	}
	return cal[0];
}

 
int main(void)
{
	char  express[] ="#21+((42-2)*15+6)-18#"; / / the answer is 609
	//char  express[] ="30*(40+20)/2-50#";//  The answer is 850
	printf("Infix expression:");
	printf("%s\n", express);
	printf("Suffix expression:");
	NiBoLan(express);
	printf("\n");
	printf("The calculation result is:%d\n", Calculate(result));
	return 0;
}

3.3 experimental results

4, Algorithm priority analysis

4.1 experimental requirements

Understand the syntax analysis method of expression with operator priority method, and master the manual construction method of top-down predictive syntax analysis program.
The requirements are as follows: the basic functions of an interactive object-oriented operator priority analyzer are:
(1) Input grammar rules
(2) Convert grammar
(3) Generate FirstVT and LastVT for each non terminator
(4) Generate operator priority analysis table
(5) Then enter the grammar symbol string
(6) Generate move in protocol steps
Test case: e - > e + T; E->T; T->T*F; T->F; F->(E); F->i

4.2 experimental code

#include "stdio.h"
#include "stdlib.h"
#include "iostream"
using namespace std;
char data[20][20];    //Operator precedence relation
char s[100];    //Analog symbol stack s 
char lable[20];    //Grammar ultimate symbol set
char input[100];    //Grammar input symbol string
char ch[20][10];    //Analysis for input string
int k; 
char a; 
int j; 
char q; 
int r;    //Number of grammar rules
int r1; 
int m,n,N;      //Number of grammar rules after conversion
char st[10][30];     //Used to store grammar rules
char first[10][10];     //Grammar non terminator FIRSTVT set
char last[10][10];     //Grammar non terminator LASTVT set
int fflag[10]={0};    //Indicates whether the FIRSTVT set of the ith non terminator has been evaluated
int lflag[10]={0};    //Flag whether the LASTVT set of the ith non terminator has been evaluated
int deal();    //Analysis of input string
int zhongjie(char c);   //Determine whether the character c is the ultimate character
int xiabiao(char c);    //Find the subscript of character c in the operator priority relationship table
void out( int j,int k,char *s);  //Print s stack
void firstvt(char c);   //Find the FIRSTVT set of non terminator c
void lastvt(char c);    //Find LASTVT set of non terminator c
void table();    //Create grammar precedence table
void main()
{
 int i,j,k=0;
 printf("Please enter the number of grammar rules:");
 scanf("%d",&r);
 printf("Please enter grammar rules:\n");
 for(i=0;i<r;i++)
 {
   scanf("%s",st[ i]);  //Store grammar rules and initialize FIRSTVT set and LASTVT set*/          
   first[i][0]=0;  /* first[i][0]And last[i][0] respectively indicate that st[i][0] is not ultimate
 Number of elements in FIRSTVT set and LASTVT set of */
   last[i][0]=0;
 }
 for(i=0;i<r;i++)    //Judge whether grammar is legal
 {
   for(j=0;st[i][j]!='\0';j++)
   {
     if(st[i][0]<'A'||st[i][0]>'Z')
     {
       printf("Not operator grammar!\n");
     exit(-1);
     }
     if(st[i][j]>='A'&&st[i][j]<='Z')
     {
     if(st[i][j+1]>='A'&&st[i][j+1]<='Z')
       {
         printf("Not operator grammar!\n");
     exit(-1);
       }
     }
   }
 }
 for(i=0;i<r;i++)
 {
   for(j=0;st[i][j]!='\0';j++)
   {
     if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|')
       lable[k++]=st[i][j];
   }
 }
 lable[k]='#';
 lable[k+1]='\0'; 
 table();
 printf("Of each non Terminator FIRSTVT Set to: \n");  //Outputs the FIRSTVT set for each non terminator
 for(i=0;i<r;i++)
 {
   printf("%c: ",st[i][0]);
   for(j=0;j<first[i][0];j++)
   {
     printf("%c ",first[i][j+1]);
   }
   printf("\n");
 }
 printf("Of each non Terminator LASTVT Set to: \n");   //Outputs the LASTVT set for each non terminator
 for(i=0;i<r;i++)
 {
   printf("%c: ",st[i][0]);
   for(j=0;j<last[i][0];j++)
   {
     printf("%c ",last[i][j+1]);
   }
   printf("\n");
 }
 printf("The operator priority analysis table is as follows:\n");
 for(i=0;lable[i]!='\0';i++) 
   printf("\t%c",lable[i]);
 printf("\n"); 
 for(i=0;i<k+1;i++)
 {
   printf("%c\t",lable[i]);
   for(j=0;j<k+1;j++)
   {
     printf("%c\t",data[i][j]);
   }
   printf("\n");
 }
 printf("Please enter a grammar string to#End: ";
 scanf("%s",input); 
 
 deal();
}

void table()
{
 char text[20][10];
 int i,j,k,t,l,x=0,y=0;
 int m,n;
 x=0;
 for(i=0;i<r;i++)
 {
   firstvt(st[i][0]);
   lastvt(st[i][0]);
 }
 for(i=0;i<r;i++)
 {
   text[x][y]=st[i][0];
   y++;
   for(j=1;st[i][j]!='\0';j++)
   {
     if(st[i][j]=='|')
     {
       text[x][y]='\0';
       x++;
       y=0;
       text[x][y]=st[i][0];
       y++;
       text[x][y++]='-';
       text[x][y++]='>';
     }
     else
     {
       text[x][y]=st[i][j];
       y++;
     }
   }
   text[x][y]='\0';
   x++;
   y=0;
 }
 r1=x;
 printf("The converted grammar is:\n");
 for(i=0;i<x;i++)     //Output converted grammar rule string
 {
   printf("%s\n",text[i]);
 }
 for(i=0;i<x;i++) /* Find the derivation result of each Terminator (remove "-")
Post conversion grammar for final specification) */
 {
   ch[i][0]=text[i][0];
   for(j=3,l=1;text[i][j]!='\0';j++,l++)
     ch[i][l]=text[i][j];
   ch[i][l]='\0';
 }
 for(i=0;i<x;i++)
 {
   for(j=1;text[i][j+1]!='\0';j++)
   {
     if(zhongjie(text[i][j])&&zhongjie(text[i][j+1]))
     {
       m=xiabiao(text[i][j]);
       n=xiabiao(text[i][j+1]);
       data[m][n]='=';
     }
     if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1]))
     {
       m=xiabiao(text[i][j]);
       n=xiabiao(text[i][j+2]);
       data[m][n]='=';
     }
     if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1]))
     {
       for(k=0;k<r;k++)
       {
         if(st[k][0]==text[i][j+1])
           break;
       }
       m=xiabiao(text[i][j]);
       for(t=0;t<first[k][0];t++)
       {
         n=xiabiao(first[k][t+1]);
         data[m][n]='<';
       }
     }
     if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1]))
     {
       for(k=0;k<r;k++)
       {
         if(st[k][0]==text[i][j])
           break;
       }
       n=xiabiao(text[i][j+1]);
       for(t=0;t<last[k][0];t++)
       {
         m=xiabiao(last[k][t+1]);
         data[m][n]='>';
       }
     }
   }
 }
 m=xiabiao('#');
 for(t=0;t<first[0][0];t++)
 {
   n=xiabiao(first[0][t+1]);
   data[m][n]='<';
 }
 n=xiabiao('#');
 for(t=0;t<last[0][0];t++)
 {
   m=xiabiao(last[0][t+1]);
   data[m][n]='>';
 }
 data[n][n]='=';
}
void firstvt(char c)    //Find FIRSTVT set
{
 int i,j,k,m,n;
 for(i=0;i<r;i++)
 {
   if(st[i][0]==c)
     break;
 }
 if(fflag[i]==0)
 {
   n=first[i][0]+1;
   m=0;
   do
   {
     if(m==2||st[i][m]=='|')
     {
       if(zhongjie(st[i][m+1]))
       {
         first[i][n]=st[i][m+1];
         n++;
       }
       else
       {
         if(zhongjie(st[i][m+2]))
         {
           first[i][n]=st[i][m+2];
           n++;
         }
         if(st[i][m+1]!=c)
         {
           firstvt(st[i][m+1]);
           for(j=0;j<r;j++)
           {
             if(st[j][0]==st[i][m+1])
               break;
           }
           for(k=0;k<first[j][0];k++)
           {
             int t;
             for(t=0;t<n;t++)
             {
               if(first[i][t]==first[j][k+1])
                 break;
             }
             if(t==n)
             {
               first[i][n]=first[j][k+1];
               n++;
             }
           }
         }
       }
     }
     m++;
   }while(st[i][m]!='\0');
   first[i][n]='\0';
   first[i][0]=--n;
   fflag[i]=1;
 }
}
void lastvt(char c)     //Find LASTVT set
{
 int i,j,k,m,n;
 for(i=0;i<r;i++)
 {
   if(st[i][0]==c)
     break;
 }
 if(lflag[i]==0)
 {
   n=last[i][0]+1;
   m=0;
   do
   {
     if(st[i][m+1]=='\0'||st[i][m+1]=='|')
     {
       if(zhongjie(st[i][m]))
       {
         last[i][n]=st[i][m];
         n++;
       }
       else
       {
         if(zhongjie(st[i][m-1]))
         {
           last[i][n]=st[i][m-1];
           n++;
         }
         if(st[i][m]!=c)
         {
           lastvt(st[i][m]);
           for(j=0;j<r;j++)
           {
             if(st[j][0]==st[i][m])
               break;
           }
           for(k=0;k<last[j][0];k++)
           {
             int t;
             for(t=0;t<n;t++)
             {
               if(last[i][t]==last[j][k+1])
                 break;
             }
             if(t==n)
             {
               last[i][n]=last[j][k+1];
               n++;
             }
           }
         }
       }
     }
     m++;
   }while(st[i][m]!='\0');
   last[i][n]='\0';
   last[i][0]=--n;
   lflag[i]=1;
 }
}
int deal()
{
 int i,j;
 int x,y;
 int z; //Enter the length of the string
 k=1;
 s[k]='#'; // Stack initial value
 for(i=0;input[i]!='\0';i++); //Calculates the length of the input string
 z=i--;
 i=0;
 while((a=input[i])!='\0')
 {
   if(zhongjie(s[k]))
     j=k;
   else
     j=k-1;
   x=xiabiao(s[j]);
   y=xiabiao(a);
   if(data[x][y]=='>')
   {
     out(1,k,s);
     printf("%c",a);
     out(i+1,z,input);
     printf("Statute\n");
     do
     {
       q=s[j];
       if(zhongjie(s[j-1]))
         j=j-1;
       else j=j-2;
       x=xiabiao(s[j]);
       y=xiabiao(q);
     }while(data[x][y]!='<');
     int m,n,N;
     for(m=j+1;m<=k;m++)
     {
       for(N=0;N<r1;N++)
		   for(n=1;ch[N][n]!='\0';n++)
         {
           if(!zhongjie(s[m])&&!zhongjie(ch[N][n]))
{
if(zhongjie(s[m+1])&&zhongjie(ch[N][n+1])
&&s[m+1]==ch[N][n+1])
             {
               s[j+1]=ch[N][0];
             break;
             }
           }
         else
             if(zhongjie(s[m]))
               if(s[m]==ch[N][n])
               {
                 s[j+1]=ch[N][0];
               break;
               }
         }
     }
 k=j+1;
     if(k==2&&a=='#')
     {
       out(1,k,s);
       printf("%c",a);
       out(i+1,z,input);
       printf("end\n");
       printf("The input string conforms to the definition of grammar!\n");
       return 1;     //The input string conforms to the definition of grammar
     }
   }
   else
     if(data[x][y]=='<'||data[x][y]=='=')
     { //Move in
       out(1,k,s);
       printf("%c",a);
       out(i+1,z,input);
       printf("Move in\n");
       k++;
       s[k]=a;
       i++;
     }
     else
     {
       printf("\nflase");
       return 0;
     }
 }
 printf("\nflase");
 return 0;
}
void out(int j,int k,char *s)
{
 int n=0;
 int i;
 for(i=j;i<=k;i++)
 {
   printf("%c",s[i]);
   n++;
 }
 for(;n<15;n++)
 {
   printf(" ");
 }
}
int xiabiao(char c)    //Find the subscript of character c in the operator priority relationship table
{
 int i;
 for(i=0;lable[i]!='\0';i++)
 {
   if(c==lable[i])
     return i;
 }
 return -1;
}
int zhongjie(char c)   //Determine whether the character c is the ultimate character
{
 int i;
 for(i=0;lable[i]!='\0';i++)
 {
   if(c==lable[i])
     return 1;
 }
 return 0;
}

4.3 experimental results

5, LR(1) analysis method

5.1 test requirements

Parse any input string according to the LR (1) analysis table established by grammar rules in advance. It is required to output the analysis process table.

5.2 experimental code

#include<stdio.h>
#include<string.h>
const char* action[10][3] = { "S3#","S4#", NULL, /*ACTION table*/
 NULL,NULL,"acc",
		 "S6#","S7#",NULL,
		 "S3#","S4#",NULL,
		 "r3#","r3#",NULL,
		 NULL,NULL,"r1#",
		 "S6#","S7#",NULL,
		 NULL,NULL,"r3#",
		 "r2#","r2#",NULL,
		 NULL,NULL,"r2#"
};
int goto1[10][2] = { 1,2, /*QOTO surface */
 0,0,
	   0,5,
	   0,8,
	   0,0,
	   0,0,
	   0,9,
	   0,0,
	   0,0,
	   0,0 };
char vt[3] = { 'a','b','#' }; /*  Store non Terminator*/
char vn[2] = { 'S','B' }; /* Store Terminator */
const char* LR[4] = { "E->S#","S->BB#","B->aB#","B->b#"}; / * store production*/
int a[10];
char b[10], c[10], c1;
int top1, top2, top3, top, m, n;
void main() {
	int g, h, i, j, k, l, p, y, z, count;
	char x, copy[10], copy1[10];
	top1 = 0; top2 = 0; top3 = 0; top = 0;
	a[0] = 0; y = a[0]; b[0] = '#';
	count = 0; z = 0;
	printf(" Please enter an expression \n");
	do {
		scanf_s("%c", &c1);
		c[top3] = c1;
		top3 = top3 + 1;
	} while (c1 != '#');
	printf("step\t State stack\t\t Symbol stack\t\t Input string\t\tACTION\tGOTO\n");
	do {
		y = z; m = 0; n = 0; /*y,z Point to the top of the status stack */
		g = top; j = 0; k = 0;
		x = c[top];
		count++;
		printf("%d\t", count);
		while (m <= top1) { /* Output status stack */
			printf("%d", a[m]);
			m = m + 1;
		}
		printf("\t\t");
		while (n <= top2) { /* Output symbol stack */
			printf("%c", b[n]);
			n = n + 1;
		}
		printf("\t\t");
		while (g <= top3) { /* Output input string */
			printf("%c", c[g]);
			g = g + 1;
		}
		printf("\t\t");
		while (x != vt[j] && j <= 2) j++;
		if (j == 2 && x != vt[j]) {
			printf("error\n");
			return;
		}
		if (action[y][j] == NULL) {
			printf("error\n");
			return;
		}
		else
			strcpy_s(copy, action[y][j]);
		if (copy[0] == 'S') { /* Process move in */
			z = copy[1] - '0';
			top1 = top1 + 1;
			top2 = top2 + 1;
			a[top1] = z;
			b[top2] = x;
			top = top + 1;
			i = 0;
			while (copy[i] != '#') {
				printf("%c", copy[i]);
				i++;
			}
			printf("\n");
		}
		if (copy[0] == 'r') { /* Processing reduction */
			i = 0;
			while (copy[i] != '#') {
				printf("%c", copy[i]);
				i++;
			}
			h = copy[1] - '0';
			strcpy_s(copy1, LR[h]);
			while (copy1[0] != vn[k]) k++;
			l = strlen(LR[h]) - 4;
			top1 = top1 - l + 1;
			top2 = top2 - l + 1;
			y = a[top1 - 1];
			p = goto1[y][k];
			a[top1] = p;
			b[top2] = copy1[0];
			z = p;
			printf("\t");
			printf("%d\n", p);
		}
	} while (action[y][j] != "acc");
	printf("acc\n");
}

5.3 experimental results