随便写了下,没仔细调试。
大约这么定义 double parse_expr(char *input, char **output);
input就是表达式的字符串,output是解析剩下的部分。如果output==input,就是解析失败。如果正确,返回运算结果。
用起来大约这样
char *out, *exp="2+(1+3)*4";
double r = parse_expr(exp, &out);
if (out==exp){
printf("parse fail\n");
return 0;
}
printf("%s => %f \n", exp, r);
回头想下,思路跟以前写的parser几乎是葫芦画瓢,也该算是递归下降吧。
代码如下
exp.h
double parse_expr(char *input, char **output);
double parse_term(char *input, char **output);
double parse_fact(char *input, char **output);
double parse_numb(char *input, char **output);
exp.c
#include "exp.h"
// expr ::= term {[+-] term}
double parse_expr(char *input, char **output){
double r=0;
char *tmp, op;
tmp = input;
// factor
r = parse_term(tmp, output);
if (output==tmp){
return 0;
}
// {[+-] term}
tmp = *output;
while ((op=*tmp)=='+' || op=='-'){
double r2 = parse_term(++tmp, output);
if (tmp==*output){
*output = input;
return 0;
}
r = (op=='+')? r+r2: r-r2;
tmp = *output;
}
return r;
}
// term ::= factor {[*/] factor}
double parse_term(char *input, char **output){
double r=0;
char *tmp, op;
tmp = input;
// factor
r = parse_fact(tmp, output);
if (output==tmp){
return 0;
}
// {[*/] factor}
tmp = *output;
while ((op=*tmp)=='*' || op=='/'){
double r2 = parse_fact(++tmp, output);
if (tmp==*output){
*output = input;
return 0;
}
r = (op=='*')? r*r2: r/r2;
tmp = *output;
}
return r;
}
// fact ::= (expr) | numb
double parse_fact(char *input, char **output){
double r=0;
char *tmp;
// (expr)
if (*input=='(') {
tmp = input+1;
r = parse_expr(tmp, output);
if(**output==')'){
(*output)++;
return r;
}
// if fail, output == input
else {
*output = input;
return 0;
}
}
// numb
r = parse_numb(input, output);
return r;
}
double parse_numb(char *input, char **output){
double r = 0;
char ch, *tmp=input;
while((ch = *tmp++)>='0' && ch<='9'){
r = r*10+ch-'0';
}
*output = tmp-1;
return r;
}
main.c
int main(){
double r;
char *out, exp[1024];
scanf("%256s", exp);
r = parse_expr(exp, &out);
if (out==exp){
printf("parse fail\n");
return 0;
}
printf("%s => %f \n", exp, r);
return 0;
}