编译原理实验一 词法分析

本文详细介绍了如何根据PL/0语言文法编写词法分析程序,包括状态图绘制、正则表达式设计、NFA到DFA转换,以及使用C++实现的简单词法分析器。通过这个过程,读者可以深化理解编译原理,提升词法分析实践能力。
摘要由CSDN通过智能技术生成

编译原理实验一 词法分析

实验目的

(1)根据 PL/0 语言的文法规范,编写PL/0语言的词法分析程序;或者调研词法分析程序的自动生成工具LEX或FLEX,设计并实现一个能够输出单词序列的词法分析器。
(2)通过设计调试词法分析程序,实现从源程序中分出各种单方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
(3)掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的法。
(4)掌握词法分析的实现方法。
(5)上机调试编出的词法分析程序。

实验内容

根据PL/0语言的文法规范,编写PL/0语言的词法分析程序。要求:把词法分析器设计成一个独立一遍的过程。词法分析器的输出形式采用二元式序列,即:(单词种类, 单词的值)

实验步骤

(1) 根据PL/0语言的单词符号集,分析词法规则,画出识别单词的状态图。
PL/0语言的词汇表:在这里插入图片描述
识别单词的状态图:在这里插入图片描述
(2) 写出关键字、标识符、常数、运算符、界符各个表达式的正则式。

正规式:(设字母为Z,数字为D,运算符为Y,界符为J)
r = Z(Z|D)|D(D)|Y|J
(3)根据正规式画出NFA
r->NFA:
在这里插入图片描述
(4)NFA确定化为DFA,并对DFA最小化
在这里插入图片描述
DFA(已最小化)
在这里插入图片描述
各个终态含义:
2:界符匹配
3:运算符匹配
4:常数匹配
5:基本字匹配,除基本字外的为标识符
(5)程序的算法流程图:
在这里插入图片描述

源程序及调试运行

#include<iostream>
#include<string>
using namespace std;
int flag=1;   //flag用于判断是关键字还是标识符,为0表示是标识符,为1表示是关键字
void reserved(string str);
int main()
{

    string str1,str;
    while(cin>>str1)   //读入代码
    {
        str=str+' '+str1;
    }

    //开始处理读入的代码
    int length=str.length();
    for(int i=0; i<length; i++)
    {
        if(str[i]==' '||str[i]=='\n')   //当遇到空格或者换行时,跳过该判断继续往下执行
            continue;

        //   识别常数
        else if(isdigit(str[i]))    //如果是数字
        {
            string numbers;
            while(isdigit(str[i]))
            {
                numbers+=str[i];
                i++;
            }
            i--;
            cout<<"(number,"<<numbers<<")"<<endl;
        }

        //  识别基本字/标识符
        else if(isalpha(str[i])) //如果是字母
        {
            string letters;
            while(isalpha(str[i]))
            {
                letters+=str[i];
                i++;
            }
            i--;
            reserved(letters);
            if(flag==0)
            {
                cout<<"(ident,"<<letters<<")"<<endl;
                flag=1;
            }
        }

        //   识别运算符、界符
        else
        {
            switch(str[i])

                //   识别运算符
            {
            case '+':
                cout<<"(plus,+)"<<endl;
                break;
            case '-':
                cout<<"(minus,-)"<<endl;
                break;
            case '*':
                cout<<"(times,*)"<<endl;
                break;
            case '/':
                cout<<"(slash,/)"<<endl;
                break;
            case '=':
                cout<<"(eql,=)"<<endl;
                break;
            case '<':
                i++;
                if(str[i]=='>')
                    cout<<"(neq,<>)"<<endl;
                else if(str[i]=='=')
                    cout<<"(leq,<=)"<<endl;
                else
                {
                    i--;
                    cout<<"(lss,<)"<<endl;
                }
                break;
            case '>':
                i++;
                if(str[i]=='=')
                    cout<<"(geq,>=)"<<endl;
                else
                {
                    i--;
                    cout<<"(gtr,>)"<<endl;
                }
                break;
            case ':':
                i++;
                if(str[i]=='=')
                    cout<<"(becomes,:=)"<<endl;
                else
                    cout<<"illegal character!"<<endl;
                break;

            //  识别界符
            case '(':
                cout<<"(lparen,()"<<endl;
                break;
            case ')':
                cout<<"(rparen,))"<<endl;
                break;
            case ',':
                cout<<"(comma,,)"<<endl;
                break;
            case ';':
                cout<<"(semicolon,;)"<<endl;
                break;
            case '.':
                cout<<"(period,.)"<<endl;
                break;

            // 其他非法字符输出错误信息
            default:
                cout<<"illegal character!"<<endl;
                break;
            }
        }
    }
    return 0;
}

//  识别关键字,若是关键字则直接输出对应的语句,否则说明是标识符,将flag置为0
void reserved(string str)
{

    if(str=="begin")
        cout<<"(beginsym,begin)"<<endl;
    else if(str=="call")
        cout<<"(callsym,call)"<<endl;
    else if(str=="const")
        cout<<"(constsym,const)"<<endl;
    else if(str=="do")
       cout<<"(dosym,do)"<<endl;
    else if(str=="end")
        cout<<"(endsym,end)"<<endl;
    else if(str=="if")
        cout<<"(ifsym,if)"<<endl;
    else if(str=="odd")
        cout<<"(oddsym,odd)"<<endl;
    else if(str=="procedure")
        cout<<"(proceduresym,procedure)"<<endl;
    else if(str=="read")
        cout<<"(readsym,read)"<<endl;
    else if(str=="then")
        cout<<"(thensym,then)"<<endl;
    else if(str=="while")
        cout<<"(whilesym,while)"<<endl;
    else if(str=="var")
        cout<<"(varsym,var)"<<endl;
    else if(str=="write")
        cout<<"(writesym,write)"<<endl;
    else
        flag=0;
}     

程序运行结果:

在这里插入图片描述

实验总结与体会

此资源包含源代码和实验报告。 一、实验目的 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。 二、实验要求 该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、数据、运算符、分界符等五大类,并依次输出各个单词的种类及单词符号自身值。若遇到错误则显示“Error”,然后跳过错误部分继续显示 。 三、实验内容 通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示。 以下是实现词法分析设计的主要工作: (1)从源程序文件中读入字符。 (2)删除空格类字符,包括回车、制表符空格。 (3)按拼写单词,并用(单词,属性)二元式表示。 (4)如果发现错误则报告出错。 单词的基本分类: 关键字:由程序语言定义的具有固定意义的标识符。也称为保留字例如 i f、const; 单词种别码为1。 标识符:用以表示各种名字,如变量名、数组名、函数名;种别码为2。 数据: 任何数值常数。如 125,3.14等;种别码为3。 运算符:+、-、*、/、<、、>=、;种别码为4。 分界符: ; 、, 、(、) 、[、];种别码为5。 Error:#、%等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值