Compilation Principle Program Design Practice (6) Process Code of statements and sub-Processes

Source: Internet
Author: User
/* Statement processing statement * // * parameter description: fsys: the collection of symbols that can be used to restore syntax analysis if an error occurs */void Statement (const symset & fsys, const Int & lev, int & Tx)/* Expression Processing Process expression * // * parameter description: fsys: indicates the collection of symbols used to restore syntax analysis if an error occurs */{int I, cx1, CX2; /* statement */If (sym = ident)/* the so-called "statement" may be a value assignment statement, starting with an identifier */{I = position (ID, TX ); /* locate the identifier in the symbol table */if (I = 0)/* if not found */error (11 ); /* Throw error 11 */elseif (Table [I]. kind! = Variable)/* If this identifier is found in the symbol table, but this identifier is not the variable name */{error (12);/* Throw error 12 */I = 0; /* I sets 0 as the error flag */} getsym ();/* gets the next token. Normally, it should be assigned a value */If (sym = becomes) /* if it is indeed the value */getsym ();/* Get the next token, normally it should be an expression */elseerror (13 ); /* if no value is assigned after the left mark of the value assignment statement, a 13-digit error is thrown */expression (fsys, lev, Tx);/* processing expression */if (I! = 0)/* if no error occurs, I will not be 0. I refers to the position of the Left identifier of the current language name in the symbol table */Gen (STO, lev-table [I]. level, table [I]. ADR);/* generate a line to write the expression value to the STO target code in the specified memory */} elseif (sym = readsym)/* if it is not a value assignment statement, the read statement */{getsym ();/* is used to obtain the next token. Normally, it should be left parenthesis */If (sym! = Lparen)/* If the read Statement is followed by a non-left brace */error (34);/* Throw error No. 34 */elsedo {/* to obtain the parameter table in the brackets of the read Statement cyclically, generate the corresponding "read from the keyboard" target code */getsym ();/* Get a token. Normally, it should be a variable name */If (sym = ident) /* if it is indeed an identifier * // * There is a slight problem here, you should also determine whether this identifier is a variable name, if it is a constant name or process name, an error should occur */I = position (ID, TX);/* query the symbol table and locate it to I, when I cannot be found, I will be 0 */elseI = 0;/* if it is not an identifier, there is a problem. I set 0 as the error mark */if (I = 0) /* if an error exists */error (35);/* Throw error 35 */else/* otherwise, the corresponding target code is generated */{Gen (OPR, 0, 16);/* generate the 16th Operation Command: read numbers from the keyboard */Gen (STO, lev-table [I]. level, table [I]. ADR);/* generate the STO command and store the read value to the space where the specified variable is located */} getsym ();/* obtain the next token, if it is a comma, the read statement is not complete yet; otherwise, it should be the right parenthesis */} while (sym = comma);/* continuously generate code until the variable in the parameter table of the read Statement is traversed, this is not a comma. It should be a right brace */If (sym! = Rparen)/* if it is not the right parenthesis we expected */{error (33);/* Throw error 33 */while (! (IN (sym, fsys)/* depending on the fsys set, locate the next valid token and restore the syntax analysis */getsym ();} elsegetsym (); /* If the read statement ends normally, get the next token, which is generally a semicolon or end */} elseif (sym = writesym) /* If the Write statement */{getsym ();/* gets the next token, it should be a left bracket */If (sym = lparen) /* if it is a left brace */{do {/*, obtain each value in the brackets in sequence, and output */getsym ();/* to get a token, here it should be an identifier */expression (symset {rparen, comma} + fsys, lev, Tx);/* call the expression process analysis expression, add the right parenthesis and comma */Gen (OPR, 0, 14) to the set for error recovery./* generate Command 14: Output */} while (sym = comma) to the screen;/* loop until it is no longer a comma, then it should be a right brace */If (sym! = Rparen)/* if it is not a right brace */error (33);/* Throw error 33 */elsegetsym ();/* normally, you need to get the next token, prepare */} gen (OPR, 0, 15);/* to generate the target code for the operation on the 15th, function is to output a line break */*. Therefore, we can see that the Write statement in PL/0 is similar to the writeln statement in Pascal, and it is a line break with the output */} elseif (sym = callsym) /* if it is a call statement */{getsym ();/* Get the token, it should be a process name identifier */If (sym! = Ident)/* If the call is not followed by the identifier */error (14);/* Throw error No. 14 */else {I = position (ID, TX ); /* Find the corresponding Identifier from the symbol table */if (I = 0)/* if not found */error (11 ); /* error 11 */else/* If the identifier is found at the position I of the symbol table */If (Table [I]. kind = procedure)/* If this identifier is a process name */Gen (CAL, lev-table [I]. level, table [I]. ADR);/* generate the Cal target code, call this process */elseerror (15);/* If the call is not followed by the process name, the 15th error is thrown */getsym (); /* Get the next token and prepare for the following. */} elseif (sym = ifsym)/* if it is an if statement */{Ge Tsym ();/* obtain a token. It should be a logical expression */condition (symset {thensym, dosym} + fsys, lev, Tx ); /* analyze and compute the logical expression, and add the then and do statements in the error recovery set */If (sym = thensym)/* after the expression */getsym (); /* the token obtained after then should be a statement */elseerror (16);/* If then does not exist after if, a 16th error is thrown */cx1 = Cx; /* write down the pointer position of the current Code allocation */Gen (JPC, 0, 0);/* generate the conditional jump command. Set the jump position to 0, after the analysis, enter */Statement (fsys, lev, Tx);/* the statement after then analysis */code [cx1]. A = Cx;/* The jump position of the previous command line (indicated by cx1) should be the position pointed by the current CX */} e Lseif (sym = beginsym)/* If begin */{getsym ();/* Get the next token */Statement (symset {semicolon, endsym} + fsys, lev, TX);/* analyze and process the begin and end statements */while (in (sym, symset {semicolon} + statbegsys )) /* if you encounter a semicolon or a statement prefix after analyzing the next sentence */{If (sym = semicolon) /* If the statement is a semicolon (may be a null statement) */getsym ();/* Get the next token for further analysis */elseerror (10 ); /* if there is no semicolon between the statement and the statement, the system Returns Error 10 */Statement (symset {semicolon, endsym} + fsys, lev, Tx ); /* analyze a statement */} If (Sym = endsym)/* If the statement has been fully analyzed, end */getsym () should be encountered;/* is indeed End, read the next token */elseerror (17 ); /* if it is not end, a 17 error is thrown */} elseif (sym = whilesym)/* If a while statement */{cx1 = Cx; /* write down the current Code allocation position, which is the starting position of the while loop */getsym ();/* Get the next token, it should be a logical expression */condition (symset {dosym} + fsys, lev, Tx);/* analysis and calculation of this logical expression */CX2 = Cx; /* write down the current Code allocation position, which is the start position of the statement in the while do */Gen (JPC, 0, 0);/* generate the conditional jump command, enter 0 */If (sym = dosym)/* after the logical expression, it must be D. O statement */getsym ();/* Get the next token */elseerror (18);/* Do is missing after condition *, and error 18 */Statement (fsys, lev, TX);/* analyze the DO statement block */Gen (JMP, 0, cx1);/* jump to the cx1 position cyclically, that is, make another logical judgment */code [CX2]. A = Cx;/* change the jump position filled in 0 to the current position, and complete the processing of the while statement */} test (fsys, symset (), 19 ); /* if the current statement is processed successfully, symbols in the fsys set will be encountered. If not, the 19 th error will be thrown */}/* statement */; /* block in the syntax analysis process * // * parameter: lev: the level of the syntax analysis * // * TX: symbol table pointer * // * fsys: word set used for error recovery */void block (INT levet, int Tx, Const symset & fsys) {int DX;/* Data Allocation Index * // * Data Segment memory allocation pointer, pointing to the offset position of the next allocated space in the data segment */INT tx0; /* initial table Index * // * records the position of the symbol table at the beginning of the current layer */INT cx0; /* initial code Index * // * records the position of the code segment allocation at the beginning of this layer * // * block */dx = 3; /* The address indicator shows the relative position of the local volume allocated to each layer. The reason for setting the initial value to 3 is that each layer has three spaces at the beginning for storing static link SL, dynamic link DL, and return address Ra */tx0 = TX; /* The initial symbol table Pointer Points to the starting position of the symbol at the current layer in the symbol table */table [TX]. ADR = Cx;/* mark the start position of the current layer code in the current position of the symbol table */Gen (JMP, 0, 0);/* generate a line of jump command, unknown jump position: enter 0 */If (levmax)/* if the number of nested layers in the current process is greater than the maximum number of nested layers */error (32 ); /* issue error No. 32 */do {/* start to process all declarations in the source program cyclically */If (sym = constsym)/* if the current token is a reserved word of const, start to declare constants */{getsym ();/* Get the next token. Normally, it should be the identifier used as the constant name */do {/* repeatedly declare constants */constdeclar Ation (lev, Tx, dx);/* declares the constant with the current token */while (sym = comma) /* If a comma is encountered, the next constant */{getsym () is repeatedly declared;/* gets the next token, which is exactly the identifier */constdeclaration (lev, Tx, dx ); /* declare the constant with the current token */} If (sym = semicolon)/* If the constant declaration ends, a semicolon */getsym () should be encountered (); /* Get the next token and prepare for the next cycle */elseerror (5 ); /* If a semicolon is not encountered after the constant declaration statement ends, the system will issue error 5 */} while (sym = ident);/* If a non-identifier is encountered, then the constant declaration ends */}/* the syntax of the constant declaration here is different from the ebnf paradigm in the textbook: it can accept the declaration method as follows, and according to the E The BNF paradigm cannot draw the following syntax: const A = 3, B = 3; C = 6; D = 7, E = 8; that is, it can accept constant declarations separated by semicolons or commas, while only declarations separated by commas can be accepted according to the ebnf paradigm */If (sym = varsym) /* if the current token is a reserved var word, start variable declaration, similar to the constant Declaration */{getsym ();/* Get the next token, normally, it should be an identifier */do {/* used as the variable name to repeatedly declare the variable */vardeclaration (lev, Tx, dx ); /* declare a variable with the current token as the identifier */while (sym = comma)/* If a comma is encountered, repeatedly declare the next variable */{getsym (); /* Get the next token, which is exactly the identifier */vardeclaration (lev, Tx, dx);/* declares that the current token is Identifier variable */} If (sym = semicolon)/* If the variable declaration ends, a semicolon */getsym () should be encountered;/* Get the next token, prepare for the next round of loop */elseerror (5);/* If the variable declaration statement does not encounter a semicolon after it ends, issue error 5 */} while (sym = ident ); /* If a non-identifier is encountered, the variable declaration ends * // * There is also a problem with the above constant Declaration: there is a conflict with the PL/0 syntax specification. */} While (sym = procsym)/* cyclically declare sub-Processes */{getsym ();/* Get the next token, normally, it should be the process name identifier */If (sym = ident)/* If the token is indeed the identifier */{enter (procedure, lev, Tx, dx ); /* log in to the name table */getsym ();/* Get the next token. Normally, it should be a semicolon */} elseerror (4 ); /* Otherwise, error 4 */If (sym = semicolon)/* if the current token is a semicolon */getsym ();/* Get the next token, recursive call to prepare for syntax analysis */elseerror (5);/* Otherwise, error No. 5 */block (lev1, TX, symset {semicolon} + fsys) is thrown ); /* recursively call the syntax analysis process. Add one at the current level and pass the header index and valid word character */If (sym = semicolon) /* after recursive return, the current token should be the semicolon after the last end of the recursive call */{getsym ();/* Get the next token */test (statbegsys + symset {Ident, procsym}, fsys, 6);/* check whether the current token is valid. If the token is invalid, use fsys to restore the syntax analysis and throw Error 6 */} elseerror (5 ); /* If the post-declaration symbol is not a semicolon, the system will throw error 5 */} test (statbegsys + symset {ident}, declbegsys, 7);/* check whether the current status is valid, if the program does not conform to the rules, use the Declaration start symbol to make error recovery, and throw the 7 th Error */} while (in (sym, declbegsys);/* until the declarative source program has been analyzed, continue to run down and analyze the main program */code [Table [tx0]. ADR]. A = Cx;/* change the jump position of the previously generated jump statement to the current position * // * record in the symbol table */table [tx0]. ADR = Cx;/* The address is the address allocated to the current Code */table [tx0]. size = DX;/* The length is the current data segment allocation position */cx0 = Cx;/* write down the current Code allocation position */Gen (_ int, 0, dx ); /* generate the space allocation command and allocate DX space */Statement (symset {semicolon, endsym} + fsys, lev, Tx ); /* process the currently encountered statement or statement block */Gen (OPR, 0, 0);/* generate the operation instruction returned from the subroutine */test (fsys, symset (), 8);/* use fsys to check whether the current status is valid. If the current status is invalid, an error 8 */listcode (cx0) is thrown ); /* list the pcode code of the current layer */}/* block */;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.