/* Error handling process error * // * parameter: N: Error Code */void error (int n) {cout <"***" <SETW (cc-1) <'! '<SETW (2) <n <Endl;/* display in the cc-1 position on the screen! And error code prompt, because CC is a row buffer pointer, so! The specified location is the error location */fa1 <"***" <SETW (cc-1) <'! '<SETW (2) <n <Endl;/* output at file cc-1 location! And error code prompts */+ + err;/* Total number of errors plus one */}/* Error * // determine whether the bool eoln (istream & IS) at the end of the line has been reached) {return is. peek () = '\ n';} // obtain the digit int ord (char ch) {return ch-'0 ';} /* getch (); */void getch (void) {If (Cc = LL) /* If the row buffer pointer points to the last character of the row buffer, read a row from the file to the row buffer */{If (Fin. peek () = EOF)/* If the file ends */{cout <"program incomplete";/* if an error occurs, exit the Program */throw (99 );} LL =-1;/* place the row buffer length at the beginning of the row */CC =-1;/* set the row buffer pointer to the beginning of the row */cout <SETW (4) <CX <'' ;/* Output CX value, width: 4 */fa1 <SETW (4) <CX <'';/* output CX value, the width is 4 to the file */while (! Eoln (FIN)/* When the row is not reached */{++ ll;/* the length of the row buffer plus one X/Fin. get (CH);/* read a character from the file to Ch */cout <ch;/* output Ch */fa1 on the screen <ch; /* output ch to the file */line [ll] = CH;/* store the characters to the corresponding location of the row buffer, the PL/0 source program requires that each line be less than 81 characters */cout <Endl; ++ ll;/* Add one to the length of the row buffer, used to hold the carriage return to be read */Fin. get (line [ll]);/* read #13 (CR) into the end of the row buffer */fa1 <Endl ;}++ cc;/* Add a row buffer pointer, point to the character to be read */CH = line [CC];/* read the character and put it into the global variable Ch */}/* getch () * // * getsym */void g Etsym (void) {int I, j, k;/* getsym */while (isspace (CH )) /* read a valid character (skipping the extra spaces in the characters to be read), but in fact you have to skip the extra carriage return */getch (); If (isalpha (CH )) /* If the read character is a letter, it indicates a reserved word or identifier */{k =-1; /* identifier buffer pointer set 0 */do {/* this loop is used to read the characters in the source file in turn constitute the identifier */If (k <Al-1) /* If the length of an identifier does not exceed the maximum length (if the length is exceeded, take the previous part and discard the excess) */{++ K; A [k] = CH ;} getch ();/* read the next character */} while (isalpha (CH) | isdigit (CH);/* until it is not a letter or number, from this we can see that the identifier of PL/0 is a rule that begins with a letter, followed by several letters or Number */If (k> = KK)/* if the length of the currently obtained identifier is greater than or equal to KK */KK = K; /* Make kk The length of the current identifier */elsedo {/* this loop is used to fill up the space without the corresponding letters or spaces at the end of the identifier buffer with Spaces */A [Kk] =' '; kk = KK-1;} while (KK! = K);/* when this process is run for the first time, the value of KK is Al, that is, the maximum identifier length. If the length of the read identifier is less than KK, fill in space without letters at the back of array a with spaces. In this case, the value of KK becomes the number of non-space characters in the front of array. When you run getsym later, if the length of the read identifier is greater than or equal to KK, the value of KK is changed to the length of the current identifier. In this case, you do not need to fill in spaces behind it, because it must be followed by spaces. Otherwise, if the length of the recently read identifier is less than KK, it is necessary to move forward from the KK position and fill the space exceeding the length of the current identifier with spaces. The above logic is entirely out of consideration of program performance. In fact, the space after the [k] element in array A can be simply filled with spaces no matter whether it is null or not. * // * Perform the following two-way query to see if the read identifier is one of the reserved words */memcpy (ID, A, Al);/* The Last read identifier is equal to a */I = 0; /* I points to the first reserved word */J = norw-1;/* j points to the last reserved word */do {k = (I + J)/2; /* k points to a reserved word in the middle */If (memcmp (ID, word [K], Al) <= 0) /* if the current identifier is less than the reserved word referred to by K */J = k-1;/* move the J pointer */If (memcmp (ID, word [K], Al)> = 0)/* if the current identifier is greater than the reserved word referred to by K */I = k + 1;/* move I pointer */} while (I <= J ); /* loop until the reserved word table is found */if (I-1> J)/* If I-1> J indicates that the corresponding item is found in the reserved word table, and the reserved word is saved in the ID. */Sym = wsym [k];/* locate the reserved word and set sym to the corresponding reserved word value */elsesym = ident;/* The reserved word is not found, set sym to Ident, indicates the identifier */}/*. If the character is a letter, the reserved word or identifier is processed. */else/* If the character is not a letter */If (isdigit (CH )) /* If the read character is a number */{/* Number * // * start to process the number */k = 0;/* number of digits */num = 0; /* set the number to 0 */sym = number;/* Set sym to number, it indicates that the number */do {/* is read from the source file in turn, forming a number */num = 10 * num + (ord (CH) -ord ('0');/* num * 10 plus the recently read ASCII characters minus the '0' ASCII to get the corresponding Value of */+ k;/* digit plus one digit */getch ();} while (isdigit (CH )); /* until the characters read are not numbers */If (k> Nmax)/* if the number of digits is greater than the maximum allowed number of digits */error (30 ); /* issue error No. 30 */}/* identification of numbers now ends */elseif (CH = ':') /* If the read result is neither a letter nor a number, but a colon */{getch ();/* read another character */If (CH = ') /* If you read an equal sign, you can create a value pair with the colon */{sym = becomes;/* set the sym type to the value pair becomes */getch (); /* then read the next word */} elsesym = NUL;/* If the equals sign is not read, then a separate colon is nothing more than */}/* processing the assignment number. */else/* if no It is a letter, a number, or a colon */If (CH = '<')/* If you read a lower sign */{getch (); /* read another character */If (CH = ')/* if you read the equal sign */{sym = Leq; /* purchase a character less than or equal to the number */getch ();/* read a character */} else/* if it is not the same as the equals sign after the sign */sym = LSS; /* It is a separate minor sign */} else/* if it is read, it is neither a letter nor a number, nor a colon or a minor sign */If (CH = '> ') /* If the number is greater than the number, the processing process is similar to processing the number less than the number */{getch ();/* read another character */If (CH = ') /* if you read the equal sign */{sym = geq;/* Buy A equals sign */getch (); /* read a character */} else/* if it is not the same as the equal sign */sym = gtr ;/* It is a separate greater than number */} else/*. If it is read, neither a letter nor a number, nor a colon, nor a smaller than number */{/*, it means it is not an identifier/ reserved Words, it is not a complex double-byte operator. It should be a common symbol */sym = ssym [CH-''];/* You can directly find its type in the symbol table, assigned to sym */getch ();/* read the next character */}/* determine the end of the entire if statement */}/* getsym * // * The getsym process is summarized as follows: read several valid characters from the source file to form a token string. It is identified as a reserved word, identifier, number, or other symbol. If it is a reserved word, set sym to the corresponding reserved word type. If it is an identifier, set sym to an ident to indicate it is an identifier. At the same time, the ID variable is stored as a reserved word string or identifier name. If it is a number, set sym to number, and store the value of this number in the num variable. If it is another operator, you can directly set sym to the corresponding type. After this process, the CH variable stores the next character to be recognized */