合肥工业大学编译原理实验一词法分析

2023-11-14

基本思路

词法分析是对输入语句串中一个个单词符号进行分析,最后格式化输出种别码,类型,位置等信息。那么,就可以考虑一次读入一个字符将它们拼接成一个字符串,当碰到空格或者分界符(‘,’, ‘;’, ‘)’, ‘(’, ‘[’, ‘]’ )时,就把前面已读的字符串格式化输出,再输出当前分界符,然后再往后读下一个字符,直到程序尾部。

看代码之前

这个程序写得并不是很好,当时时间有限,就随便写写应付验收,但效果还是不错的。还可在此基础上修改修改,提高效率,缩减代码量,比如用利用字典来索引种别码,判断逻辑修改为循环而不是多个if-else等。

完整代码

#include <iostream>
#include <ctype.h>
#include <cstdlib>
#include <cstdio>
using namespace std;
int typeOfWord(string word);//字符串的种别码
void printsub(string word, int row, int col); //格式化输出
bool isDivider(char c);//是否是分界符
bool isrela(char c);//是否是关系运算符
bool isAlop(char c);//算术运算符

string k[8] = {"do", "end", "for", "if", "printf", "scanf", "then", "while"};//关键字
string s[6] = {",", ";", "(", ")", "[", "]"}; //分界符
string aop[4] = {"+", "-", "*", "/"}; //算术运算符表
string rop[6] = {"<", "<=", "=", ">", ">=", "<>"};//关系运算符
string identi[10] = {"a", "i", "n"}; //标识符

int main()
{
    int row, col;
    char c;
    string inString = "", alString = "";
    row = col = 1; //从第一行第一列开始计数
    FILE *fp;
    fp = fopen("source.txt", "r");
    if(fp == NULL)//打开操作不成功
    {
        printf("file open failed.\n");
        return -1;
    }
    cout << "单词\t二元序列\t类型\t位置(行,列)\n";
    cout << "\t(单词种别,单词属性)\n";
    do
    {
        c = fgetc(fp); //读取一个字符
        if(c == EOF)
            break;
        if(isalpha(c))//如果是字母
        {
            inString += c;
            continue;
        }
        else if(isrela(c)) //关系符
        {
            inString += c;
            continue;
        }
        else if(isdigit(c)) //数字
        {
            inString += c;
            continue;
        }
        else if (c == ' ') //如果是空格,就执行输出程序
        {
            printsub(inString, row, col);
            inString = "";
            col += 1; //列加1
            continue;
        }
        else if (c == '\n') //换行符
        {
            row += 1;
            col = 1;
            continue;
        }
        else if(isAlop(c)) //算数运算符
        {
            if(inString.size() != 0)
            {
                printsub(inString, row, col); //先把前一个字符输出
                inString = "";
                col += 1; //列加1
            }
            alString += c;
        }
        else if(isDivider(c))
        {
            if(inString.size() != 0) //如果inString长度不为0,就先输出它
            {
                printsub(inString, row, col); //先把前一个字符输出
                inString = "";
                col += 1; //列加1
            }
            if(alString.size() != 0)//如果alString长度不为0,就再输出它
            {
                printsub(alString, row, col);
                col += 1;
                alString = "";
            }
            //然后再输出当前分界符
            inString = c;
            printsub(inString, row, col);
            inString = "";
            col += 1; //列加1
        }
        else //else啥都不是,就是error
        {
            printf("%6s\t%6s\t%9s\t(%d,%d)\n",inString.c_str(), "Error", "Error", row, col);
            col += 1;
        }
    }while(!feof(fp));
    return 0;
}

int typeOfWord(string word)
{
    int res = 0, i;
    bool found = false;
    if(!found)
        for(i = 0; i < 8; i++) //判断是否为关键字
        {
            if (k[i] == word)
            {
                res = 1;
                found = true;
                break;
            }
        }
    //判断是否为分界符
    if(!found)
        for (i = 0; i < 6; i++)
        {
            if (s[i] == word)
            {
                res = 2;
                found = true;
                break;
            }
        }
    //判断算术运算符
    if(!found)
        for (i = 0; i < 4; i++)
        {
            if (aop[i] == word)
            {
                res = 3;
                found = true;
                break;
            }
        }
    //关系运算符
    if(!found)
        for (i = 0; i < 6; i++)
        {
            if (rop[i] == word)
            {
                res = 4;
                found = true;
                break;
            }
        }
    //判断无符号数
    bool isDigit = true;
    if(!found)
    {
        for (i = 0; i < int(word.size()); i++)
        {
            if (!isdigit(word[i]))
            {
                isDigit = false;
                break;
            }
        }
        if (isDigit)
        {
            found = true;
            res = 5;
        }
        else
            res = -1;
    }
    //查标识符
    bool isIden = false;
    if(!found)
    {
        for (i = 0;i < 10; i++)
        {
            if (word == identi[i])
            {
                isIden = true;
                break;
            }
        }
        if(isIden)
            res = 6;
        else res = -1;
    }
    return res;
}
//格式化输出
void printsub(string word, int row, int col)
{
    int type = typeOfWord(word);
    switch (type)
    {
    case 1:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "关键字", row, col);
        break;

    case 2:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "分界符", row, col);
        break;

    case 3:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "算数运算符", row, col);
        break;

    case 4:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "关系运算符", row, col);
        break;

    case 5:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "常数", row, col);
        break;

    case 6:
        printf("%6s\t(%d,%3s)\t%10s\t(%d,%d)\n",word.c_str(), type, word.c_str(), "标识符", row, col);
        break;

    case -1:
        printf("%6s\t%6s\t%9s\t(%d,%d)\n",word.c_str(), "Error", "Error", row, col);
        break;
    }
}

bool isrela(char c)
{
    bool res = false;
    if (c == '>')
        res = true;
    else if(c == '<')
        res = true;
    else if(c == '=')
        res = true;
    return res;
}

bool isAlop(char c)//这里就可以修改成循环的形式
{
    bool res = false;
    if (c == '+')
        res = true;
    else if(c == '-')
        res = true;
    else if(c == '*')
        res = true;
    else if (c == '/')
        res = true;
    return res;
}

bool isDivider(char c)
{
    char s[] = {',', ';', '(', ')', '[', ']'};
    bool res = false;
    for(int i = 0; i < 6; i++)
    {
        if(s[i] == c)
        {
            res = true;
            break;
        }
    }
    return res;
}

敲重点!

这个实验最坑的是把++运算符也识别为错误,验收时老师可能会问这个怎么实现的,还有就是后面识别3b这种为错是怎么实现的,换成3b45之类的还能不能识别,就这两点需要注意。

如果可能的话

如果这篇文章对你有帮助的话,能否动动小手打个赏呢?下一篇是实验二LL1分析。886

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

合肥工业大学编译原理实验一词法分析 的相关文章

  • AutoSAR系列讲解(实践篇)7.7-实验:配置SWC&RTE(下)

    AutoSAR系列讲解 实践篇 7 7 实验 配置SWC RTE 下 实验 配置SWC RTE 下 三 步骤二 配置Runnable及其Tasks映射 1 添加及配置Runnable 2 打开Cfg并同步工程 3 导入DBC文件 4 创建T
  • FLEX & BISON 联合使用

    flex是词法分析器 bison是语法分析器 基本原理就是flex解析出token后 让bison来使用 实际上 一般是先编写bison脚本 里面的token就是一个定义 没有实现 里面的yylex也是没有实现 只有定义 为什么先做biso
  • 吉首大学_编译原理实验题_基于预测方法的语法分析程序的设计【通过代码】

    一 实验要求 实验二 基于预测方法的语法分析程序的设计 一 实验目的 了解预测分析器的基本构成及用自顶向下的预测法对表达式进行语法分析的方法 掌握预测语法分析程序的手工构造方法 二 实验内容 1 了解编译程序的基于预测方法的语法分析过程 2
  • 编译执行与解释执行的区别

    今天在看到一篇关于分层编译优化的文章时 看到了解释执行与编译执行两个专业词汇 看着熟悉 但不甚理解 然后在网上搜索了一下 说一下自己的理解 对于我们平时写的代码 一般计算机是没办法直接识别的 需要相应的编译器将其编译层机器代码 一些计算机可
  • C++ 实现自动产生LR1分析器的产生器

    C 实现自动产生LR1分析器的产生器 1 介绍 2 总体思路 2 1 拓广文法 2 2 计算First集合 2 3 计算每个闭包的项目集以及GO函数 2 4 计算分析表的动作函数ACTION和状态转换函数GOTO 2 5 对语句进行语法分析
  • 操作系统-在分页式管理方式下采用位示图来表示主存分配情况,实现主存空间的分配和回收。

    实验六 一 实验题目 在分页式管理方式下采用位示图来表示主存分配情况 实现主存空间的分配和回收 二 实验内容 1 分页式存储器把主存分成大小相等的若干块 作业的信息也按块的大小分页 作业装入主存时可把作业的信息按页分散存放在主存的空闲块中
  • LLVM IR / LLVM指令集入门

    本文基于LLVM 12官方文档的LLVM Language Reference Manual 以学习笔记为主 所以本文会摘录一些常见 常用的指令 对于一些更加深层次的指令属性 特性 待我对LLVM有更深的理解再单独写文章记录 1 LLVM
  • 编译原理 实验四 LR(1)分析法程序

    源代码仓库 CompilePrincipleLearning experiment 4 yusixian CompilePrincipleLearning github com 源代码在demo文件夹中 一 实验目的 掌握LR 1 分析法的
  • 解析目标文件

    最近在看 程序员的自我修养 颇有体会 故化繁为简 整理书中部分内容 作为学习笔记 PC平台上流行的可执行文件格式主要是windows下的PE Portable Executable 和Linux下的ELF Executable Linkab
  • PL0语言出错编号表

    Notes 编译原理第 3 版的书貌似没有这个表 做实验和写课设的时候很不方便 把别人拍的第 2 版书上的这个表在这备份一份 Error Code Table 出错编号 出错原因 1 常数说明中的 写成 2 常数说明中的 后应是数字 3 常
  • 编译原理 CS-143(更新至week4)

    编译原理 CS 143 Pre Course Survey Navigation Your Course 01 01 Introduction 8m20s 01 02 Structure of a Compiler 13m53s 编译器结构
  • 数据压缩实验之 JPEG原理分析及JPEG解码器的调试

    文章目录 1 实验名称 2 实验目的 3 主要设备 4 实验内容 4 1 JPEG文件格式 4 2 JPEG编解码原理 4 2 1 编码流程 4 2 2 解码流程 5 实验步骤 5 1 逐步调试JPEG解码器程序 5 1 1 理解程序设计的
  • The Backus-Naur Form (BNF) & The Extended Backus-Naur Form (EBNF)

    The Backus Naur Form BNF The Backus Naur Form BNF is a notation used for formal description of the syntax of programming
  • 语法分析—自上而下分析

    1 美图 2 位置 语法分析器的功能 语法分析的任务是分析一个文法的句子结构 语法分析器的功能 按照文法的产生式 语言的语法规则 识别输入符号串是否为一个句子 合式程序 语法分析的方法 不行 看不懂 我太难了 不看了
  • 【Python】代码实现LL(1),LR(1)上下文无关文法(Stack()类)

    任务要求 针对书上第三章中的表达式文法 采用LL 1 LR 1 进行分析 相关文法 需要进行消除左递归等操作 顺手分享一下课本资源好了 可能不是最新版 排版略有点别扭 后文的书上内容就是指这本书 编译原理 陈意云 文字版 提取码 e0ag
  • LLVM是如何编译指令的

    本文将会通过一条指令在LLVM中的不同阶段 从源程序语言中的语义结构到成为机器二进制码来研究LLVM的工作原理 本文不会介绍LLVM是如何工作的 这需要理解LLVM的设计以及code以及各种细节 输入代码 我们从一段C代码开始探险 如下 i
  • LL(1)文法的预测分析表以及对某输入串的分析过程

    举例说明LL 1 文法的预测分析 以及对 a a 的分析过程 文法G S S gt a S gt S gt T T gt SN N gt SN N gt 是否 gt First集 Follow集 S 否 a T 否 a N 是 Select
  • 编译原理_计算器_flex、bison实现(详细辅助理解)

    编译原理 计算器 flex bison实现 详细辅助理解 个人博客 https www yuque com ngp blog tuanh6 https www yuque com ngp blog tuanh6 P S 这篇文章只能助你理解
  • Compiler- 自增运算

    我们来看一下C语言中的前自增 i 和后自增 i 这个经典案例 大家在学习C的时候肯定学过前自增是先自增 然后将结果用于计算 后自增是先参与计算 再增加 好 看一下这段代码的结果 include
  • 合肥工业大学 汇编语言程序设计 高分实验代码

    感觉最困难的就是写汇编代码了 当时成功完美运行的时候兴奋的像当年第一次 Hello World 一样 且几乎所有关键之处都有注释 需要的朋友自取 链接 https pan baidu com s 1q4nVJ7aK4JEPQ F6PH45R

随机推荐

  • input()函数的使用方法

    关键词 input 函数 摘要 input 函数的使用方法 目录 一 input 函数输入机制与强制转换 二 input 函数的提示项 三 一次性输入多个变量值 一 input 函数输入机制与强制转换 input 函数返回的数据类型均为st
  • 图像分割语义分割mobilenetv1-unet网络 基于pytorch框架制作

    图像分割语义分割mobilenetv1 unet网络 基于pytorch框架制作 全套项目 包含网络模型 训练代码 预测代码 直接下载数据集就能跑 拿上就能用 简单又省事儿 内附四五个数据 供验证使用 ID 1524966108394844
  • 分布式解决方案

    笔者会慢慢写一些关于分布式系统的解决方案 现在微服务系统的流行 所以以前的一些组件已经无法满足系统的高可用性了 笔者会慢慢的介绍一下内容 1 分布式缓存篇 redis 2 分布式存储 MongoDB Mycat 对mysql进行集成 3 分
  • webpack5配置CSS

    webpack只能解析js 需要依赖相关loader进行解析css css css loader 负责将 Css 文件编译成 Webpack 能识别的模块 style loader 会在输出文件中动态创建一个 Style标签 以模块化的形式
  • 世界会走向哪里?

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 世界会走向哪里 作者 阮一峰 1 围棋可能是世界上最复杂的游戏 在一个19根横线乘19根竖线的棋盘上面 有着无穷多种的变化 根据计算 围棋可能的下法共有2 08 x 101
  • 测试用例设计方法-边界值分析法

    边界值分析法 定义 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法 通常边界值分析法是作为对等价类划分法的补充 这种情况下 其测试用例来自等价类的边界 与等价类区别 1 边界值分析不是从某等价类中随便挑一个作为代表 而是使这
  • oracle数据库insert报错:无效的数据类型

    今天工作中往oracle数据库中insert数据的时候遇到这样一个错误 无效的数据类型 日志也打印出error occurred setting parameters 大概就是这意思吧 具体的字母忘了 我也能看出是赋值的数据与数据库对应字段
  • OpenWRT编译错误:Package missing dependencies for the following libraries

    发现问题 今天在 OpenWRT 上增加了个 package 编译的时候 报出如下错误 Package test modules is missing dependencies for the following libraries lib
  • 数据库基本操作练习

    目录 创建数据库sqlserver test1 使用数据库 创建students表 创建classes表 增加数据 注意主键使用自动增加时必须用0代替 查询 查询所有字段 查询指定字段 使用as给字段起别名 使用as给表起别名 消除重复行
  • 【Python数据分析 - 2】:多个坐标系的绘制

    文章目录 多个坐标系绘制的代码 绘图结果 多个坐标系绘制的代码 本文无过多讲解 大部分为代码 提供了解 import matplotlib pyplot as plt import random 设置字体 plt rcParams font
  • 关于Comparator接口和Comparable接口的对比(实例展示)

    我们首先来看看API上是如何解释的 Comparable接口 该接口对实现它的每个类的对象强加一个整体排序 这个排序被称为类的自然排序 类的compareTo方法被称为其自然比较方法 Collections sort 和Arrays sor
  • 用浏览器打不开eureka,且其他服务连接eureka异常

    原因 没有在eureka服务的启动类上添加 EnableEurekaServer注解
  • 回答一位同学的来信

    由于个人隐私的原因 将这位同学的名字匿掉了 因为事先并未征求该同学的意见就将这封信贴了上来 如果该同学认为我侵犯了你的隐私请及时告知我 我会将这篇文章撤掉 之所以发表这篇文章是因为个人觉得它很有代表性 很有可能别的同学也正在为此事困扰着 希
  • 拦截一切的CoordinatorLayout Behavior

    原文地址 http jcodecraeer com a anzhuokaifa androidkaifa 2016 0224 3991 html 如果没有深入CoordinatorLayout 你注定无法在探索Android Design
  • Kibana环境安装及常用命令

    已成功起飞 将自己进大厂前花4w买的java全套教程 整整300集 现在拿出来分享给大家 拿走不谢 从入门到精通 学会即可就业 哔哩哔哩 bilibili 1 安装包解压 tar zxvf kibana 6 4 3 linux x86 64
  • 服务器虚拟cd,如何在VMware虚拟机上安装CD或DVD数据?

    如何在VMware ESX或ESXi里使用CD安装诸如Windows XP Windows Server或Linux这样的操作系统 知道这些是在新子虚拟机上获取操作系统及其应用的关键 对于我们这些使用了好些年服务器和桌面虚拟化的人来说 这些
  • [Python人工智能] 三十六.基于Transformer的商品评论情感分析 (2)keras构建多头自注意力(Transformer)模型

    从本专栏开始 作者正式研究Python深度学习 神经网络及人工智能相关知识 前一篇文章利用Keras构建深度学习模型并实现了情感分析 这篇文章将介绍Transformer基础知识 并通过Keras构建多头自注意力 Transformer 模
  • Qt之右键菜单实现

    最近在看C GUI Qt4部分其中有个例子对于扩展一个应用程序提供一个上下文菜单 Qt中的部件的弹出菜单 ContextMenu 依据ContextMenuPolicy的值的不同 有四种形式 一 默认菜单 此时 ContextMenuPol
  • Python 10(Socket网络编程 )

    本节内容 Socket介绍 参数介绍 基本实例 Socket实现多连接处理 通过Socket实现简单SSH 通过Socket实现文件传送 Socket网络编程 此部分内容涉及到 计算机网络相关知识 OSI七层网络模型 大概的流程如下 通信实
  • 合肥工业大学编译原理实验一词法分析

    基本思路 词法分析是对输入语句串中一个个单词符号进行分析 最后格式化输出种别码 类型 位置等信息 那么 就可以考虑一次读入一个字符将它们拼接成一个字符串 当碰到空格或者分界符 时 就把前面已读的字符串格式化输出 再输出当前分界符 然后再往后