C语言实现词法分析器

某电大三学生党。从文件里读字符进行词法分析,实验要求用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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值