/* The syntax of the simple language to be analyzed is expressed as follows using the expanded BNF: (1) <program >::= begin <statement string> end (2) <statement string> :: = <statement >{; <statement >}< statement >::=< value assignment statement> (4) <value assignment statement >:=id :=< expression> comment <expression>: :=< item >{+ <item >|- <item >}items <item> :: = <factor >{* <factor >|/ <factor> percent <factor >::= ID | num | (<expression>) */# include "stdio. H "# include" string. H "char prog [100], Token [8], ch; // prog [100], used to store the object to be processed, token is used to compare with the keyword, ch is used to store a character char * rwtab [6] = {"begin", "if", "then", "while", "do", "end "}; // keyword table int SYN, P, M, N, sum;/* SYN is a type of code, P is a pointer to the prog array, and m is the pointer to the token Array The needle, n is the pointer to the rwtab array, and sum is the numeric value in the lexical analyzer */INT flag; // flag is related to void factor (void) to determine whether the end is used ); // factorvoid expression (void); // expression expressionvoid yucu (void); void term (void); // termvoid Statement (void ); // statement statementvoid Parser (void); void scaner (void); // scanner int main (void) {P = Flag = 0; printf ("\ nplease input a string (end with '#'): \ n");/* read the object to be processed from the command line, and stored in the prog [] array */do {scanf ("% C", & Ch); // printf ("\ N input % C now \ n", c H); prog [p ++] = CH;} while (Ch! = '#'); P = 0; scaner (); // mainly performs the Parser () function for lexical analysis, such as assignment type codes. // call various recursive subprograms, syntax analysis process // getch ();}/* call a variety of recursive subprograms to complete the syntax analysis process */void Parser (void) {If (SYN = 1) // begin {scaner ();/* read the next word symbol */yucu ();/* call the yucu () function; */If (SYN = 6) // end {scaner (); If (SYN = 0) & (flag = 0) // appears # And flag = 0 printf ("success! \ N ");} else {If (flag! = 1) printf ("the string haven't got a 'end '! \ N "); // flag to determine whether endflag is 1;} else {printf (" haven't got a 'begin '! \ N "); flag = 1;} return;} void yucu (void) {Statement ();/* call the function Statement (); */while (SYN = 26) // semicolon {scaner ();/* read the next word symbol */If (syn! = 6) Statement ();/* call the function Statement (); */} return;} void Statement (void) {If (SYN = 10) {scaner (); /* read the next word symbol */If (SYN = 18) {scaner ();/* read the next word symbol */expression ();/* call the function expression (); */} else {printf ("the sing ': =' is wrong! \ N "); flag = 1 ;}} else {printf (" wrong sentence! \ N "); flag = 1;} return;} void expression (void) {term (); While (SYN = 13) | (SYN = 14 )) {scaner ();/* read the next word symbol */term ();/* call the function term (); */} return;} void term (void) {factor (); While (SYN = 15) | (SYN = 16) {scaner ();/* read the next word symbol */factor (); /* call the function factor (); */} return;} void factor (void) // type the processing function {If (SYN = 10) | (SYN = 11) // identifier, number {scaner ();} else if (SYN = 27) // start with a left bracket ({scaner (); /* read the next word symbol */expression ();/* call the function state Ment (); */If (SYN = 28) // parentheses appear) {scaner (); /* read the next word symbol */} else {printf ("the error on '\ n"); flag = 1 ;}} else {printf ("the expression error! \ N "); flag = 1;} return;}/* mainly completes lexical analysis functions such as assignment type codes */void scaner (void) // scanner, lexical analyzer content {sum = 0; // number is initialized to 0for (m = 0; m <8; m ++) // tokentoken [M ++] = NULL; m = 0; // m is the token pointer CH = prog [p ++]; // array pointer + 1 while (CH = '') // encounter space + 1ch = prog [p ++]; If (CH <= 'Z') & (CH> = 'A ')) | (CH <= 'Z') & (CH> = 'A') // encounter a letter {While (CH <= 'Z ') & (CH> = 'A') | (CH <= 'Z') & (CH> = 'A ')) | (CH> = '0') & (CH <= '9') {token [M ++] = CH; ch = prog [p ++]; // P + 1, next loop use} p --; // loop jump out,-1syn = 10; // 10, token [M ++] = '\ 0' at the beginning of the letter; // \ 0 indicates the string Terminator/* determines whether it is a keyword */For (n = 0; n <6; N ++) // n is the rwtab pointer if (strcmp (token, rwtab [N]) = 0) // strcmp returns 0, then the two parameters are of the same size {SYN = n + 1; break ;}} else if (CH> = '0') & (CH <= '9 ')) // number {While (CH> = '0') & (CH <= '9') {sum = sum * 10 + CH-'0 '; ch = prog [p ++];} p --; // backtracking SYN = 11; // 11 is a number}/* Other symbols except the start of a number and a letter */elseswitch (CH) {case' <': m = 0; ch = prog [p ++]; If (CH = '>') {SYN = 21;} else if (CH = ') {SYN = 22 ;} else {SYN = 20; p --; // backtracking} break; Case '>': m = 0; CH = prog [p ++]; if (CH = ') {SYN = 24;} else {SYN = 23; p --;} break; Case': m = 0; ch = prog [p ++]; If (CH = ') {SYN = 18;} else {SYN = 17; p --;} break; case '+': SYN = 13; break; Case '-': SYN = 14; break; Case '*': SYN = 15; break; Case '/': SYN = 16; break; Case '(': SYN = 27; break; Case ')': SYN = 28; break; Case '=': SYN = 25; break; case ';': SYN = 26; break; Case '#': SYN = 0; break; default: SYN =-1; break ;}}
Compilation Principle experiment-syntax analyzer