编译原理实验一 词法分析

编译原理实验一 词法分析

实验目的

(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;
}     

程序运行结果:

在这里插入图片描述

实验总结与体会

  • 3
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
附录c 编译程序实验 实验目的:用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 语法分析 C2.1 实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. C2.2 实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. C2.2.1待分析的简单语言的语法 实验目的 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法. 实验要求 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 实验的输入和输出 输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4;x:=(a+b)/c end# 输出的三地址指令如下: (1) t1=3*4 (2) t2=2+t1 (3) a=t2 (4) t3=a+b (5) t4=t3/c (6) x=t4 算法思想 1设置语义过程 (1) emit(char *result,char *arg1,char *op,char *ag2) 该函数功能是生成一个三地址语句送到四元式表中。 四元式表的结构如下: struct {char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[20]; (2)char *newtemp() 该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,…. Char *newtemp(void) { char *p; char m[8]; p=(char *)malloc(8); k++; itoa(k,m,10); strcpy(p+1,m); p[0]=’t’; return(p); } (2)主程序示意图如图c.10所示。 (2) 函数lrparser在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。 语义分析程序的C语言程序框架 int lrparser() { int schain=0; kk=0; if(syn=1) { 读下一个单词符号; schain=yucu; /调用语句串分析函数进行分析/ if(syn=6) { 读下一个单词符号; if(syn=0 && (kk==0)) 输出(“success”); } else { if(kk!=1 ) 输出 ‘缺end’ 错误;kk=1;} else{输出’begin’错误;kk=1;} } return(schain); int yucu() { int schain=0; schain=statement();/调用语句分析函数进行分析/ while(syn=26) {读下一个单词符号; schain=statement(); /调用语句分析函数进行分析/ } return(schain); } int statement() { char tt[8],eplace[8]; int schain=0; {switch(syn) {case 10: strcpy(tt,token); scanner(); if(syn=18) {读下一个单词符号; strcpy(eplace,expression()); emit(tt,eplace,””,””); schain=0; } else {输出’缺少赋值号’的错误;kk=1; } return(schain); break; } } char *expression(void) {char *tp,*ep2,*eplace,*tt; tp=(char *)malloc(12);/分配空间/ ep2=(char *)malloc(12); eplace=(char *)malloc(12); tt =(char )malloc(12); strcpy(eplace,term ());/调用term分析产生表达式计算的第一项eplace/ while(syn=13 or 14) { 操作符 tt= ‘+’或者‘—’; 读下一个单词符号; strcpy(ep2,term());/调用term分析产生表达式计算的第二项ep2/ strcpy(tp,newtemp());/调用newtemp产生临时变量tp存储计算结果/ emit(tp,eplace,tt,ep2);/生成四元式送入四元式表/ strcpy(eplace,tp); } return(eplace); } char *term(void)/仿照函数expression编写/ char *factor(void) {char *fplace; fplace=(char *)malloc(12); strcpy(fplace, “ ”); if(syn=10) {strcpy(fplace,,token);/将标识符token的值赋给fplace/ 读下一个单词符号; } else if(syn=11) {itoa(sum,fplace,10); 读下一个单词符号; } else if (syn=27) {读下一个单词符号; fplace=expression();/调用expression分析返回表达式的值/ if(syn=28) 读下一个单词符号; else{输出‘}’错误;kk=1; } } else{输出‘(’错误;kk=1; } return(fplace); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值