【编译原理】【C语言】实验一:手动构造词法分析器


C语言
实验环境:Visual Studio 2019
author:zoxiii


词法分析器

  • 1、实验内容
  • 2、前期准备
    • 2.1 待分析的C语言子集的词法
    • 2.2 C语言子集的单词符号表示表
    • 2.3 C语言子集对应的状态转换图
  • 3、分析过程
    • 3.1 词法分析子程序
    • 3.2 主程序
    • 3.3 源代码
  • 4、测试
  • 5、遇到的问题

1、实验内容

  写出完整词法分析器程序,并用一段程序语句进行调试、运行。

2、前期准备

2.1 待分析的C语言子集的词法

单词大概可分为的5类:标识符、保留字、常数、运算符、界符。

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

2.2 C语言子集的单词符号表示表

  首先根据我们要构造的C语言子集的简单词法分析器,列出所要实现的单词符号以及它们的种别编码和内码值。
  为了方便记忆,还添加了助记符来表示单词符号。具体如下表:

单词符号种别编码助记符内码值
while1while
if2if
else3else
switch4switch
case5case
标识符6idid在符号表中的位置
常数7numnum在常数表中的位置
+8+
-9-
*10*
<=11relopLE
<11relopLT
==11relopEQ
=12=
;13;

2.3 C语言子集对应的状态转换图

  根据需要构造的词法分析器的单词符号,设计了对应的状态转换图。其中,首先对输入串预处理,去除空格、制表符等,再根据单子符号表得到状态转换图,并分析每种状态应输出的单词二元组信息。

在这里插入图片描述

图1-C语言子集对应的状态转换图

3、分析过程

3.1 词法分析子程序

  对于前期分析要实现的词法分析器需引入相应的变量和函数:
  变量如下:
(1) token:用来存放构成单词符号的字符串;
(2) ch:用来存放每一次词法分析获取的字符;
(3) ptr_token:单词缓冲区指针;
  函数如下:
(1) void Getchar():将下一输入字符读到ch中,扫描指针前移一字符位置;
(2) void getbe():检查ch中的字符是否为空白。若是,则调用Getchar直至ch中为非空字符为止 ;
(3) void concatenation():将ch中的字符连接到token之后作为新的字符串;
(4) bool letter():判断ch中的字符是否为字母,是则返回true(1),不是则返回false(0);
(5) bool digit():判断ch中的字符是否为数字,是则返回true(1),不是则返回false(0);
(6) int reserve():按token中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0值(假定0不是保留字的编码);
(7) void retract():将扫描指针回退一个字符位置,将ch置为空白字符;
(8) void buildlist():将标识符登录到符号表中或将常数登录到常数表中;
(9) void error():出现非法字符,词法分析出错,显示出错的字符;
(10) void LexicalAnalysis():词法分析过程函数;
  扫描子程序的主要流程图如下图2所示:
在这里插入图片描述

图2-词法分析子程序流程图

3.2 主程序

  主程序流程较为简单,如下图图3所示。但在之前需要在程序开始时定义一些全局变量,如关键字数组、需分析的语句数组、空的标识符表数组、常数表数组等以及相应的数组指针,便于后面的词法分析。
在这里插入图片描述

图3-主程序流程图

3.3 源代码

#include<iostream>
#include<string.h>
using namespace std;
//声明数组变量+指针
char input[] = "Hello World;I am XXX;x=5;y=9;if x<y	x=y;else   x=x; case 7  x>7;";  //需要分析的词句
const char *keyword[] = {"while","if","else","switch","case"};//关键字
int keyword_length=sizeof(keyword)/sizeof(char*);
int ptr_input = 0; //测试程序数组指针
int ptr_token;     //读取到的字符数组指针
char ch;         //字符变量,存放最新读入的源程序字符
char token[255] = "";  //字符数组,存放构成单词符号的字符串
//声明buildlist的相关变量+指针
int num_table[50] = { 0 }; //常数表,存放构成的常数
int ptr_num=0;              //常数表指针
char id_table[255][255] = {0};//标识符表,存放构成的标识符
int ptr_id=0;                           //标识符表指针
int ptr_present;                        //当前指针
//声明函数定义 
void Getchar();//将下一输入字符读到ch中,扫描指针前移一字符位置
void getbe();//检查ch中的字符是否为空白。若是,则调用Getchar直至ch中为非空字符为止 
void concatenation();//将ch中的字符连接到token之后作为新的字符串
bool letter();//判断ch中的字符是否为字母,是则返回true(1),不是则返回false(0)
bool digit();//判断ch中的字符是否为数字,是则返回true(1),不是则返回false(0)
int reserve();//按token中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0值(假定0不是保留字的编码)
void retract();//将扫描指针回退一个字符位置,将ch置为空白字符
void buildlist();//将标识符登录到符号表中或将常数登录到常数表中
void error();//出现非法字符,词法分析出错,显示错误信息
void LexicalAnalysis();//词法分析过程函数
/*** 函数功能:从输入缓冲区下一输入字符读到ch中,并将扫描指针前移一字符位置。*/
void Getchar()
{ch = input[ptr_input];ptr_input++;
} 
/*** 函数功能:检查ch中的字符是否为空白;若是,则调用Getchar直至ch中为非空字符为止。*/
void getbe()
{while (ch == ' '||ch == '\t')Getchar();
} 
/*** 函数功能:将ch中的字符连接到token之后作为新的字符串*/
void concatenation()
{token[ptr_token] = ch;ptr_token++;token[ptr_token] = '\0';
} 
/*** 函数功能:判断ch中的字符是否为字母,是则返回true(1),不是则返回false(0)*/
bool letter()
{if (ch >= 'a'&&ch <= 'z' || ch >= 'A'&&ch <= 'Z')return 1;elsereturn 0;
}
/*** 函数功能:判断ch中的字符是否为数字,是则返回true(1),不是则返回false(0)*/
bool digit()
{if (ch >= '0'&&ch <= '9')return 1;elsereturn 0;
} 
/*** 函数功能:按token中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0值(假定0不是保留字的编码)*/
int reserve()
{int i = 0;while(i < keyword_length){if (!strcmp(keyword[i], token))return i + 1;   //如果相等,则返回该关键字的种别编码i++;}return 0;       //如果不是关键字,则返回0
} 
/*** 函数功能:将扫描指针回退一个字符位置,将ch置为空白字符*/
void retract()
{ptr_input--;
}
/*** 函数功能:出现非法字符,词法分析出错,显示错误信息*/
void error()
{cout<<"Illegal character:"<<ch<<endl;
}
/*** 函数功能:将标识符登录到符号表中或将常数登录到常数表中*/    
void buildlist()
{ char ch_head=token[0]-'0';if(ch_head >= 0 && ch_head <= 9){int j=0;while(j < ptr_num){if(atoi(token)==num_table[j]){ptr_present=j;break;}j++;}if(j==ptr_num){num_table[ptr_num]=atoi(token);ptr_present=ptr_num;ptr_num++;}}else{int i = 0;while(i < ptr_id){if (!strcmp(id_table[i], token)){ptr_present = i;break;}i++;}if(i==ptr_id){strcpy(id_table[ptr_id],token);ptr_present=ptr_id;ptr_id++;       }}
}
/*** 函数功能:词法分析过程函数*/
void LexicalAnalysis()                  
{         ptr_token = 0;   //单词缓冲区指针Getchar();       //获取当前字符到ch中getbe();         //滤除空格if(letter())            //首字符为字母{while (letter() || digit ()){concatenation();        //将当前读入的字符送入token数组Getchar();              //获取下个字符}retract();    //扫描指针回退一个字符int index = reserve();//查询是否为关键字if (index==0)                   {buildlist();//将标识符登录到符号表中cout<<"(\t"<<"id"<<"\t,\t"<<ptr_present<<"\t)\tid_table["<<ptr_present<<"]="<<token<<"\n";//是标识符//return (id,指向id的符号表入口指针);}elsecout<<"(\t"<<keyword[index-1]<<"\t,\t"<<" "<<"\t)\n";//是关键字//return (关键字码, null);}else if (digit())  //首字符是数字{while (digit()){concatenation();Getchar();}retract();buildlist(); /*将常数登录到常数表中*/cout<<"(\t"<<"num"<<"\t,\t"<<ptr_present<<"\t)\tnum_table["<<ptr_present<<"]="<<token<<"\n";//是常数//return (num, num的常数表入口指针);}else switch (ch){case '+':cout<<"(\t"<<"'+'"<<"\t,\t"<<" "<<"\t)\n";//是"+"//return ('+', null);break;case '?':cout<<"(\t  "<<"'-'"<<"\t,\t"<<" "<<"\t)\n";//是"-"//return ('?', null);break;case '*':cout<<"(\t"<<"'*'"<<"\t,\t"<<" "<<"\t)\n";//是"*"//return ('*', null);break;case '<':Getchar();if (ch == '=')cout<<"(\t"<<"relop"<<"\t,\t"<<"LE"<<"\t)\n";//是"<="//return (relop,LE);else{retract();cout<<"(\t"<<"relop"<<"\t,\t"<<"LT"<<"\t)\n";//是"<"//return (relop,LT);}break;case '=':Getchar();if (ch == '=')cout<<"(\t"<<"relop"<<"\t,\t"<<"EQ"<<"\t)\n";//是"=="//return (relop, EQ);else{retract();cout<<"(\t"<<"="<<"\t,\t"<<" "<<"\t)\n";//是"="//return ('=', null);}break;case ';':cout<<"(\t"<<";"<<"\t,\t"<<" "<<"\t)\n";//是";"//return (';', null);break;default:error();}
}
/*** 主函数*/
int main()
{while(ptr_input<strlen(input))LexicalAnalysis();//进行词法分析return 0;
}

4、测试

  如下图图4所示为对程序语句

Hello World;
I am XXX;
x=5;y=9;
if x<yx=y;
elsex=x;case 7x>7;

  进行词法分析得到的单词二元组。为便于观察,还将单词及其标识符表或常数表中的位置在二元组之后输出,便于观察结果是否正确。
在这里插入图片描述

图4-词法分析得到的单词二元组

5、遇到的问题

(1) 在建立标识符表和常数表时,一开始通过链表的方法来建立,如下建立了对应的标识符表和常数表:

struct NodeId
{int index_id;char node_id[255];NodeId *next;
};
struct NodeNum
{int index_num;char node_num[255];NodeNum *next;
};

但在运行过程中,由于链表是动态分配地址的,所以地址的变化导致每次往表中插入新的字符时都会改变地址,无法得到有效的表。
因此最终选择了使用初始化数组作为标识符和常数存储的位置则解决掉了这个问题。
(2) 再将标识符或常数登记到对应的表中时,忽略了token是有结束符号的,在匹配时一直没有成功。所以在每次匹配时都对得到的单词token处理,去掉结尾的结束符“0”,然后再进行匹配就可以了。

参考文献:《编译原理教程 (第4版)》 胡元义 2016

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/36620.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

编译原理实验(1) 开发环境的安装与配置

flex词法分析器的安装与配置 版本&#xff1a;使用的Flex分析器版本为2.5.4。 下载并使用安装程序安装。 进行环境变量的设置&#xff1a; 此电脑–右键–属性–高级系统设置–环境变量 在系统变量中找到PATH&#xff0c;将flex安装后的bin目录加入PATH&#xff1b; 找到CLA…

Eclipse:使用Eclipse创建一个Java小练习项目

1、创建工程 就是说现在创建的工程是符合java的工程&#xff0c;而我们创建的是JAVAEE的工程&#xff0c;要不要使用java的透视图&#xff0c;这里选择 NO:https://blog.csdn.net/weixin_63610637/article/details/125099915?spm1001.2014.3001.5501http://这里选择yes的&…

反垃圾邮件网关工作原理-Coremail带你了解杰创智能如何使用邮件网关安全升级

杰创智能科技股份有限公司&#xff08;以下简称杰创智能)成立于2008年&#xff0c;于2022年在深交所创业板挂牌上市。 公司采用广州、北京双总部运作模式&#xff0c;在全国范围内设立近30家分支机构&#xff0c;业务覆盖全国辐射全球。 随着杰创智能业务的飞速发展&#xff0…

零代码编程:用ChatGPT打造小宇宙播客下载软件2.0

之前用ChatGPT写了一个简单的小宇宙播客下载应用&#xff0c;但是实际使用一段时间后&#xff0c;发现有几个问题&#xff0c;比如&#xff1a;如果文件名中有一些特殊符号&#xff0c;下载不成功&#xff1b;有些m4a格式的也下载不成功&#xff1b;文件大下载的慢&#xff1b;…

零代码编程:用ChatGPT批量下载播客音频文件

国外有很多优质的播客podcast资源&#xff0c;且都是可以免费下载的。 比如&#xff0c;我们想下载ChatGPT相关的播客。可以先打开播客搜索网站&#xff1a;https://podnews.net/ 在搜索框里面输入&#xff1a;ChatGPT&#xff0c;上面是stories&#xff0c;往下拉一下&#x…

流量玩家必看,微信问一问轻松获取200+引流秘籍

最近&#xff0c;微信推出了全新的“问一问”功能&#xff0c;为流量玩家带来了巨大的流量红利。这一新的流量入口势必成为流量玩家们追逐的热门目标。 “问一问”可以被视为一个问答型平台&#xff0c;可以简单理解为“微信版的知乎”。熟悉在知乎上进行问答引流的人都知道&am…

DNSPod十问林洪祥:顶级带货主播,其实是数字人?

本期嘉宾 林洪祥 风平智能CEO 林洪祥&#xff0c;风平智能CEO。风平智能拥有全球领先的数字人AIGC预训练大模型技术&#xff0c;利用数字人AI知识大模型打造视频版ChatGPT&#xff0c;实现数字人名师、数字人医生、数字人保险客服、数字广告模特、数字人AI直播等&#xff0c;…

chatgpt赋能python:Python机器学习手册

Python机器学习手册 介绍 Python机器学习手册提供了从数据预处理到深度学习的全面指南。本手册适合有一定Python编程经验的工程师和数据科学家。 数据预处理 数据预处理是机器学习流程的重要一步&#xff0c;包括数据清洗、特征选择和数据转换等。Python提供了很多数据预处…

机器学习复习(下)

严正声明&#xff1a;本文的答案是ChatGPT的回答&#xff0c;仅供参考&#xff0c;不代表就是正确答案&#xff01;&#xff01;&#xff01; 9.什么是泛化误差和经验误差&#xff0c;是不是越小越好?为什么? 泛化误差&#xff1a;在“未来”样本上的误差 经验误差&#xff…

【回答问题】ChatGPT上线了!请使用C++语言写一个谷歌 LaMDA模型?

【回答问题】ChatGPT上线了!请使用C++语言写一个谷歌 LaMDA模型? 很高兴为您服务!您可以使用以下 C 语言代码来实现 Google LaMDA 模型: 复制 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX

Edge解决默认Bing搜索跳转到国内版的问题

近期BingGPT申请通过以后&#xff0c;每次用PC端Edge去跳转的时候不管是否念Proxy咒都会进入国内版本Bing&#xff0c;排查得到默认Bing参数如下 因此&#xff0c;在edge://settings/searchEngines内添加搜索引擎&#xff0c;具体参数如下&#xff1a; 搜索引擎&#xff1a;必应…

微软Bing突然爆炸级更新!BingChat全面开放,下一代搜索要来啦!

夕小瑶科技说 分享 来源 | 量子位 作者 | 杨净 明敏 所有人都能上手微软Bing了&#xff01; 今天&#xff0c;微软突然官宣全面开放BingChat&#xff1a; 无需任何等待。只需注册一个账户&#xff0c;首页即可体验。 更关键的是&#xff0c;还有一大堆堪称“家底”的新功能来…

ChatGPT 让 Python 爬虫再次伟大!

ChatGPT 的爆火改变了很多东西&#xff0c;就与多年前移动互联网的普及一样&#xff0c;我们正处于 AI 改变世界的前夜。 在 OpenAI 为其推出了 GPT-4 语言模型后&#xff0c;ChatGPT 的回答准确性有了极大提高&#xff0c;也具备了更高水平的识图能力&#xff0c;这让 ChatGPT…

程序员离开上海回农村会后悔吗?年薪50万,存款180万,想回老家建别墅,搞自媒体,过田园生活!

现代版的“归园田居”什么样&#xff1f; 来看一位网友的案例&#xff1a;想离开上海回农村建个别墅&#xff0c;会后悔吗&#xff1f; 1.想回去的原因&#xff1a;和老公在上海八年&#xff0c;觉得日子真没意思&#xff0c;我们都喜欢田园生活&#xff0c;互联网也不可能有…

花几万元报IT培训班,只为进入互联网大厂:有人年薪百万,有人黯然退场

俗话说&#xff0c;英雄不问出处。但在职场中&#xff0c;“出处”却是一个敏感的话题&#xff0c;是否拥有高学历、大厂背景&#xff0c;是否是科班出身&#xff0c;这些都是招聘方会考虑的重要因素。 程序员千千万万&#xff0c;出身也是五花八门&#xff0c;有人是985高校计…

AIGC热门技术岗平均年薪超百万,脉脉林凡认为白领可能先于蓝领失业

3月&#xff0c;国内外AIGC新品相继发布引发热议&#xff0c;AIGC的人才需求也更加旺盛。脉脉高聘人才智库近期发布《2023 AIGC人才趋势报告》&#xff0c;数据显示&#xff0c;AIGC人才供需结构性失衡&#xff0c;热招岗位偏技术岗位&#xff0c;以算法工程师、自然语言处理、…

一位失业的P9,以及他的四页半简历

前几天在脉脉上看到一个热帖&#xff0c;是刚从PDD毕业的P9级别员工吴可发的&#xff0c;同时附上了他的简历&#xff0c;这个简历很有意思&#xff0c;基本上和国内互联网这十多年来的发展步骤重叠&#xff0c;能够反映出&#xff0c;在这样一个跌宕起伏的时代里&#xff0c;个…

程序员想要年薪五十万,需要付出多少努力?

关 &#x1f381;福利&#x1f381; 全网最全《Python学习资料》免费赠送&#x1f193;&#xff01; 最近火热ChatGPT 等人工智能应用对 Python 编程语言产生了积极的影响&#xff0c;它推动了 Python 的普及和发展&#xff0c;在文本处理和 NLP 领域提升了 Python 的地位&…

Meta员工年薪高达 213 万元,反超谷歌成 top 1,网友:“还是别人家公司香!”...

整理 | 朱珂欣 出品 | CSDN程序人生&#xff08;ID&#xff1a;coder_life&#xff09; 硅谷寒冬之下&#xff0c;有人猜测科技公司会「降本增效」&#xff0c;在员工薪酬上精打细算。 出人意料的是&#xff0c;事实恰恰相反。 据《华尔街日报》最新报道&#xff0c;多家公司…

网传美团今年应届生年薪 35w+,严重倒挂老员工,为什么互联网大厂校招的薪资一年比一年高?

1 为什么薪资越来越高&#xff1f; 10月27日&#xff0c;“网传美团今年应届生年薪 35w&#xff0c;严重倒挂老员工&#xff0c;为什么互联网大厂校招的薪资一年比一年高&#xff1f;”话题&#xff0c;登上知乎热搜。 从网上信息来看&#xff0c;今年美团给2021届校招算法方…