📄 althorm.h
字号:
///////////////////////////////////////////////////////////////////////////////
// 名称:可编程计算器
// 功能描述:
// 本计算器可以实现对诸如 3+(1+7)*6+4*((5+4))这样的表达式的计算,
// 目前仅限于带括号的 +, * 运算
// 实现描述:
// 本计算器的是在教材 pp.49, 文法 (3.8)基础上稍加修改后,
// 利用自上而下的递归程序实现。每个非终结符对应一个分析函数。
//
// 修改后的文法如下所示,其中 e 代表空串
//
// E-->TE'
// E'-->+TE'|-TE'|e
// T-->FT'
// T'-->*FT'|/FT'|e
// F-->(E)|num|+num|-num
//
// 程序中使用了一个词法分析函数 yylex,变量yylval代表最近的整数
// 记号的数值。'\0'对应着$符号,预示着输入串结束.
//
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
// 这一段是极好的定义
#define ADD 0
#define MIN 1
#define MUL 2
#define DIV 3
#define LBRACE 4
#define RBRACE 5
#define NUM 6
#define END 7
#define OTHER 8
char input[200]; // 输入串。
int lookahead;
int pCur;
double yylval;
char last;
char before;
CString error;
// 函数声明
int yylex();
void Match(int t);
double T();
double E_();
double E();
double T_();
double F();
// 词法分析器,读入一个记号
int yylex()
{
char num[20];
int temp = 0;
// 过滤掉空白
while ( input[pCur]==' ' ) pCur++;
// 如果是数字,那么把这个记号的数值计算出来放在 yylval 中
while ((input[pCur] >= '0' && input[pCur] <= '9')||input[pCur]=='.'){
num[temp++] = input[pCur++];
}
last = input[pCur];
if(pCur == 0)
before = '@';
else
before = input[pCur-1];
if (temp >0)
{
sscanf(num, "%lf", &yylval);
return NUM;
}
// 其他记号的处理
switch (input[pCur++]) // 注意:这里指针往前移了一位
{
case '+': return ADD;
case '-': return MIN;
case '*': return MUL;
case '/': return DIV;
case '(': return LBRACE;
case ')': return RBRACE;
case '\0': return END;
default: return OTHER;
}
}
// 匹配函数,若当前记号与参数相同,则读入下一个记号
void Match(int t)
{
if (lookahead == t)
lookahead = yylex();
else
{
error = "括号不匹配,左括号和右括号必须成对出现!\n";
throw error;
}
}
// 处理 E-->TE'
double E()
{
switch (lookahead)
{
case LBRACE: // FIRST(E)={(,num,+,-}
case NUM:
case ADD:
case MIN:
return T() + E_();
case END:
error = "";
error = error + "表达式不能以字符 " + before +" 结尾!\n表达式只能以右括号或数字结尾!\n";
throw error;
break;
default:
if(pCur == 1)
{
error = "";
error = error + "表达式不能以字符 "+ last +" 开头!\n表达式只能以左括号或数字开头!\n";
throw error;
}
else
{
error = "";
error = error + "左括号后不能跟字符 "+ last +" !\n左括号后只能跟左括号或数字!\n";
throw error;
}
}
}
// 处理 E'-->+TE'|-TE'|e
double E_()
{
switch (lookahead)
{
case ADD: // FIRST(E')={+,-,e}
Match(ADD);
if(lookahead==ADD || lookahead==MIN)
{
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
return T() + E_();
case MIN:
Match(MIN);
if(lookahead==ADD || lookahead==MIN)
{
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
return -T() + E_();
case RBRACE: // E'-->e 的情况,这个时候需要处理 FOLLOW集合, FOLLOW(E')={), $}
case END:
return 0;
default:
error = "不可能发生的错误!";
throw error; //这个错误一般不会发生,因为在他执行之前如果有错误的话一般会被发现。
}
}
// 处理 T-->FT'
double T()
{
switch (lookahead)
{
case LBRACE: // FIRST(T)={(,num,+,-}
case NUM:
case ADD:
case MIN:
return F()*T_();
case END:
error = "";
error = error + "\n表达式不能以操作符 "+ before +" 结尾!\n";
throw error;
default:
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
}
// 处理 T'-->*FT'|/FT'|e
double T_()
{
switch (lookahead)
{
case MUL: // FIRST(T')={*,/,e}
Match(MUL);
if(lookahead==ADD || lookahead==MIN)
{
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
return F() * T_();
case DIV:
Match(DIV);
if(lookahead==ADD || lookahead==MIN)
{
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
return 1/F() * T_();
case ADD: // T'-->e 的情况,这个时候需要处理 FOLLOW集合, FOLLOW(T')={+,-,),$}
case MIN:
case RBRACE:
case END:
return 1;
case NUM:
error = "右括号后不能直接跟数字,只能跟+、-、*、/操作符!";
throw error;
default:
error = "";
error = error + "字符 + before + 后不能跟字符 " + last + " !\n数字或右括号后只能跟+、-、*、/和右括号!\n";
throw error;
}
}
// 处理 F-->(E)|num|+num|-num
double F()
{
double temp;
switch(lookahead)
{
case LBRACE: // FIRST((E))={(}
Match(LBRACE);
temp = E();
Match(RBRACE);
return temp;
case NUM: // FIRST(num) = {num}
temp = yylval;
Match(NUM);
return temp;
case ADD:
Match(ADD);
return F();
case MIN:
Match(MIN);
return -F();
case END:
error = "";
error = error + "表达式不能以操作符 " + before + " 结尾!\n";
throw error;
default:
error = "";
error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
throw error;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -