❶ 編譯原理 詞法分析
C語言詞法分析器
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
FILE *f; //定義一個文件變數
static int line = 1; //表示游標所在的行數
struct ID{ char *name; int count;}id[100];//用於存放ID號碼
static int I = 0; //用於記錄ID存放的數量
int Number[100]; //用於存放數字
static int P = 0; //用於記錄存放數字的個數
int error[100] = {0}; //用於記錄錯誤所在的行數
static int K = 0; //記錄錯誤次數
void Error(); //記錄錯誤
void loginID(char *); //注冊ID號
void loginNumber(int &); //記錄數字
void noteLine(char &); //記錄游標所在的行數
void print(); //輸出分析結果
int same(char *chr); //判斷單詞是否已經存在
void Error()
{ error[K++] = line; }
void loginID(char *chr) //注冊ID號
{
int k = 0;
int h = 0;
for(int i = 0; i < I; i++)
{
if(!strcmp(chr,id.name)) //如果單詞已經存在
{
id.count++;
k = 1;
}
}
if(k == 0) //該單詞不存在
{
h = I + 1;
//I = h;
id[h].count++;
id[h].name = chr;
//strcpy(id[h].name ,chr);
}
}
void loginNumber(int &nu)
{ Number[P++] = nu; }
void noteLine(char &ch)
{
if ( ch == ' ' )
++line;
}
void print()//輸出部分
{
//cout << "關鍵字以及變數:" << endl;
//for(int i = 0; i < 100; i++)
//cout << i <<" " << id.name << " " << id.count << endl;
cout << "數字:" << endl;
for(int i = 1; i <= P; i++)
cout << i << ": " << Number[i-1] << endl;
if(error[0] != 0)
{
cout << "出現的錯誤!" << endl;
for(int i = 1; i <= K; i++)
cout << "第" << i << "個錯誤: " << "第" << error[i-1] << "行" << endl;
}
else cout << "沒有錯誤!" << endl;
}
//文件處理部分
void noblank( char &ch) //跳過空格,回車
{
noteLine(ch);
while(ch == ' ' || ch == ' ')
ch = fgetc(f);
}
void identifier(char name[],char &ch)//字母變數
{
int i;
for(i = 0; i < 20; i++)
name = '';
i = 0;
while (('0'<= ch && ch <= '9')||('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))
{
name = ch;
i++;
ch = fgetc(f);
}
loginID(name);
//for(int j = 0; j < i; j++)
//{cout << name[j];}
// cout << ' ';
}
int number(char &ch)//數字
{
int num=0;
while('0'<= ch && ch <= '9')
{
num = num* 10 + (ch-'0');
ch = fgetc(f);
}
if( ('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))
{
Error();
}
else if( ch == '.')
{;}
loginNumber(num); //記錄數字
return num;
}
void test(char &ch)//符號
{
char str[2]={'0/'};
if(ch == '*')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '.')
{ str[0] = ch; ch = fgetc(f);}
if(ch == ',')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '"')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '/')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '%')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '^')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '-')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '{')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '}')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '[')
{ str[0] = ch; ch = fgetc(f);}
if(ch == ']')
{ str[0] = ch; ch = fgetc(f);}
if(ch == ';')
{str[0] = ch; ch = fgetc(f);}
if(ch == ':')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '?')
{ str[0] = ch; ch = fgetc(f);}
if(ch == '(')
{ str[0] = ch; ch = fgetc(f);}
if(ch == ')')
{str[0] = ch; ch = fgetc(f);}
if(ch =='+')
{
str[0] = ch;
if((ch = fgetc(f)) == '+' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
//cout << str[0]<< endl;
}
if(ch == '-')
{
str[0] = ch;
if((ch = fgetc(f)) == '-' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
//cout << str[0]<< endl;
}
if(ch == '&')
{
str[0] = ch;
if((ch = fgetc(f)) == '&' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
//cout << str[0]<< endl;
}
if(ch == '|')
{
str[0] = ch;
if((ch = fgetc(f)) == '|' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
//cout << str[0]<< endl;
}
if(ch == '!')
{
str[0] = ch;
if((ch = fgetc(f)) == '=' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
//cout << str[0]<< endl;
}
if(ch == '=')
{
str[0] = ch;
if((ch = fgetc(f)) == '=' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
}
if(ch == '>')
{
str[0] = ch;
if((ch = fgetc(f)) == '=' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
else
if(ch == '>' )
{
str[1] = ch;
ch = fgetc(f);
//cout << str[0] << str[1] << endl;
}
}
if(ch == '<')
{
str[0] = ch;
if((ch = fgetc(f)) == '=' )
{
str[1] = ch;
ch = fgetc(f);
}
else
if(ch == '<' )
{
str[1] = ch;
ch = fgetc(f);
}
}
}
int main()
{
char ch;
char name[30];
for(int i = 0; i < 30; i++)
name = '/0';
f = fopen("c.txt","r"); //打開指定輸入文件
if (f == NULL)
cout<<"文件不存在!"<<endl;
ch = fgetc(f);
while(!feof(f))
{
noblank( ch ); //跳過回車,空格
if( ( ch >= 'a' && ch <= 'z' )||( ch >= 'A' && ch <= 'Z' ))
{ identifier(name,ch); } //處理字母
else if( ch >= '0'&& ch <= '9')
{ number(ch); } //處理數字
else
{ test(ch); } //處理符號
}
print(); //列印詞法分析結果
fclose(f); //關閉文件
system("pause");
return 0;
}
❷ 請問編譯原理的詞法分析用C語言編寫的演算法是怎樣的
ε只能出現在NFA中,當然不是為了方便直觀,而是連通NFA和DFA的橋梁。編譯原理講授的不是如何繪制NFA或者DFA,二是告訴讀者怎樣能夠自動實現NFA或DFA的構造。在實際應用中ε可以幫助計算機轉換NFA為DFA,而在屬性文法和語法制導階段,它也是溝通綜合屬性與繼承屬性、執行語義動作不可或缺的一部分。另外ε的使用可以大大簡化文法產生式的構造難度。我記得最初使用ε是為了使得文法體系(字母表)更加完善,但是在實際應用中卻變得應用廣泛(此觀點不一定正確)。 最後想說的是,在編譯中,ε也帶來了不小的麻煩,否則也就不會有諸如「去空產生式」這樣的演算法了:)
採納哦
❸ 編譯原理詞法分析程序
(一)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};
❹ 求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語言編寫一個編譯原理實驗的簡單優先分析法程序
編譯原理IF條件語句的翻譯程序設計—簡單優先法、輸出四元式通過設計、編制、調試一個條件語句的語法及語義分析程序,加深對語法及語義分析原理的理解,並實現詞法分析程序對單詞序列的詞法檢查和分析。具體做到以下幾點:①對輸入語句進行詞法分析。將輸入的字元串進行掃描和分解,識別出一個個合法的單詞。單詞種類包括:關鍵字,標識符,運算符,常數和界限符②進行語法分析。編寫條件語句的相應文法,按照語法分析方法中的簡單優先分析法為文法設計簡單優先表,對詞法分析得到的單詞序列進行語法分析,以判別輸入的語句是否屬於該文法的條件語句。③語法制導翻譯。設計中間代碼(四元式)序列的結構及屬性文法,運用語法制導翻譯,在進行語法分析的同時,執行相應的語義規則描述的動作,從而實現語義處理,生成中間代碼以四元式的形式輸出。④錯誤提示。對不同的錯誤給出簡略描述,並終止程序的繼續執行。下載地址如下,有你要的東西!pile.rar
❻ 編譯原理課程設計-詞法分析器設計(C語言)
#include"stdio.h"/*定義I/O庫所用的某些宏和變數*/
#include"string.h"/*定義字元串庫函數*/
#include"conio.h"/*提供有關屏幕窗口操作函數*/
#include"ctype.h"/*分類函數*/
charprog[80]={'