编译原理实验(二):自上而下语法分析-根据 PL/0 语言的文法规范,编写 PL/0 语言的语法分析程序

**

任务说明

**
1. 实验目的
  给出 PL/0 文法规范,要求编写 PL/0 语言的语法分析程序。
  通过设计、编制、调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
  选择最有代表性的语法分析方法,如递归下降分析法、预测分析法;
  选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。
2. 实验准备
  微机安装好 C 语言,或 C++,或 Visual C++.
3.实验内容
  已给 PL/0 语言文法,构造表达式部分的语法分析器。
  分析对象〈算术表达式〉的 BNF 定义如下:
    <表达式> ::= [+|-]<项>{<加法运算符> <项>}
    <项> ::= <因子>{<乘法运算符> <因子>}
    <因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
    <加法运算符> ::= +|-
    <乘法运算符> ::= *|/
    <关系运算符> ::= =|#|<|<=|>|>=
4. 实验要求
  将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”, 指出错误原因。
  把语法分析器设计成一个独立一遍的过程。
  采用递归下降分析法或者采用预测分析法实现语法分析。
5. 输入输出
 输入:
  PL/0 表达式,用实验一的输出形式作为输入。 例如: 对于 PL/0 表达式,(a+15)b 用下列形式作为输入:
  (lparen,()
  (ident,a)
  (plus,+)
  (number,15)
  (rparen,))
  (times,
)
  (ident,b)
 输出:
  对于语法正确的表达式,报告“语法正确”;
  对于语法错误的表达式,报告“语法错误”, 指出错误原因。

具体实现

设计思想

扩充的巴科斯范式
  <表达式> ::= [+|-]<项>{<加法运算符> <项>}
  <项> ::= <因子>{<乘法运算符> <因子>}
  <因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
  <加法运算符> ::= +|-
  <乘法运算符> ::= |/
普通的巴科斯范式
  为表示方便:
  表达式E、项X、因子Y、标识符b,无符号整数z,加法运算符A,乘法运算符C
    E->AX|X|EAX
    X->Y|XCY
    Y->b|z|(E)
    A->+|-
    C->
|/
消除左递归
  E->XE’|AXE’
  E’->AXE’|ε
  X->YX’
  X’->CYX’|ε
  Y->b|z|(E)
  A->+|-
  C->|/
改进后的文法满足LL(1)文法条件,所以该文法是LL(1)的。
FIRST和FOLLOW集合
  FIRST(E)={b,z,(,+,-} FOLLOW(E)={#,)}
  FIRST(E’)={ε,+,-} FOLLOW(E’)={#,)}
  FIRST(X)={b,z,(} FOLLOW(X)={+,-,#,)}
  FIRST(X’)={ε,
,/} FOLLOW(X’)={+,-,#,)}
  FIRST(Y)={b,z,(} FOLLOW(Y)={ ,/,+,-,#}
  FIRST(A)={+,-} FOLLOW(A)={b,z,(}
  FIRST©={
,/} FOLLOW©={b,z,(}

算法流程在这里插入图片描述

代码

#include <iostream>
#include <string>
using namespace std;
int flag=1; //记录分析状态
int p=-1; //指针作用

//分析的单词,s1为编码,s2为单词符号
struct strs
{
   
    string s1,s2;
};

strs analystr;//当前分析的单词

//扫描下一个单词
void Advance(strs *S)
{
   
    p++;
    analystr = S[p];
}

void X
  • 6
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用C语言编写PL/0语言语法分析程序的基本流程: 1. 定义语法规则:首先需要定义PL/0语言语法规则,例如: - 程序:program <程序名>;<分程序>. -程序:const <常量定义部分> var <变量定义部分> procedure <过程说明部分> <语句> 2. 定义文法产生式:将语法规则转换为文法产生式,例如: - 程序:program -> "program" ID ";" <分程序> "." -程序:分程序 -> "const" <常量定义部分> "var" <变量定义部分> "procedure" <过程说明部分> <语句> 3. 构造LL(1)预测分析表:根据文法产生式构造LL(1)预测分析表,例如: | | program | ID | ; | const | var | procedure | <语句> | $ | |----|---------|----|---|-------|-----|-----------|--------|----| | P | 1 | | | | | | 1 | | | B | | | | 2 | 3 | 4 | | | | C | | | | 5 | | | | | | D | | | | | 6 | | | | | E | | 7 | | | | | | | | F | | | | | | 8 | | | | S | | | | | | | 9 | | 其中,P表示程序,B表示分程序,C表示常量定义部分,D表示变量定义部分,E表示ID,F表示过程说明部分,S表示语句。 4. 实现预测分析程序:根据LL(1)预测分析表,实现预测分析程序,例如: ```c void program() { match("program"); match(ID); match(";"); subprogram(); match("."); } void subprogram() { const_declaration(); var_declaration(); procedure_declaration(); statement(); } void const_declaration() { if (lookahead == "const") { match("const"); do { match(ID); match("="); match(NUM); } while (lookahead == ","); match(";"); } } void var_declaration() { if (lookahead == "var") { match("var"); do { match(ID); } while (lookahead == ","); match(";"); } } void procedure_declaration() { if (lookahead == "procedure") { match("procedure"); match(ID); match(";"); subprogram(); match(";"); } } void statement() { // TODO: 实现语句分析 } ``` 其中,match函数用于匹配当前读入的单词和预测分析表中的单词是否相同,如果相同则读入下一个单词,否则报错。 5. 调用预测分析程序:在主函数中,读入词法分析器输出的单词流,调用预测分析程序进行语法分析,例如: ```c int main() { // 读入词法分析结果 lex(); // 调用预测分析程序进行语法分析 program(); // 如果程序能够顺利通过语法分析,则输出“语法分析通过” printf("语法分析通过"); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值