① 怎麼用c語言編一個詞法分析器
簡而言之就是先畫一個狀態圖,然後根據圖來編碼就行
一個簡單的xml的詞法分析器供參考
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
typedef
struct
{
char
*p;
int
len;
}
xml_Text;
typedef
enum
{
xml_tt_U,
/*
Unknow
*/
xml_tt_H,
/*
Head
<?xxx?>*/
xml_tt_E,
/*
End
</xxx>
*/
xml_tt_B,
/*
Begin
<xxx>
*/
xml_tt_BE,
/*
Begin
End
<xxx/>
*/
xml_tt_T
/*
Text
xxx
*/
}
xml_TokenType;
typedef
struct
{
xml_Text
text;
xml_TokenType
type;
}
xml_Token;
int
xml_initText(xml_Text
*pText,
char
*s)
{
pText->p
=
s;
pText->len
=
strlen(s);
return
0;
}
int
xml_initToken(xml_Token
*pToken,
xml_Text
*pText)
{
pToken->text.p
=
pText->p;
pToken->text.len
=
0;
pToken->type
=
xml_tt_U;
return
0;
}
int
xml_print(xml_Text
*pText)
{
int
i;
for
(i
=
0;
i
<
pText->len;
i++)
{
putchar(pText->p[i]);
}
return
0;
}
int
xml_println(xml_Text
*pText)
{
xml_print(pText);
putchar('\n');
return
0;
}
int
xml_getToken(xml_Text
*pText,
xml_Token
*pToken)
{
char
*start
=
pToken->text.p
+
pToken->text.len;
char
*p
=
start;
char
*end
=
pText->p
+
pText->len;
int
state
=
0;
pToken->text.p
=
p;
pToken->type
=
xml_tt_U;
for
(;
p
<
end;
p++)
{
switch(state)
{
case
0:
switch(*p)
{
case
'<':
state
=
1;
break;
default:
state
=
7;
break;
}
break;
case
1:
switch(*p)
{
case
'?':
state
=
2;
break;
case
'/':
state
=
4;
break;
default:
state
=
5;
break;
}
break;
case
2:
switch(*p)
{
case
'?':
state
=
3;
break;
default:
state
=
2;
break;
}
break;
case
3:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_H;
return
1;
default:
state
=
-1;
break;
}
break;
case
4:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_E;
return
1;
default:
state
=
4;
break;
}
break;
case
5:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_B;
return
1;
case
'/':
state
=
6;
break;
default:
state
=
5;
break;
}
break;
case
6:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_BE;
return
1;
default:
state
=
-1;
break;
}
break;
case
7:
switch(*p)
{
case
'<':
p--;
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_T;
return
1;
default:
state
=
7;
break;
}
break;
default:
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_T;
return
1;
}
}
return
0;
}
int
main()
{
int
ret
=
0;
xml_Text
xml;
xml_initText(&xml,
"<?xml?><root>
ss
<haha>hoho</haha></root>");
xml_Token
token;
xml_initToken(&token,
&xml);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
return
0;
}
② 求一個C語言詞法分析器源代碼
我有,這是這學期剛做的,
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool isLetter(char ch){
if ((ch>='A' && ch<='Z') || (ch>='a' && ch<='z')) return true;
else return false;
}
bool isDigit(char ch){
if (ch>='0' && ch<='9') return true;
else return false;
}
bool isP(char ch){
if(ch=='+'||ch=='*'||ch=='-'||ch=='/') return true;
//ch==':'||ch==','||ch=='='||ch==';'||ch=='('||ch==')'
else return false;
}
bool isJ(char ch){
if(ch==','||ch==';'||ch=='.'||ch=='('||ch==')'||ch=='['||ch==']'||ch=='='||ch==':'||ch=='<'||ch=='>'||ch=='{'||ch=='}'||ch=='#') return true;
//
else return false;
}
bool isBlank(char ch){
if(ch==' '||ch=='\t') return true;
else return false;
}
int main(){
string src,ste,s;
char ch0,ch,ch1[2];
char ktt[48][20]={"and","begin","const","div","do","else","end","function","if","integer",
"not","or","procere","program","read","real","then","type","var","while","write","標識符","無符號數",
",",";",":",".","(",")","[","]","..","++","--","+","-","*","/","=","<",">","<>","<="
,">=",":=","{","}","#"};
int pos=0;
FILE *fp;
fp=fopen("d:\\in.txt","r");
ch0=fgetc(fp);
while(ch0!=EOF)
{
//if(ch0!='\t'){src+=ch0;}
src+=ch0;
ch0=fgetc(fp);
}
src+='#';
cout<<src<<endl;
ch=src[pos++];
ste=" ";
for(int j=0;j<47;j++){cout<<j<<ktt[j]<<endl;}
cout<<"詞法分析:\n";
while(ch!='#')
{
char str[20];
if(ch!='\n')
{
if(isDigit(ch))
{ //判斷常數
int i=0;
while(isDigit(ch)||ch=='.')
{
str[i++]=ch;
//i++;
ch=src[pos++];
}
str[i]='\0';
ste=ste+"|"+"22";
cout<<str;
continue;
}
else if(isLetter(ch))
{ //判斷字元
int i=0,j;
while(isLetter(ch)||isDigit(ch))
{
str[i++]=ch;
//i++;
ch=src[pos++];
}
str[i]='\0';
for(j=0;j<21;j++){ //判斷是否關鍵字
int t=strcmp(str,ktt[j]);
if(t==0) {
stringstream ss;
ste+="|";
ss<<ste;ss<<j;
ss>>ste;
break;
}
}
if(j==21){ste=ste+"|"+"21";}
// cout<<" ";
cout<<str;
continue;
}
else if(isP(ch)){ ///判斷是否運算符
int i=0,j;
str[i++]=ch;
str[i]='\0';
for(j=34;j<38;j++){
int t=strcmp(str,ktt[j]);
if(t==0) {
stringstream ss;
ste+="|";
ss<<ste;ss<<j;
ss>>ste;
break;
}
}
cout<<str;
ch=src[pos++];
continue;
}
else if(isJ(ch)) //判斷是否界符
{
int i=0,j;
while(isJ(ch))
{
str[i++]=ch;
ch=src[pos++];
}
str[i]='\0';
for(j=23;j<47;j++){
int t=strcmp(str,ktt[j]);
if(t==0) {
stringstream ss;
ste+="|";
ss<<ste;ss<<j;
ss>>ste;
break;
}
}
cout<<str;
continue;
}
else if(isBlank(ch))
{
cout<<ch;
ch=src[pos++];
continue;
}
}
else{
cout<<ste<<endl;
ste=" ";
}
ch=src[pos++];
}
return 0;
}
還有運行效果圖,和實驗報告 ,你要的話留下郵箱
③ c語言詞法分析器
任務1:識別小型語言所有單詞的詞法分析程序設計
源程序設計語言 G[<程序>]
<程序>→<變數說明><BEGIN> <語句表> <END>.
<變數說明>→VAR<變數表>:<類型>;|<空>
<變數表>→<變數表>,<變數>|<變數>
<類型>→INTEGER
<語句表>→<語句> | <語句>;<語句表>
<語句>→<賦值語句>|<條件語句>|<WHILE語句>|<復合語句>
<賦值語句>→<變數>:=<算術表達式>
<條件語句>→IF<關系表達式>THEN<語句>ELSE<語句>
<WHILE語句>→WHILE<關系表達式>DO<語句>
<復合語句>→BEGIN<語句表>END
<算術表達式>→<項>|<算術表達式>+<項>|<算術表達式>-<項>
<項>→<因式>|<項>*<因式>|<項>/<因式>
<因式>→<變數>|<整數>|(<算術表達式>)
<關系表達式>→<算術表達式><關系符><算術表達式>
<變數>→<標識符>
<標識符>→<標識符><字母>|<標識符><數字>|<字母>
<整數>→0|<非零數字><泛整數>
<泛整數>→<數字>|<數字><泛整數>|ε
<關系符>→<|<=|==|>|>=|<>
<字母>
→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<非零數字>→1|2|3|4|5|6|7|8|9
<數字>→<非零數字>|0
<空>→
要求和提示:
詞法分析階段,可以打開任意位置和名稱的源文件進行詞法分析,可以進行非法字元和數字後邊跟字母的錯誤判斷,如果沒有錯誤則提示「詞法分析正確完成!」,並且可以選擇輸出token.txt(token文件)string.txt(符號表)兩個文件;
1.詞法分析程序的主要任務如下:
① 組織源程序的輸入,識別出源程序中的各個基本語法單位(也稱為單詞或語法符號),按規則轉換成二元式的形式;
② 刪除無用的空白字元、回車符、及其它非實質性符號;
③ 刪除註解行;
④ 為後面的語法和語義分析提供二元式鏈表;
單詞 編碼 單詞 編碼
標識符 1 < 15
正整數 2 <= 16
BEGIN 3 > 17
END 4 >= 18
IF 5 <> 19
THEN 6 == 20
ELSE 7 ; 21
WHILE 8 . 22
DO 9 := 23
INTEGER 10 , 24
+ 11 ( 25
- 12 ) 26
* 13
/ 14
1) 對標識符的長度控制在8個字元(包括8個)以內,超過的做截斷處理;
2) 數字不大於65535,否則報錯;
3) 能跳過源程序中的空白格:兩個單詞之間的任何空格,製表符,回車,換行都是白空格,除了用來分隔單詞以外,沒有意義;
4) 能跳過注釋:
a) 接連出現的/*到下一次接連出現的*/之間的任何文字都是注釋(多行);
b) 從某行接連出現的//到該行的結尾的任何文字都是注釋(單行)。
3.怎樣編寫詞法分析程序:
1) 預處理:把源文件一個字元一個字元的讀入詞法分析程序設置的輸入字元結構體數組中(輸入緩沖區),讀入過程要刪除注釋,刪除多餘的白空格;
2) 從源程序字元數組中獲得單詞, 編碼為二元式.:
二元式採用結構體數組存儲, 把單詞類型和詞元記錄下來。
分解單詞的方法:
1) Case多路轉換語句根據單詞的特點直接編寫;
2) 通過描述單詞的正規文法得到相應的有窮自動機,通過case多路轉換語句完成有窮自動機的處理流程。
3.編寫詞法分析程序要注意的問題:
1) 檢查詞法是否有錯誤
檢查是否有非法字元:如 @, &, !
檢查標志符和數字是否滿足限制條件
檢查注釋符號是否配對
2) 符分隔單詞
能夠區分兩個單詞的符號為界符
有些界符不是單詞:如白空格
有些界符僅僅用來分隔:如;
有些界符本身還是源程序不可缺少的單詞,如(, ), +, /, 等等
有些界符包含兩個字元:如<>, >=等等
3) 輸出詞法錯誤
如果有錯誤,需要報告詞法錯誤的原因。並且要能夠越過錯誤,分解下一個單詞,直到源程序結束。
4) 輸出的二元式流保存在二元式結構體數組中。
④ 編譯原理課程設計-詞法分析器設計(C語言)
#include"stdio.h"/*定義I/O庫所用的某些宏和變數*/
#include"string.h"/*定義字元串庫函數*/
#include"conio.h"/*提供有關屏幕窗口操作函數*/
#include"ctype.h"/*分類函數*/
charprog[80]={'