【编译原理】LL(1)分析法代码说在前⾯:
LL(1)差不多是最简单的⽅法了,但是它具有⼀些局限性(所以还需要SLR和LR1⽂法嘛)
从这个⽅法出发,对其他⽅法的理解也能更近⼀步吧。
说第⼆句:
我们知道,LL1表驱动很好写代码,
这⾥就是构建了⼀个结构体Action,⾥⾯是各个状态的函数,对应每⼀步需要做的操作,理解起来直观⼜⽅便。
这⾥以Event1为例⼦说⼀下,这⾥的⽂法规则如下:
E->TA
A->+TA
A->e
A->-TA
T->FB
B->e
B->/FB
B->*FB
F->(E)
F->i
这⾥的事件⼀就是对上⾯的E->TA进⾏响应。注意这⾥是倒序将产⽣式push进⼊状态栈,
这⾥的goto表就是上⾯的ParseTable表。
根据LL1⽂法规定,每次规约都要把栈⾥的元素pop出来再加产⽣式的左边的式⼦(注意要倒序)每次匹配输出都要merge到已匹配⾥⾯,把程序输出,具体如下图
LL1.cpp
C++程序代码:
#include <stdio.h>
#include "stdlib.h"
#include <tchar.h>
#include <iostream>
#include<stack>
using namespace std;
const int NonterminalNum=5; //⾮终结符个数
const int TerminalNum=9; //终结符个数
char nonterminal[NonterminalNum]= {'E','A','T','B','F'}; //定义⾮终结符
char terminal[TerminalNum]= {'i', '+','*','(', ')','e','-','/'}; //定义终结符
stack <char>s;
void Event0();
void Event1();
void Event2();
void Event3();
void Event4();
void Event5();
void Event6();
void Event7();
void Event8();
void Event9();
void Error();
typedef void(*Action)();
Action ParseTable[NonterminalNum][TerminalNum]=
{
{Event1,Error,Error,Event1,Error,Error,Error,Error,Error},
{Error,Event2,Error,Error,Event3,Event3,Event3,Event4,Error},
{Event5,Error,Error,Event5,Error,Error,Error,Error,Error},
{Error,Event6,Event8,Error,Event6,Event6,Event6,Event6,Event7,},
{Event0,Error,Error,Event9,Error,Error,Error,Error,Error}
};
void Event1()
{
s.pop();
s.push('A');
s.push('T');
};
void Event2()
{
s.pop();
s.push('A');
s.push('T');
s.push('+');
};
void Event3()
{
s.pop();
};
void Event4()
{
s.pop();
s.push('A');
s.push('T');
s.push('-');
};
void Event5()
{
s.pop();
s.push('B');
s.push('F');
};
void Event6()
{
s.pop();
};
void Event7()
{
s.pop();
s.push('B');
s.push('F');
s.push('/');
};
void Event8()
{
s.pop();
s.push('B');
s.push('F');
s.push('*');
};
void Event9()
{
s.pop();
s.push(')');
s.push('E');
s.push('(');
};
void Event0()
{
s.pop();
s.push('i');
};
void Error()
{
cerr<<"------分析失败!------\n"; exit(1);
};
/**
* 看⼀下是不是终结符
* 看⼀下是不是终结符
*/
bool isVt(char ch)
{
for(int i=0; i<9; i++)
{
if(terminal[i]==ch)
return true;
else continue;
}
return false;
}
void pushTogether(char nonterminal, char terminal) {
switch(nonterminal)
{
case 'E':
switch(terminal)
{
case 'i':
ParseTable[0][0]();
break;
case '+':
ParseTable[0][1]();
break;
case '*':
ParseTable[0][2]();
break;
case '(':
ParseTable[0][3]();
break;
case ')':
ParseTable[0][4]();
break;
case ';':
ParseTable[0][5]();
break;
case 'e':
ParseTable[0][6]();
break;
case '-':
ParseTable[0][7]();
break;
case '/':
ParseTable[0][8]();
break;
case '#':
ParseTable[0][9]();
break;
default:
break;
}error parse new
break;
case 'A':
switch(terminal)
{
case 'i':
ParseTable[1][0]();
break;
case '+':
ParseTable[1][1]();
break;
case '*':
ParseTable[1][2]();
break;
case '(':
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论