一、实验目的:

利用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 <stdio.h>

#include <string.h>

#include <stdlib.h>

 

char prog[50],token[20];  //定义程序段,单词符号 

char ch;

int syn,p,m,n,sum=0;   //定义syn为单词符号类型 ,sum为整数,识别程序段第一个字符指针p 

int k=0;

char  *rwtab[6]={"begin","if","then","while","do","end"};

 

void parser();

void yucu(); 

void statement();

void expression();

void term();

void factor();    

void scaner();    //词法分析 

 

 

int main(){

p=0;

int i;

printf("请输入需要分析的源程序:\n");

printf("语法分析结果为:\n");

do{

scanf("%c",&ch);

prog[p++]=ch;

while(ch!='#');

p=0;

scaner();

parser();

printf("语法分析结束!\n");

}

void scaner(){   //读取单词符号 

for(n=0;n<20;n++) 

token[n]=NULL;

m=0;

sum=0;

ch=prog[p++];

while(ch==' '){

ch=prog[p++];

}

//if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){   

 if (ch>='a' && ch<='z'){ 

while((ch>='a'&&ch<='z')||(ch>='0'&&ch<='9'))

{

token[m++]=ch;

ch=prog[p++];

}

syn=10;

p=p--;  //回退一个字符 

for(n=0;n<6;n++){   //标识符是否为关键字

if(strcmp(token,rwtab[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=prog[p++];

}

syn=11;

p--;  

}

else{

switch(ch){

case '<' :

token[m++]=ch;

ch=prog[p++];

if(ch=='>') {

syn=21;

token[m++]=ch;

}

else if(ch=='=') {

syn=22;

token[m++]=ch;

} else {

syn=20;

p--;

}

break;

case '>':m=0,token[m++]=ch;

ch=prog[p++];

if(ch=='=') {

syn=24;

token[m++]=ch;

} else {

syn=23;

p=p-1;

}

break;

case ':':m=0,token[m++]=ch;

ch=prog[p++];

if(ch=='=') {

syn=18;

token[m++]=ch;

} else {

syn=17;

p=p-1;

}

break;

case '+':

syn=13;

token[0]=ch;

break;

case '-':

syn=14;

token[0]=ch;

break;

case '*':

syn=15;

token[0]=ch;

break;

case '/':

syn=16;

token[0]=ch;

break;

case ';':

syn=26;

token[0]=ch;

break;

case '(':

syn=27;

token[0]=ch;

break;

case ')':

syn=28;

token[0]=ch;

break;

case '=':

syn=25;

token[0]=ch;

break;

case '#':

syn=0;

token[0]=ch;

break;

default:

syn=-1;

token[0]=ch;

}

}

 

void parser() {

    if (syn==1) { //begin

        scaner();

        yucu();

        if (syn==6) { //end

            scaner();

            if (syn==0 && k==0) printf("success \n");

        } else {

            if(k!=1) printf("error,lose 'end' ! \n");

            k=1;

        }

    } else {

        printf("error,lose 'begin' ! \n");

        k=1;

    }

    return;

}

 

void yucu(){

statement();

while(syn==26){  //判断是否为‘;’ 

scaner();

statement(); 

}

return;

}

 

void statement(){

if(syn==10){  //判断是否为标识符

scaner();

if(syn==18){   //判断是否为‘:=’ 

scaner();

expression(); 

else{

printf("error!\n");

k=1;

}

}

else{

printf("error!\n");

k=1;

}

return;

 

void expression() {

term();

while(syn==13||syn==14) {    //判断是否为 ‘+’或‘-’ 

scaner();

term();

}

return;

}

 

void term() {

factor();

while(syn==15||syn==16) {    //判断是否为 ‘*’或‘/’

scaner();

factor();

}

return;

}

 

void factor() {

if(syn==10||syn==11)

scaner();                //当为标识符或整常数时,读下一个单词符号

else if(syn==27) {       //判断是否有'(' 

scaner();

expression();

if(syn==28)          //判断是否有')' 

scaner();

else {

printf(" ')' error!\n");

k=1;

}

}

else {

printf("表达式错误\n");

k=1;

}

return;

}