表达式计算器(LL1文法)
LL(1)文法求算数表达式的值
递归子程序法
分析过程:
表达式文法G[E]:
E->E+T|E-T|T
T->T*F|T/F|T%F|F
F->N^F|N
N->(E)|NUM|+NUM|-NUM
消除左递归、左公共因子
E ->TE'
E'->+TE'|-TE'|ε
T ->FT'
T'->*FT'|/FT'|%FT'|ε
F ->NF'
F'->^F|ε
N->(E)|NUM|+NUM|-NUM
FIRST集和FOLLOW集
LL(1)分析表
(应该没错吧……表示昨天刚考完试……)
(嗯。。我承认我抄。。咳咳。。借鉴了这份代码http://ideone.com/o2Ag4。。还是炮姐写的好。。)
#include <cstdio> #include <cmath> /** * LL(1)文法求算数表达式的值 * 递归子程序法 **/ enum SYM_KIND { // 符号类型 SYM_NUM, // num SYM_ADD, // + SYM_SUB, // - SYM_MUL, // * SYM_DIV, // / SYM_MOD, // % SYM_POW, // ^ SYM_LBR, // ( SYM_RBR, // ) SYM_END, // '\0' SYM_ERR // 其他不合法符号 }; enum ERR_KIND { // 状态 ERR_OK, ERR_INVALID_CHAR, ERR_NO_OPERATOR, ERR_BR_NOT_MATCH, ERR_NO_NUM, ERR_END }; char expr[2000]; // 表达式 int pos; // 读取到表达式的位置 double val; ERR_KIND err; void F(); void E(); void NUM() { val = 0; while (expr[pos] <= '9' && expr[pos] >= '0') { val = val * 10 + expr[pos] - '0'; pos++; } if (expr[pos] == '.') { pos++; double eo = 0.1; while (expr[pos] <= '9' && expr[pos] >= '0') { val += (expr[pos] - '0') * eo; eo *= 0.1; pos++; } } } SYM_KIND get_sym() // 读取一个单词 { char ch = expr[pos++]; while (ch == ' ' || ch == '\t') // 忽略空格 ch = expr[pos++]; if (ch <= '9' && ch >= '0') { pos--; NUM(); return SYM_NUM; } else if (ch == '+') return SYM_ADD; else if (ch == '-') return SYM_SUB; else if (ch == '*') return SYM_MUL; else if (ch == '/') return SYM_DIV; else if (ch == '%') return SYM_MOD; else if (ch == '^') return SYM_POW; else if (ch == '(') return SYM_LBR; else if (ch == ')') return SYM_RBR; else if (ch == '\0') { err = ERR_END; return SYM_END; } err = ERR_INVALID_CHAR; return SYM_ERR; } void N() // N->(E)|NUM|+NUM|-NUM { if (err != ERR_OK) return ; SYM_KIND kind = get_sym(); if (kind == SYM_LBR) { E(); if (err == ERR_END) { err = ERR_BR_NOT_MATCH; } else if (err == ERR_OK) { kind = get_sym(); if (kind != SYM_RBR) err = ERR_BR_NOT_MATCH; } } else if (kind == SYM_ADD) { kind = get_sym(); if (kind != SYM_NUM) { err = ERR_NO_NUM; } } else if (kind == SYM_SUB) { kind = get_sym(); if (kind != SYM_NUM) { err = ERR_NO_NUM; } val = -val; } else if (kind != SYM_NUM) { err = ERR_NO_NUM; } } void F_() // F'->^F|ε { if (err != ERR_OK) return ; SYM_KIND kind = get_sym(); double tmp = val; if (kind == SYM_POW) { F(); val = pow(tmp, val); } else if (kind == SYM_ADD || kind == SYM_SUB || kind == SYM_MUL || kind == SYM_DIV || kind == SYM_MOD || kind == SYM_END || kind == SYM_RBR) { pos--; } else if (kind != SYM_ERR) err = ERR_NO_OPERATOR; } void F() // F ->NF' { if (err != ERR_OK) return ; N(); F_(); } void T_() // T'->*FT'|/FT'|%FT'|ε { if (err != ERR_OK) return ; SYM_KIND kind = get_sym(); double tmp = val; if (kind == SYM_MUL) { F(); val *= tmp; T_(); } else if (kind == SYM_DIV) { F(); val = tmp / val; T_(); } else if (kind == SYM_MOD) { F(); val = fmod(tmp, val); T_(); } else if (kind == SYM_ADD || kind == SYM_SUB || kind == SYM_RBR || kind == SYM_END) { pos--; } else if (kind != SYM_ERR) { err = ERR_NO_OPERATOR; } } void T() // T ->FT' { if (err != ERR_OK) return ; F(); T_(); } void E_() // E'->+TE'|-TE'|ε { if (err != ERR_OK) return ; SYM_KIND kind = get_sym(); double tmp = val; if (kind == SYM_ADD) { T(); val = tmp + val; E_(); } else if (kind == SYM_SUB) { T(); val = tmp - val; E_(); } else if (kind == SYM_END || kind == SYM_RBR) { pos--; } else if (kind != SYM_ERR) { err = ERR_NO_OPERATOR; } } void E() // E ->TE' { if (err != ERR_OK) return ; T(); E_(); } void output_err() { if (err == ERR_OK) { err = ERR_BR_NOT_MATCH; pos++; } printf("%*s ^", pos, ""); if (err == ERR_BR_NOT_MATCH) printf("括号不匹配\n"); else if (err == ERR_NO_NUM) printf("缺少一个数字\n"); else if (err == ERR_NO_OPERATOR) printf("缺少一份运算符\n"); else if (err == ERR_INVALID_CHAR) printf("不合法字符\n"); } int main() { printf(">>"); while (gets(expr) != NULL) { pos = 0; err = ERR_OK; E(); if (err == ERR_END) printf("%g\n", val); else output_err(); printf(">>"); } return 0; }
运行结果:
>>3+4^2.2
24.1121
>>2-7/8
1.125
>>(8+0
^括号不匹配
>>7%5
2
>>7+9.9+
^缺少一个数字
加个界面……