(Connected)
5. Implementation of the top and lower grammar analysis
After 4 steps, the most exciting moment is now arrived. General "Compilation Principles" code this code is mostly pseudo code that cannot be run on the machine, here, you will see that a practical search for the error can be performed based on the top-based syntax analysis algorithm. Calculate the arithmetic expression.
If you don't lose general, we specify that the arithmetic expression can only be integrated four computments (including numbers) so we need to expand the following three functions:
INT E_ADDSUB (); / / corresponds to the generating INT T_MULDIV () corresponding to the non-finals E, corresponding to the generating INT f_number () corresponding to the non-finals F
As you see that the above functions have return value int, we need to return the three functions to return the value of the calculated results. In order to calculate the value of the neutral expression in each function, in the e_addsub () and t_muldiv () functions, I use a variable RTN to store the value of the calculation of the operator, and store the right value of the operator with the OPR2, according to The operator performs the corresponding operation.
In order to save the input arithmetic expression, I use the global static character array expr to indicate the input character buffer, use POS to represent the value of the character indicator, so that the indicator takes the adj to () operation can be replaced with POS . And the characters indicated by the indicator can be expr [POS].
In order to indicate an error, I define six wrong error code, and define the string of the corresponding six error messages. Error () function is transformed into:
Void Error (int errcode);
This allows the program to respond to an error by transmitting the error code, including indicating an error location, displaying an error message, a prompt, and the like. In addition, I declare that the error-jumping buffer static variable errjb is a STD :: jmp_buf type structure, which can record the current program to Errjb via the setjmp () macro, when the error returns, can pass longjmp ( ) Function; directly jump to the location of the main () main program setjmp () is called, not in the wrong function.
Thus, a fully equipped arithmetic expression analyzer actuator is completed, note that the program constructed cannot recognize a unit operator, such as input "-1 1" will report an error.
Here is the running result fragment:
1 (^ syntax) !!! Expression illegal end or expression is incomplete! Please re-enter! Please enter an arithmetic expression (enter "Q" or "Q" exit): 2- () ^ syntax error !! There is no expression or expression in parentheses! Please re-enter! Please enter an arithmetic expression (enter "Q" or "Q" exit): 2 (3 ^ syntax error !!! Expression illegally end or Expressible! Please re-enter! Please enter an arithmetic expression (enter "Q" or "Q" exit): 2 (3 * 9) ^ syntax error !!! Expression illegal end or expression is incomplete Please re-enter! Please enter an arithmetic expression (enter "Q" or "Q" exit): 2 * (2 4) 4 ^ syntax error !!! Right to connect illegal characters after the right bracket! Please re-enter!
The list of procedures is as follows:
/ **** Arithmetic expression analysis and calculation, file name: exp_c.cpp, code / note: hiFrog ********* Up to **** / # include under VC6 and DEV-C #include
#include
#include
#include
#define exp_len 100 // Defines the length of the input character buffer
/ * -------------------------- * / # define invalid_char_tail 0 // Expression followed by illegal characters #define char_after_right 1 // Right, connect illegal characters #define left_after_num 2 // Direct connection to the left bracket #define invalid_char_in 3 // Expression containing illegal characters #define no_right 4 // Missing Right Brand #define Empty_bracket 5 // Brand Internal no expression #define unExpected_END 6 // Expected arithmetic expression end
Using namespace std;
Const string errcodestr [] = // Expression error information {"The expression is followed by illegal characters!", "" The right bracket is connected to the illegal characters! " Character! "," Lack of right brackets! "," There is no expression or expression in parentheses! "," "Expressions illegally end or express incomplete!"}
Static char expr [exp_len]; // Math Expression Enter the character buffer Static INT POS; // character indicator flag: used to save the position of the character in the analysis static jmp_buf errjb; // Error jump buffer
// ******** The following is a function declaration ********* // generated "E -> T E | TE | T" function, used to analyze the reduction of arithmetic expression . INT E_ADDSUB (); // Generate a function of "T-> F * T | F / T | F" to analyze the multiplication arithmetic expression. INT T_MULDIV (); // Generate a function of "F -> I | (e)" to analyze expressions within numbers and parentheses. INT f_number (); // error handling function, you can point out the error location, error information. Void Error (int errcode);
INT main () {int AS; // Save the calculation result of the arithmetic expression BOOL quit = false; // Whether to exit the calculation
DO {// This sets a jump target. If the other functions of this program calls longjmp, // The execution instruction is jumped here, and will continue from here. If (setjmp (errjb) == 0) // If there is no error {POS = 0; // initializes the character indicator is 0, that is, the first character of the input string is directed. Cout << "Please enter an arithmetic expression (enter" Q "or" Q "exit):" <
CIN >> EXPR; / / Input expression, fill the expression character buffer.
IF (expr [0] == 'q' || expr [0] == 'q') // Check the first character, is it? Quit = true;
ELSE {// Call the function of the derived "E -> T E | T-E | T", // Start from the start symbol "E". ANS = E_ADDSUB ();
// At this time, the program believes that the syntax analysis of the expression has been completed, and the reason for the error is judged below:
// If you follow the numbers or other characters directly after a certain bracket in the expression, then an error is reported because the number i does not belong to the FOLLOW ()) set. IF (expr [pOS-1] == ')' && exclish! = '/ 0') Error (char_after_right);
// If a number or the right bracket in the expression follows the left parentheses, // reports an error because the left brackets do not belong to the FOLLOW (E) set. IF (EXPR [POS] == '(') error (left_after_num);
/ / If there is other illegal character if (expr [pOS]! = '/ 0') error (invalid_char_tail); Cout << "calculated the value of the expression is:" <
<
}
}
Else
{
// setjmp (errjb)! = 0:
Cout << "Please re-enter!" <
}
}
While (! quit);
Return 0;}
// Generate a function of "E -> T E | T-E | T" to analyze the additional arithmetic expression. // Return the calculation result int E_addsub () {int = t_muldiv (); // calculate the left element of the additive expression
While (Expr [POS] == ' ' || EXPR [POS] == '-') {INT OP = EXPR [POS ]; // Take the symbol of the current position in the character buffer to OP Int opr2 = t_muldiv ( ); / / Calculate the right element of the additive expression expression
/ / Calculate the value IF (OP == ' ') // If it is " " RTN = OPR2; // uses the addition to calculate the else // otherwise ("-" 号) RTN- = OPR2; // Use subtraction calculations} RETURN RTN;} // Due to the "T -> F * T | F / T | F" function to analyze the multiplication arithmetic expression. // Return the calculation result int T_muldiv () {int = f_number (); // calculate the left element of the arithmetic expression
While (expr [pOS] == '*' || expr [pOS] == '/') {int OP = expr [POS ]; // Take symbols in the current location in the character buffer to OP Int opr2 = f_number ); / / Calculate the right element of the arithmetic expression
// Calculate value IF (OP == '*') // If it is "*" 号 r * = opr2; // calculates ELSE / / otherwise (Yes "/" 号) RTN / = OPR2; / / Use division calculation} Return RTN;}
// Generate a function of "F -> I | (E)" to analyze expressions in numbers and parentheses. INT f_number () {int RTN; // Declare the variable of the returned value
// derive with the production formula F -> (e): if (expr [pOS] == '(') // If the symbol of the current position of the character buffer is "(" {POS ; // indicator plus one point The next symbol RTN = E_ADDSUB (); // Call the analysis function IF (expr [pOS ]! = ')') // if there is no "(" match ")" Error (no_right); // generates an error
Return RTN;}
IF (isDigit (expr [pOS]) // If the character of the current location in the character buffer is a digital {// delivers // converts the string of the current location in the character buffer into an integer RTN = ATOI (EXPR POS); / / Change the value of the indicator, skip the number of characters buffers, find the next input character. While (isDigit (expr [pOS])) POS ;} else // If not a number, the corresponding error {if (expr [pOS] == ')') // If you find a ")" error (EMPTY_BRACKET); // The brackets are empty, ie, no braces, no intramectomy. ELSE IF (expr [pOS] == '/ 0') // If the input string ends error (Unexpected_end); //, the arithmetic expression illegally ends the else error (invalid_char_in); / / otherwise the input string contains illegal Character} Return RTN;}
// Error handle function, enter the error code, you can point out the error position, error information. void error (int errcode) {cout << '/ r'; // Wrap While (POS -) cout << '; // Print space, move the "^" indicating the error to the error position of the input string Cout << "^ syntax !!!" <
<
<< '/ a'; ?????????????? FONT issued a warning <>
Longjmp (Errjb, 1); // Jump to the SetJMP call in the main () function, and set the return value of setjmp (errjb) to 1} (full text)