某电大三学生党。从文件里读字符进行词法分析,实验要求用lex,多写了C语言的,直接贴代码了
主要是识别关键字和标识符,先从文件读到缓冲区,再进行比较。
还有组合形成的各种符号,例如<和<=,需要单独提出来识别。
以及fseek函数,回退一字符,这个是学习别人代码使用的,在这里是算法的关键。
点个赞拿走吧。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXBUFF 100 // 缓冲区大小
#define MAXKEY 11
int LINE = 1;
int i = 0;
char ch;
char keystr[MAXKEY][10] = {"int", "float", "const", "main", "if", "else", "void", "return", "while", "break", "continue"};
int IsKeyword(char* arr);
int IsNumber(char ch);
int IsLetter(char ch);
int IsSeparator(char ch);
int IsOperator(char ch);
void WordAnalyse(FILE *fpin);
int IsKeyword(char* arr)
{
for (i = 0; i < MAXKEY; i++)
{
char key[8];
strcpy(key, keystr[i]);
if(strcmp(key, arr) == 0) break;
}
if(i < MAXBUFF) return 1;
else return 0;
}
int IsNumber(char ch)
{
if((ch >= '0') && (ch <= '9')) return 1;
return 0;
}
int IsLetter(char ch)
{
if(((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))){
return 1;
}
return 0;
}
int IsSeparator(char ch)
{
switch (ch)
{
case ';':
printf("界符 ; \n");
return 1;
case '(':
printf("界符 ( \n");
return 1;
case ')':
printf("界符 ) \n");
return 1;
case '[':
printf("界符 [ \n");
return 1;
case ']':
printf("界符 ] \n");
return 1;
case '{':
printf("界符 { \n");
return 1;
case '}':
printf("界符 } \n");
return 1;
case '"':
printf("界符 \" \n");
return 1;
case '\'':
printf("界符 \' \n");
return 1;
case ',':
printf("界符 , \n");
return 1;
case '.':
printf("界符 . \n");
return 1;
default:
break;
}
return 0;
}
int IsOperator(char ch)
{
switch (ch)
{
case '+':
printf("运算符 + \n");
return 1;
case '-':
printf("运算符 - \n");
return 1;
case '*':
printf("运算符 * \n");
return 1;
case '%':
printf("运算符 % \n");
return 1;
default:
break;
}
return 0;
}
void WordAnalyse(FILE *fpin)
{
char arr[MAXBUFF];
while ((ch = fgetc(fpin)) != EOF)
{
// 空格不做处理
if (ch == ' ' || ch == '\t'){}
else if(ch == '\n') {
LINE++;
}
// 注释
else if(ch == '/'){
ch = fgetc(fpin);
if(ch == '/'){
while (ch != '\n')
{
ch = fgetc(fpin);
}
LINE++;
}
else if(ch == '*'){
while(ch != '*' && ch != EOF){
ch = fgetc(fpin);
if(ch == '\n') {
LINE++;
}
}
if(ch == EOF) break;
else if(ch == '*'){
if((ch == fgetc(fpin)) != '/'){
printf("注释出错,缺失一个/");
return;
}
}
}
// 除法运算符
else{
fseek(fpin, -1L, SEEK_CUR);
printf("运算符 / \n");
}
}
// 运算符
else if(IsOperator(ch)){}
// 界符
else if(IsSeparator(ch)){}
// 字符串
else if(IsLetter(ch)){
int j = 0;
while (IsLetter(ch) || IsNumber(ch) || (ch == '_'))
{
arr[j] = ch;
j++;
ch = fgetc(fpin);
}
fseek(fpin, -1L, SEEK_CUR);
arr[j] = '\0';
if(IsKeyword(arr)){
printf("关键字 %s \n",arr);
}
else{
printf("标识符 %s \n",arr);
}
}
// 常数
else if(IsNumber(ch)){
int j = 0;
int flag = 1;
while (IsNumber(ch) || IsLetter(ch))
{
if(IsNumber(ch)){
arr[j] = ch;
j++;
ch = fgetc(fpin);
}
else if(IsLetter(ch)){
arr[j] = ch;
j++;
ch = fgetc(fpin);
flag = 0;
}
}
fseek(fpin, -1L, SEEK_CUR);
arr[j] = '\0';
if(flag == 0){
printf("第%d行标识符命名 %s 出错 \n",LINE,arr);
}
else if(flag == 1){
printf("常数 %s \n",arr);
}
}
// 其他两个单位组成的符号
else switch (ch)
{
case '>':
ch = getc(fpin);
if(ch == '='){
printf("运算符 >= \n");
}
else{
printf("运算符 > \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
case '<':
ch = getc(fpin);
if(ch == '='){
printf("运算符 <= \n");
}
else{
printf("运算符 < \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
case '!':
ch = getc(fpin);
if(ch == '='){
printf("运算符 != \n");
}
else{
printf("运算符 ! \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
case '|':
ch = getc(fpin);
if(ch == '|'){
printf("运算符 || \n");
}
else{
printf("无效字符 | \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
case '&':
ch = getc(fpin);
if(ch == '&'){
printf("运算符 && \n");
}
else{
printf("无效字符 & \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
case '=':
ch = getc(fpin);
if(ch == '='){
printf("运算符 == \n");
}
else{
printf("运算符 = \n");
fseek(fpin, -1L, SEEK_CUR);
}
break;
default:
printf("在第%d行存在无效字符%c\n",LINE,ch);
break;
}
}
}
int main()
{
FILE *fpin;printf("开始词法分析\n");
fpin = fopen("D:\\大三\\编译原理\\实验\\test_cases\\00.txt","r");
WordAnalyse(fpin);
printf("词法分析完成");
fclose(fpin);
system("pause");
return 0;
}