编译原理——词法分析器

article/2025/11/1 12:51:34

1 概述

设计、编制并调试一个简单的C语言词法分析程序,掌握利用状态转换图设计词法分析器的基本方法,利用该词法分析器完成对源程序字符串的词法分析。通过对该词法分析器的设计,加深对词法分析原理、状态转换图等编译原理知识的理解。

2 使用的基本概念和原理

词法分析器读取的主要功能是输入源程序,输出单词符号,对源程序从左到右,从上到下对逐个字符进行扫描,把把构成源程序的字符串转换成单词符号的序列,输出单词序列用于语法分析。同时还可以滤掉空格、换行符、注释、行列计数,发现错误等功能。语法分析中单词符号主要分为:关键字、标识符、常数、运算符、界符5类,词法分析器可作为独立的一遍,也可作为语法分析器的子程序。

NFA与DFA转换

可以用子集法将NFA转换为DFA,再利用分割法将DFA最小化,正规式的整体变换如图所示:

3 总体设计

词法分析器首先将输入的文件进行读取,读取后对源程序的字符调用词法分析程序分析,根据字符种类来确定调用函数,将结果进行保存,随后输出,主程序示意图如图所示:

 程序在调用词法分析器进行词法分析,根据类码表进行分析,词法分析程序框图如图所示

词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常数等,本课程设计的数据定义表如表所示:

表 部分单词符号及其分类码表

单词符号

类别编码

类别码的助记符号

单词值

begin

1

BEGIN

关键字

end

2

END

if

3

IF

else

4

ELSE

return

5

RETURN

while

6

WHILE

then

7

THEN

for

8

FOR

int

9

INT

char

10

CHAR

float

11

FLOAE

main

12

MAIN

cin

13

CIN

cout

14

COUT

标识符

15

BA

字母数字串

常数(0-9)

16

CA

数字串

运算符

(+、-、*、%、<、>、=、!)

17

DA

数学运算符号

界符

(; , { } [ ]  ( ) :))

18

EA

分隔符号

4 代码实现

/*************Written By WFP************//*******Date : 12,16,2022********/
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <iomanip>using namespace std;
string KEYWORD[100] = { "begin","end", "if","else","return","while","then","for",      //关键字"int","char","float","main","cin","cout" };
char SEPARATER[50] = { ';',',','{','}','[',']','(',')',':' };    //界符
char OPERATOR[50] = { '+','-','*','/','>','<','=','!','%'};     //运算符
char FILTER[10] = { ' ','\n','\t'};                    //过滤符
const int IDENTIFIER = 100;         //标识符值
const int CONSTANT = 101;           //常数值
const int FILTER_VALUE = 102;
/**判断是否为关键字**/
int l = 1, a = 0;
bool IsKeyword(string word) {for (int i = 0; i < 18; i++) {if (KEYWORD[i] == word) {if (KEYWORD[i] == "begin")printf("助记符号:BEGIN\t");if (KEYWORD[i] == "end")printf("助记符号:END\t");if (KEYWORD[i] == "if")printf("助记符号:IF\t");if (KEYWORD[i] == "else")printf("助记符号:ELSE\t");if (KEYWORD[i] == "while")printf("助记符号:WHILE\t");if (KEYWORD[i] == "int")printf("助记符号:INT\t");if (KEYWORD[i] == "char")printf("助记符号:CHAR\t");if (KEYWORD[i] == "for")printf("助记符号:FOR\t");if (KEYWORD[i] == "return")printf("助记符号:RETURN");if (KEYWORD[i] == "cout")printf("助记符号:COUT\t");if (KEYWORD[i] == "float")printf("助记符号:FLOAT\t");if (KEYWORD[i] == "main")printf("助记符号:MAIN\t");if (KEYWORD[i] == "cin")printf("助记符号:CIN\t");if (KEYWORD[i] == "then")printf("助记符号:THEN\t");a++;return true;}}return false;
}
/**判断是否为界符**/
int b = 0;
bool IsSeparater(char ch) {for (int i = 0; i < 10; i++) {if (SEPARATER[i] == ch) {return true;}}return false;
}/**判断是否为运算符**/
int c = 0;
bool IsOperator(char ch) {for (int i = 0; i < 10; i++) {if (OPERATOR[i] == ch) {return true;}}return false;
}
/**判断是否为过滤符**/
bool IsFilter(char ch) {for (int i = 0; i < 4; i++) {if (FILTER[i] == ch) {if(ch=='\n')l++;return true;}}return false;
}
/**判断是否为大写字母**/
int e = 0;
bool IsUpLetter(char ch) {if (ch >= 'A' && ch <= 'Z') return true;return false;
}
/**判断是否为小写字母**/bool IsLowLetter(char ch) {if (ch >= 'a' && ch <= 'z') return true;return false;
}
/**判断是否为常数**/
int f = 0;
bool IsDigit(char ch) {if (ch >= '0' && ch <= '9') return true;return false;
}template <class T>
int value(T* a, int n, T str) {for (int i = 0; i < n; i++) {if (a[i] == str) return i + 1;}return -1;
}
int g = 0;
int h = 0;
int i = 0;
/**词法分析**/void analyse(FILE* fpin) {char ch = ' ';string arr = "";while ((ch = fgetc(fpin)) != EOF) {arr = "";if (IsFilter(ch)) {/*while (IsFilter(ch)) {arr += ch;if (ch == '\n') {l++;}ch = fgetc(fpin);}*/if(ch!=' ')printf("*********************第%d行*********************\n", l);}              //判断是否为过滤符else if (IsLowLetter(ch)) {       //判断是否为关键字while (IsLowLetter(ch)) {arr += ch;ch = fgetc(fpin);}//fseek(fpin,-1L,SEEK_CUR);if (IsKeyword(arr)) {printf("类别编码:%d\t", value(KEYWORD, 100, arr));//cout << arr  << "  关键字" << endl;//if(IaKeyword(arr))cout << "文件中符号:" << arr << " 单词类型:" << "关键字" << endl;//printf("第%d行\t", l);}else{printf("助记符号:BA\t");printf("类别编码:15\t");//cout << arr << "  标识符" << endl;cout << "文件中符号:" << arr << " 单词类型:" << "标识符" << endl;//printf("第%d行\t", l);e++;}}else if (IsDigit(ch)) {           //判断是否为常数while (IsDigit(ch) || (ch == '.' && IsDigit(fgetc(fpin)))) {arr += ch;printf("助记符号:CA\t");ch = fgetc(fpin);}fseek(fpin, -1L, SEEK_CUR);printf("类别编码:16\t");//cout << arr << "  整形数" <<endl;cout << "文件中符号:" << arr << " 单词类型:" << "常数" << endl;//printf("第%d行\t", l);f++;}else if (IsUpLetter(ch) || IsLowLetter(ch) || ch == '_') {while (IsUpLetter(ch) || IsLowLetter(ch) || ch == '_' || IsDigit(ch)) {arr += ch;ch = fgetc(fpin);}fseek(fpin, -1L, SEEK_CUR);printf("类别编码:15\t");//cout << arr << "  标识符" << endl;cout << "文件中符号:" << arr <<" 单词类型:" << "标识符" << endl;//printf("第%d行\t", l);e++;}else if (IsOperator(ch)||ch== '/') {arr += ch;if (ch == '*'){arr += ch;ch = fgetc(fpin);while (ch != '*') {arr += ch;ch = fgetc(fpin);if (ch == '*') {arr += ch;ch = fgetc(fpin);if (ch == '/') {i++;break;}}}}else if (ch == '/') {arr += ch;ch = fgetc(fpin);while (ch != '\n') {arr += ch;ch = fgetc(fpin);if (ch == ' ') {i++;break;}}}else {printf("助记符号:DA\t");printf("类别编码:17\t");//cout << arr << "  运算符" << endl;cout << "文件中符号:" << arr << " 单词类型:" << "运算符" << endl;//printf("第%d行\t", l);c++;}}//else if()else switch (ch) {case '+':case '-':case '*':case '/':case '>':case '<':case '=':case '!':{arr += ch;printf("助记符号:DA\t");printf("类别编码:17\t");//cout << arr << "  运算符" << endl;cout << "文件中符号:" << arr << " 单词类型:" << "运算符" << endl;//printf("第%d行\t", l);c++;break;}case ';':case ',':case '(':case ')':case '[':case ']':case '{':case '}':case ':':{arr += ch;printf("助记符号:EA\t");printf("类别编码:18\t");cout << "文件中符号:" << arr << " 单词类型:"<< "界符" << endl;//printf("第%d行\t", l);b++;break;}default:cout << "\"" << ch << "\":无法识别的字符!" << endl;g++;}}h = a + b + c + e + f + g;printf("文件内容一共有 %d 行\n", l);printf("一共有 %d 个字符\n", h);printf("基本保留字一共有 %d 个\n", a);printf("界符一共有 %d 个\n", b);printf("运算符一共有 %d 个\n", c);printf("标识符一共有 %d 个\n", e);printf("常数一共有 %d 个\n", f);printf("注释共有 %d 处\n", i);printf("错误共有 %d 个\n", g);}int main()
{char inFile[40];FILE* fpin;cout << "请输入源文件名(包括路径和后缀):";while (true) {cin >> inFile;if ((fpin = fopen(inFile, "r")) != NULL)break;else {cout << "文件名错误!" << endl;cout << "请输入源文件名(包括路径和后缀):";}}/*char ch = ' ';while ((ch = fgetc(fpin)) != EOF) {printf("%c", ch);}*/cout << "------词法分析如下------" << endl;cout << "*********************第1行*********************" << endl;//read(fpin);analyse(fpin);system("pause");return 0;}

6 测试和试运行

程序测试

进行测试文件编写,采用txt文件,程序内容如下所示:

int main (){

int a=1,b=2;

b / a;

b >a;

c=a +b;

cout <<c;return 0;int

}

通过对程序进行调试,调试控制台如图所示:

 

输入文件路径并运行,如图所示:

 

 

 

源码地址: https://github.com/wen3017/word-analyse/blob/analyse/word.cpp

课设文件需要留言


http://chatgpt.dhexx.cn/article/81GjhZxj.shtml

相关文章

编译原理词法分析器(C/C++)

前言&思路 词法分析器不用多说&#xff0c;一开始我还不知道是什么样的&#xff0c;看了下别人的博客&#xff0c;再看看书&#xff0c;原来是输出二元组&#xff0c;这不就是字符串操作嘛。然后细看几篇博客&#xff0c;发现大都是用暴力判断来写的。我对代码重复性比较高…

【编译原理】词法分析(C/C++源代码+实验报告)

文章目录 1 实验目的和内容1.1实验目的1.2实验内容 2 设计思想2.1单词种类及其正规式2.2 根据正规式构造NFA2.3根据NFA构造DFA2.3.1根据替换规则构造未化简的DFA2.3.2最小化DFA 3算法流程4源程序5调试数据5.1 测试样例一5.2 测试样例二5.3 测试样例三 6实验调试情况及体会6.1 实…

session 每次请求都会产生新的sessionID

问题描述&#xff1a; 最近在写一个项目时&#xff0c;在运行项目后每刷新一次都会产生一个新的Session ID&#xff0c;导致无法取值。 原因分析&#xff1a; 搞了很久发现是URL路径的问题&#xff0c;把http://localhost:8080//的双斜杠该为单斜杠就行了 解决方案&#xf…

JavaWeb - Cookie、Session、SessionId 详解

一、概述 会话&#xff08;Session&#xff09;跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 本章将系统地讲述Co…

JSESSIONID和sessionid的区别

要保持登陆状态&#xff0c;但是sessionid 和 JSESSIONID的值不一致&#xff0c; 情况一&#xff1a;部署到测试机上&#xff0c;利用本机登陆网页&#xff0c;sessionid和jsessionid不一样。 情况二&#xff1a;部署在本机&#xff0c;本机登陆页面&#xff0c;sessionid和js…

关于两次访问接口的sessionid不一致问题

在测试验证邮箱、注册逻辑时&#xff0c;出现验证码错误的问题。验证码是存放在session内的&#xff0c;在排除了逻辑代码的问题后&#xff0c;检查出这两次访问接口的sessionid并不一致&#xff0c;而在swagger测试接口时是一致的。因此我比较了swagger与ajax请求/响应头的区别…

cookie、session、sessionid 与jsessionid

cookie、session、sessionid 与jsessionid&#xff0c;要想明白他们之间的关系&#xff0c;下面来看个有趣的场景来帮你理解。 我们都知道银行&#xff0c;银行的收柜台每天要接待客户存款/取款业务&#xff0c;可以有几种方案&#xff1a; 凭借柜台职员的记忆&#xff0c;由收…

如何根据sessionID获取session解决方案

点个赞&#xff0c;看一看&#xff0c;好习惯&#xff01;本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录&#xff0c;这是我花了3个月总结的一线大厂Java面试总结&#xff0c;本人已拿腾讯等大厂offer。 另外&#xff0c;原创文章首发在我的个人博客&#…

sessionId的生成过程和过期时间

支持作者 最便宜的卫生纸 浏览器第一次请求服务器时&#xff0c;服务器会生成一个sessionId&#xff0c;并返回给浏览器&#xff0c;这个sessionId会被保存在浏览器的会话cookie中。如下图 在浏览器不关闭的情况下&#xff0c;之后的每次请求请求头都会携带这个sessionId到服务…

session,sessionid,cookie之间的关系解析

session&#xff0c;sessionid&#xff0c;cookie之间的关系解析 文章目录 session&#xff0c;sessionid&#xff0c;cookie之间的关系解析1.简介2.session和cookie定义&#xff0c;创建&#xff0c;周期和联系2.1cookie2.2session 3.如果禁用cookie后&#xff0c;如何解决账号…

dubbox拦截器配置

dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务框架&#xff0c;即使从国际视野来看应该也是一个非常全面的SOA基础框架。作为一个重要的技术研究课题&#xff0c;在当当网我们根据自身的需求&#xff0c;为Dubbo实现了一些新的功能&#xff0c;并将其命名为Dubbox&…

Springboot+Dubbox 提供Rest服务实践

背景 在开发过程中&#xff0c;dubbo接口自测时&#xff0c;通过控制台的invoke方式调用dubbo服务不方便&#xff0c;主要体现在入参设置和入参保存上&#xff08;invoke方式调用dubbo服务请参考&#xff1a;命令行中调用dubbo服务及入参写法_Ypc_victor的专栏-CSDN博客&#…

Dubbo2

一、基础知识 1、分布式基础理论 1.1&#xff09;、什么是分布式系统&#xff1f; 《分布式系统原理与范型》定义&#xff1a; “分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统” 分布式系统&#xff08;distributed system&#…

Dubbox 是什么?

1. Dubbo是什么&#xff1f; Dubbo是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。简单的说&#xff0c;dubbo就是个服务框架&#xff0c;如果没有分布式的需求&#xff0c;其实是不需要用的&#xff0c;只…

分布式服务框架 dubbo/dubbox 入门示例

http://www.cnblogs.com/Javame/p/3632473.html 1. Dubbo是什么&#xff1f; Dubbo是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。简单的说&#xff0c;dubbo就是个服务框架&#xff0c;如果没有分布式的…

SpringBoot整合Dubbox(无XML配置)

##简介 Dubbox是当当网对阿里的Dubbo进行增强的一个分支。在使用springboot之后&#xff0c;我们发现很多配置并不一定要使用xml。这篇文章的目的是让你使用Dubbox时能像使用springboot的其它功能一样可以在application.properties中配置。 ##基础整合 进入https://github.co…

Dubbo进阶(十一)—— Dubbo与DubboX区别

前世今生 Dubbo源于阿里的淘宝网开源分布式服务架构&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;是SOA服务化治理方案的核心框架。淘宝网将其开源之后&#xff0c;得到了很多的拓展和支持&#xff08;比较出名的有&#xff1a;当当网的扩展版本dub…

[Dubbox基础]-- 文档

一、网址 官方&#xff1a;https://github.com/dangdangdotcom/dubbox 参考&#xff1a;https://www.douban.com/note/488997143/ 二、说明 1、问题&#xff1a;https://github.com/dangdangdotcom/dubbox/issues 2、主要&#xff1a; Dubbox now means Dubbo eXtensions. …

浅谈Dubbox原理

Dubbox介绍 Dubbox是一个分布式服务框架&#xff0c;前身是阿里旗下的开源项目Dubbo&#xff0c;后来阿里停止维护&#xff0c;当当网在Dubbo的基础上进行优化&#xff0c;并继续维护&#xff0c;为了与原来的Dubbo区分故将其改名为Dubbox&#xff0c;当当网在其原有的基础上实…

Dubbox 和Dubbo 为何选择

1. 前言 随着现在互联网行业的发展&#xff0c;越来越多的框架、中间件、容器等开源技术不断地涌现&#xff0c;更好地来服务于业务&#xff0c;解决实现业务的问题。然而面对众多的技术选择&#xff0c;我们要如何甄别出适合自己团队业务的技术呢&#xff1f;对于人来说&#…