表达式计算器(LL1文法)

时间:2023-03-10 03:42:54
表达式计算器(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集

表达式计算器(LL1文法)

LL(1)分析表

表达式计算器(LL1文法)

(应该没错吧……表示昨天刚考完试……)

(嗯。。我承认我抄。。咳咳。。借鉴了这份代码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[]; // 表达式
int pos; // 读取到表达式的位置
double val;
ERR_KIND err; void F();
void E(); void NUM()
{
val = ;
while (expr[pos] <= '' && expr[pos] >= '')
{
val = val * + expr[pos] - '';
pos++;
}
if (expr[pos] == '.')
{
pos++;
double eo = 0.1;
while (expr[pos] <= '' && expr[pos] >= '')
{
val += (expr[pos] - '') * eo;
eo *= 0.1;
pos++;
}
}
} SYM_KIND get_sym() // 读取一个单词
{
char ch = expr[pos++];
while (ch == ' ' || ch == '\t') // 忽略空格
ch = expr[pos++];
if (ch <= '' && ch >= '')
{
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 = ;
err = ERR_OK;
E();
if (err == ERR_END) printf("%g\n", val);
else output_err();
printf(">>");
}
return ;
}

运行结果:
>>3+4^2.2
24.1121
>>2-7/8
1.125
>>(8+0
           ^括号不匹配
>>7%5
2
>>7+9.9+
              ^缺少一个数字

加个界面……

表达式计算器(LL1文法)