【编译原理】LL1文法语法分析器
作者:杨博东的博客
原文:https://blog.csdn.net/yangbodong22011/article/details/53415401
上篇文章 【编译原理】语法分析——自上向下分析 分析了LL1语法,文章最后说给出栗子,现在补上去。
说明:
这个语法分析器是利用LL1分析方法实现的。
预测分析表和终结符以及非终结符都是针对一个特定文法定义好的。
输入的分析串必须以 # 开头和结尾。
原始文法:
E -> E + T | T
T -> T * T | F
F -> (E) | i
消除左递归之后:
E -> TE'
E' -> +TE' | e
T -> FT'
T' -> *FT' | e
F -> (E) | i//备注
e 表示 一步赛楞
E' 在实际程序中用Z代替
T' 在实际程序中用Y代替
程序如下:
// LL2.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<cstdlib>
#include<vector>
#include<string>
#include<stack>
#define BEGIN_SYB 'E'
class Tab { //预测分析表中单个产生式
public:
Tab(char n, char e, std::string p) :noend(n), end(e), prod(p) {};
char noend;
char end;
std::string prod;
};
std::vector<Tab> pTab; //预测分析表
std::stack<char> pStack; //栈
std::string pStr; //输入串
int index = 0; //输入串的下标
int num = 0; //下标
char X; //从栈顶取出的符号
char a; //字符串目前分析到的位置
std::vector<char> VT{ 'i','+','*','(',')','#' }; //终结符号集合
std::vector<char> VN{ 'E','Z','T','Y','F' }; //非终结符号集合
int
isPartVT(char ch)
{
for (auto u : VT) {
if (u == ch) {
return 1;
}
}
return 0;
}
int
isPartVN(char ch)
{
for (auto u : VN) {
if (u == ch) {
return 1;
}
}
return 0;
}
void
initpTab()
{
pTab.push_back(Tab('E', 'i', "TZ")); //Z表示E'
pTab.push_back(Tab('E', '(', "TZ"));
pTab.push_back(Tab('Z', '+', "+TZ"));
pTab.push_back(Tab('Z', ')', "$"));
pTab.push_back(Tab('Z', '#', "$"));
pTab.push_back(Tab('T', 'i', "FY"));
pTab.push_back(Tab('T', '(', "FY")); //Y表示T'
pTab.push_back(Tab('Y', '+', "$"));
pTab.push_back(Tab('Y', '*', "*FY"));
pTab.push_back(Tab('Y', ')', "$"));
pTab.push_back(Tab('Y', '#', "$"));
pTab.push_back(Tab('F', 'i', "i"));
pTab.push_back(Tab('F', '(', "(E)"));
}
void
printStack()
{
std::stack<char> pTemp(pStack);
while (pTemp.size() != 0) {
std::cout << pTemp.top() << " ";
pTemp.pop();
}
std::cout << " ";
}
int
synaly()
{
pStack.push(pStr[index++]);
pStack.push(BEGIN_SYB);
a = pStr[index++];
bool flag = true;
while (flag) {
std::cout << num++ << " "; //输出行号
printStack();
if (pStack.size() != 0) {
X = pStack.top(); //将符号栈顶给X
pStack.pop();
}
if (isPartVT(X)) { //如果是终结符
if (X == '#' && a == '#') {
flag = false;
}
else if (X == a) {
std::cout << std::endl;
a = pStr[index++];
}
else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}
else if (X == '#') {
if (X == a) {
flag = false;
}
else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}
else if (isPartVN(X) && isPartVT(a)) { //如果非终结符
int type = 0;
for (auto u : pTab) {
if (u.noend == X && u.end == a) {
std::string tempProd = u.prod;
std::cout << X << "->" << tempProd << std::endl;
if (tempProd == "$") {
type = 1;
break;
}
else {
for (int i = tempProd.size() - 1; i >= 0; --i) {
pStack.push(tempProd[i]);
}
type = 1;
break;
}
}
}
if (type != 1) {
std::cout << "EROOR!" << std::endl;
return 0;
}
}
else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}
return 1;
}
int main(int argc, char *argv[])
{
initpTab();
std::cout << "请输入语法串:";
std::cin >> pStr;
std::cout << "步骤" << " " << "符号栈" << " " << "所用产生式" << std::endl;
int flag = synaly();
std::cout << std::endl;
if (flag == 1) {
std::cout << "分析成功~~" << std::endl;
}
else {
std::cout << "分析失败~~" << std::endl;
}
system("pause");
return 0;
}