编译原理系列 实验二自上而下语法分析

系列第二更!

实验二 自上而下语法分析

实验目的

  • 给出 PL/0 文法规范,要求编写 PL/0 语言的语法分析程序。
  • 通过设计、编制、调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
  • 选择最有代表性的语法分析方法,如递归下降分析法、预测分析法;选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。

题目

【问题描述】
最基本的要求,能对一个算术表达式(a+15)*b做自上而下的语法分析,具体内容见实验指导实验二的内容,文法在实验指导最开始几页,重点关注以下几条文法的EBNF,若不习惯看文法的巴科斯范式EBNF,可先将文法改写成常规的产生式形式P75:
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
考虑到大家用的编程语言不同,且实验一有少数同学没有得到正确结果,为不影响实验二的开展,实验二的输入统一采用词法分析器的输出结果为输入。输入形式如下:
【输入形式】

(lparen,()
(ident,a)
(plus,+)
(number,15)
(rparen,))
(times,*)
(ident,b)

【输出形式】
对于语法正确的表达式,报告“语法正确”,输出为“Yes,it is correct.”
对于语法错误的表达式,报告“语法错误”,输出为“No,it is wrong.”
【样例输入】

(lparen,()
(ident,a)
(plus,+)
(number,15)
(rparen,))
(times,*)
(ident,b)

【样例输出】

Yes,it is correct.

补充说明:学有余力的同学,可以在完成本实验后思考如何将词法分析的程序和语法分析的程序写在一起?以语法分析程序为主程序,词法分析程序为被调用程序,直接用(a+15)b做输入。(注意:这个扩展的写法请不要传到编程题!!!可以写在实验报告中。因为实验二的编程题的测试输入形式我给的不是(a+15)b,而是用(a+15)*b的词法分析的输出作为实验二语法分析的输入,如上面的样例输入形式。)

设计思想

选择递归下降分析方法:
1.设计出每个非终结符的文法识别过程
2.将输入数据进行处理,提取出单词的编码
3.为每个非终结符写识别递归函数
4.函数相互调用

源程序

数据读入和错误处理部分我处理的不是很妥当,对于这个题目是OK的,但是不健壮。

#include <iostream>
#include <string>
#include<bits/stdc++.h>
#define N 8
using namespace std;

string words[N];//每个元素都是“lparen”/“ident”这样的标志符
int sym=0;//words的指针

// 函数声明
void E();
void T();
void F();
// 填充words数组
void getwords()
{
    string line;
    for(int i=0; i<N-1; i++)
    {
        cin >> line;
        int pos = line.find(',', 0);
        words[i] = line.substr(1, pos-1);
        // cout << words[i];
    }
}

// 指针前进
void advance()
{
    ++sym;
    if(sym > N-1){
        cout << "ERROR!words指针越界";
        exit(0);
    }
}
// 因子分析
void F()
{
    //cout << "F正在分析" << words[sym] << endl;

    if(words[sym] == "ident"){
        advance();
    }
    else if(words[sym] == "number") {
        advance();
    }
    else if(words[sym] == "lparen") {
        advance();
        E();
        //cout << "E返回,F正在分析" << words[sym] << endl;
        if(words[sym] == "rparen") {
            advance();
        }
        else {
            //cout << "ERROR!未能匹配右括号!语法错误" << endl;
            exit(0);
        }
    }
    return;
}

// 项分析
void T()
{
    //cout << "T正在分析" << words[sym] << endl;

    F();
    //cout << "1F返回,T正在分析" << words[sym] << endl;
    while(words[sym] == "times" || words[sym] == "slash"){
        advance();
        F();
        //cout << "2F返回,T正在分析" << words[sym] << endl;
    }
    return;
}

// 表达式分析
void E()
{
    //cout << "E正在分析" << words[sym] << endl;

    if(words[sym] == "plus" || words[sym] == "minus"){
        advance();
    }

    T();
    //cout << "1T返回,E正在分析" << words[sym] << endl;

    while(words[sym] == "plus" || words[sym] == "minus") {
        advance();
        T();
        //cout << "2T返回,E正在分析" << words[sym] << endl;
    }
    return;
}
int main()
{
    getwords();
    E();
    if(sym == N-1) {
        cout << "Yes,it is correct." << endl;
    }
    else {
        cout << "No,it is wrong.";
    }

    return 0;
}

image.png

posted @ 2020-05-16 23:43  小塞  阅读(2839)  评论(0编辑  收藏  举报