实验二 递归下降语法分析

一、实验目的:

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二、实验原理

每个非终结符都对应一个子程序。

该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

  • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
  • 每遇到一个非终结符,则调用相应的子程序

三、实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

例如:

输入begin a:=9;x:=2*3;b:=a+x end #

输出success

输入x:=a+b*c  end #

输出‘end' error

四、实验步骤

1.待分析的语言的语法(参考P90)

2.将其改为文法表示,至少包含

–语句

–条件

–表达式

3. 消除其左递归

4. 提取公共左因子

5. SELECT集计算

6. LL(1)文法判断

7. 递归下降分析程序

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;
char ch;
char arr1[100], arr2[15],arr3[15];//arr1输入,arr2输出
int syn, row, sum ; //syn为单词种别码,sum为整形常数。
int p=0,m=0,n=0;
int flag=0;
char* words[6] = {"begin", "if", "then", "while", "do", "end"};
void sca();
void S();//解析语句
void S1();
void S2();
void S3();
void S4();
void C();//解析条件
void E();//解析表达式
void E1();
void T();//解析项
void T1();
void F();//解析因子
void S(){
if(flag != 0){
if(syn == 10){ //<id>:=<表达式>
sca();
S1();
}
else if(syn == 2){ //if
sca();
S2();
}
else if(syn == 4){//while
sca();
S3();
}
else if(syn == 0){
}
else{
printf("语句语法错误 ");
exit(0);
}
}
else{
if(syn == 1){//begin
sca();
flag = 1;
S4();
}else{
printf("error,缺少begin! ");
exit(0);
}
}
}
void S1(){
if(syn==18){
sca();
E();
}
else{
printf("语句语法错误 ");
exit(0);
}
}
void S2(){//if
C();
if(syn== 3 ){
sca();
S();
}
else{
printf("语句语法错误 ");
exit(0);
}
}
void S3(){//while
C();
if(syn== 5 ){
sca();
S();
}
else{
printf("语句语法错误 ");
exit(0);
}
}
void S4(){//begin
S();
while(syn == 26){
sca();
S();
}
if(syn == 6){
sca();
if(syn == 0){
printf("success!");
}
else{
printf("语句语法错误 ");
}
}
else{
printf("error,缺少end ");
exit(0);
}
}
void C(){
E();
if(syn==25||syn==0||syn==20||syn==21||syn==23||syn==24){
sca();
sca();
}
else{
printf("条件语法错误 ");
exit(0);
}
E();

}
void E(){
T();
E1();
}


void E1(){
if(syn == 13 || syn == 14){
sca();
T();
E1();
}
else if(syn == 28 || syn == 0){
}
}

void T(){
F();
T1();
}

void T1(){
if(syn == 15 || syn == 16){
sca();
F();
T1();
}
else if(syn == 13 ||syn == 14 || syn == 28 || syn == 0){
}
}
void F(){
if(syn == 27){
sca();
E();
if(syn == 28){
sca();
}
else{
printf("因子错误 ");
exit(0);
}
}
else if(syn == 10 || syn == 11){
sca();

}
else{
printf("因子错误");
exit(0);
}
}

int main()
{
p = 0;
row = 1;
cout << "请输入字符,以#号结束" << endl;

do
{
cin.get(ch);
arr1[p++] = ch;
} while (ch != '#');

p = 0;

// do
//
// {
//
// sca();
//
// switch (syn)
//
// {
//
// case 11:
//
// cout << '(' << syn << "," << sum << ")" << endl;
//
// break;
//
// case -1:
//
// cout << "该符号“"<<arr3<<"”无种别码" << "!" << endl;
//
// break;
//
// case -2:
//
// ++row;
//
// break;
//
// default:
//
// cout << "(" << syn << "," << arr2 << ")" << endl;
//
// break;
//
// }
//
// } while (syn != 0);
sca();
S();
}
void sca()
{
for (n = 0; n < 8; n++)
{
arr2[n] = NULL;
}
ch = arr1[p++];

while(ch == ' ')//空指针+1
{
ch = arr1[p];
p++;
}
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
m = 0;
while((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
arr2[m++] = ch;
ch = arr1[p++];
}
arr2[m++] = '';
--p;
syn = 10;
for (n = 0; n < 6; ++n)
{
if (strcmp(arr2, words[n]) == 0)
{
syn = n + 1;
break;
}
}
}
else if ((ch >= '0' && ch <= '9'))
{
sum = 0;
while (ch >= '0' && ch <= '9')
{
sum = sum * 10 + ch - '0';
ch = arr1[p++];
}
--p;
syn = 11;
if (sum > 32767)
{
syn = -1;
}
}
else switch (ch)
{
case '<':
m = 0;
arr2[m++] = ch;
ch = arr1[p++];
if (ch == '>')
{
syn = 21;
arr2[m++] = ch;
}
else if (ch == '=')
{
syn = 22;
arr2[m++] = ch;
}
else
{
syn = 23;
--p;
}
break;
case '>':
m = 0;
arr2[m++] = ch;
ch = arr1[p++];
if (ch == '=')
{
syn = 24;
arr2[m++] = ch;
}
else
{
syn = 20;
--p;
}
break;
case ':':
m = 0;
arr2[m++] = ch;
ch = arr1[p++];
if (ch == '=')
{
syn = 18;
arr2[m++] = ch;
}
else
{
syn = 17;
--p;
}
break;
case '*':
syn = 13;
arr2[0] = ch;
break;
case '/':
syn = 14;
arr2[0] = ch;
break;
case '+':
syn = 15;
arr2[0] = ch;
break;
case '-':
syn = 16;
arr2[0] = ch;
break;
case '=':
syn = 25;
arr2[0] = ch;
break;
case ';':
syn = 26;
arr2[0] = ch;
break;
case '(':
syn = 27;
arr2[0] = ch;
break;
case ')':
syn = 28;
arr2[0] = ch;
break;
case '#':
syn = 0;
arr2[0] = ch;
break;
case ' ':
syn = -2;
break;
default:
syn = -1;
arr3[0]=ch;
break;
}
}

原文地址:https://www.cnblogs.com/chock/p/11957759.html