目錄
1、定義目標語言的可用符號表
- 關鍵字:if,else,for,while,do,int,read,write,return
- 標識符:①標識符由字母、數字組成;②不能把c語言關鍵字作為標識符;③標識符對大小寫敏感;④首字符只能是字母,不能是數字。
- 常數:無符號整數值。
- 運算符:+、-、*、/、==、<=、>=、!=、=
- 界符:,、;、{、}、(、)
2、定義程序輸入輸出
- 程序輸入:依照c語言程序規則輸入,以txt文本形式存儲;
- 程序輸出:程序依照 類型 值 的形式每行一個進行輸出,例如 int int。
3、代碼
(1)頭文件 analysis.h
#include<stdio.h>
#include<ctype.h>
#include<string.h>
//下面定義保留字表,為簡化程序,使用字符指針數組保存所有保留字
//如果想增加保留字,可繼續添加,並修改保留字數目 keywordSum
#define keywordSum 9
char *keyword[keywordSum] = {"if","else","for","while","do","int","read","write","return"};
//下面定義純單分界符的首字符
char singleword[50] = "!+-*(){};,:";
//下面定義雙分界符的首字符
char doubleword[10] = "><=!&|";
extern char Scanin[300], Scanout[300];
//用於接收輸人輸出文件名,在 test _ main.c 中定義
extern FILE *fin ,*fout; //用於指向輸入輸出文件的指針,在 test _ main.c 中定義
int TESTscan () //詞法分析函數
{
char ch , token[40]; //ch 為每次讀人的字符,token 用於保存識別出的單詞
int es = 0,j,n; //es錯誤代碼,0表示沒有錯誤
//j, n為臨時變量,控制組合單詞時的下標等
printf("請輸人源程序文件名(包括路徑):");
scanf("%s",Scanin);
printf("請輸人詞法分析輸出文件名(包括路徑):");
scanf("%s",Scanout);
if(( fin = fopen(Scanin ,"r")) == NULL) //判斷輸人文件名是否正確
{
printf("\n打開詞法分析輸人文件出錯!\n");
return (1); //輸人文件出錯返回錯誤代碼1
}
if (( fout = fopen (Scanout ,"w")) == NULL ) //判斷輸出文件名是否正確
{
printf("\n創建詞法分析輸出文件出錯!\n");
return(2); //輸出文件出錯返回錯誤代碼2
}
ch = getc(fin);
while(ch != EOF)
{
while(ch == ' '|| ch == '\n' || ch == '\t') ch = getc(fin);
if(isalpha(ch)) //如果是字母則組合標識符
{
token[0] = ch; j = 1;
ch = getc(fin);
while(isalnum(ch)) //如果是字符數字則組合標識符
//如果不是則標識符組合結束
{
token[j++] = ch; //組合的標識符保存在token中
ch = getc(fin); //都下一個字符
}
token[j] = '\0'; //標識符組合結束
//查保留字
n = 0;
while((n < keywordSum) && strcmp(token,keyword[n])) n++;
if(n >= keywordSum) //不是保留字,輸出標識符
fprintf(fout,"%s\t%s\n","ID",token); //輸出標識符符號
else //是保留字,輸出保留字
fprintf(fout,"%s\t%s\n",token,token); //輸出保留字符號
}else if(isdigit(ch)) //數組處理
{
token[0] = ch; j = 1;
ch = getc(fin); //讀下一個字符
while(isdigit(ch)) //如果是數字則組合整數;如果不是則整數組合結束
{
token[j++] = ch; //組合整數保存在token中
ch = getc(fin); //都下一個字符
}
token[j] = '\0'; //整數組合結束
fprintf(fout,"%s\t%s\n","NUM",token); //輸出整數符號
}else if(strchr(singleword,ch) > 0) //單分界符處理
{
token[0] = ch; token[1] = '\0';
ch = getc(fin); //讀下一個字符以便識別下一個單詞
fprintf(fout,"%s\t%s\n",token,token); //輸出單分界符符號
}else if(strchr(doubleword,ch) > 0) //雙分界符處理
{
token[0] = ch;
ch = getc(fin); //讀下一個字符判斷是否為雙分界符
if(ch == '=') //如果是=,組合雙分界符 != == >= <=
{
token[1] = ch; token[2] = '\0'; //組合雙分界符結束
ch = getc(fin); //讀下一個符號以便識別下一個單詞
} else if(ch == '&') //判斷是否是&&
{
token[1] = ch; token[2] = '\0';
ch = getc(fin);
}
else if(ch == '|') //判斷是否是||
{
token[1] = ch; token[2] = '\0';
ch = getc(fin);
} else
token[1] = '\0';
fprintf(fout,"%s\t%s\n",token,token); //輸出單或雙分界符
}else if(ch == '/') //注釋處理
{
ch = getc(fin); //讀下一個字符
if(ch == '*') //如果是*,則開始處理注釋
{
char ch1;
ch1 = getc(fin); //讀下一個字符
do
{
ch = ch1; ch1 = getc(fin); //刪除注釋
} while((ch != '*' || ch1 != '/')&&ch1 != EOF);
//直到遇到注釋結束符 * / 或文件尾
ch = getc(fin); //讀下一個字符以便識別下一個單詞
}else //不是*則處理單分界符
{
token[0] = '/'; token[1] = '\0';
fprintf(fout,"%s\t%s\n",token,token); //輸出單分界符
}
}else //錯誤處理
{
token[0] = ch; token[1] = '\0';
ch = getc(fin); //讀下一個符號以便識別下一個單詞
es = 3; //設置錯誤代碼
fprintf(fout,"%s\t%s\n","ERROR",token); //輸出錯誤符號
}
}
fclose(fin); //關閉輸入輸出文件
fclose(fout);
return(es); //返回主程序
}
(2)測試 main.cpp
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include"analysis.h"
extern int TESTscan();
char Scanin[300],Scanout[300]; //用於接收輸入輸出文件名
FILE *fin,*fout; //用於指向輸入輸出文件的指針
int main() {
int es = 0;
es = TESTscan();
if(es > 0)
printf("詞法分析有錯,編譯停止!");
else
printf("詞法分析成功!\n");
}