一個詞法分析器原始碼的剖析
一,詞法分析器
作用:讀取源程式的輸入字元、將他們組成詞素,生成並輸出一個詞法單元序列
二,設計原理
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;
}
作用:讀取源程式的輸入字元、將他們組成詞素,生成並輸出一個詞法單元序列
二,設計原理
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;
}
相關文章
- 詞法分析器詞法分析
- Lex詞法分析器詞法分析
- 實現指令碼直譯器 - 詞法分析器指令碼詞法分析
- Monkey 01 lexer 詞法分析器詞法分析
- 【編譯原理】手工打造詞法分析器編譯原理詞法分析
- 用Python實現 詞法分析器(Lexical Analyzer)Python詞法分析
- Kafka 原始碼剖析(一)Kafka原始碼
- Flutter 原始碼剖析(一)Flutter原始碼
- vue原始碼剖析(一)Vue原始碼
- Java集合原始碼剖析——ArrayList原始碼剖析Java原始碼
- C++原始碼單詞掃描程式(詞法分析)C++原始碼詞法分析
- Hanlp自然語言處理工具之詞法分析器HanLP自然語言處理詞法分析
- 剖析 React 原始碼:render 流程(一)React原始碼
- Spring原始碼剖析9:Spring事務原始碼剖析Spring原始碼
- 【水汐の編譯原理】 詞法分析器 課題1編譯原理詞法分析
- Flutter原始碼剖析(一):原始碼獲取與構建Flutter原始碼
- PHP-7.1 原始碼學習:詞法分析PHP原始碼詞法分析
- Shading-jdbc原始碼分析-sql詞法解析JDBC原始碼SQL
- YYCache 原始碼剖析:一覽亮點原始碼
- Kubernetes: client-go 原始碼剖析(一)clientGo原始碼
- 編譯器前端之如何實現基於DFA的詞法分析器編譯前端詞法分析
- epoll–原始碼剖析原始碼
- Thread原始碼剖析thread原始碼
- Handler原始碼剖析原始碼
- HashMap原始碼剖析HashMap原始碼
- 一個分詞指令碼分詞指令碼
- 我的原始碼閱讀之路:redux原始碼剖析原始碼Redux
- Graphx 原始碼剖析-圖的生成原始碼
- 全面剖析 Redux 原始碼Redux原始碼
- 深入剖析LinkedList原始碼原始碼
- Java LinkedList 原始碼剖析Java原始碼
- Ohcount:原始碼行計數器和分析器原始碼
- PostgreSQL 原始碼解讀(167)- 查詢#87(基礎知識-語法分析器Bison)SQL原始碼語法分析
- jQuery 原始碼剖析(一) - 核心功能函式jQuery原始碼函式
- Python物件初探(《Python原始碼剖析》筆記一)Python物件原始碼筆記
- OC原始碼剖析物件的本質原始碼物件
- 漢語言處理包HanLPv1.6.0釋出,感知機詞法分析器HanLP詞法分析
- spark核心原始碼深度剖析Spark原始碼
- STL原始碼剖析——vector容器原始碼