简单词法分析器——C++实现 (编译原理作业)

这篇博客介绍了一个用C++编写的词法分析器,它能够识别和处理标识符、保留字、常数、运算符、界符等基本元素。程序包括了对字符的判断、保留字查找、符号表登记等功能,并提供了错误处理机制。通过示例输入和输出展示了其工作过程。

词法分析器——C++实现

在这里插入图片描述
在这里插入图片描述

单词符号表示

(1)标识符:以字母开头的包含字母和数字的符号
(2)保留字:while、if、else、switch、case
(3)常数:数字0~9
(4)运算符:+、-、*、<、<=、==、=
(5)界符:;
(6)需略除的:空格、制表符、换行符

主要函数

concatenation() //连接token和character中字符作为token中新的字符串
letter ()//判断是否字母
digit() //判断是否数字
reserve() //按照token数组中的字符串查找表判断是否为保留字,是返回编码,否则返回0
retract() //扫描指针回退一个字符,同时将character置换为空白
buildlist() //将标识符登录到符号表中或将常数登录到常数表中
error() //出现非法字符,显示错误信息
getchar_syx()//读取数据
getbe() //剔除多余的空白符
solve() //进行测试

代码实现

变量
const int N = 1005;
const char keyWord[][20] = {"while", "if", "else", "switch", "case"};

int number_table[N], number_point, id_point; //常数表,常数数量,标识符数量
char identifier_table[N][105];               //标识符表
int present_point;                           //当前点位

char inn[N]; //输入
int inn_point;

char character;  //字符,存最新读入的源程序字符
char token[N];   //字符数组,存构成单词符号的字符串
int token_point; //字符串当前字符
连接字符串
void concatenation() //连接token和character中字符作为token中新的字符串
{
    token[token_point] = character;
    token_point++;
    token[token_point] = '\0';
}
判断字母或数字
bool letter(char tem) //判断是否字母
{
    if (tem >= 'a' && tem <= 'z')
        return true;
    if (tem >= 'A' && tem <= 'Z')
        return true;
    return false;
}
bool digit(char tem) //判断是否数字
{
    if (tem >= '0' && tem <= '9')
        return true;
    return false;
}
查找保留字符串
int reserve() //按照token数组中的字符串查找表判断是否为保留字,是返回编码,否则返回0
{
    for (int i = 0; i < 5; i++)
    {
        if (!strcmp(token, keyWord[i]))
            return i + 1;
    }
    return 0;
}
回退字符
void retract() //扫描指针回退一个字符,同时将character置换为空白
{
    inn_point--;
    character = ' ';
}
登录到表中
void buildlist() //将标识符登录到符号表中或将常数登录到常数表中
{

    char temp = token[0] - '0'; //用于判断当前token中的字符串是标识符还是常数
    int temp_num = 0;           //存放转换后的常数值

    /*******************************常数登记到常数表中*********************************/
    if (temp >= 0 && temp <= 9)
    {
        temp_num = atoi(token); //将token中的字符串转换成常数
        int i;
        for (i = 0; i < number_point; i++)
        {
            if (temp_num == number_table[i])
            { //如果常数表中已存在该常数
                present_point = i;
                cout << "已存在该常数"
                     << " ";
                break;
            }
        }
        if (i == number_point)
        { //如果常数表中没有该常数,则登记该常数
            number_table[number_point] = temp_num;
            present_point = number_point;
            number_point++;
        }
    }
    /************************将标识符登记到常数表中*****************************/
    else
    {
        int i = 0;
        for (i; i < id_point; i++)
        {
            if (strcmp(token, identifier_table[i]) == 0)
            { //如果标识符表中已存在该字符串
                present_point = i;
                cout << "已存在该字符串"
                     << " ";
                break;
            }
        }
        if (i == id_point)
        { //如果标识符表中没有该字符串,则登记该标识符
            strcpy_s(identifier_table[i], sizeof(token), token);
            present_point = id_point;
            id_point++;
        }
    }
}
错误信息
void error() //出现非法字符,显示错误信息
{
    printf("非法字符:%c\n", character);
}
扫描数据
void getchar_syx()
{
    character = inn[inn_point++];
}
去除空格
void getbe() //剔除多余的空白符
{
    while (character == ' ')
    {
        character = inn[inn_point++];
    }
}
进行测试
void solve()
{
    token_point = 0; // token指针初始化
    getchar_syx();   //获取字符
    getbe();         //滤除空格
    if (character >= 'a' && character <= 'z'||character >= 'A' && character <= 'Z')
    {
        /*字母开头,为标识符/保留字*/
        while (letter(character) || digit(character))
        {
            /*标识符包括字母和数字*/
            concatenation(); //将当前读入的字符送入token数组
            getchar_syx();
        }
        retract(); //扫描指针回退一个字符
        int c = reserve();
        if (c == 0)
        {
            buildlist(); //将标识符登录到符号表中
            cout << identifier_table[present_point] << " " << present_point << endl;
        }
        else
        {
            cout << c << " " << keyWord[c - 1] << endl;
        }
    }
    else if (character >= '0' && character <= '9')
    {
        /*数字开头,为常数*/
        while (digit(character))
        {
            /*常数只包括数字*/
            concatenation();
            getchar_syx();
        }
        retract();
        buildlist(); //将常数登录到常数表中
        
        cout << number_table[present_point] << " " << present_point << endl;
    }
    else if (character == '+')
        cout << "+" << endl;
    else if (character == '-')
        cout << "-" << endl;
    else if (character == '*')
        cout << "*" << endl;
    else if (character == '<')
    {
        getchar_syx();
        if (character == '=')
            cout << "relop"
                 << ","
                 << "LE" << endl;
        else
        {
            retract();
            cout << "relop"
                 << ","
                 << "LT" << endl;
        }
    }
    else if (character == '=')
    {
        getchar_syx();
        if (character == '=')
            cout << "relop"
                 << ","
                 << "EQ" << endl;
        else
        {
            retract();
            cout << "=" << endl;
        }
    }

    else if (character == ';')
        cout << ";" << endl;
    else
    {
        if (character == '\n' || character == '\t' || character == EOF)
            return;
        error(); //出错
    }
}
主函数
int main()
{
    strcpy(inn, "this is test one AXasd fDSxt 123321 +asd123 555<=124 55==45"); //测试数据
    inn_point = 0;
    while (inn[inn_point] != '\0')
    {
        solve();
    }
    return 0;
}

样例输出

this 0
is 1
test 2
one 3
AXasd 4
fDSxt 5
123321 0
+
asd123 6
555 1
relop,LE
124 2
55 3
relop,EQ
45 4

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值