一個詞法分析器原始碼的剖析

一劍平江湖發表於2013-08-04
一,詞法分析器
作用:讀取源程式的輸入字元、將他們組成詞素,生成並輸出一個詞法單元序列
二,設計原理
1)C程式語言的符號分類:關鍵字、識別符號、常數、運算子、界符
2)詞法分析器的二元輸出:<單詞種別,單詞符號屬性值>
3)正規式和狀態轉換圖


4)程式說明:
1>main 中開啟原始碼檔案,從第一個字元流讀取
2>如果第一個是字元,則交給letterprocess(str); 處理
3>如果第一個是數字,則交給numberprocess(str); 處理
4>如果第一個是數字,則交給otherprocess(str);處理
5>注意上述過程中,File *fp每讀取一個詞素,fp都會移動到下一個詞素。對於空格的處理:isspace(ch)檢查引數c是否為空格字元,也就是判斷是否為空格('')、定位字元
  ('\t')、CR('\r')、換行('\n')、垂直定位字元('\v')或翻頁('\f')的情況
這個程式輸出結果情況彙總:關鍵字、算術運算子、關係運算子、分割符號、特殊符號、註釋符號、邏輯運算子、非法符號
三,程式原始碼
Html程式碼  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <ctype.h>  
#include <malloc.h>  
#include <conio.h>  
#define NULL 0  
FILE *fp;  
char ch;  
char *keyword[34]={"auto","break","case","char","const","continue","default","do","double",   
"else","enum","extern","float","for","goto","if","int","long","register",   
"return","short","signed","sizeof","static","struct","switch","typedef", "printf",  
"union","unsigned","void","volatile","while","main"};  
char *operatornum[6]={"+","-","*","/","++","--"};  
char *comparison[8]={"<","<=","=",">",">=","<>","==","!="};  
char *interpunction[8]={",",";",":=",".","(",")","{","}"};  
char *biaoshifu[6]={"%","$","^","&","_","#"};//特殊識別符號  
char *zhushifu[3]={"//","/*","*/"};//註釋符  
char *luoji[3]={"&&","||","!"};//邏輯運算子  
  
  
bool search(char searchstr[],int wordtype)//符號匹配   
{  
    int i;  
    switch (wordtype)  
    {  
        case 1:  
            for(i=0;i<=33;i++)  
            {  
                if(strcmp(keyword[i],searchstr)==0)  
                return(true);  
            }  
            break;  
        case 2:  
            for(i=0;i<=5;i++)  
            {  
                if(strcmp(operatornum[i],searchstr)==0)  
                return(true);  
            }  
         break;  
              
        case 3:   
            for(i=0;i<=7;i++)  
            {  
             if(strcmp(comparison[i],searchstr)==0)  
                return(true);  
            }  
            break;  
     
        case 4:   
            for(i=0;i<=7;i++)  
            {  
                if(strcmp(interpunction[i],searchstr)==0)  
                return(true);  
            }  
    
            break;  
        case 5:   
            for(i=0;i<=5;i++)  
            {  
                if(strcmp(biaoshifu[i],searchstr)==0)  
                    return(true);  
            }  
            break;  
        case 6:  
             for(i=0;i<=2;i++)  
             {  
                if(strcmp(zhushifu[i],searchstr)==0)  
                    return(true);  
            }  
            break;  
        case 7:   
            for(i=0;i<=2;i++)  
            {  
                if(strcmp(luoji[i],searchstr)==0)  
                    return(true);  
            }  
        break;  
    }  
  
    return false;  
}  
  
char letterprocess (char ch)//字母處理函式  
{  
    int i=-1;  
    char letter[20];  
    while (isalnum(ch)!=0)  
    {  
        letter[++i]=ch;  
        ch=fgetc(fp);  
    }  
    letter[i+1]='\0';  
    if (search(letter,1))  
    {  
        printf("<%s,關鍵字>\n",letter);  
        //strcat(letter,"\n");  
        //fputs('<' letter '>\n',outp);  
    }  
    else  
    {  
        printf("<%s,自定義變數>\n",letter);  
        //strcat(letter,"\n");  
        //fputs(letter,outp);  
    }  
  
    return(ch);  
}  
  
char numberprocess(char ch)//數字處理程式  
{  
    int i=-1;  
    char num[20];  
    while (isdigit(ch)!=0)  
    {  
        num[++i]=ch;  
        ch=fgetc(fp);  
    }  
    if(isalpha(ch)!=0)//數字後面是字元   
    {  
        while(isspace(ch)==0)  
        {  
            num[++i]=ch;  
            ch=fgetc(fp);  
        }  
        num[i+1]='\0';  
        printf("錯誤!非法識別符號:%s\n",num);  
    goto u;  
    }  
    num[i+1]='\0';  
    printf("<%s,數字>\n",num);  
  
    u: return(ch);  
}  
  
char otherprocess(char ch)//其他處理程式   
{  
    int i=-1;  
    char other[20];  
    if (isspace(ch)!=0)  
    {  
        ch=fgetc(fp);  
        goto u;  
    }  
    while ((isspace(ch)==0)&&(isalnum(ch)==0))  
    {  
        other[++i]=ch;  
        ch=fgetc(fp);  
    }  
    other[i+1]='\0';  
    if (search(other,2))  
        printf("<%s,算數運算子>\n",other);  
    else if (search(other,3))  
        printf("<%s,關係運算子號>\n",other);  
    else if (search(other,4))  
        printf("<%s,分隔符號>\n",other);  
    else if (search(other,5))  
        printf("<%s,特殊識別符號號>\n",other);  
    else if (search(other,6))  
        printf("<%s,註釋符號>\n",other);  
    else if (search(other,7))  
        printf("<%s,邏輯運算子號>\n",other);  
    else   
        printf("錯誤!非法字元:%s\n",other);  
    u: return (ch);  
}  
  
int main ()  
{  
    char str;  
    printf("**********************************詞法分析器************************************\n");  
    if ((fp=fopen("源程式.txt","r"))==NULL)  
        printf("源程式無法開啟!\n");  
    else  
    {  
        str =fgetc(fp);//從流中讀取字元   
        while (str!=EOF)  
        {  
            if (isalpha(str)!=0)//如果是字元    isalpha包含在#include <cctype>  
                str=letterprocess(str);  
            else  
            {  
                if (isdigit(str)!=0)  
                    str=numberprocess(str);  
                else  
                    str=otherprocess(str);  
            }  
      
        };  
     printf("詞法分析結束,謝謝使用!\n");  
     //printf("點任意鍵退出!\n");  
   }  
   //c=getch();  
     
   return 0;  
}  

相關文章