LL(1)分析器 实验二
实验要求
简单要求:
至少做到对下列已知的文法,用LL(1)分析法对任意输入的符号串进行分析:
(1)E->TG
(2)G->+TG
(3)G->ε
(4)T->FS
(5)S->*FS
(6)S->ε
(7)F->(E)
(8)F->I
高要求:
1、手动输入文法
2、显示文法的非终结符的Follow集
3、显示规则的可选集合
3、构造预测分析表
4、对任意输入的符号串进行分析
记号和规定
- 空串:$
- 符号栈终止符:#
- 规定第一个产生式的左边那个非终结符就是开始符号
简单要求的固定文法(无左递归)
(1)E->TG
(2)G->+TG
(3)G->ε
(4)T->FS
(5)S->*FS
(6)S->ε
(7)F->(E)
(8)F->I
First Follow Select 集合
非终结符 | First集 | Follow集 | Select集 |
---|---|---|---|
E | ( I | # ) | ( I |
T | ( I | + # ) | ( I |
G | + ε | # ) | + # ) |
F | ( I | + * # ) | ( I |
S | * ε | + # ) | * + # ) |
产生式对应的SELECT集
非终结符 | 产生式 | Slect集 |
---|---|---|
E | E->TG | ( I |
T | T->FS | ( I |
G | G->+TG | + |
G | G->ε | # ) |
S | S->*FS | * |
S | S->ε | + # ) |
F | F->(E) | ( |
F | F->I | I |
分析表
( | I | + | * | ) | # | |
---|---|---|---|---|---|---|
E | TG | TG | synch | synch | ||
T | FS | FS | synch | synch | synch | |
G | +TG | ε | ε | |||
F | (E) | I | synch | synch | synch | synch |
S | ε | *FS | ε | ε |
简单要求(固定文法递归的预测分析)
在主函数中构造一个RecursionSimple对象调用run方法即可运行
运行示例
[递归式固定文法]请输入需要分析的字符串:
I
[递归式固定文法]*****输入的字符串符合该文法*****success*****
[递归式固定文法]请输入需要分析的字符串:
***
[递归式固定文法]#####输入的字符串符不合该文法#####error#####
[递归式固定文法]请输入需要分析的字符串:
(I)
[递归式固定文法]*****输入的字符串符合该文法*****success*****
头文件 RecursionSimple.h
#pragma once
#include<iostream>
using namespace std;
//简单的递归版本 固定文法
class RecursionSimple{
public:
static const string name;
static enum over{Run,Error,Success};
int isOver;
char cur;
int len;
int pos;//当前指向的字符位置
string text;//需要分析的文本
//文法函数
void E();
void T();
void G();
void S();
void F();
//执行函数
void run();
//读入数据 在末尾插入#
void cinData();
//输入的字符串符合文法
void success();
//输入的内容不符合文法处理函数
void error();
//获取下一个字符 如果已经到了末尾则执行 error()
void next();
//输出结果
void coutResult();
};
源文件 RecursionSimple.cpp
#include "RecursionSimple.h"
#define IS_OVER if(isOver!=Run)return;
const string RecursionSimple::name = "[递归式固定文法]";
void RecursionSimple::E(){
IS_OVER
T();
G();
}
void RecursionSimple::T(){
IS_OVER
F();
S();
}
void RecursionSimple::G(){
IS_OVER
if(cur == '+'){
next();
T();
G();
} else if(cur != '+' && cur != ')' && cur != '#')error();
}
void RecursionSimple::S(){
IS_OVER
if(cur == '*'){
next();
F();
S();
} else if(cur != '+' && cur != ')' && cur != '#')error();
}
void RecursionSimple::F(){
IS_OVER
if(cur == '('){
next();
E();
if(cur == ')')next(); else error();
} else if(cur == 'I'){
next();
} else error();
}
void RecursionSimple::run(){
cout << "文法:\n" << "E->TG\n" << "G->+TG\n" << "G->ε\n" << "T->FS\n" << "S->*FS\n" << "S->ε\n" << "F->(E)\n" << "F->I\n";
cinData();//读入数据 并初始化
next();//获取第一个字符
E();//分析开始(首个非终结符函数)
if(cur == '#')success();
else error();
coutResult();//输出结果
}
void RecursionSimple::cinData(){
cout << name << "请输入需要分析的字符串:" << endl;
cin >> text;
text += '#';
pos = 0;
isOver = false;
len = text.length();
}
void RecursionSimple::success(){
isOver = Success;
}
void RecursionSimple::error(){
isOver = Error;
}
void RecursionSimple::next(){
if(pos < len){
cur = text[pos++];
return;
}
error();
}
void RecursionSimple::coutResult(){
if(isOver==Success) cout << name << "*****输入的字符串符合该文法*****success*****" << endl;
else cout << name << "#####输入的字符串符不合该文法#####error#####" << endl;
}
高要求(任意文法非递归的预测分析)
- 读入文法
- 确定终结符与非终结符
- 去除左递归
- First集 Follow集
- 判断是否为LL(1)文法(First与Follow元素不相交)
- Select集
- 预测分析表
- 分析
解析
-
读入文法: A -> @B a | c | $
- 先输入左边 (在这里输入含有 # 的会结束文法输入)
- 再输入右边 (同时输入各种可能 用 | 隔开 非终结符要在前面加@ ,#号结束本次右边输入)
- 不可以包含下划线
- 包含$的将自动转换为$单个字符
-
确定终结符与非终结符
-
去除左递归
- 先将间接左递归转换为直接左递归
- 将所有直接左递归消除
- 删除所有不可达的产生式
-
First集 Follow集
- First集:
- 遍历每一个左部为x的产生式
- 如果产生式右部第一个字符为终结符,则将其计入左部非终
- First集: