钱塘烟雨

长风破浪会有时,直挂云帆济沧海! Free Website Counter 在线人数:

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  24 随笔 :: 0 文章 :: 43 评论 :: 0 引用
 

       针对简单的文法(PASCAL语言子集),制作相应的词法分析器和递归下降的语法分析器。

       文法要求如下:

1、  关键字、标识符、数字等:

1.begin         2.if             3.then         4.while       5.do            6.end          10.标识符           11.数字

13.+             14.-            15.*            16./             17.:             18.:=          20.<                     21.<>

22.<=          23.>           24.>=         25.=           26.;             27.(            28.)

2、  文法规则:

程序 → begin 语句串 end

语句串 → 语句 { ; 语句 }

语句 → 赋值语句 | 条件语句 | 循环语句

赋值语句 → 变量 := 表达式

条件语句 → if 条件 then ( 语句 | 程序 )

循环语句 → while 条件 do ( 语句 | 程序 )

表达式 → 项 { + | - }

条件 → 表达式 关系符 表达式

关系符 → < | <> | <= | > | >= | =

项 → 因子 { * 因子 | / 因子 }

因子 → 变量 | 数字 | ( 表达式 )

变量 → 标识符

一、  词法分析器

词法分析器的任务是清除源文件中多余的空格、换行、制表符等,识别文法符号。按顺序输出识别的标识符及其种别编号,供语法分析器调用。

 

代码如下:

 

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#define BOOL int

#define TRUE 1

#define FALSE 0

#define MAXSIZE 50

 

 

typedef char datatype;

 

typedef struct                              /*定义缓冲队列*/

{

  datatype data[MAXSIZE*2];

  int front,rear;

}Queue;

void setnull(Queue *q)                      /*队列初始化*/

{

  q->front = MAXSIZE*2 - 1;

  q->rear = MAXSIZE*2 - 1;

}

BOOL empty(Queue *q)                   /*判队空*/

{

  if(q->front==q->rear)

       return TRUE;

  return FALSE;

}

BOOL full(Queue *q)                         /*判队满*/

{

  if(q->front == (q->rear+1) % (MAXSIZE*2))

       return TRUE;

  return FALSE;

}

int quantity(Queue *q)                      /*求队列中元素个数*/

{

  int n;

  n = q->rear - q->front;

    if(n<0)

       n += MAXSIZE*2;

  return n;

}

datatype front(Queue *q)               /*取队头元素*/

{

  int n;

  if(empty(q))

       return 0;

  n = (q->front+1) % (MAXSIZE*2);

  return q->data[n];

}

BOOL enqueue(Queue *q,datatype x)      /*入队*/

{

  if(full(q))

       return FALSE;

  q->rear = ++q->rear % (MAXSIZE*2);

  q->data[q->rear]=x;

  return TRUE;

}

datatype dequeue(Queue *q)                  /*出队*/

{

  if(empty(q))

       return 0;

  q->front = ++q->front % (MAXSIZE*2);

  return q->data[q->front];

}

 

char token[MAXSIZE];

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

int syn;

Queue prog;

 

BOOL letter(char ch)                   /*判断是否字母*/

{

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

       return TRUE;

  return FALSE;

}

BOOL digit(char ch)                         /*判断是否数字*/

{

  if(ch>='0'&&ch<='9')

       return TRUE;

  return FALSE;

}

void saner()                                /*扫描器*/

{

  int i;

  char ch;

  for(i=0;i<50;i++)

       token[i]=0;

  i=0;

  do                                        /*去除多余空格、换行及制表符*/

  {

       ch=dequeue(&prog);

  }while(ch==' ' || ch=='\n' || ch=='\t');

  if(letter(ch))                            /*识别标识符(编号10*/

  {

       while(1)

       {

           token[i++]=ch;

           ch=front(&prog);

           if(letter(ch) || digit(ch))

                dequeue(&prog);

           else

                break;

       }

       token[i]='\0';

       syn=10;

       for(i=0;i<6;i++)

           if(!strcmp(token,rwtab[i]))

                syn=i+1;                    /*识别关键字(编号16*/

  }

  else if(digit(ch))                   /*识别无符号整数(编号11*/

  {

       while(1)

       {

           token[i++]=ch;

           ch=front(&prog);

           if(digit(ch))

                dequeue(&prog);

           else

                break;

       }

       token[i]='\0';

       syn=11;

  }

  else

       switch(ch)

       {

       case '#':                        /*识别结束符‘#’(编号0*/

           syn=0;

           token[i++]='#';

           token[i]='\0';

           break;

       case '+':                        /*识别‘+’(编号13*/

           syn=13;

           token[i++]='+';

           token[i]='\0';

           break;

       case '-':                        /*识别‘-’(编号14*/

           syn=14;

           token[i++]='-';

           token[i]='\0';

           break;

       case '*':                        /*识别‘*’(编号15*/

           syn=15;

           token[i++]='*';

           token[i]='\0';

           break;

       case '/':                        /*识别‘/’(编号16*/

           syn=16;

           token[i++]='/';

           token[i]='\0';

           break;

       case ':':

           token[i++]=':';

           ch=front(&prog);

           switch(ch)

           {

           case '=':                   /*识别‘:=’(编号18*/

                syn=18;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*识别‘:’(编号17*/

                syn=17;

                token[i]='\0';

                break;

           }

           break;

       case '<':

           token[i++]='<';

           ch=front(&prog);

           switch(ch)

           {

           case '>':                   /*识别‘<>’(编号21*/

                syn=21;

                token[i++]='>';

                token[i]='\0';

                dequeue(&prog);

                break;

           case '=':                   /*识别‘<=’(编号22*/

                syn=22;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*识别‘<’(编号20*/

                syn=20;

                token[i]='\0';

                break;

           }

           break;

       case '>':

           token[i++]='>';

           ch=front(&prog);

           switch(ch)

           {

           case '=':                   /*识别‘>=’(编号24*/

                syn=24;

                token[i++]='=';

                token[i]='\0';

                dequeue(&prog);

                break;

           default:                    /*识别‘>’(编号23*/

                syn=23;

                token[i]='\0';

                break;

           }

           break;

       case '=':                        /*识别‘=’(编号25*/

           syn=25;

           token[i++]='=';

           token[i]='\0';

           break;

       case ';':                        /*识别‘;’(编号26*/

           syn=26;

           token[i++]=';';

           token[i]='\0';

           break;

       case '(':                        /*识别‘(’(编号27*/

           syn=27;

           token[i++]='(';

           token[i]='\0';

           break;

       case ')':                        /*识别‘)’(编号28*/

           syn=28;

           token[i++]=')';

           token[i]='\0';

           break;

       default:                         /*出错!*/

           syn=-1;

           break;

       }

}

 

main(int argc,char* argv[])

{

  FILE *in,*out;

  int i;