编译原理实验二:标识符的识别

实验要求

【任务介绍】根据给定源语言的构词规则,从任意字符串中识别出所有的合法标识符。

【输入】字符串。

【输出】单词符号流,一行一个单词。

【题目】设计一个程序,从任意字符串中识别出所有可视为C语言“名字”的子串。注意:

  1. 构词规则:以字母打头,后跟任意多个字母、数字的单词;长度不超过15;不区分大小写;把下划线视为第27个字母。

  2. 关键字保留,即:语言定义中保留了某些单词用作关键字,程序员不可以将这些单词用作“名 字“(变量名、常量名、函数名、标号名等等)。

编程环境和语言

编程语言:C++

IDE:vs 2019

实验原理分析

预处理结束后,因为C语言中的关键字、运算符和界符都是有限个,而标识符则是无限个,所以我们只需要判断一个词不是关键字、运算符、界符、字符串,第一个字符不是数字,那么我们就可以断定这个词就是一个标识符。

程序关键部分分析

用来预处理的函数为pre_process(char *buff, int &in_comment)(相对于实验一的预处理有所修改),用来识别标识符的函数为identifyID(ifstream& fin, ofstream& fout)。

定义

首先,我定义了关键字数组、运算符数组和界符数组,用于后面判断一个字符串是否为标识符:

#define MAXN 1024  //缓冲区的最大容量
char keywords[33][20] = {  //关键字,包括main在内共有33个
    "auto", "short", "int", "long", "float", "double", "char", "struct", 
    "union", "enum", "typedef", "const", "unsigned", "signed", "extern", 
    "register", "static", "volatile", "void", "if", "else", "switch", 
    "case", "for", "do", "while", "goto", "continue", "break", "default",
    "sizeof", "return", "main"
};
char operators[38][10] = {  //运算符,共38个
    "+", "-", "*", "/", "%", "++", "--", "==", "!=", ">", ">=", "<", "<=",
    "&&", "||", "!", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=",
    "^=", "|=", "&", "|", "^", "~", "<<", ">>", "?", ":", ",", ".", "->"
};
char delimiters[7] = { '(', ')', '[', ']', '{', '}', ';' };  //分隔符,共7个

然后定义了几个函数:

bool isKey(char* s);  //用来判断字符串是否为关键字,是则返回true,否则返回false
bool isOP(char* s);  //用来判断字符串是否为运算符,是则返回true,否则返回false
bool isDE(char s);  //用来判断字符是否为分隔符,是则返回true,否则返回false
void pre_process(char *buff, int &in_comment);  //预处理
void identifyID(ifstream& fin, ofstream& fout);  //将标识符找出并输出

关键部分分析

pre_process()预处理中首先去掉注释,这里的操作与我的上一篇《编译原理实验一:预处理》稍稍有些不同,即并没有将所有的空白字符去掉,可以与我的上一篇进行对照。

while (i < strlen(buff)) {  //去注释
    cur_c = buff[i++];  //首先将获取的字符存入缓存中
    switch (in_comment) {
    case 0:
        if (cur_c == '\"') {  //进入双引号中
            data[j++] = cur_c;
            in_comment = 3;
        }
        else if (cur_c == '\'') {  //进入单引号中
            data[j++] = cur_c;
            in_comment = 4;
        }
        else if (old_c == '/' && cur_c == '*') {  //进入多行注释中
            j--;
            in_comment = 1;
        }
        else if (old_c == '/' && cur_c == '/') {  //进入单行注释中
            j--;
            in_comment = 2;
        }
        else {  //其他情况则直接将数据写入data中
            data[j++] = cur_c;
        }
        break;
    case 1:if (old_c == '*' && cur_c == '/') in_comment = 0;  //多行注释结束
        break;
    case 2:if (i == strlen(buff)) in_comment = 0;  //单行注释到这行结束时标志位置为0
        break;
    case 3:
        data[j++] = cur_c;
        if (cur_c == '\"') in_comment = 0;
        break;
    case 4:
        data[j++] = cur_c;
        if (cur_c == '\'') in_comment = 0;
        break;
    }
    old_c = cur_c;  //保留上一个字符
}

pre_process()预处理中,去掉注释的数据存放在data数组中,分隔词后的数据存放在

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花无凋零之时

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值