C++写的一个简单的词法分析器(分析C语言)

实验用:

几点注意:

1.代码又长又臭,时间关系,没有优化,冗余项多(我都看不下去了。囧)

2.加了一下简单的错误检测。(在mapping.h中定义了错误类型,可以查阅)

3.使用头文件宏定义来表示单词的各种属性,也可以用文件

4.对于标志符的入口地址,无非是为了唯一识别,只要名字相同,都作为一个,使用自增的Int来模拟入口地址,即唯一标识。不考虑变量类型。

5.最后输出有三个表:Token表,错误表,标志符表。

6.一个字符一个字符的读文件,其实可以每次读到一个固定长度的缓冲区,双缓冲区进行分析。也可以读每一行。

代码:

mapping.h:

/*
头文件:mapping.h
*/

//关键字
#define AUTO 1
#define BREAK 2
#define CASE 3
#define CHAR 4
#define CONST 5
#define CONTINUE 6
#define DEFAULT 7
#define DO 8
#define DOUBLE 9
#define ELSE 10
#define ENUM 11
#define EXTERN 12
#define FLOAT 13
#define FOR 14
#define GOTO 15
#define IF 16
#define INT 17
#define LONG 18
#define REGISTER 19
#define RETURN 20
#define SHORT 21
#define SIGNED 22
#define SIZEOF 23
#define STATIC 24
#define STRUCT 25
#define SWITCH 26
#define TYPEDEF 27
#define UNION 28
#define UNSIGNED 29
#define VOID 30
#define VOLATILE 31
#define WHILE 32
#define KEY_DESC "关键字"

//标志符
#define IDENTIFER 40
#define IDENTIFER_DESC "标志符"

//常量
#define INT_VAL 51 //整形常量
#define CHAR_VAL 52 //字符常量
#define FLOAT_VAL 53 //浮点数常量
#define STRING_VAL 54 //双精度浮点数常量
#define MACRO_VAL 55 //宏常量
#define CONSTANT_DESC "常量"

//运算符
#define NOT 61   // !
#define BYTE_AND 62 //&
#define COMPLEMENT 63 // ~
#define BYTE_XOR  64 // ^
#define MUL 65 // *
#define DIV 66// /
#define MOD 67 // %
#define ADD 68 // +
#define SUB 69 // -
#define LES_THAN 70 // <
#define GRT_THAN 71 // >
#define ASG 72 // =
#define ARROW 73 // ->
#define SELF_ADD 74 // ++
#define SELF_SUB 75 // --
#define LEFT_MOVE 76 // <<
#define RIGHT_MOVE 77 // >>
#define LES_EQUAL 78 // <=
#define GRT_EQUAL 79 // >=
#define EQUAL 80 // ==
#define NOT_EQUAL 81 // !=
#define AND 82 // &&
#define OR 83 // ||
#define COMPLETE_ADD 84 // +=
#define COMPLETE_SUB 85 // -=
#define COMPLETE_MUL 86 // *=
#define COMPLETE_DIV 87 // /=
#define COMPLETE_BYTE_XOR 88 // ^=
#define COMPLETE_BYTE_AND 89 // &=
#define COMPLETE_COMPLEMENT 90 // ~=
#define COMPLETE_MOD 91 //%=
#define BYTE_OR 92 // |

#define OPE_DESC "运算符"

//限界符
#define LEFT_BRA 100 // (
#define RIGHT_BRA 101 // )
#define LEFT_INDEX 102 // [
#define RIGHT_INDEX 103 // ]
#define L_BOUNDER 104 //  {
#define R_BOUNDER 105 // }
#define POINTER 106 // .
#define JING 107 // #
#define UNDER_LINE 108 // _
#define COMMA 109 // ,
#define SEMI 110 // ;
#define SIN_QUE 111 // '
#define DOU_QUE 112 // "

#define CLE_OPE_DESC "限界符"

#define NOTE1 120 // "/**/"注释
#define NOTE2 121 // "//"注释
#define NOTE_DESC "注释"


#define HEADER 130 //头文件
#define HEADER_DESC "头文件"

//错误类型
#define FLOAT_ERROR "float表示错误"
#define FLOAT_ERROR_NUM 1
#define DOUBLE_ERROR "double表示错误"
#define DOUBLE_ERROR_NUM 2
#define NOTE_ERROR "注释没有结束符"
#define NOTE_ERROR_NUM 3
#define STRING_ERROR "字符串常量没有结束符"
#define STRING_ERROR_NUM 4
#define CHARCONST_ERROR "字符常量没有结束符"
#define CHARCONST_ERROR_NUM 5
#define CHAR_ERROR "非法字符"
#define CHAR_ERROR_NUM 6
#define LEFT_BRA_ERROR "'('没有对应项"
#define LEFT_BRA_ERROR_NUM 7
#define RIGHT_BRA_ERROR "')'没有对应项"
#define RIGHT_BRA_ERROR_NUM 8
#define LEFT_INDEX_ERROR "'['没有对应项"
#define LEFT_INDEX_ERROR_NUM 9
#define RIGHT_INDEX_ERROR "']'没有对应项"
#define RIGHT_INDEX_ERROR_NUM 10
#define L_BOUNDER_ERROR "'{'没有对应项"
#define L_BOUNDER_ERROR_NUM 11
#define R_BOUNDER_ERROR "'}'没有对应项"
#define R_BOUNDER_ERROR_NUM 12
#define PRE_PROCESS_ERROR "预处理错误" //头文件或者宏定义错误
#define PRE_PROCESS_ERROR_NUM  13

#define _NULL "无"

main.cpp:

//main.cpp

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include "mapping.h"

using namespace std;

const char * key[] = {"auto","break","case","char","const","continue","default","do","double",
                      "else","enum","extern","float","for","goto","if","int","long","register",
                      "return","short","signed","sizeof","static","struct","switch","typedef",
                      "union","unsigned","void","volatile","while"
                     };//C语言的关键字
int leftSmall = 0;//左小括号
int rightSmall = 0;//右小括号
int leftMiddle = 0;//左中括号
int rightMiddle = 0;//右中括号
int leftBig = 0;//左大括号
int rightBig = 0;//右大括号
int lineBra[6][1000] = {0};//括号和行数的对应关系,第一维代表左右6种括号
int static_iden_number = 0;//模拟标志符的地址,自增
//Token节点
struct NormalNode
{
    char content[30];//内容
    char describe[30];//描述
    int type;//种别码
    int addr;//入口地址
    int line;//所在行数
    NormalNode * next;//下一个节点
};

NormalNode * normalHead;//首结点

//错误节点
struct ErrorNode
{
    char content[30];//错误内容
    char describe[30];//错误描述
    int type;
    int line;//所在行数
    ErrorNode * next;//下一个节点
};

ErrorNode * errorHead;//首节点

//标志符节点
struct IdentiferNode
{
    char content[30];//内容
    char describe[30];//描述
    int type;//种别码
    int addr;//入口地址
    int line;//所在行数
    IdentiferNode * next;//下一个节点
};
IdentiferNode * idenHead;//首节点


void initNode()
{
    normalHead = new NormalNode();
    strcpy(normalHead->content,"");
    strcpy(normalHead->describe,"");
    normalHead->type = -1;
    normalHead->addr = -1;
    normalHead->line = -1;
    normalHead->next = NULL;

    errorHead = new ErrorNode();
    strcpy(errorHead->content,"");
    strcpy(errorHead->describe,"");
    errorHead->line = -1;
    errorHead->next = NULL;

    idenHead = new IdentiferNode();
    strcpy(idenHead->content,"");
    strcpy(idenHead->describe,"");
    idenHead->type = -1;
    idenHead->addr = -1;
    idenHead->line = -1;
    idenHead->next = NULL;
}

void createNewNode(char * content,char *descirbe,int type,int addr,int line)
{
    NormalNode * p = normalHead;
    NormalNode * temp = new NormalNode();

    while(p->next!=NULL)
    {
        p = p->next;
    }

    strcpy(temp->content,content);
    strcpy(temp->describe,descirbe);
    temp->type = type;
    temp->addr = addr;
    temp->line = line;
    temp->next = NULL;

    p->next = temp;
}
void createNewError(char * content,char *descirbe,int type,int line)
{
    ErrorNode * p = errorHead;
    ErrorNode * temp = new ErrorNode();

    strcpy(temp->content,content);
    strcpy(temp->describe,descirbe);
    temp->type = type;
    temp->line = line;
    temp->next = NULL;
    while(p->next!=NULL)
    {
        p = p->next;
    }
    p->next = temp;
}
//返回值是新的标志符的入口地址
int createNewIden(char * content,char *descirbe,int type,int addr,int line)
{
    IdentiferNode * p = idenHead;
    IdentiferNode * temp = new IdentiferNode();
    int flag = 0;
    int addr_temp = -2;
    while(p->next!=NULL)
    {
        if(strcmp(content,p->next->content) == 0)
        {
            flag = 1;
            addr_temp = p->next->addr;
        }
        p = p->next;
    }
    if(flag == 0)
    {
        addr_temp = ++static_iden_number;//用自增来模拟入口地址
    }
    strcpy(temp->content,content);
    strcpy(temp->describe,descirbe);
    temp->type = type;
    temp->addr = addr_temp;
    temp->line = line;
    temp->next = NULL;
    p->next = temp;
    return addr_temp;
}

void printNodeLink()
{
    NormalNode * p = normalHead;
    p = p->next;
    cout<<"************************************分析表******************************"<<endl<<endl;
    cout<<setw(30)<<"内容"<<setw(10)<<"描述"<<"\t"<<"种别码"<<"\t"<<"地址"<<"\t"<<"行号"<<endl;
    while(p!=NULL)
    {
        if(p->type == IDENTIFER)
        {
            cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<p->addr<<"\t"<<p->line<<endl;
        }
        else
        {
            cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<"\t"<<p->line<<endl;
        }
        p = p->next;
    }
    cout<<endl<<endl;
}
/*
错误种类:
1.float表示错误
2.double表示错误
3.注释没有结束符
4.字符串常量没有结束符
5.字符常量没有结束符
6.非法字符
7.'('没有对应项
8.预处理错误
*/
void printErrorLink()
{
    ErrorNode * p = errorHead;
    p = p->next;
    cout<<"************************************错误表******************************"<<endl<<endl;
    cout<<setw(10)<<"内容"<<setw(30)<<"描述"<<"\t"<<"类型"<<"\t"<<"行号"<<endl;
    while(p!=NULL)
    {
        cout<<setw(10)<<p->content<<setw(30)<<p->describe<<"\t"<<p->type<<"\t"<<p->line<<endl;
        p = p->next;
    }
    cout<<endl<<endl;
}
//标志符表,有重复部分,暂不考虑
void printIdentLink()
{
    IdentiferNode * p = idenHead;
    p = p->next;
    cout<<"************************************标志符表******************************"<<endl<<endl;
    cout<<setw(30)<<"内容"<<setw(10)<<"描述"<<"\t"<<"种别码"<<"\t"<<"地址"<<"\t"<<"行号"<<endl;
    while(p!=NULL)
    {
        cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<p->addr<<"\t"<<p->line<<endl;
        p = p->next;
    }
    cout<<endl<<endl;
}
int mystrlen(char * word)
{
    if(*word == '\0')
    {
        return 0;
    }
    else
    {
        return 1+mystrlen(word+1);
    }
}
//预处理,处理头文件和宏定义
void preProcess(char * word,int line)
{
    const char * include_temp = "include";
    const char * define_temp = "define";
    char * p_include,*p_define;
    int flag = 0;
    p_include = strstr(word,include_temp);
    if(p_include!=NULL)
    {
        flag = 1;
        int i;
        for(i=7;;)
        {
            if(*(p_include+i) == ' ' || *(p_include+i) == '\t')
            {
                i++;
            }
            else
            {
                break;
            }
        }
        createNewNode(p_include+i,HEADER_DESC,HEADER,-1,line);
    }
    else
    {
        p_define = strstr(word,define_temp);
        if(p_define!=NULL)
        {
            flag = 1;
            int i;
            for(i=7;;)
            {
                if(*(p_define+i) == ' ' || *(p_define+i) == '\t')
                {
                    i++;
                }
                else
                {
                    break;
                }
            }
            createNewNode(p_define+i,CONSTANT_DESC,MACRO_VAL,-1,line);
        }
    }
    if(flag == 0)
    {
        createNewError(word,PRE_PROCESS_ERROR,PRE_PROCESS_ERROR_NUM,line);
    }
}

void close()
{
    delete idenHead;
    delete errorHead;
    delete normalHead;
}

int seekKey(char * word)
{
    for(int i=0; i<32; i++)
    {
        if(strcmp(word,key[i]) == 0)
        {
            return i+1;
        }
    }
    return IDENTIFER;
}

void scanner()
{
    char filename[30];
    char ch;
    char array[30];//单词长度上限是30
    char * word;
    int i;
    int line = 1;//行数


    FILE * infile;
    printf("请输入要进行语法分析的C语言程序:\n");
    scanf("%s",filename);
    infile = fopen(filename,"r");
    while(!infile)
    {
        printf("打开文件失败!\n");
        return;
    }
    ch = fgetc(infile);
    while(ch!=EOF)
    {

        i = 0;
        //以字母或者下划线开头,处理关键字或者标识符
        if((ch>='A' && ch<='Z') || (ch>='a' && ch<='z') || ch == '_')
        {
            while((ch>='A' && ch<='Z')||(ch>='a' && ch<='z')||(ch>='0' && ch<='9') || ch == '_')
            {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            word = new char[i+1];
            memcpy(word,array,i);
            word[i] = '\0';
            int seekTemp = seekKey(word);
            if(seekTemp!=IDENTIFER)
            {
                createNewNode(word,KEY_DESC,seekTemp,-1,line);
            }
            else
            {
                int addr_tmp = createNewIden(word,IDENTIFER_DESC,seekTemp,-1,line);
                createNewNode(word,IDENTIFER_DESC,seekTemp,addr_tmp,line);
            }
            fseek(infile,-1L,SEEK_CUR);//向后回退一位
        }
        //以数字开头,处理数字
        else if(ch >='0' && ch<='9')
        {
            int flag = 0;
            int flag2 = 0;
            //处理整数
            while(ch >='0' && ch<='9')
            {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            //处理float
            if(ch == '.')
            {
                flag2 = 1;
                array[i++] = ch;
                ch = fgetc(infile);
                if(ch>='0' && ch<='9')
                {
                    while(ch>='0' && ch<='9')
                    {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                }
                else
                {
                    flag = 1;
                }

                //处理Double
                if(ch == 'E' || ch == 'e')
                {
                    array[i++] = ch;
                    ch = fgetc(infile);
                    if(ch == '+' || ch == '-')
                    {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    if(ch >='0' && ch<='9')
                    {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    else
                    {
                        flag = 2;
                    }
                }

            }
            word = new char[i+1];
            memcpy(word,array,i);
            word[i] = '\0';
            if(flag == 1)
            {
                createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);
            }
            else if(flag == 2)
            {
                createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);
            }
            else
            {
                if(flag2 == 0)
                {
                    createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);
                }
                else
                {
                    createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);
                }
            }
            fseek(infile,-1L,SEEK_CUR);//向后回退一位
        }
        //以"/"开头
        else if(ch == '/')
        {
            ch = fgetc(infile);
            //处理运算符"/="
            if(ch == '=')
            {
                createNewNode("/=",OPE_DESC,COMPLETE_DIV,-1,line);
            }
            //处理"/**/"型注释
            else if(ch == '*')
            {
                ch =  fgetc(infile);
                while(1)
                {
                    while(ch != '*')
                    {
                        if(ch == '\n')
                        {
                            line++;
                        }
                        ch = fgetc(infile);
                        if(ch == EOF)
                        {
                            createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);
                            return;
                        }
                    }
                    ch = fgetc(infile);
                    if(ch == '/')
                    {
                        break;
                    }
                    if(ch == EOF)
                    {
                        createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);
                        return;
                    }
                }
                createNewNode(_NULL,NOTE_DESC,NOTE1,-1,line);
            }
            //处理"//"型注释
            else if(ch == '/')
            {
                while(ch!='\n')
                {
                    ch = fgetc(infile);
                    if(ch == EOF)
                    {
                        createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);
                        return;
                    }
                }
                line++;
                createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);
                if(ch == EOF)
                {
                    return;
                }
            }
            //处理除号
            else
            {
                createNewNode("/",OPE_DESC,DIV,-1,line);
            }
        }
        //处理常量字符串
        else if(ch == '"')
        {
            createNewNode("\"",CLE_OPE_DESC,DOU_QUE,-1,line);
            ch = fgetc(infile);
            i = 0;
            while(ch!='"')
            {
                array[i++] = ch;
                if(ch == '\n')
                {
                    line++;
                }
                ch = fgetc(infile);
                if(ch == EOF)
                {
                    createNewError(_NULL,STRING_ERROR,STRING_ERROR_NUM,line);
                    return;
                }
            }
            word = new char[i+1];
            memcpy(word,array,i);
            word[i] = '\0';
            createNewNode(word,CONSTANT_DESC,STRING_VAL,-1,line);
            createNewNode("\"",CLE_OPE_DESC,DOU_QUE,-1,line);
        }
        //处理常量字符
        else if(ch == '\'')
        {
            createNewNode("\'",CLE_OPE_DESC,SIN_QUE,-1,line);
            ch = fgetc(infile);
            i = 0;
            while(ch!='\'')
            {
                array[i++] = ch;
                if(ch == '\n')
                {
                    line++;
                }
                ch = fgetc(infile);
                if(ch == EOF)
                {
                    createNewError(_NULL,CHARCONST_ERROR,CHARCONST_ERROR_NUM,line);
                    return;
                }
            }
            word = new char[i+1];
            memcpy(word,array,i);
            word[i] = '\0';
            createNewNode(word,CONSTANT_DESC,CHAR_VAL,-1,line);
            createNewNode("\'",CLE_OPE_DESC,SIN_QUE,-1,line);
        }
        else if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
        {
            if(ch == '\n')
            {
                line++;
            }
        }
        else
        {
            if(ch == EOF)
            {
                return;
            }
            //处理头文件和宏常量(预处理)
            else if(ch == '#')
            {
                while(ch!='\n' && ch!=EOF)
                {
                    array[i++] = ch;
                    ch = fgetc(infile);
                }
                word = new char[i+1];
                memcpy(word,array,i);
                word[i] = '\0';
                preProcess(word,line);

                fseek(infile,-1L,SEEK_CUR);//向后回退一位
            }
            //处理-开头的运算符
            else if(ch == '-')
            {
                array[i++] = ch;
                ch = fgetc(infile);
                if(ch >='0' && ch<='9')
                {
                    int flag = 0;
                    int flag2 = 0;
                    //处理整数
                    while(ch>='0' && ch<='9')
                    {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    //处理float
                    if(ch == '.')
                    {
                        flag2 = 1;
                        array[i++] = ch;
                        ch = fgetc(infile);
                        if(ch>='0' && ch<='9')
                        {
                            while(ch>='0' && ch<='9')
                            {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                        }
                        else
                        {
                            flag = 1;
                        }
                        //处理Double
                        if(ch == 'E' || ch == 'e')
                        {
                            array[i++] = ch;
                            ch = fgetc(infile);
                            if(ch == '+' || ch == '-')
                            {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                            if(ch >='0' && ch<='9')
                            {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                            else
                            {
                                flag = 2;
                            }
                        }
                    }
                    word = new char[i+1];
                    memcpy(word,array,i);
                    word[i] = '\0';
                    if(flag == 1)
                    {
                        createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);
                    }
                    else if(flag == 2)
                    {
                        createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);
                    }
                    else
                    {
                        if(flag2 == 0)
                        {
                            createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);
                        }
                        else
                        {
                            createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);
                        }
                    }
                    fseek(infile,-1L,SEEK_CUR);//向后回退一位
                }
                else if(ch == '>')
                {
                    createNewNode("->",OPE_DESC,ARROW,-1,line);
                }
                else if(ch == '-')
                {
                    createNewNode("--",OPE_DESC,SELF_SUB,-1,line);
                }
                else if(ch == '=')
                {
                    createNewNode("--",OPE_DESC,SELF_SUB,-1,line);
                }
                else
                {
                    createNewNode("-",OPE_DESC,SUB,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理+开头的运算符
            else if(ch == '+')
            {
                ch = fgetc(infile);
                if(ch == '+')
                {
                    createNewNode("++",OPE_DESC,SELF_ADD,-1,line);
                }
                else if(ch == '=')
                {
                    createNewNode("+=",OPE_DESC,COMPLETE_ADD,-1,line);
                }
                else
                {
                    createNewNode("+",OPE_DESC,ADD,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理*开头的运算符
            else if(ch == '*')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("*=",OPE_DESC,COMPLETE_MUL,-1,line);
                }
                else
                {
                    createNewNode("*",OPE_DESC,MUL,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理按^开头的运算符
            else if(ch == '^')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("^=",OPE_DESC,COMPLETE_BYTE_XOR,-1,line);
                }
                else
                {
                    createNewNode("^",OPE_DESC,BYTE_XOR,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理%开头的运算符
            else if(ch == '%')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("%=",OPE_DESC,COMPLETE_MOD,-1,line);
                }
                else
                {
                    createNewNode("%",OPE_DESC,MOD,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理&开头的运算符
            else if(ch == '&')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("&=",OPE_DESC,COMPLETE_BYTE_AND,-1,line);
                }
                else if(ch == '&')
                {
                    createNewNode("&&",OPE_DESC,AND,-1,line);
                }
                else
                {
                    createNewNode("&",OPE_DESC,BYTE_AND,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理~开头的运算符
            else if(ch == '~')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("~=",OPE_DESC,COMPLETE_COMPLEMENT,-1,line);
                }
                else
                {
                    createNewNode("~",OPE_DESC,COMPLEMENT,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理!开头的运算符
            else if(ch == '!')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("!=",OPE_DESC,NOT_EQUAL,-1,line);
                }
                else
                {
                    createNewNode("!",OPE_DESC,NOT,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理<开头的运算符
            else if(ch == '<')
            {
                ch = fgetc(infile);
                if(ch == '<')
                {
                    createNewNode("<<",OPE_DESC,LEFT_MOVE,-1,line);
                }
                else if(ch == '=')
                {
                    createNewNode("<=",OPE_DESC,LES_EQUAL,-1,line);
                }
                else
                {
                    createNewNode("<",OPE_DESC,LES_THAN,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理>开头的运算符
            else if(ch == '>')
            {
                ch = fgetc(infile);
                if(ch == '>')
                {
                    createNewNode(">>",OPE_DESC,RIGHT_MOVE,-1,line);
                }
                else if(ch == '=')
                {
                    createNewNode(">=",OPE_DESC,GRT_EQUAL,-1,line);
                }
                else
                {
                    createNewNode(">",OPE_DESC,GRT_THAN,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            //处理|开头的运算符
            else if(ch == '|')
            {
                ch = fgetc(infile);
                if(ch == '|')
                {
                    createNewNode("||",OPE_DESC,OR,-1,line);
                }
                else
                {
                    createNewNode("|",OPE_DESC,BYTE_OR,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            else if(ch == '=')
            {
                ch = fgetc(infile);
                if(ch == '=')
                {
                    createNewNode("==",OPE_DESC,EQUAL,-1,line);
                }
                else
                {
                    createNewNode("=",OPE_DESC,ASG,-1,line);
                    fseek(infile,-1L,SEEK_CUR);
                }
            }
            else if(ch == '(')
            {
                leftSmall++;
                lineBra[0][leftSmall] = line;
                createNewNode("(",CLE_OPE_DESC,LEFT_BRA,-1,line);
            }
            else if(ch == ')')
            {
                rightSmall++;
                lineBra[1][rightSmall] = line;
                createNewNode(")",CLE_OPE_DESC,RIGHT_BRA,-1,line);
            }
            else if(ch == '[')
            {
                leftMiddle++;
                lineBra[2][leftMiddle] = line;
                createNewNode("[",CLE_OPE_DESC,LEFT_INDEX,-1,line);
            }
            else if(ch == ']')
            {
                rightMiddle++;
                lineBra[3][rightMiddle] = line;
                createNewNode("]",CLE_OPE_DESC,RIGHT_INDEX,-1,line);
            }
            else if(ch == '{')
            {
                leftBig++;
                lineBra[4][leftBig] = line;
                createNewNode("{",CLE_OPE_DESC,L_BOUNDER,-1,line);
            }
            else if(ch == '}')
            {
                rightBig++;
                lineBra[5][rightBig] = line;
                createNewNode("}",CLE_OPE_DESC,R_BOUNDER,-1,line);
            }
            else if(ch == '.')
            {
                createNewNode(".",CLE_OPE_DESC,POINTER,-1,line);
            }
            else if(ch == ',')
            {
                createNewNode(",",CLE_OPE_DESC,COMMA,-1,line);
            }
            else if(ch == ';')
            {
                createNewNode(";",CLE_OPE_DESC,SEMI,-1,line);
            }
            else
            {
                char temp[2];
                temp[0] = ch;
                temp[1] = '\0';
                createNewError(temp,CHAR_ERROR,CHAR_ERROR_NUM,line);
            }
        }
        ch = fgetc(infile);
    }
}
void BraMappingError()
{
    if(leftSmall != rightSmall)
    {
        int i = (leftSmall>rightSmall) ? (leftSmall-rightSmall) : (rightSmall - leftSmall);
        bool  flag = (leftSmall>rightSmall) ? true : false;
        if(flag)
        {
            while(i--)
            {
                createNewError(_NULL,LEFT_BRA_ERROR,LEFT_BRA_ERROR_NUM,lineBra[0][i+1]);
            }
        }
        else
        {
            while(i--)
            {
                createNewError(_NULL,RIGHT_BRA_ERROR,RIGHT_BRA_ERROR_NUM,lineBra[1][i+1]);
            }
        }
    }
    if(leftMiddle != rightMiddle)
    {
        int i = (leftMiddle>rightMiddle) ? (leftMiddle-rightMiddle) : (rightMiddle - leftMiddle);
        bool flag = (leftMiddle>rightMiddle) ? true : false;
        if(flag)
        {
            while(i--)
            {
                createNewError(_NULL,LEFT_INDEX_ERROR,LEFT_INDEX_ERROR_NUM,lineBra[2][i+1]);
            }
        }
        else
        {
            while(i--)
            {
                createNewError(_NULL,RIGHT_INDEX_ERROR,RIGHT_INDEX_ERROR_NUM,lineBra[3][i+1]);
            }
        }
    }
    if(leftBig != rightBig)
    {
        int i = (leftBig>rightBig) ? (leftBig-rightBig) : (rightBig - leftSmall);
        bool flag = (leftBig>rightBig) ? true : false;
        if(flag)
        {
            while(i--)
            {
                createNewError(_NULL,L_BOUNDER_ERROR,L_BOUNDER_ERROR_NUM,lineBra[4][i+1]);
            }
        }
        else
        {
            while(i--)
            {
                createNewError(_NULL,R_BOUNDER_ERROR,R_BOUNDER_ERROR_NUM,lineBra[5][i+1]);
            }
        }
    }
}

int main()
{
    initNode();
    scanner();
    BraMappingError();
    printNodeLink();
    printErrorLink();
    printIdentLink();
    close();
    return 0;
}


测试的C文件:test.c(一个错误很多的C程序)

#include          <stdio.h>
#include "my.h"
#define max 90
#de some

int char main()
{
    8888char yn;
    do
    {
	int 9801;
	float 9.;
	double 9.ef;
	float -9.876;
	double hello.8.9;
	float 7.9e-5;
	int e-5;
	a /= 6;
        init(); /*初始化*/
        scanner();//扫描源程序//
        printf("Are You continue(y/n)\n");
        yn=getch();
	if(a == 7)
	{
		
	}
	else
	{
		
	}
@

    }
    while(yn=='y'||yn=='Y');
    
    return 0;
[hello
	



//

//
//
	
	printf("hello");
	/*我是头猪
	

程序运行结果:


请输入要进行语法分析的C语言程序:
test.c
************************************分析表******************************

                          内容      描述        种别码  地址    行号
                     <stdio.h>    头文件        130             1
                        "my.h"    头文件        130             2
                        max 90      常量        55              3
                           int    关键字        17              6
                          char    关键字        4               6
                          main    标志符        40      1       6
                             (    限界符        100             6
                             )    限界符        101             6
                             {    限界符        104             7
                          8888      常量        51              8
                          char    关键字        4               8
                            yn    标志符        40      2       8
                             ;    限界符        110             8
                            do    关键字        8               9
                             {    限界符        104             10
                           int    关键字        17              11
                          9801      常量        51              11
                             ;    限界符        110             11
                         float    关键字        13              12
                             ;    限界符        110             12
                        double    关键字        9               13
                             f    标志符        40      3       13
                             ;    限界符        110             13
                         float    关键字        13              14
                        -9.876      常量        53              14
                             ;    限界符        110             14
                        double    关键字        9               15
                         hello    标志符        40      4       15
                             .    限界符        106             15
                           8.9      常量        53              15
                             ;    限界符        110             15
                         float    关键字        13              16
                        7.9e-5      常量        53              16
                             ;    限界符        110             16
                           int    关键字        17              17
                             e    标志符        40      5       17
                            -5      常量        51              17
                             ;    限界符        110             17
                             a    标志符        40      6       18
                            /=    运算符        87              18
                             6      常量        51              18
                             ;    限界符        110             18
                          init    标志符        40      7       19
                             (    限界符        100             19
                             )    限界符        101             19
                             ;    限界符        110             19
                            无      注释        120             19
                       scanner    标志符        40      8       20
                             (    限界符        100             20
                             )    限界符        101             20
                             ;    限界符        110             20
                            无      注释        121             21
                        printf    标志符        40      9       21
                             (    限界符        100             21
                             "    限界符        112             21
       Are You continue(y/n)\n      常量        54              21
                             "    限界符        112             21
                             )    限界符        101             21
                             ;    限界符        110             21
                            yn    标志符        40      2       22
                             =    运算符        72              22
                         getch    标志符        40      10      22
                             (    限界符        100             22
                             )    限界符        101             22
                             ;    限界符        110             22
                            if    关键字        16              23
                             (    限界符        100             23
                             a    标志符        40      6       23
                            ==    运算符        80              23
                             7      常量        51              23
                             )    限界符        101             23
                             {    限界符        104             24
                             }    限界符        105             26
                          else    关键字        10              27
                             {    限界符        104             28
                             }    限界符        105             30
                             }    限界符        105             33
                         while    关键字        32              34
                             (    限界符        100             34
                            yn    标志符        40      2       34
                            ==    运算符        80              34
                             '    限界符        111             34
                             y      常量        52              34
                             '    限界符        111             34
                            ||    运算符        83              34
                            yn    标志符        40      2       34
                            ==    运算符        80              34
                             '    限界符        111             34
                             Y      常量        52              34
                             '    限界符        111             34
                             )    限界符        101             34
                             ;    限界符        110             34
                        return    关键字        20              36
                             0      常量        51              36
                             ;    限界符        110             36
                             [    限界符        102             37
                         hello    标志符        40      4       37
                            无      注释        121             43
                            无      注释        121             45
                            无      注释        121             46
                        printf    标志符        40      9       47
                             (    限界符        100             47
                             "    限界符        112             47
                         hello      常量        54              47
                             "    限界符        112             47
                             )    限界符        101             47
                             ;    限界符        110             47


************************************错误表******************************

      内容                          描述        类型    行号
  #de some                    预处理错误        13      4
        9.                 float表示错误        1       12
       9.e                double表示错误        2       13
         @                      非法字符        6       31
        无                注释没有结束符        3       49
        无                 '['没有对应项        9       37
        无                 '{'没有对应项        11      7


************************************标志符表******************************

                          内容      描述        种别码  地址    行号
                          main    标志符        40      1       6
                            yn    标志符        40      2       8
                             f    标志符        40      3       13
                         hello    标志符        40      4       15
                             e    标志符        40      5       17
                             a    标志符        40      6       18
                          init    标志符        40      7       19
                       scanner    标志符        40      8       20
                        printf    标志符        40      9       21
                            yn    标志符        40      2       22
                         getch    标志符        40      10      22
                             a    标志符        40      6       23
                            yn    标志符        40      2       34
                            yn    标志符        40      2       34
                         hello    标志符        40      4       37
                        printf    标志符        40      9       47



Process returned 0 (0x0)   execution time : 5.629 s
Press any key to continue.


  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
词法分析器是编译器的一个重要组成部分,用于将输入的程序源代码转化为单词序列(Token),其中单词序列是由单词(Token)组成的,每个单词代表源代码中的一个基本单元,例如关键字、标识符、运算符等等。在词法分析器中,识别浮点数是一个重要的任务,因为浮点数是C语言中的基本数据类型之一。以下是一个简单C语言浮点数词法分析器的实现: ```c #include<stdio.h> #include<ctype.h> #include<stdlib.h> #include<string.h> #define FLOAT 1 struct token { int type; char* value; }; int is_float(char* str) { int len = strlen(str); int i = 0; int flag = 0; //标记是否有小数点 while(i < len){ if(isdigit(str[i])){ i++; }else if(str[i] == '.' && !flag){ flag = 1; i++; }else{ return 0; } } return 1; } struct token* next_token(char* input) { struct token* t = (struct token*)malloc(sizeof(struct token)); int len = strlen(input); char* p = input; while (p - input < len && isspace(*p)) { // 跳过空格 p++; } if (*p == '\0') { // 到达字符串末尾 t->type = -1; t->value = NULL; return t; } if (isdigit(*p) || *p == '.') { // 找到数字或小数点,往后扫描,直到找到不是数字或小数点的字符 char* q = p + 1; while (q - input < len && (isdigit(*q) || *q == '.')) { q++; } // 将这段字符拷贝到新的字符串中 int length = q - p; char* temp = (char*)malloc(length + 1); strncpy(temp, p, length); temp[length] = '\0'; // 判断是否为浮点数 if (is_float(temp)) { // 是浮点数 t->type = FLOAT; t->value = temp; } else { // 不是浮点数 free(temp); t->type = -1; t->value = NULL; } return t; } // 其他情况暂时不处理 t->type = -1; t->value = NULL; return t; } int main() { char input[100]; printf("请输入一个字符串: "); fgets(input, 100, stdin); struct token* t; while ((t = next_token(input)) != NULL && t->type != -1) { if (t->type == FLOAT) { printf("浮点数: %s\n", t->value); } free(t->value); } return 0; } ``` 该程序通过 `next_token` 函数实现了词法分析器的基本功能,每次调用该函数可以得到下一个单词,如果单词是浮点数,则输出相应的提示信息。程序中的 `is_float` 函数与前面的例子中的相同,用于判断一个字符串是否为浮点数。由于 `next_token` 函数每次都会动态分配内存,因此在使用完每个单词后,需要释放相应的内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值