📄 gram.cpp
字号:
/*递归下降分析器示例程序,可识别的加法运算表达式文法为:
E->E+E | i ;i表示整数 (1)
(1)转化为LL(1)文法后为:
E->iE1 (2)
E1->+EE1 | e(空串) (3)
程序是根据文法规则(2)(3)进行设计的。程序设计思路:
为每文法的非终结符设计一个子程序,子程序实现代码根据非终结符
对应的产生式的右部而编写,右部符号及其对应代码:
|--- 用条件分枝语句实现。
终结符---- 用匹配输入的代码去实现,如:if (sym==终结符) {Advance();... }。
非终结符----用相应的子程序调用去实现。
e(空串)----直接返回。
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include "gram.h"
char ch; //字符变量,存放最新读进的源程序字符。
char strToken[30]; //字符数组,存放构成单词符号的字符串。
int lvalue; //单词的内码值
char inbuf[300]; //扫描缓冲区
int sp; //起点指示器
int ep; //扫描指示器
token sym; //向前看单词
/*函数GetChar,GetBC,Concat,isDigit,Retract,Lex用于词法分析。
词法分析器的调用接口函数为Lex(),参考实验1*/
void GetChar()
{
int i = 0;
ch = inbuf[ep];
ep++;
}
void GetBC()
{
while (ch==' ')
GetChar();
}
void Concat()
{
int length;
length = ep-sp-1;
strToken[length] = ch;
}
bool isDigit()
{
if ((ch>='0')&&(ch<='9'))
return true;
return false;
}
void Retract()
{
if (ep==0)
ep = 299;
else
ep--;
ch = ' ';
}
int Lex()
{
memset(strToken, 0, 30);
GetChar();
GetBC();
sp = ep-1;
lvalue = 0;
if (isDigit())
{
while (isDigit())
{
Concat();GetChar();
}
Retract();
sscanf(strToken, "%d", &lvalue);
return $INT;
}
else if (ch == '+')
{
strToken[0] = '+';
return $PLUS;
}
else if (ch == '-')
{
strToken[0] = '-';
return $MINUS;
}
else if (ch == '*')
{
strToken[0] = '*';
return $MUL;
}
else if (ch == '/')
{
strToken[0] = '/';
return $DIV;
}
else if (ch == '\n')
{
return $END;
}
else
{
strToken[0] = ch;
return $UNKNOWN;
}
}
/*读入向前看符号*/
void Advance()
{
sym.code = Lex();
sym.value = lvalue;
strcpy(sym.name, strToken);
}
void ProcError()
{
switch (sym.code)
{
case $UNKNOWN:
printf("错误(1):第%d个字符为非法字符。\n", sp+1);
break;
case $INT:
printf("错误(2):第%d个字符开始处的单词%s前缺运算符。\n", sp+1, sym.name);
break;
case $PLUS:
case $MINUS:
case $MUL:
case $DIV:
printf("错误(3):第%d个字符开始处的单词%s前缺操作数。\n", sp+1, sym.name);
break;
case $END:
printf("错误(4):语法错,非正常输入结束。\n");
break;
default:
;
}
}
int E1()
{
if (sym.code == $PLUS)
{
Advance();
if (E() == FAIL)
return FAIL;
if (E1() == FAIL)
return FAIL;
return SUCCESS;
}
if (sym.code == $MINUS)
{
Advance();
if (E() == FAIL)
return FAIL;
if (E1() == FAIL)
return FAIL;
return SUCCESS;
}
if (sym.code == $MUL)
{
Advance();
if (E() == FAIL)
return FAIL;
if (E1() == FAIL)
return FAIL;
return SUCCESS;
}
if (sym.code == $DIV)
{
Advance();
if (E() == FAIL)
return FAIL;
if (E1() == FAIL)
return FAIL;
return SUCCESS;
}
//当sym属于FOLLOW(E1)时,用E->e (空串)自动匹配输入,否则发现错误。
if (sym.code != $END)
return FAIL;
return SUCCESS;
}
int E()
{
if (sym.code == $INT)
{
Advance();
if (E1() == FAIL)
return FAIL;
//匹配结束符号
if (sym.code != $END)
return FAIL;
return SUCCESS;
}
return FAIL;
}
void main()
{
bool quit = false;
int i;
while (!quit)
{
memset(inbuf, 0, 300);
printf("请输入四则运算表达式(回车结束):");
i = 0;
while ((inbuf[i] = getchar()) != '\n')
i++;
printf("\n");
ep = 0;
Advance();
if (E() == SUCCESS)
printf("分析成功,没有语法错误\n");
else
ProcError();
printf("退出吗?(y/n)");
if (toupper(getch()) == 'Y')
quit = true;
printf("\n");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -