編譯原理中詞法分析程序
⑴ 求 編譯原理 語法分析程序
可以參考我的空間,我在三年前寫過類似代碼。
http://hi..com/逄韶華/ihome/myblog
⑵ 編譯原理中詞法分析和語法分析的任務分別是什麼
在編譯原理中,語法規則和詞法規則不同之處在於:規則主要識別單詞,而語法主要識別多個單片語成的句子。
詞法分析和詞法分析程序:
詞法分析階段是編譯過程的第一個階段。這個階段的任務是從左到右一個字元一個字元地讀入源程序,即對構成源程序的字元流進行掃描然後根據構詞規則識別單詞(也稱單詞符號或符號)。詞法分析程序實現這個任務。詞法分析程序可以使用lex等工具自動生成。
語法分析(Syntax analysis或Parsing)和語法分析程序(Parser)
語法分析是編譯過程的一個邏輯階段。語法分析的任務是在詞法分析的基礎上將單詞序列組合成各類語法短語,如「程序」,「語句」,「表達式」等等.語法分析程序判斷源程序在結構上是否正確.源程序的結構由上下文無關文法描述.
語義分析(Syntax analysis)
語義分析是編譯過程的一個邏輯階段. 語義分析的任務是對結構上正確的源程序進行上下文有關性質的審查, 進行類型審查.語義分析將審查類型並報告錯誤:不能在表達式中使用一個數組變數,賦值語句的右端和左端的類型不匹配.
⑶ 編譯原理語法分析器程序
#include #include #include #include #include using namespace std; struct Node1 { char vn; char vt; char s[10]; }MAP[20];//存儲分析預測表每個位置對應的終結符,非終結符,產生式 int k; //用R代表E',W代表T',e代表空 char G[10][10]={"...
⑷ 如何通俗易懂地解釋編譯原理中語法分析的過程
語法分析(Syntax analysis或Parsing)和語法分析程序(Parser)
語法分析是編譯過程的一個邏輯階段。語法分析的任務是在詞法分析的基礎上將單詞序列組合成各類語法短語,如「程序」,「語句」,「表達式」等等.語法分析程序判斷源程序在結構上是否正確.源程序的結構由上下文無關文法描述.
⑸ 求C語言編譯原理語法分析程序
一繼承的詞法來自
http://blog.sina.com.cn/s/blog_67c9fc300100srad.html
二語法
用擴充的BNF表示如下:
⑴<程序>::=begin<語句串>end
⑵<語句串>::=<語句>{;<語句>}
⑶<語句>::=<賦值語句>
⑷<賦值語句>::=ID:=<表達式>
⑸<表達式>::=<項>{+<項> | -<項>}
⑹<項>::=<因子>{*<因子> | /<因子>
⑺<因子>::=ID | NUM | (<表達式>)
三要求
輸入單詞串,以「#」結束,如果是文法正確的句子,則輸出成功信息,列印「success」,否則輸出「error」。
例如:
輸入 begin a:=9; x:=2*3; b:=a+x end #
輸出 success!
輸入 x:=a+b*c end #
輸出 error!
⑹ 編譯原理語法分析器程序,用C語言或C++
你可以去看看《高級編譯器設計與實現(Steven.S.Muchnick).(中文版)》。
⑺ 怎樣較容易理解編譯原理中詞法分析的原理即實現過程,最好配上圖文解說
詞法分析的本質是讓計算機程序理解詞法規則。例如,在我們平時用的語言里,「你」是指一個人,當「你們」出現的時候就是一個詞是指多個人,這就是一種規則,但是是人能理解的規則,詞法分析要用數學的表達方式讓計算機理解,計算機的做法是對每個遇到的字先判斷是不是「你」,如果不是,那麼不符合這條規則;如果是,就要記下現在這個狀態---即已經看到一個「你」字,然後判斷下一個字是不是「們」,是則這條規則成立,也就是讓計算機理解了這一個詞,而不是單個的兩個字。詞法分析不是編譯原理才有的,在搜索、數據挖掘等領域都用到。編譯原理中的詞法分析就是把源程序中的字元按順序一個一個輸入給計算機,計算機對每個字元按照所有規則進行判斷,例如輸入了一個「a」,要判斷它是不是「and「的開頭,是不是一個變數名,函數名,還是字元串等等,每個可能性都是一條規則決定的。根據規則的復雜性,可以用多種數學方法描述,比如基本的方法是狀態機、正則表達式。
⑻ 編譯原理詞法分析程序
(一)Block子程序分析
procere enter(k: object1); //填寫符號表
begin {enter object into table}
tx := tx + 1; //下標加1,tx的初始值為零,零下標不地址不填寫標志符,用於查找失敗使用
with table[tx] do //填入內容,保存標志符名和類型
begin name := id; kind := k;
case k of //根據類型判斷是否正確
constant: begin if num > amax then //如果是常量,判斷是否大於最大值,若是則報30號錯
begin error(30); num :=0 end;
val := num //否則保存數值
end;
varible: begin level := lev; adr := dx; dx := dx + 1; //如果是變數,填寫變數內部表示,LEVEl是變數的層次,adr為地址
end;
proc: level := lev //如果是過程,保存過程的層次
end
end
end {enter};
//查找符號表的位置
function position(id: alfa): integer;
var i: integer;
begin {find indentifier id in table} //從後向前查找
table[0].name := id; i := tx; //找到保存類型
while table[i].name <> id do i := i-1;
position := i //返回標志符在符號表中的位置
end {position};
procere block(lev,tx: integer; fsys: symset);
var dx: integer; {data allocation index} //數據分配索引
tx0: integer; {initial table index} //初始符號表索引
cx0: integer; {initial code index} //初始代碼索引
procere enter(k: object1); //填寫符號表,下次分析
begin {enter object into table}
tx := tx + 1;
with table[tx] do
begin name := id; kind := k;
case k of
constant: begin if num > amax then
begin error(30); num :=0 end;
val := num
end;
varible: begin level := lev; adr := dx; dx := dx + 1;
end;
proc: level := lev
end
end
end {enter};
function position(id: alfa): integer; //查找符號表,下次分析
var i: integer;
begin {find indentifier id in table}
table[0].name := id; i := tx;
while table[i].name <> id do i := i-1;
position := i
end {position};
procere constdeclaration; //常量聲明
begin if sym = ident then //如果是標志符,讀入一個TOKEN
begin getsym;
if sym in [eql, becomes] then //讀入的是等號或符值號繼續判斷
begin if sym = becomes then error(1); //如果是「=」報1號錯
getsym; //讀入下一個TOKEN
if sym = number then //讀入的是數字,填寫符號表
begin enter(constant); getsym
end
else error(2) //如果不是數字,報2號錯
end else error(3) //不是等號或符值號,報3號錯
end else error(4) //如果不是標志符,報4號錯
end {constdeclaration};
procere vardeclaration; //變數聲明
begin if sym = ident then //讀入的是標志符,填寫符號表
begin enter(varible); getsym
end else error(4) //不是標志符,報4號錯
end {vardeclaration};
procere listcode;
var i: integer;
begin {list code generated for this block}
for i := cx0 to cx-1 do
with code[i] do
writeln(i:5, mnemonic[f]:5, 1:3, a:5)
end {listcode};
procere statement(fsys: symset);
var i, cx1, cx2: integer;
procere expression(fsys: symset); //表達式分析
var addop: symbol;
procere term(fsys: symset); //項分析
var mulop: symbol;
procere factor(fsys: symset); //因子分析
var i: integer;
begin test(facbegsys, fsys, 24); //讀入的是「(」,標志符或數字
while sym in facbegsys do
begin
if sym = ident then //是標志符,查表
begin i:= position(id);
if i = 0 then error(11) else //未找到,報11號錯
with table[i] do //找到,讀入標志符類型
case kind of
constant: gen(lit, 0, val); //寫常量命令
varible: gen(lod, lev-level, adr);//寫變數命令
proc: error(21) //過程名,報21號錯
end;
getsym //讀入下一個TOKEN
end else
if sym = number then //讀入的是數字
begin if num > amax then //如果數字大於最大數,報30號錯誤
begin error(30); num := 0
end;
gen(lit, 0, num); getsym //調用數字命令,讀入下一個TOKEN
end else
if sym = lparen then //讀入的是「(」
begin getsym; expression([rparen]+fsys); //調用表達式分析函數
if sym = rparen then getsym else error(22) //如果「(」後無「)」,報22號錯
end;
test(fsys, [lparen], 23)
end
end {factor};//因子分析結束
//項分析
begin {term} factor(fsys+[times, slash]); //調用因子分析程序
while sym in [times, slash] do //取得是乘、除號循環
begin mulop:=sym;getsym;factor(fsys+[times,slash]); //記錄符號,調用因子分析
if mulop=times then gen(opr,0,4) else gen(opr,0,5) //寫乘除指令
end
end {term};
begin {expression}
if sym in [plus, minus] then //如果是加減號
begin addop := sym; getsym; term(fsys+[plus,minus]); //記錄符號,調用項分析程序
if addop = minus then gen(opr, 0,1) //寫加減指令
end else term(fsys+[plus, minus]);
while sym in [plus, minus] do //如果是加減號循環
begin addop := sym; getsym; term(fsys+[plus,minus]);
if addop=plus then gen(opr,0,2) else gen(opr,0,3)
end
end {expression};
//條件過程
procere condition(fsys: symset);
var relop: symbol;
begin
if sym = oddsym then //如果是判奇符
begin getsym; expression(fsys); gen(opr, 0, 6) //取下一個TOKEN,調用expression,填指令
end else
begin expression([eql, neq, lss, gtr, leq, geq]+fsys);
if not(sym in [eql, neq, lss, leq, gtr, geq]) then //如果不是取到邏輯判斷符號,出錯.20
error(20) else
begin relop := sym; getsym; expression(fsys);
case relop of
eql: gen(opr, 0, 8); // =,相等
neq: gen(opr, 0, 9); // #,不相等
lss: gen(opr, 0, 10); // <,小於
geq: gen(opr, 0, 11); // ],大於等於
gtr: gen(opr, 0, 12); // >,大於
leq: gen(opr, 0, 13); // [,小於等於
end
end
end
end {condition};
begin {statement}
if sym = ident then //如果是標識符
begin i := position(id); //查找符號表
if i = 0 then error(11) else //未找到,標識符未定義,報11號錯
if table[i].kind <> varible then //如果標識符不是變數,報12號錯
begin {assignment to non-varible} error(12); i := 0
end;
getsym; if sym = becomes then getsym else error(13); //如果是變數讀入下一個TOKEN,不是賦值號,報13好錯;是則讀入一個TOKEN
expression(fsys); //調用表達是過程
if i <> 0 then //寫指令
with table[i] do gen(sto, lev-level, adr)
end else
if sym = callsym then //如果是過程調用保留字,讀入下一個TOKEN
begin getsym;
if sym <> ident then error(14) else //不是標識符報14號錯
begin i := position(id);
if i = 0 then error(11) else //是標識符,未定義,報13號錯
with table[i] do // 已定義的標識符讀入類型
if kind=proc then gen(cal, lev-level, adr) //是過程名寫指令
else error(15); //不是過程名,報15號錯
getsym
end
end else
if sym = ifsym then //如果是IF
begin getsym; condition([thensym, dosym]+fsys); //讀入一個TOKEN,調用條件判斷過程
if sym = thensym then getsym else error(16); //如果是THEN,讀入一個TOKEN,不是,報16號錯
cx1 := cx; gen(jpc, 0, 0); //寫指令
statement(fsys); code[cx1].a := cx
end else
if sym = beginsym then //如果是BEGIN
begin getsym; statement([semicolon, endsym]+fsys); //讀入一個TOKEN
while sym in [semicolon]+statbegsys do
begin
if sym = semicolon then getsym else error(10); //如果讀入的是分號
statement([semicolon, endsym]+fsys)
end;
if sym = endsym then getsym else error(17) //如果是END 讀入一個TOKEN,不是,報17號錯
end else
if sym = whilesym then //如果是WHILE
begin cx1 := cx; getsym; condition([dosym]+fsys); //調用條件過程
cx2 := cx; gen(jpc, 0, 0); //寫指令
if sym = dosym then getsym else error(18); //如果是DO讀入下一個TOKEN,不是報18號錯
statement(fsys); gen(jmp, 0, cx1); code[cx2].a := cx
end;
test(fsys, [], 19)
end {statement};
begin {block}
dx:=3;
tx0:=tx;
table[tx].adr:=cx;
gen(jmp,0,0);
if lev > levmax then error(32);
repeat
if sym = constsym then //如果是CONST
begin getsym; //讀入TOKEN
repeat constdeclaration; //常量聲明
while sym = comma do
begin getsym; constdeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分號讀入下一個TOKEN,不是報5號錯
until sym <> ident //不是標志符常量聲明結束
end;
if sym = varsym then 如果是VAR
begin getsym; 讀入下一個TOKEN
repeat vardeclaration; //變數聲明
while sym = comma do
begin getsym; vardeclaration
end;
if sym = semicolon then getsym else error(5) //如果是分號讀入下一個TOKEN,不是報5號錯
until sym <> ident; //不是標志符常量聲明結束
end;
while sym = procsym do //過程聲明
begin getsym;
if sym = ident then
begin enter(proc); getsym
end
else error(4); //不是標志符報4號錯
if sym = semicolon then getsym else error(5); //如果是分號讀入下一個TOKEN,不是報5號錯
block(lev+1, tx, [semicolon]+fsys);
if sym = semicolon then //如果是分號,取下一個TOKEN,不是報5號錯
begin getsym;test(statbegsys+[ident,procsym],fsys,6)
end
else error(5)
end;
test(statbegsys+[ident], declbegsys, 7)
until not(sym in declbegsys); //取到的不是const var proc結束
code[table[tx0].adr].a := cx;
with table[tx0] do
begin adr := cx; {start adr of code}
end;
cx0 := 0{cx}; gen(int, 0, dx);
statement([semicolon, endsym]+fsys);
gen(opr, 0, 0); {return}
test(fsys, [], 8);
listcode;
end {block};
⑼ 急求!!!編譯原理詞法分析器代碼
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define norw 13 /* 關鍵字個數 */
#define nmax 14 /* number的最大位數 */
#define al 10 /* 符號的最大長度 */
#define cn 11
#define IDENT "ident"
#define NUM "number"
#define SYM "sym"
#define ISLETTER(c) ((c)>='A'&&(c)<='Z'||(c)>='a'&&(c)<='z')
#define ISNUMBER(c) ((c)>='0'&&(c)<='9')
void letter();void number();
char ch; /* 獲取字元的緩沖區,getch使用 */
char a[al+1]; /* 臨時符號,多出的一個位元組用於存放0 */
FILE *fin;
char fname[al];
char *word[] = {
"begin", "call" , "const" , "do" , "end" ,
"if" , "odd" , "procere" , "read" , "then" ,
"var" , "while" , "write"
};
int k=0,i=0;
char ssym[][10]={"plus","minus","times","slash","lparen", "rparen","eql","comma","neq","semicolon"};
char csym[]={'+','-','*','/','(',')','=',',','#',';'};
void main() {
do{
printf("Input pl/0 filename:");
gets(fname);
fin=fopen(fname,"r");
}while(!fin);
ch=fgetc(fin);
while(ch!='.'){
for(;' '==ch;ch=fgetc(fin));
if(ISLETTER(ch)){
k=0;
letter();
}else if(ISNUMBER(ch)){
k=0;
number();
}else{
switch(ch){
case ':':
if('='==(ch=fgetc(fin))){
printf("(\":=\",eql)\n");
ch=fgetc(fin);
}break;
case '>':
if('='==(ch=fgetc(fin))){
printf("(\">=\",gtr)\n");
ch=fgetc(fin);
break;
}else
printf("(\">\",geq)\n");break;
case '<':
if('='==(ch=fgetc(fin))){
printf("(\"<=\",leq)\n");
ch=fgetc(fin);break;
}
else
printf("(\"<\",lss)\n");break;
default:
for(i=0;i<norw && ch!=csym[i];i++);
if(i<norw)
printf("(\"%c\",%s)\n",ch,ssym[i]);
ch=fgetc(fin);
}
}
}printf("(\"%c\",period)\n",ch);
}
void letter(){
do{
if(al>k) {
a[k]=ch;
k+=1;
}
ch=fgetc(fin);
}while(ISLETTER(ch));
a[k]='\0';
for(i=0;i<norw && strcmp(a,word[i]);i++);
if(i<norw)
printf("(\"%s\",%s%s)\n",a,a,SYM);
else
printf("(\"%s\",%s)\n",a,IDENT);
}
void number(){
do{
if(nmax>k) {
a[k]=ch;
k+=1;
}
ch=fgetc(fin);
}while(ISNUMBER(ch));
a[k]='\0';
printf("(\"%s\",%s)\n",a,NUM);
}
⑽ 求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