詞法分析器編譯原理
A. 編譯器有哪幾部分構成.編譯原理
1. 詞法分析
詞法分析器根據詞法規則識別出源程序
中的各個記號(token),每個記號代表一類單詞(lexeme)。源程序中常見的記號可以歸為幾大類:關鍵字、標識符、字面量和特殊符號。詞法分析器
的輸入是源程序,輸出是識別的記號流。詞法分析器的任務是把源文件的字元流轉換成記號流。本質上它查看連續的字元然後把它們識別為「單詞」。
2. 語法分析
語法分析器根據語法規則識別出記號流中的結構(短語、句子),並構造一棵能夠正確反映該結構的語法樹。
3. 語義分析
語義分析器根據語義規則對語法樹中的語法單元進行靜態語義檢查,如果類型檢查和轉換等,其目的在於保證語法正確的結構在語義上也是合法的。
4. 中間代碼生成
中間代碼生成器根據語義分析器的輸出生成中間代碼。中間代碼可以有若干種形式,它們的共同特徵是與具體機器無關。最常用的一種中間代碼是三地址碼,它的一種實現方式是四元式。三地址碼的優點是便於閱讀、便於優化。
B. 怎樣較容易理解編譯原理中詞法分析的原理即實現過程,最好配上圖文解說
詞法分析的本質是讓計算機程序理解詞法規則。例如,在我們平時用的語言里,「你」是指一個人,當「你們」出現的時候就是一個詞是指多個人,這就是一種規則,但是是人能理解的規則,詞法分析要用數學的表達方式讓計算機理解,計算機的做法是對每個遇到的字先判斷是不是「你」,如果不是,那麼不符合這條規則;如果是,就要記下現在這個狀態---即已經看到一個「你」字,然後判斷下一個字是不是「們」,是則這條規則成立,也就是讓計算機理解了這一個詞,而不是單個的兩個字。詞法分析不是編譯原理才有的,在搜索、數據挖掘等領域都用到。編譯原理中的詞法分析就是把源程序中的字元按順序一個一個輸入給計算機,計算機對每個字元按照所有規則進行判斷,例如輸入了一個「a」,要判斷它是不是「and「的開頭,是不是一個變數名,函數名,還是字元串等等,每個可能性都是一條規則決定的。根據規則的復雜性,可以用多種數學方法描述,比如基本的方法是狀態機、正則表達式。
C. 編譯原理 詞法分析器的問題
#include <iostream>
#include <vector>
#include <utility>
#include <string>
#include <fstream>
#include <algorithm>
#include <cstdlib>
using namespace std;
//用來存儲目標文件名
string file_name;
//提取文本文件中的信息。
string GetText();
//獲得一個單詞符號,從位置i開始查找。
//並且有一個引用參數j,用來返回這個單詞最後一個字元在str的位置。
string GetWord(string str,int i,int& j);
//這個函數用來除去字元串中連續的空格和換行
//第一個參數為目標字元串,第二個參數為開始位置
//返回值為連續的空格和換行後的第一個有效字元在字元串的位置
int DeleteNull(string str,int i);
//判斷i當前所指的字元是否為一個分界符,是的話返回真,反之假
bool IsBoundary(string str,int i);
//判斷i當前所指的字元是否為一個運算符,是的話返回真,反之假
bool IsOperation(string str,int i);
//此函數將一個pair數組輸出到一個文件中
void OutFile(vector<pair<int,string> > v);
//此函數接受一個字元串數組,對它進行詞法分析,返回一個pair型數組
vector<pair<int,string> > analyst(vector<string> vec);
//此函數判斷傳遞的參數是否為關鍵字,是的話,返回真,反之返回假
bool IsKey(string str);
int main()
{
cout<<"###########################\n";
cout<<"###right: Giftedbird###\n";
cout<<"###########################\n";
string com1=" ";
string com2="\n";
string fileline=GetText();
int begin=0,end=0;
vector<string> array;
do
{
begin=DeleteNull(fileline,begin);
string nowString;
nowString=GetWord(fileline,begin,end);
if(end==-1)
break;
if(nowString.compare(com1)&&nowString.compare(com2))
array.push_back(nowString);
begin=end+1;
}while(true);
vector<pair<int,string> > mid_result;
mid_result=analyst(array);
OutFile(mid_result);
cout<<"**********************************************************************\n";
cout<<"***程序已完成詞法分析,分析結果已經存儲在文件"<<file_name<<"中!!!***\n";
cout<<"**********************************************************************\n";
system("pause");
return 0;
}
//提取文本文件中的信息
string GetText()
{
string file_name1;
cout<<"請輸入源文件名(包括路徑和後綴名):";
cin>>file_name1;
ifstream infile(file_name1.c_str(),ios::in);
if (!infile)
{
cerr<<"哦!無法打開文件 "<<file_name1.c_str()<<" !!!"<<endl;
exit(-1);
}
cout<<endl;
char f[1000];
infile.getline(f,1000,EOF);
infile.close();
return f;
}
//獲得一個單詞符號,從位置i開始查找。
//並且有一個引用參數j,用來返回這個單詞最後一個字元在原字元串的位置。
string GetWord(string str,int i,int& j)
{
string no_use("(){} , ; \n+=*/-<>\"");
j=str.find_first_of(no_use,i);
if(j==-1)
return "";
if(i!=j)
j--;
return str.substr(i,j-i+1);
}
//這個函數用來除去字元串中連續的空格和換行
//第一個參數為目標字元串,第二個參數為開始位置
//返回值為連續的空格和換行後的第一個有效字元在字元串的位置
int DeleteNull(string str,int i)
{
for(;;i++)
if(str[i]!=' '&&str[i]!='\n')
return i;
}
//判斷i當前所指的字元是否為一個分界符,是的話返回真,反之假
bool IsBoundary(string str,int i)
{
int t;
char arr[7]={',',';','{','}','(',')','\"'};
for (t=0;t<7;t++)
if(str[i]==arr[t])
return true;
return false;
}
//判斷i當前所指的字元是否為一個運算符,是的話返回真,反之假
bool IsOperation(string str,int i)
{
int t;
char arr[7]={'+','-','*','/','=','<','>'};
for (t=0;t<7;t++)
if(str[i]==arr[t])
return true;
return false;
}
//此函數將一個個字元串數組輸出到一個文件中
void OutFile(vector<pair<int,string> > v)
{
cout<<"請輸入目標文件名(包括路徑和後綴名):";
cin>>file_name;
ofstream outfile(file_name.c_str(),ios::out);
if (!outfile)
{
cerr<<"哦!無法打開文件 "<<file_name.c_str()<<" !!!"<<endl;
exit(-1);
}
cout<<endl;
int i;
outfile<<"###########################\n";
outfile<<"###right: Giftedbird###\n";
outfile<<"###########################\n\n";
for(i=0;i<v.size();i++)
outfile<<"<"<<v[i].first<<" , \""<<v[i].second<<"\">"<<endl;
outfile<<"\n\n*********************************\n";
outfile.close();
return;
}
//此函數接受一個字元串數組,對它進行詞法分析,返回一個pair型數組
vector<pair<int,string> > analyst(vector<string> vec)
{
vector<pair<int,string> > temp;
int i;
for(i=0;i<vec.size();i++)
{
if(vec[i].size()==1)
{
if((vec[i]==">"||vec[i]=="<"||vec[i]=="!")&&vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair<int,string> pp(4,jk);
temp.push_back(pp);
continue;
}
if((vec[i]=="+"&&vec[i+1]=="+")||(vec[i]=="-"&&vec[i+1]=="-"))
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair<int,string> pp(4,jk);
temp.push_back(pp);
continue;
}
if(IsBoundary(vec[i],0))
{
pair<int,string> pp(5,vec[i]);
temp.push_back(pp);
}
else if(IsOperation(vec[i],0))
{
pair<int,string> pp(4,vec[i]);
temp.push_back(pp);
}
else if(vec[i][0]<='9'&&vec[i][0]>='0')
{
pair<int,string> pp(3,vec[i]);
temp.push_back(pp);
}
else
{
pair<int,string> pp(2,vec[i]);
temp.push_back(pp);
}
}
else if(vec[i][0]<='9'&&vec[i][0]>='0')
{
pair<int,string> pp(3,vec[i]);
temp.push_back(pp);
}
else if(IsKey(vec[i]))
{
pair<int,string> pp(1,vec[i]);
temp.push_back(pp);
}
else
{
pair<int,string> pp(2,vec[i]);
temp.push_back(pp);
}
}
return temp;
}
//此函數判斷傳遞的參數是否為關鍵字,是的話,返回真,反之返回假
bool IsKey(string str)
{
string p[16]={"char","double","int","long","double","float","for","while","do","break","continue","switch","short","case","return","if"};
vector<string> ppp(p,p+16);
int u;
for(u=0;u<ppp.size();u++)
if(!str.compare(ppp[u]))
return true;
return false;
}
//finished
D. 編譯原理詞法分析器
用C++語言
#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);
}
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);
//strcat(num,"\n");
//fputs(num,outp);
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);
}
/////////////////////////////////////////////////////////////////////////////////////////////
void main ()
{
char str,c;
printf("**********************************詞法分析器************************************\n");
//outp=fopen("二元式表.txt","w");
if ((fp=fopen("源程序.txt","r"))==NULL)
printf("源程序無法打開!\n");
else
{
str =fgetc(fp);
while (str!=EOF)
{
if (isalpha(str)!=0)
str=letterprocess(str);
else
{
if (isdigit(str)!=0)
str=numberprocess(str);
else
str=otherprocess(str);
}
};
printf("詞法分析結束,謝謝使用!\n");
printf("點任意鍵退出!\n");
}
c=getch();
}
E. 編譯原理的詞法分析器的原理......
將文件讀入內存中
然後從首字元開始分析,匹配規則一般是採用自動機,以語句
int
a
=
12;為例
首先從字元i開始
每次取一個單詞
即從一個非空白字元開始
到下一個空白字元出現為止
為一個單詞
先
看看
該單詞是不是關鍵字
如看看是不是if
是不是int
都不是的話
則將其當做
字元標記
依此類推
F. 編譯原理中詞法分析和語法分析的任務分別是什麼
在編譯原理中,語法規則和詞法規則不同之處在於:規則主要識別單詞,而語法主要識別多個單片語成的句子。
詞法分析和詞法分析程序:
詞法分析階段是編譯過程的第一個階段。這個階段的任務是從左到右一個字元一個字元地讀入源程序,即對構成源程序的字元流進行掃描然後根據構詞規則識別單詞(也稱單詞符號或符號)。詞法分析程序實現這個任務。詞法分析程序可以使用lex等工具自動生成。
語法分析(Syntax analysis或Parsing)和語法分析程序(Parser)
語法分析是編譯過程的一個邏輯階段。語法分析的任務是在詞法分析的基礎上將單詞序列組合成各類語法短語,如「程序」,「語句」,「表達式」等等.語法分析程序判斷源程序在結構上是否正確.源程序的結構由上下文無關文法描述.
語義分析(Syntax analysis)
語義分析是編譯過程的一個邏輯階段. 語義分析的任務是對結構上正確的源程序進行上下文有關性質的審查, 進行類型審查.語義分析將審查類型並報告錯誤:不能在表達式中使用一個數組變數,賦值語句的右端和左端的類型不匹配.
G. 編譯原理
編譯原理是計算機專業的一門重要專業課,旨在介紹編譯程序構造的一般原理和基本方法。內容包括語言和文法、詞法分析、語法分析、語法制導翻譯、中間代碼生成、存儲管理、代碼優化和目標代碼生成。 編譯原理是計算機專業設置的一門重要的專業課程。編譯原理課程是計算機相關專業學生的必修課程和高等學校培養計算機專業人才的基礎及核心課程,同時也是計算機專業課程中最難及最挑戰學習能力的課程之一。編譯原理課程內容主要是原理性質,高度抽象[1]。
中文名
編譯原理[1]
外文名
Compilers: Principles, Techniques, and Tools[1]
領域
計算機專業的一門重要專業課[1]
快速
導航
編譯器
編譯原理課程
編譯技術的發展
編譯的基本流程
編譯過程概述
基本概念
編譯原理即是對高級程序語言進行翻譯的一門科學技術, 我們都知道計算機程序由程序語言編寫而成, 在早期計算機程序語言發展較為緩慢, 因為計算機存儲的數據和執行的程序都是由0、1代碼組合而成的, 那麼在早期程序員編寫計算機程序時必須十分了解計算機的底層指令代碼通過將這些微程序指令組合排列從而完成一個特定功能的程序, 這就對程序員的要求非常高了。人們一直在研究如何如何高效的開發計算機程序, 使編程的門檻降低。[2]
編譯器
C語言編譯器是一種現代化的設備, 其需要藉助計算機編譯程序, C語言編譯器的設計是一項專業性比較強的工作, 設計人員需要考慮計算機程序繁瑣的設計流程, 還要考慮計算機用戶的需求。計算機的種類在不斷增加, 所以, 在對C語言編譯器進行設計時, 一定要增加其適用性。C語言具有較強的處理能力, 其屬於結構化語言, 而且在計算機系統維護中應用比較多, C語言具有高效率的優點, 在其不同類型的計算機中應用比較多。[3]
C語言編譯器前端設計
編譯過程一般是在計算機系統中實現的, 是將源代碼轉化為計算機通用語言的過程。編譯器中包含入口點的地址、名稱以及機器代碼。編譯器是計算機程序中應用比較多的工具, 在對編譯器進行前端設計時, 一定要充分考慮影響因素, 還要對詞法、語法、語義進行分析。[3]
1 詞法分析[3]
詞法分析是編譯器前端設計的基礎階段, 在這一階段, 編譯器會根據設定的語法規則, 對源程序進行標記, 在標記的過程中, 每一處記號都代表著一類單詞, 在做記號的過程中, 主要有標識符、關鍵字、特殊符號等類型, 編譯器中包含詞法分析器、輸入源程序、輸出識別記號符, 利用這些功能可以將字型大小轉化為熟悉的單詞。[3]
2 語法分析[3]
語法分析是指利用設定的語法規則, 對記號中的結構進行標識, 這包括句子、短語等方式, 在標識的過程中, 可以形成特殊的結構語法樹。語法分析對編譯器功能的發揮有著重要影響, 在設計的過程中, 一定要保證標識的准確性。[3]
3 語義分析[3]
語義分析也需要藉助語法規則, 在對語法單元的靜態語義進行檢查時, 要保證語法規則設定的准確性。在對詞法或者語法進行轉化時, 一定要保證語法結構設置的合法性。在對語法、詞法進行檢查時, 語法結構設定不合理, 則會出現編譯錯誤的問題。前端設計對精確性要求比較好, 設計人員能夠要做好校對工作, 這會影響到編譯的准確性, 如果前端設計存在失誤, 則會影響C語言編譯的效果。[3]