When learning the data structure, you will learn how to use the stack to solve the infix expression. The idea is to scan it again and output the number. The symbol determines the time of the incoming and outgoing stacks based on the priority, then, a suffix expression is generated. It is easy to solve the suffix expression. You can scan the extension expression directly once. When a number is added to the stack, the two elements at the top of the stack are directly used for calculation.
A long time ago, implementing the above mentioned program was the first to feel the feeling of "Compiling", and it was very nice. So I always wanted to learn the real compilation principle. longshu is more profound, it has never been justified. These two days I have read many articles, such as vczh's series of articles "handwritten syntax analyzer" and "Regular Expression Engine.
Expressions are much easier than definition languages, because they can easily combine lexical analysis and syntax analysis, because all symbols except numbers in expressions are single characters, you can directly determine the token type, which is relatively simple.
The core of recursive descent is to write a non-left recursive syntax. After writing it, you can simply write a program to explain this regular expression. Click here for source code
The following describes the recursive descent Analysis of prefix or suffix expressions:
For prefixes, expressions in scheme all adopt this form. Therefore, lexical analysis is not required and there is no priority ambiguity.
The syntax is defined as follows:
expr="(" op number number ")" | "(" expr ")" |number number= [0-9]* op=‘+‘ | ‘-‘ | ‘* | ‘/‘
We can translate each part;
For example
The getnumber function should be written as follows:
Expr getnumber (char * & stream) {expr number; // stores the result as an expr Class Object char * lookup = stream; while (* lookup) = '') lookup ++; bool flag = false; while (true) {If (* lookup) <= '9' & (* lookup)> = '0') {number. result = number. result * 10 + (* lookup)-'0'; ++ lookup; flag = true;} else break;} If (FLAG) // obtain the number starting with the current, and adjust the current pointer to a stream = lookup behind the number; else // the start of the current is not a number, the current pointer remains unchanged {number. error = "There ne Ed a number! \ N "; number. error_position = lookup;} return number ;}
With getnumber, getexpression is easy. The core part is as follows:
Expr expression; char * lookup = stream; expression = getnumber (lookup); If (expression. error) {If (is (lookup, "(") {expression. error = 0; char op = 0; If (OP = isoperator (lookup) {expr left_expr = getexpression (lookup); If (left_expr.error) return left_expr; char * copy_lookup = lookup; expr right_expr = getexpression (lookup); If (right_expr.error) return right_expr; Switch (OP) {Case '+': expr Ession. result = left_expr.result + right_expr.result; break; Case '-': expression. result = left_expr.result-right_expr.result; break; Case '*': expression. result = left_expr.result * right_expr.result; break; Case '/': {If (right_expr.result = 0) {expression. error = "The number divided can not be zero! \ N "; expression. error_position = copy_lookup; break;} else {expression. Result = left_expr.result/right_expr.result; break ;}} default: {expression. Error =" the wrong Operator! \ N "; expression. error_position = lookup; return expression ;}} else {expression = getexpression (lookup); If (expression. Error! = 0) return expression;} If (! Is (lookup, ")") {expression. Error = "there need right bracket! \ N "; expression. error_position = lookup ;}}if (expression. error = 0) // The number is successfully obtained. Therefore, the stream pointer is placed after the number {stream = lookup;} return expression;
You have to write your own codes for the infix. After I write a prefix for the large Prefix Code of vczh, I write a infix for myself. We can easily draw inspiration from it, find the core of recursive descent, and then write the fix expression solution (the fix solution code is completely written by myself, and the error handling part may have some vulnerabilities ), I believe there will be a lot of GAINS to write an infix based on the above.
Recursive descent to solve the infix, suffix, or prefix expression