第1关:使用C/C++语言编写PL/0编译程序的词法分析程序

这篇具有很好参考价值的文章主要介绍了第1关:使用C/C++语言编写PL/0编译程序的词法分析程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

任务描述

使用C/C++语言编写PL/0编译程序的词法分析程序。需要注意的点:

(1)识别非法字符:如 @ 、 & 和 ! 等;

(2)识别非法单词:数字开头的数字字母组合;

(3)标识符和无符号整数的长度不超过8位;

(4)能自动识别并忽略/* */及//格式的注释信息;

(5)词法分析过程中遇到错误后能继续往下识别,并输出错误信息。

编程要求

完成上述编程任务,将C/C++语言源程序复制粘贴到右侧代码编辑器,点击“评测”按钮,运行程序,系统会自动进行结果对比。

测试说明

平台会对你编写的代码进行测试:

测试输入:

const a = 10;
var   b, c;

procedure fun1;
    if a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b # 0 do
        begin
            call fun1;
            write(2 * c);
            read(b);
        end
end.

预期输出:

(保留字,const)
(标识符,a)
(运算符,=)
(无符号整数,10)
(界符,;)
(保留字,var)
(标识符,b)
(界符,,)
(标识符,c)
(界符,;)
(保留字,procedure)
(标识符,fun1)
(界符,;)
(保留字,if)
(标识符,a)
(运算符,<=)
(无符号整数,10)
(保留字,then)
(保留字,begin)
(标识符,c)
(运算符,:=)
(标识符,b)
(运算符,+)
(标识符,a)
(界符,;)
(保留字,end)
(界符,;)
(保留字,begin)
(保留字,read)
(界符,()
(标识符,b)
(界符,))
(界符,;)
(保留字,while)
(标识符,b)
(运算符,#)
(无符号整数,0)
(保留字,do)
(保留字,begin)
(保留字,call)
(标识符,fun1)
(界符,;)
(保留字,write)
(界符,()
(无符号整数,2)
(运算符,*)
(标识符,c)
(界符,))
(界符,;)
(保留字,read)
(界符,()
(标识符,b)
(界符,))
(界符,;)
(保留字,end)
(保留字,end)
(界符,.)

测试输入:

const 2a = 123456789;
var   b, c;

//单行注释

/*
* 多行注释
*/

procedure function1;
    if 2a <= 10 then
        begin
            c := b + a;
        end;
begin
    read(b);
    while b @ 0 do
        begin
            call function1;
            write(2 * c);
            read(b);
        end
end.

预期输出:

(保留字,const)
(非法字符(串),2a,行号:1)
(运算符,=)
(无符号整数越界,123456789,行号:1)
(界符,;)
(保留字,var)
(标识符,b)
(界符,,)
(标识符,c)
(界符,;)
(保留字,procedure)
(标识符长度超长,function1,行号:10)
(界符,;)
(保留字,if)
(非法字符(串),2a,行号:11)
(运算符,<=)
(无符号整数,10)
(保留字,then)
(保留字,begin)
(标识符,c)
(运算符,:=)
(标识符,b)
(运算符,+)
(标识符,a)
(界符,;)
(保留字,end)
(界符,;)
(保留字,begin)
(保留字,read)
(界符,()
(标识符,b)
(界符,))
(界符,;)
(保留字,while)
(标识符,b)
(非法字符(串),@,行号:17)
(无符号整数,0)
(保留字,do)
(保留字,begin)
(保留字,call)
(标识符长度超长,function1,行号:19)
(界符,;)
(保留字,write)
(界符,()
(无符号整数,2)
(运算符,*)
(标识符,c)
(界符,))
(界符,;)
(保留字,read)
(界符,()
(标识符,b)
(界符,))
(界符,;)
(保留字,end)
(保留字,end)
(界符,.)

解题思路

双指针 + map

思路分为两步,分别为筛选与识别,筛选就是扫描筛选字符串,提取出符合要求的字符串,为识别做准备,这一步可以用双指针算法实现,而识别就是识别提取出来的字符串,看是否是保留字、运算符、界符、无符号整数、标识符这五个中的一个,这一步可以用map实现识别。

运用双指针算法扫描提取字符串的过程中,注意做好分类识别保留字、运算符、界符、无符号整数、标识符的标记,为后面分类识别做准备。因为保留字、无符号整数、标识符都是由数字或字母组成,所以可以直接扫描筛选由数字或字母组成的字符串,至于界符、运算符可以单独扫描筛选。当扫描提取出字符串时,我们就可以进行分类识别了。最后注释里的内容是无效的,不用识别。文章来源地址https://www.toymoban.com/news/detail-492993.html

代码

//识别保留字、运算符、标识符、界符、无符号整数 (可能还存在没有考虑的情况,仅供参考)
#include<bits/stdc++.h>
using namespace std;
map<string,int> B, Y; //B(保留字)、Y(运算符)
map<char,int> J, y; //J(界符)
string s;
int F; //(标记'/*''*/'注释) 
int main()
{
    B["const"]=B["var"]=B["procedure"]=B["begin"]=B["end"]=B["odd"]=B["if"]=B["then"]=B["call"]=B["while"]=B["do"]=B["read"]=B["write"]=1; //保留字,13个 
    Y["+"]=Y["-"]=Y["*"]=Y["/"]=Y["<"]=Y["<="]=Y[">"]=Y[">="]=Y["#"]=Y["="]=Y[":="]=1; //运算符,11个 
    y['+']=y['-']=y['*']=y['/']=y['<']=y['>']=y['=']=y['#']=y[':']=1;
    J['(']=J[')']=J[',']=J[';']=J['.']=1; //界符,5个
    string s1 = "//", s2 = "/*", s3 = "*/", str;
    for(int id = 1; getline( cin, s); id++) {
        int f = 0; // (标记'//'注释) 
        for(int i=0; s[i]!='\0'; i++) { //双指针算法(扫描识别) 
            while(s[i]!='\0' && (s[i]==' ' || s[i]=='\t')) i++; //去掉空格与'\t'
            int f1 = 0, f2 = 0, f3 = 0, f4 = 0, flog = 0;
            int j1 = i, j2 = i; //j1(保留字、标识符、无符号整数)、j2(运算符)
            if(!((s[i]>='0'&&s[i]<='9') || (s[i]>='a'&&s[i]<='z') || (s[i]>='A'&&s[i]<='Z') || y[s[i]]==1 || J[s[i]]==1)) flog = 1; //标记非法字符
            while(s[j1]!='\0' && ((s[j1]>='0'&&s[j1]<='9') || (s[j1]>='a'&&s[j1]<='z') || (s[j1]>='A'&&s[j1]<='Z')) ) {//识别数字与字母串
                if( s[j1]>='0'&& s[j1]<='9' ) f1 = 1; //标记数字 
                else f2 = 1; //标记字母 
                j1 ++;
            }
            while(s[j2]!='\0' && y[ s[j2] ] == 1) f3 = 1, j2 ++; //识别运算符,并标记运算符 
            if(J[ s[i] ] == 1) f4 = 1; //识别界符,并标记界符
            if(f1 || f2) str =  s.substr( i, j1-i); //提取字符串
            if(f1 == 1 && f2 == 0 && !f && !F) { //无符号整数
                if(str.size() <= 8)  cout<<"(无符号整数,"<<str<<")"<<endl;
                else cout<<"(无符号整数越界,"<<str<<",行号:"<<id<<")"<<endl;
            }
            else if(f2 == 1 && B[str] != 1 && !f && !F) { //标识符
                if(s[i]>='0' && s[i]<='9') cout<<"(非法字符(串),"<<str<<",行号:"<<id<<")"<<endl; //识别非法字符串
                else if(str.size() <= 8) cout<<"(标识符,"<<str<<")"<<endl;
                else cout<<"(标识符长度超长,"<<str<<",行号:"<<id<<")"<<endl;
            }
            else if(f2 == 1 && B[str] == 1 && !f && !F) cout<<"(保留字,"<<str<<")"<<endl; //保留字
            else if( f3 == 1) { //运算符及注释
                str = s.substr( i, j2-i); // 提取字符串
                if(str == s1) f = 1; // '//'注释,标记'//' 
                else if(str == s2) F = 1; // '/*'注释,标记'/*'
                else if(str == s3) F = 0; // '*/'注释,解除'/*/'标记
                else if(!f && !F)
                    cout<<"(运算符,"<<str<<")"<<endl;
            }
            else if(f4 == 1 && !f && !F) //界符 
                cout<<"(界符,"<<s[i]<<")"<<endl;
            else if(flog == 1 && !f && !F) cout<<"(非法字符(串),"<<s[i]<<",行号:"<<id<<")"<<endl; //识别非法字符
            if(j1 != i) i = j1 - 1;
            else if(j2 != i) i = j2 - 1; 
        }
    }
    return 0;
 }

到了这里,关于第1关:使用C/C++语言编写PL/0编译程序的词法分析程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何快速搭建springboot+前后端分离(vue),多商户客户端实现微信小程序+ios+app使用uniapp(一处编写,处处编译)

    kxmalls外卖生鲜多商户,针对中小商户、企业和个人学习者开发。使用Java编码,采用SpringBoot、Mybatis-Plus等易用框架,适合个人学习研究。同时支持单机部署、集群部署,用户与店铺范围动态定位,中小商户企业可根据业务动态扩容。kxmalls使用uniapp前端框架,可同时编译到 微

    2024年01月25日
    浏览(68)
  • 基于天问block编译环境下ASRPRO语音芯片程序编写教程(三)串口通信,多线程模块,ADC篇

    本篇教程将基于天问block内的官方范例代码讲解如何编写ASRPRO语音芯片程序以实现串口通信多线程模块编程和ADC数据读入功能。 ASRPRO语音芯片具有3组可用串口(UART1对应PA2,PA3,UART2对应PA5,PA6,UART0 对应PB5,PB6),同时 UART0 默认是APSRPRO语音芯片的 程序烧录口 ,故在使用时不会

    2023年04月10日
    浏览(45)
  • C语言中程序的编译(预处理操作)+链接详解(详细介绍程序预编译过程)

    今天我们来学习C语言中程序的编译和链接是如何进行的。 在ANSI C的任何一种实现中,存在两个不同的环境。 第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境,它用于实际执行代码。 本文主要是介绍预编译阶段的相关知识。 1.组成一个程

    2023年04月09日
    浏览(35)
  • 基于天问block编译环境下ASRPRO语音芯片程序编写教程(二)语音识别,GPIO输入输出,PWM输出篇

    本篇教程将基于天问block内的官方范例代码讲解如何编写ASRPRO语音芯片程序以实现语音识别,GPIO输入输出和PWM输出功能。  该程序中 添加识别词功能添加命令词选项(黑色部分) 为语音识别功能的核心,通过设定命令词和回复语音实现基础语音对话,通过 对于语音识别ID的运用

    2024年02月04日
    浏览(81)
  • 程序的编译相关操作(C语言)

    📜📜📜📜📜📜📜📜📜📜📜📜📜📜📜 📜📜📜📜📜📜秋已深📜📜📜📜📜📜📜 📜📜📜📜 📜📜 冬将至 📜📜📜📜📜📜 📜📜📜📜📜人间至此秋色尽📜📜📜📜📜 📜📜📜📜📜一世繁华一世荒📜📜📜📜📜 📜📜📜📜📜📜📜📜📜📜📜📜📜📜

    2024年02月21日
    浏览(39)
  • Ubuntu 用gcc/CMakefile编译器 编译、运行c语言程序

    目录 一. 在Ubuntu系统下用c语言编写一个简单的输出hello world 的程序,并编译、运行。 1.1 gcc/g++简介 1.2 c++程序输出 Hello World: 1.3 c语言程序输出 Hello World: 二. 编写一个主程序文件main1.c和一个子程序文件sub1.c,实现函数间的调用 2.1  编写sub1.c 和main1.c 函数 2.1.1 编写sub1.c函数

    2024年02月04日
    浏览(48)
  • 抖音小程序实现less语言编译样式

    2024年02月12日
    浏览(43)
  • 程序环境和预处理(含C语言程序的编译+链接)--2

    文章前言: 上章我们把      程序的翻译环境     程序的执行环境   C语言程序的编译+链接     预定义符号介绍    预处理指令   #define    宏和函数的对比     预处理操作符    #和##的介绍   的相关知识进行了梳理讲解,接下来被把剩余知识    命令定义     预处

    2024年02月14日
    浏览(51)
  • 编译原理1.6习题 程序设计语言基础

    图源:文心一言 编译原理习题整理~🥝🥝 作为初学者的我,这些习题主要用于自我巩固。由于是自学,答案难免有误,非常欢迎各位小伙伴指正与讨论!👏💡 第1版:自己的解题,与AI老师的判卷~🧩🧩 编辑: 梅头脑🌸  审核: 文心一言 题源: 龙书《编译原理》 Alfre

    2024年01月19日
    浏览(55)
  • 【JavaScript】JavaScript 简介 ④ ( 解释型语言 和 编译型语言 | 计算机程序本质 | 编译器 和 解释器 )

    计算机 的 程序 是在 CPU 上执行的 , CPU 上执行的只有匹配该 CPU 的机器码指令 , 不同类型的 CPU 执行的 机器码指令 格式不同 , X86 和 ARM 执行的 机器码 指令格式是不同的 ; 机器码指令 是 二进制的 , 所有在 计算机 上执行的程序 , 都是 若干 二进制机器码 的集合 ; 计算机 只能执

    2024年03月22日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包