閱讀124 返回首頁    go 阿裏雲 go 技術社區[雲棲]


實驗一  簡單詞法分析程序設計


 

 

 

 

 

 

實驗一  簡單詞法分析程序設計

 

一、實驗目的

了解詞法分析程序的基本構造原理,掌握詞法分析程序的手工構造方法。

二、實驗內容

1、了解編譯程序的詞法分析過程。

2根據PASCAL語言的說明語句形式,用手工方法構造一個對說明語句進行詞法分析的程序。該程序能對從鍵盤輸入或從文件讀入的形如:

const count=10,sum=81.5,char1=’f’,string1=”hj”, max=169

的常量說明串進行處理,分析常量說明串中各常量名、常量類型及常量值,並統計各種類型常量個數。

三、實驗要求

1、輸入的常量說明串,要求最後以分號作結束標誌;

2、根據輸入串或讀入的文本文件中第一個單詞是否為“const”判斷輸入串或文本文件是否為常量說明內容;

3、識別輸入串或打開的文本文件中的常量名。常量名必須是標識符,定義為字母開頭,後跟若幹個字母,數字或下劃線;

4、根據各常量名緊跟等號“=”後麵的內容判斷常量的類型。其中:字符型常量定義為放在單引號內的一個字符;字符串常量定義為放在雙引號內所有內容;整型常量定義為帶或不帶+- 號,不以0開頭的若幹數字的組合;實型常量定義為帶或不帶+- 號,不以0開頭的若幹數字加上小數點再後跟若幹數字的組合;

5、統計並輸出串或文件中包含的各種類型的常量個數;

6、以二元組(類型,)的形式輸出各常量的類型和值;

7、根據常量說明串置於高級語言源程序中時可能出現的錯誤情況,模仿高級語言編譯器對不同錯誤情況做出相應處理。

四、運行結果

1、輸入如下正確的常量說明串:

const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4S!AAsj, char2=‘@’,str2=“aa!+h”;

輸出:

count(integer,10)

sum(float,81.5)

char1(char, ‘f’)

max(integer,169)

str1(string,“h*54  2..4S!AAsj)

char2(char, ‘@’)

str2(string,“aa!+h)

 

int_num=2;  char_num=2; string_num=2; float_num=1.

2、輸入類似如下的保留字const錯誤的常量說明串:

Aconstt count=10,sum=81.5,char1=‘f’;

輸出類似下麵的錯誤提示信息:

It is not a constant declaration statement!

Please input a string again!

3、輸入類似如下含常量名或常量值錯誤的常量說明串:

const count=10,12sum=81.5,char1=‘ff’,max=0016

輸出類似下麵的錯誤提示信息:

count(integer,10)

12sum(Wrong! It is not a identifier!)

char1(Wrong! There are  more than one char in ‘’.)

max(Wrong! The integer can’t be started with ‘0’.)

int_num=1;  char_num=0; string_num=0; float_num=0.

4、其他類型的錯誤處理情況(略)。

五、提示

本實驗重點有三個:一是作為常量名的標識符的識別;二是如何根據“=”後出現的內容來判斷常量類型;三是對各種錯誤的處理。難點是對整型和實型常量的判斷必須綜合考慮多種可能情況。

建議:1、用指針或數組與指針相結合來處理輸入的常量說明串2對整型和實型常量處理時,重點考慮常數中‘0’的位置。

六、分析與討論

1、若考慮用Ee的科學計數法來表示整數和實數,應該如何實現?

2、若考慮布爾型常量,且規定其值隻能為truefalse,應該如何實現?

3、如何對手工構造的詞法分析程序做進一步的優化,以提高代碼質量和運行效率?


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

 

#define  N 80
#define  M 16

void check_const();
void measure_iden();
void measure_string();
void measure_digit();
void measure_char();


char cha;

int ci=0,cf=0,cc=0,cs=0;

char *p0,*t0,*p1,*t1, *p2,*str,*p3,*t3="const",*digi,*flo;

void main()
{

 printf("Please input string: \n");


 p0=(char *)malloc(N*sizeof(char));
 p1=(char *)malloc(M*sizeof(char));
 p2=(char *)malloc(M*sizeof(char));
 p3=(char *)malloc(M*sizeof(char));
 
 gets(p0);
 printf("\n");
 check_const();
 
/* 開始處理輸入串 p0  */
 while(*(p0)==' '||*(p0)==',')  /*從串p0中取標識符,並將其作為常量名存放到串p1中 */
    {
  p0++;
  if(*(p0)==' '||*(p0)==',')
   continue;
  else
  {
  measure_iden();      //*p0=="="
  if(!isdigit(*p0)&&*p0!='\"'&&*p0!='\'')//注意'和"做字符表示時用\'和\"
  {
   system("cls");
   printf("\n Const data is wrong . Exit !");
   exit(0);
     }
  else if(*p0=='\"')   /* 處理字符串常量 */
  { 
   p0++;
   measure_string();
  }
  else if(isdigit(*p0))  /* 處理數字 */
  {
   measure_digit();
  }
  else if(*p0=='\'') //處理字符常量
  {
   p0++;
   measure_char();
  }
 }
 }
 if(*p0!=';')
 {
  system("cls");
  printf("\n This centence is wrong . Exit !");
  exit(0);
 }
 else
 {
  printf("int_num=%d;  char_num=%d; string_num=%d; float_num=%d.\n",ci,cc,cs,cf);
 }
}


/*    檢查輸入串是否以"'const"開頭   */
void check_const()
{
 while(*p0!=' ') 
 {
  if(*p0==*t3)
  {
   p0++;
   t3++;
  }
  else
  {
   printf("This string isn't a const declaration!");
   exit(0);
  }
 }
}


void measure_iden()
{
 if (*p0!='_'&&(!isalpha(*p0)))
 {
  system("cls");
  printf("\n Const name is wrong . Exit !");
  exit(0);
    }
 else if (*p0=='_'||isalpha(*p0))
 {
  t1=p1;
  while(*p0!='=')
  {
   *p1=*p0;
   p0++;
   p1++;
  }
  *p1='\0';
//  printf("%s\n",p0);
  p0++;
 }
 printf("%s",t1);
}


void measure_string()
{
 str=p2; 
 while(*(p0)!='\"')
 {
  *p2=*p0;
  if(*(p0)==';')//丟了個分號,直接輸出String  data is wrong. Exit
  {
   system("cls");
   printf("\n String  data is wrong. Exit !");
   exit(0);
  }
  p0++;
  p2++;
 }
 *p2='\0';
 p0++;
 cs++;
 printf("(string,\"%s\")\n",str);
}

 


void measure_digit()
{
 char *jud;
 int mark=0;
 jud=p0;
   
 for(;*(jud)!=','&&*(jud)!=';';jud++)
 {
  if(*jud=='.')
  {
   mark=1;
   break;
  }
 }
 if(mark==0)
 {
  digi=p2;
  while(*p0!=','&&*p0!=';')
  {

   *p2=*p0;
   p0++;
   p2++;
  }
  *p2='\0';
  ci++;
  printf("(integer,%s)\n",digi);
 }
 if(mark==1)
 {
  flo=p2;
  while(*p0!=','&&*p0!=';')
  {
   *p2=*p0;
   p0++;
   p2++;
  }
  *p2='\0';
  cf++;
  printf("(float,%s)\n",flo);
 }
}

 

void measure_char()
{
 char *jud;
 jud=p0;
 if(*(jud+1)=='\''&&*(jud)!='\'')
 {
  cha=*p0;
  p0=p0+2;
  cc++;
 }
 else
 {
  system("cls");
  printf("\n char data is wrong. Exit !");
  exit(0);
 }
 printf("(char,'%c')\n",cha);
}

 

 

 

最後更新:2017-04-03 20:19:53

  上一篇:go 龍格庫塔C 語言編程實現
  下一篇:go Ubuntu 13.04 的 10 個最佳新特性