PASCAL語言子集的詞法、語法分析器之實現

 

       針對簡單的文法(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 ( 語句 | 程序 )

表達式 → 項 { + | - }

條件 → 表達式 關係符 表達式

關係符 → < | <> | <= | > | >= | =

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

因子 → 變量 | 數字 | ( 表達式 )

變量 → 標識符

一、  詞法分析器

詞法分析器的任務是清除源文件中多餘的空格、換行、製表符等,識別文法符號。按順序輸出識別的標識符及其種別編號,供語法分析器調用。%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86%E5%AE%9E%E9%AA%8C%E6%8A%A5%E5%91%8A.jpg

 

代碼如下:

 

#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*/

        &bsp;     }

           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;

       }

}

<體';" xml:lang="en-us">           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[])

case '(':                        /*識別‘(’(編號27*/

syn=27;

相關文章
相關標籤/搜索