编译原理实验课

本人没咋学编译原理,能力有限,写的不好轻点喷,大佬路过的话,那你就路过就好

东大编译原理实验课原题,22年

1. 基本题:简单的扫描器设计

【问题描述】

熟悉并实现一个简单的扫描器,设计扫描器的自动机;设计翻译、生成Token的算法;编写代码并上机调试运行通过。

要求扫描器可识别的单词包括:关键字、界符、标识符和常整形数。

其中关键字表、界符表、标识符表、常整数表如下:(表中没有的关键字、界符等可以接着编号继续扩展)
在这里插入图片描述
【输入形式】源程序文件

【输出形式】

相应单词的Token序列;

标识符表,常数表。

【样例输入】

x10=x+y1*120+10;

【样例输出】

注意每行输出最后没有多余空格,最后一行输出后不换行。

Token :(I 1)(P 11)(I 2)(P 8)(I 3)(P 9)(C 1)(P 8)(C 2)(P 13)
I :x10 x y1
C :120 10

大体思路

我这里用了unordered_map来对应存<string,int> ,但是unordered_map他存进去后的顺序是胡乱的,不利于输出,我就直接存到vector里输出了,建议可以用pair<string,int> 方便点。
然后就是把想到的一些关键字,界符什么的初始化一下。
文件输入输出就上网一查,很多用法都有,我这里用了一种比较方便的。

从文本里一行一行的读入数据,存到一个string变量里,然后就对这个string从头到尾跑一遍,分三种情况,第一种是界符,如果当前字符是界符,那就再看看下一个字母是不是+,=这样的能够满足==,++,–这样的符号。第二种情况就是第一个字母为数字,这种呢就要么是标识符,要么就是整数了,分情况讨论就行。第三种就是第一个字母是字母,那这种就是要么关键字,要么标识符了
过验收的代码(文件输入输出)
里边的小注释是我用来debug的,一些没用到的变量是给第二题的,第二题题目看着怪怪的,不想写了,也懒得改了

#include<iostream>
#include<unordered_map>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<fstream>
using namespace std;
unordered_map<string,int> keyK;//这个无序是胡乱排序,也不按照自己输入的顺序,后来知道了懒得改了,直接套个vector输出吧
unordered_map<string,int> keyP;
unordered_map<string,int> keyI;
unordered_map<string,int> keyC1;
unordered_map<string,int> keyC2;
unordered_map<string,int> keyCT;
unordered_map<string,int> keyST;
vector<string> I;
vector<string> C1;
vector<string> C2;
vector<string> CT;
vector<string> ST;
int idxI=1,idxC1=1,idxC2=1,idxCT=1,idxST=1;
int kind(char ch)
{
    if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) return 1;
    if (ch>='0'&&ch<='9') return 2;
    if (ch=='-'||ch=='/'||ch=='('||ch==')'||ch=='='||ch=='<'||ch=='>'||ch=='+'||ch=='*'||ch==','||ch==';'||ch=='{'||ch=='}'||ch=='"') return 3;
    return 0;
}
void init()
{
    keyK["int"]=1,keyK["void"]=2,keyK["break"]=3,keyK["float"]=4,keyK["while"]=5;
    keyK["do"]=6,keyK["struct"]=7,keyK["const"]=8,keyK["case"]=9,keyK["for"]=10;
    keyK["return"]=11,keyK["if"]=12,keyK["default"]=13,keyK["else"]=14;
    keyK["long"]=15,keyK["short"]=16,keyK["double"]=17,keyK["char"]=18;
    keyK["unsigned"]=19,keyK["signed"]=20,keyK["union"]=21,keyK["goto"]=22;
    keyK["switch"]=23,keyK["continue"]=24,keyK["typedef"]=25,keyK["cout"]=26;
    keyK["cin"]=27,keyK["main"]=28,keyK["printf"]=29,keyK["scanf"]=30;

    keyP["-"]=1,keyP["/"]=2,keyP["("]=3,keyP[")"]=4,keyP["=="]=5,keyP["<="]=6;
    keyP["<"]=7,keyP["+"]=8,keyP["*"]=9,keyP[">"]=10,keyP["="]=11,keyP[","]=12;
    keyP[";"]=13,keyP["++"]=14,keyP["{"]=15,keyP["}"]=16,keyP["["]=17,keyP["]"]=18;

}
int main()
{
    init();
    //for (auto i:keyK) cout<<i.first<<" "<<i.second<<"\n";
    //for (auto i:keyP) cout<<i.first<<" "<<i.second<<"\n";

    ifstream infile;
    infile.open("data2.txt",ios::in);
    if (!infile.is_open())
    {
        printf("Not found file!\n");
        return 0;
    }
    cout<<"Token :";
    string input;
    while(getline(infile,input))
    {
        for (int i=0;i<(int)input.size();i++)
        {
            string tmp;
            //cout<<i<<" "<<input[i]<<" "<<kind(input[i])<<"\n";
            if (kind(input[i])==3) {
                //cout<<"i=P"<<i<<" ";
                string tt;
                if (input[i+1]=='='||input[i+1]=='+') {
                    tt+=input[i];
                    tt+=input[i+1];
                    cout<<"(P "<<keyP[tt]<<")";
                    i++;
                }
                else {
                    tt+=input[i];
                    cout<<"(P "<<keyP[tt]<<")";
                }
            }
            else if (kind(input[i])==2) {
                //cout<<"i=C"<<i<<" ";
                bool flag=false;
                while (kind(input[i])!=3) {
                    if (kind(input[i])==1) flag=true;
                    tmp+=input[i];
                    i++;
                }
                i--;
                if (keyI.find(tmp)!=keyI.end()) {
                    cout<<"(I "<<keyI[tmp]<<")";
                }
                else if (keyC1.find(tmp)!=keyC1.end()) {
                    cout<<"(C1 "<<keyC1[tmp]<<")";
                }
                else {
                    if (flag) {
                        keyI[tmp]=idxI;
                        I.push_back(tmp);
                        cout<<"(I "<<idxI<<")";
                        idxI++;
                    }
                    else {
                        keyC1[tmp]=idxC1;
                        C1.push_back(tmp);
                        cout<<"(C1 "<<idxC1<<")";
                        idxC1++;
                    }
                }
            }
            else if (kind(input[i])==1) {
                //cout<<"i=K"<<i<<" ";
                bool Find=false;
                while (kind(input[i])!=3) {
                    tmp+=input[i];
                    if (keyK.find(tmp)!=keyK.end()) {
                        Find=true;
                        cout<<"(K "<<keyK[tmp]<<")";
                        break;
                    }
                    i++;
                }
                if (Find) continue;
                i--;
                if (keyK.find(tmp)!=keyK.end()) {
                    cout<<"(K "<<keyK[tmp]<<")";
                }
                else if (keyI.find(tmp)!=keyI.end()) {
                    cout<<"(I "<<keyI[tmp]<<")";
                }
                else {
                    keyI[tmp]=idxI;
                    I.push_back(tmp);
                    cout<<"(I "<<idxI<<")";
                    idxI++;
                }
            }
            //cout<<"2 "<<i<<" "<<input[i]<<" "<<kind(input[i])<<"\n";
        }
    }
    cout<<"\nI :";
    bool flag=false;
    for (auto i:I) {
        if (!flag) flag=true;
        else cout<<" ";
        cout<<i;
    }
    cout<<"\n";
    cout<<"C1 :";
    flag=false;
    for (auto i:C1) {
        if (!flag) flag=true;
        else cout<<" ";
        cout<<i;
    }
    return 0;
}

都能过测试点的代码,虽然说我感觉输出有点奇怪,但能满分就行,懒得管了

#include<iostream>
#include<unordered_map>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<fstream>
using namespace std;
unordered_map<string,int> keyK;//这个无序是胡乱排序,也不按照自己输入的顺序,后来知道了懒得改了,直接套个vector输出吧
unordered_map<string,int> keyP;
unordered_map<string,int> keyI;
unordered_map<string,int> keyC;
vector<string> I;
vector<string> C;
int idxI=1,idxC=1;
int kind(char ch)
{
    if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) return 1;
    if (ch>='0'&&ch<='9') return 2;
    if (ch=='-'||ch=='/'||ch=='('||ch==')'||ch=='='||ch=='<'||ch=='>'||ch=='+'||ch=='*'||ch==','||ch==';'||ch=='{'||ch=='}'||ch=='"') return 3;
    return 0;
}
void init()
{
    keyK["int"]=1,keyK["void"]=2,keyK["break"]=3,keyK["float"]=4,keyK["while"]=5;
    keyK["do"]=6,keyK["struct"]=7,keyK["const"]=8,keyK["case"]=9,keyK["for"]=10;
    keyK["return"]=11,keyK["if"]=12,keyK["default"]=13,keyK["else"]=14;
    keyK["long"]=15,keyK["short"]=16,keyK["double"]=17,keyK["char"]=18;
    keyK["unsigned"]=19,keyK["signed"]=20,keyK["union"]=21,keyK["goto"]=22;
    keyK["switch"]=23,keyK["continue"]=24,keyK["typedef"]=25,keyK["cout"]=26;
    keyK["cin"]=27,keyK["main"]=28,keyK["printf"]=29,keyK["scanf"]=30;

    keyP["-"]=1,keyP["/"]=2,keyP["("]=3,keyP[")"]=4,keyP["=="]=5,keyP["<="]=6;
    keyP["<"]=7,keyP["+"]=8,keyP["*"]=9,keyP[">"]=10,keyP["="]=11,keyP[","]=12;
    keyP[";"]=13,keyP["++"]=14,keyP["{"]=15,keyP["}"]=16,keyP["["]=17,keyP["]"]=18;

}
int main()
{
    init();
    //for (auto i:keyK) cout<<i.first<<" "<<i.second<<"\n";
    //for (auto i:keyP) cout<<i.first<<" "<<i.second<<"\n";
    /*
    ifstream infile;
    infile.open("data2.txt",ios::in);
    if (!infile.is_open())
    {
        printf("Not found file!\n");
        return 0;
    }*/ //这里是文件输入输出,你就在cpp文件位置旁边建一个data2.txt文件就行
    cout<<"Token :";
    string input;
    while(getline(cin,input))
    {
        for (int i=0;i<(int)input.size();i++)
        {
            string tmp;
            //cout<<i<<" "<<input[i]<<" "<<kind(input[i])<<"\n";
            if (kind(input[i])==3) {
                //cout<<"i=P"<<i<<" ";
                string tt;
                if (input[i+1]=='='||input[i+1]=='+') {
                    tt+=input[i];
                    tt+=input[i+1];
                    cout<<"(P "<<keyP[tt]<<")";
                    i++;
                }
                else {
                    tt+=input[i];
                    cout<<"(P "<<keyP[tt]<<")";
                }
            }
            else if (kind(input[i])==2) {
                //cout<<"i=C"<<i<<" ";
                bool flag=false;
                while (kind(input[i])!=3) {
                    if (kind(input[i])==1) flag=true;
                    tmp+=input[i];

                    i++;
                }
                i--;
                if (keyI.find(tmp)!=keyI.end()) {
                    cout<<"(I "<<keyI[tmp]<<")";
                }
                else if (keyC.find(tmp)!=keyC.end()) {
                    cout<<"(C "<<keyC[tmp]<<")";
                }
                else {
                    if (flag) {
                        keyI[tmp]=idxI;
                        I.push_back(tmp);
                        cout<<"(I "<<idxI<<")";
                        idxI++;
                    }
                    else {
                        keyC[tmp]=idxC;
                        C.push_back(tmp);
                        cout<<"(C "<<idxC<<")";
                        idxC++;
                    }
                }
            }
            else if (kind(input[i])==1) {
                //cout<<"i=K"<<i<<" ";
                bool Find=false;
                while (kind(input[i])!=3) {
                    tmp+=input[i];
                    if (keyK.find(tmp)!=keyK.end()) {
                        Find=true;
                        cout<<"(K "<<keyK[tmp]<<")";
                        break;
                    }
                    i++;
                }
                if (Find) continue;
                i--;
                if (keyK.find(tmp)!=keyK.end()) {
                    cout<<"(K "<<keyK[tmp]<<")";
                }
                else if (keyI.find(tmp)!=keyI.end()) {
                    cout<<"(I "<<keyI[tmp]<<")";
                }
                else {
                    keyI[tmp]=idxI;
                    I.push_back(tmp);
                    cout<<"(I "<<idxI<<")";
                    idxI++;
                }
            }
            //cout<<"2 "<<i<<" "<<input[i]<<" "<<kind(input[i])<<"\n";
        }
    }
    cout<<"\nI :";
    bool flag=false;
    for (auto i:I) {
        if (!flag) flag=true;
        else cout<<" ";
        cout<<i;
    }
    cout<<"\n";
    cout<<"C :";
    flag=false;
    for (auto i:C) {
        if (!flag) flag=true;
        else cout<<" ";
        cout<<i;
    }
    return 0;
}

2. 扩展题:扫描器类的设计

【问题描述】

熟悉并实现一个简单的扫描器,设计扫描器的自动机;设计翻译、生成Token的算法;编写代码并上机调试运行通过。

扫描器可识别的单词包括:关键字、界符、标识符和常数(常数包括如:123 123.567 0.567 12.34e+23 …);

要求常整数输出按十进制输出(测试数据中只有16进制与10进制整数),浮点数考虑到精度问题按输入格式输出(测试数据只有10进制浮点数)。同时使用科学计数法的数字都是浮点数。为降低难度,样例3给出一种边界情况供大家调试。

在面对诸如"a+++++b"以及"a+++b"这种丧心病狂的输入时,界符匹配按照从左向右贪心匹配最长界符的策略进行匹配。

判断字符常量及字符串常量单词,将字符和字符串常量分别保存进单独的常量表CT、ST。例如’a’、”OK”;同时字符串与字符常量均不考虑转义字符("“和带”"的都不考虑)。

可以识别简单的词法错误主要形式为’sdddd’、1.sdasf等,尚未定义的单词等。

其中关键字表、界符表、标识符表、常整数表、常实数表、字符表、字符串表如下:(表中除关键词与界符表的表都可以接着编号继续扩展)

在这里插入图片描述
【输入形式】一行带空格的输入。其中关于数字,对于整型保证仅需考虑10进制与16进制数据,对于浮点型保证仅需考虑10进制数据。

【输出形式】

相应单词的Token序列;

标识符表,整数表,实数表,字符表,字符串表

如果错误则输出"ERROR"。
样例输入】

样例1输入:
120+10.3*12.3e-1;

样例2输入:
a="xyz";

样例3输入:
int a=12.1; float b=15e2, c=0x15e2;

样例4输入:
int a='label';

【样例输出】

样例1输出:
Token :(C1 1)(P 8)(C2 1)(P 9)(C2 2)(P 13)
I :
C1 :120
C2 :10.3 12.3e-1
CT :
ST :

样例2输出:
Token :(I 1)(P 11)(ST 1)(P 13)
I :a
C1 :
C2 :
CT :
ST :xyz

样例3输出:
Token :(K 1)(I 1)(P 11)(C2 1)(P 13)(K 4)(I 2)(P 11)(C2 2)(P 12)(I 3)(P 11)(C1 1)(P 13)
I :a b c 
C1 :5602 
C2 :12.1 15e2 
CT :
ST :

样例4输出:
ERROR

语文不好看这第二题题目看的实在蛋疼,小弟这两天事比较多,日后有缘再补下题

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第49题字母异位词分组

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 自定义对 array<int, 26> 类型的哈希函数auto arrayHash [fn hash<int>{}] (const array<int, 26>&…

黑马点评(十二) -- UV统计

一 . UV统计-HyperLogLog 首先我们搞懂两个概念&#xff1a; UV&#xff1a;全称Unique Visitor&#xff0c;也叫独立访客量&#xff0c;是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站&#xff0c;只记录1次。 PV&#xff1a;全称Page View&…

linux权限维持(四)

6.inetd服务后门 inetd 是一个监听外部网络请求 ( 就是一个 socket) 的系统守护进程&#xff0c;默认情况下为 13 端口。当 inetd 接收到 一个外部请求后&#xff0c;它会根据这个请求到自己的配置文件中去找到实际处理它的程序&#xff0c;然后再把接收到的 这个socket 交给那…

机器学习 -- 分类问题

场景 探讨了一个回归任务——预测住房价格&#xff0c;用到了线性回归、决策树以及随机森林等各种算法。本次中我们将把注意力转向分类系统。我们曾经对MNIST进行了分类任务&#xff0c;这次我们重新回到这里&#xff0c;细致的再来一次。 开始 获取数据 Scikit-Learn提供了…

力扣爆刷第127天之动态规划五连刷(整数拆分、一和零、背包)

力扣爆刷第127天之动态规划五连刷&#xff08;整数拆分、一和零、背包&#xff09; 文章目录 力扣爆刷第127天之动态规划五连刷&#xff08;整数拆分、一和零、背包&#xff09;关于0 1 背包问题的总结01背包遍历顺序&#xff1a;完全背包遍历顺序&#xff1a; 一、343. 整数拆…

Lock-It for Mac(应用程序加密工具)

OSXBytes Lock-It for Mac是一款功能强大的应用程序加密工具&#xff0c;专为Mac用户设计。该软件具有多种功能&#xff0c;旨在保护用户的隐私和数据安全。 Lock-It for Mac v1.3.0激活版下载 首先&#xff0c;Lock-It for Mac能够完全隐藏应用程序&#xff0c;使其不易被他人…

【Pytorch】(十四)C++ 加载TorchScript 模型

文章目录 &#xff08;十四&#xff09;C 加载TorchScript 模型Step 1: 将PyTorch模型转换为TorchScriptStep 2: 将TorchScript序列化为文件Step 3: C程序中加载TorchScript模型Step 4: C程序中运行TorchScript模型 【Pytorch】&#xff08;十三&#xff09;PyTorch模型部署: T…

平衡二叉树、红黑树、B树、B+树

Tree 1、前言2、平衡二叉树和红黑树3、B树和B树3.1、B树的构建3.2、B树和B树的区别3.3、数据的存储方式 1、前言 本文侧重在理论方面对平衡二叉树、红黑树、B树和B树的各方面性能进行比较。不涉及编程方面的实现。而关于于平衡二叉树在C中的实现&#xff0c;我的上一篇文章平衡…

Nginx基本使用 反向代理与负载均衡

什么是Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。 其特点是占有内存少&#xff0c;并发能力强&#xff0c;nginx的并发能力在同类型的网页服务器中表现较好&#xff0c;而且几乎可以做到7*24不间断运行&#xff0c;即使运行数个月也不需要重新启动。 …

操作系统安全:Linux安全审计,Linux日志详解

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

【树莓派】yolov5 Lite,目标检测,树莓派4B,推理v5lite-e_end2end.onnx,摄像头实时目标检测

文章目录 YOLOv5 Lite: 在树莓派上轻松运行目标检测1. 环境配置2. 克隆项目3. 安装依赖项4. 下载模型权重5. 理解end2end的含义6. 示例推理7. 文件介绍8. 把文件弄到树莓派4B执行9. 进一步尝试fp16的onnx&#xff08;行不通&#xff09;10. 视频流检测 这里有大概的环境配置&am…

80个在线小游戏源码

源码简介 搭建80个在线小游戏网站源码&#xff0c;解压即可食用&#xff0c;支持在本地浏览器打开。 安装教程 纯HTML&#xff0c;直接将压缩包上传网站目录解压即可 首页截图 源码下载 80个在线小游戏源码-小8源码屋

Mac虚拟机装Windows Mac环境安装Win虚拟机教程 macbookpro安装windows虚拟机

在如今多元的数字时代&#xff0c;我们经常需要在不同的操作系统环境下进行工作和学习。而对于Mac用户来说&#xff0c;有时候需要在自己的电脑上安装Windows操作系统&#xff0c;以体验更多软件及功能&#xff0c;而在Mac安装Windows虚拟机是常用的一种操作。下面就来看看Mac虚…

前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统(LIMS)成品源码 B/S架构

前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统&#xff08;LIMS&#xff09;成品源码 B/S架构 LIMS实验室管理系统 发展历史 实验室信息管理系统(LIMS)&#xff0c;就是指通过计算机网络技术对实验的各种信息进行管理的计算机软、硬件系统。也就是将计算机网络技术与现…

新手答疑 | 零基础该怎么学习嵌入式?嵌入式Linux学习路线是什么?嵌入式开发板推荐?

很多初学者想要涉足嵌入式Linux开发领域&#xff0c;但往往在刚入门阶段&#xff0c;会因为初次接触到大量复杂的概念术语和深奥的技术文档感到压力重重&#xff0c;面对这些内容不知从何下手&#xff0c;感到十分迷茫&#xff0c;网上的内容也纷繁复杂&#xff0c;没有清晰的学…

《前端面试题》- React - 如何区分函数组件和类组件

问题 如何区分函数组件和类组件&#xff1f; 答案 可以使用instanceof 或者Component.prototype.isReactComponent。 示例 函数组件 export default function FunctionComonent() {if(FunctionComonent.prototype.isReactComponent){console.log(FunctionComonent是类组件…

白平衡简介

文章目录 白平衡的概念白平衡的调节常见的白平衡模式 白平衡的概念 白平衡是指摄影、摄像和显示技术中的一项重要概念&#xff0c;用于调节图像中的白色或中性灰色的色彩&#xff0c;使其看起来在不同光源条件下都是准确的白色或灰色。白平衡的主要目的是确保图像的色彩准确性…

C++的二叉搜索树

目录 基本概念 二叉搜索树的实现 插入结点 查找结点 删除结点 删除结点左为空 删除结点右为空 基于特殊情况的优化 删除结点左右不为空 基于特殊情况的优化 完整代码 二叉搜索树的实际应用 K和KV模型 改造二叉搜索树为为KV模型 基本概念 1、二叉搜索树又称二叉…

科技云报道:走入商业化拐点,大模型“开箱即用”或突破行业困局

科技云报道原创。 大模型加速狂飙&#xff0c;AI商业化却陷入重重困境。 一方面&#xff0c;传统企业不知道怎么将AI融入原始业务&#xff0c;另一方面&#xff0c;AI企业难以找到合适的商业化路径。 纵观海外AI玩家&#xff0c;已经有许多企业趟出了自己的商业化道路。 微…

Linux系统安全与应用【一】

目录 1.账号安全控制 1.1 系统账号清理 1.2 密码安全控制 1.3 命令历史限制 1.4 命令总结 2.系统引导和登录控制 2.1 使用su命令切换用户 2.2 限制使用su命令的用户 3.可插拔式认证模块PAM 3.1 linux中的PAM安全认证 3.2 PAM认证原理​编辑 3.3 PAM认证的构成 3.4 P…