编译原理笔记7:语法分析(1)语法分析器的任务、语法错误的处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理笔记7:语法分析(1)语法分析器的任务、语法错误的处理相关的知识,希望对你有一定的参考价值。

参考技术A 语法分析器的两项主要任务,分别:

源程序中的错误可以分为词法/语法错误、语义错误两类。前者主要形式是命名不合法、关键字书写错误、语法结构有问题(比如缺分号、该配对的东西不配对)等;后者则可分为静态/动态两种,静态例如类型使用错误、参数使用错误等,动态语义错误则是无穷递归这类逻辑性的问题。

例如:

紧急恢复:x = a+b+d; // 丢弃掉 b 后的记号,直到遇到 +

短语级恢复: x = a+b; // 加入分号

在写程序时,要养成减少错误的好习惯:每次用变量、参数时,要在使用之前进行初始化,并在直接使用之前检查一下是否出现值为空等问题,防止出现不可预知的错误

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

系列第二更!

实验二 自上而下语法分析

实验目的

  • 给出 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;
}

技术图片
















以上是关于编译原理笔记7:语法分析(1)语法分析器的任务、语法错误的处理的主要内容,如果未能解决你的问题,请参考以下文章

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

编译原理笔记 2

编译原理笔记--语法分析

编译原理笔记--语法分析

编译原理复习

编译原理笔记 1