课 程 设 计 书
目 录
一、设计内容·····························································1 二、目的与基本要求·······················································1 三、语法分析器的功能·····················································1 四、算法分析····················································1 4.1相关理论介绍········································1 4.2设计原理····················································2 4.3构造LL(1)分析表·································3 4.4利用分析表进行预测分析的步骤······························5 4.5···································6 五、流程框图·················································6 六、函数相关说明··············································8 七、参考程序清单·············································8 八、程序运行结果···········································17 九、使用方法·················································19 十、····················································20 ···························································20
课 程 设 计 书
语 法 分 析 器
—预测分析法
一、设计内容
用预测分析法(即LL (1)分析法)构造文法G[E]:
E → E + T | T T → T * F | F
F → ( E ) | i | x | y
的预测分析程序(即语法分析器)。
二、目的与基本要求
1析的条件。
2、学会用C/C++LL (1)分析法的语法分析器; 3
4.1相关理论介绍
语法分析是编译过程的核心部分。语法分析的任务就是识别词法分析程序输出的单词序列是否为给定方法的正确句子,并确定其语法结构。尽管目前已提出很多语法分析方法,但总体上语法分析的方法可分为两大类:自顶向下的分析方法和自底向上的分析方法。
课 程 设 计 书
自底向上的分析方法就是归约的方法,即从待分析符号串出发,从底向上构造语法树,若能够造至树根(能够归约到方法开始符号),则表示该符号串是方法的句子。
自顶向下的分析法其实就是推导的方法,也就是从方法的开始符号出发,试图向下构造待分析符号串的语法树,若语法的叶结点可以构成该符号串(能够推导出该符号串),则表示这个符号串是方法的句子。自顶向下的分析方法又分为:带回溯的自顶向下分析方法和确定的自顶向下分析方法。一个文法如果要能进行确定的自顶向下分析,必须满足什么条件呢?
由可选集的定义可知,规则A →x 的可选集SELECT (A →x 推导出的下一个终结符号的集合。因此利用SELECT 据当前输入的符号有目的的选择产生式。
U →X i )(i=1,2,3,„,n ) ,求可选集。这样,U ,待输入符号为a, 且a ∈SELECT (U →X i 一定能推导出等输入符号a 。
a ∉SELECT (U (,n,i ≠j ) 。
一个非终结符A A x 1 |x2|„|xn ,满足SELECT (A →x i )⋂SELECT(A→x j )=φ„,即同一个非终结符各规则的SELECT 集两两不相交。
LL (1)分析法等, 下面详细介绍预测,的相关理论,分析表构造,预测分析过程。
4.2设计原理
所谓LL (1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL (1)分析的程序又称为LL (1)分析程序或LL (1)分析器。
我们知道一个文法要能进行LL (1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST 和
课 程 设 计 书
FOLLOW 集合,然后根据FIRST 和FOLLOW 集合构造LL (1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL (1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:
的
4.3 构造LL(1)分析表
考查文法G[E]:
E →E+T | T
T →T*F | F
F →( E ) | i | x | y
课 程 设 计 书
我们容易看出此文法没有左公因子也没有二义性,但却存在两个直接左递归,这里我们利用引入新非终结符的方法来消除它使方法满足要求,即:
对形如:U →Ux|y的产生式(其中x,y ∈V + ,y 不以U 开头),引入一个新的非终结符U ’后,可以等价地改写成为:
U →yU ’
U ’→x U’|ε
显然改写后,U 和U ’都不是左递归的非终结符。因此文法G [E 归后可等价地写成:
E →TP
P→+TP | ε T→FQ
Q→*FQ | ε
F →( E ) | i | x | y
在构造LL(1)FIRST 和FOLLOW ①FIRST 集合的构造算法:
(1)若X ∈V T ,则FIRST ((2)若X ∈V N X a 加入到FIRST(X)中;若X →ε也是一条产生式,则把ε(3)若X →Y V N ,则把FIRST(Y)中的所有非ε-元素都加到FIRST(X)中;若Y 1Y 2k Y 1,„,Y i-1都是非终结符,而且,对于任何j ,1≤j ≤j ε(即Y 1„Y i-1*⇒ε),则把FIRST(Yj ) 中的所有非ε-FIRST(Yj ) 均含有ε,j=1,2,„,k ,则把ε加到FIRST 不再增大为止。
S ,置#于FOLLOW(S)中;
(2)若→αB β是一个产生式,则把FIRST(β)| {ε}加至FOLLOW(B)中; (3)若A →αB 是一个产生式,或A →αB β是一个产生式而β⇒ε(即ε∈FIRST(β) ),则把FOLLOW(A)加至FOLLOW(B)中。
连续使用上面的规则,直至每个集合FOLLOW 不再增大为止。
根据以上描述的算法,可以构造文法G [E ]的FIRST 和FOLLOW 集合如下:
FIRST(E) = {( , i,x ,y } FOLLOW(E) = { ) , # }
课 程 设 计 书
FIRST(P) = { + ,ε} FIRST(T) = { ( , i,x ,y } FIRST(Q) = { * , ε} FIRST(F) = { ( , i,x ,y } FOLLOW(P) = { ) , # } FOLLOW(T) = { + , ) , # } FOLLOW(Q) = { + , ) , # } FOLLOW(F) = { * , + , ) , # }
现在来构造G [E ]的LL (1)预测分析表。预测分析表M[A, a]是如下形式的一个矩阵。A 为非终结符,a 是终结符或‘#’。矩阵元素 M[A, a]中存放这一条关于A 的产
课 程 设 计 书
4.5预测分析程序的总控程序的算法描述
实现LL(1)的一种有效方法是使用一张分析表和一个栈进行联合控制。如果前面已经设计好了分析表和栈的话,那么现在就开始具体实现这个LL(1)LL(1)分析程序的算法的描述如下:
BEGIN
首先把‘#’然后把文法开始符号推进STACK 分析栈; 把第一个输入符号读进a ; FLAG = TURE; WHILE FLAG DO BEGIN
把STACK IF X∈V T THEN
a ELSE ‘ →X 1X 2„„X k } THEN 把X k-1X 1,一一推进STACK 栈 若1X k = ε,不推进什么进栈 */ 分析成功 */
五、流程框图
课 程 设 计 书
课 程 设 计 书
六、函数相关说明
分析栈可以采取许多的存储方法来设计,在这里采用的顺序栈。这里定义了一个类Stack ,将所有对栈的操作封装在Stack 类中,作为它的成员函数。
根据预测分析器模型,LL(1)分析器的实现关键在于分析栈和分析表是采用何种数据结构来实现。分析表是一个矩阵,当我们要调用分析表来分析时,就根据栈顶的非终结符和当前输入的终结符来决定执行哪种过程。具体设计思想如下:
//声明:每个Event 执行一个特定的进栈处理,Error 将抛出错误 void Event1(); void Event2(); void Event3(); void Event4(); void Event5(); void Event6(); void Event7(); void Error();
typedef void (*Action)();
// };
#if !defined(AFX_STACK_H__AA8994AF_8B3A_477C_A4CC_6F18499CA9BE__INCLUDED_)
#define AFX_STACK_H__AA8994AF_8B3A_477C_A4CC_6F18499CA9BE__INCLUDED_
#if _MSC_VER > 1000 #pragma once
课 程 设 计 书
#endif // _MSC_VER > 1000
class Stack {
public:
Stack(); ~Stack();
void push(char token); char pop(); bool isEmpty();
private:
char *_stack; int _top; int _bottom; };
#endif
// D_)
// stack
// Construction/Destruction
Stack::Stack() {
_stack=new char [InitStackSize]; _top=_bottom=-1;
课 程 设 计 书
}
Stack::~Stack() {
_top=_bottom=-1; delete _stack; }
// Attributes
void Stack::push(char token) {
if(_top>=InitStackSize-1) {
exit(1); }
_top++;
_stack[_top]=token; }
{
{
}
}
bool Stack::isEmpty() {
if(_top==_bottom) return true; else
课 程 设 计 书
return false; }
// 分析表的构造 #include "Stack.h" #include
using namespace std;
const int NonterminalNum=5; //非终结符个数 const int TerminalNum=7; //终结符个数
char nonterminal[]={'E', 'P', 'T', 'Q','F'}; //
定义终结符 Stack stack;
// 事件描述与LL (1)分析表
void Event1(); void Event2(); void Event3(); void Event4(); void Event5(); void Event6();
{Event4, Error, Error, Event4, Error, Error}, {Error, Event3, Event5, Error, Event3, Event3}, {Event6, Error, Error, Event7, Error, Error} };
// 定义事件
课 程 设 计 书
void Event1() {
stack.push('P'); stack.push('T'); };
void Event2() {
stack.push('P'); stack.push('T'); stack.push('+'); };
void Event3() { };
void Event4() {
stack.push('Q'); };
{
void Event6() {
stack.push('i'); stack.push('x'); stack.push('y'); };
课 程 设 计 书
void Event7() {
stack.push(')'); stack.push('E'); stack.push('('); };
// 出错处理
void Error() {
cerr
// 判断 Token
bool isVt(char ch) {
{
// 字符串入 Stack 分析栈
void pushTogether(char nonterminal, char terminal) {
switch(nonterminal) {
课 程 设 计 书
case 'E':
switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': ParseTable[4][3](); break; case '*': ParseTable[4][4](); break; case '(': ParseTable[4][5](); break; case ')': ParseTable[4][6](); break; case '#': ParseTable[4][7](); break; default: break; }
break;
case 'P':
switch(terminal) {
case 'i': case 'x': case 'y': switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': ParseTable[4][3](); break; case '*': ParseTable[4][4](); break;
课 程 设 计 书
case '(': case ')': case '#': default: }
break;
ParseTable[4][5](); break; ParseTable[4][6](); break; ParseTable[4][7](); break; break;
case 'Q':
switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': case '*': case '(': case ')': case '#': default: break; }
break;
case 'F':
{
ParseTable[4][2](); break; ParseTable[4][3](); break; ParseTable[4][4](); break; ParseTable[4][5](); break; case ')': ParseTable[4][6](); break; case '#': ParseTable[4][7](); break; default: break; }
break; default:
课 程 设 计 书
Error(); break; } }
// LL(1)分析程序 #include #include "Stack.h" #include "Parse.h"
using namespace std; void LL1Parse() {
stack.push('#'); stack.push('E');
char a;
cout
{
//match
Error(); {
if(X==a) //parse successfully flag=false; else
Error(); }
else //reverse, push into stack
课 程 设 计 书
pushTogether(X, a); }
if(stack.isEmpty())
cout
// 主程序
#include #include "LL1.h" using namespace std; void main() {
cout
cout
cout
cout
i+i*i#, 显示“分析成功”。
课 程 设 计 书
显示“分析失败!”。运行结果如下:
课 程 设 计 书
九、使用方法
程序在VC++6.0下调试通过。打开VC6.0执行“文件”—>“新建”, 编辑上面的源程序,完成后单击“保存”(aa.cpp ),再单击菜单栏的“编译”—>“编译 aa.cpp”或按Ctrl+F7;“编译”—>“构件 aa.exe”或按F7;“编译”—>“执行 aa.exe”或按Ctrl+F5。
当然你也可以找aa.cpp 文件所在目录的“debug 目录”aa.exe, 拷贝到别的目录下面再在DOS 下来执行它。这里我把它拷到“然后执行“Win+R”,输入“CMD ”进入DOS, 接着执行“cd\”C:\录,再执行aa 回车。如下图:
课 程 设 计 书
十、课程设计心得
本次课程设计完成了语法分析器-预测分析法(即LL (1)分析法)的算法分析到实现的全部过程,结果满足设计要求,验证无误。在整整一个星期的日子里同时做两个课程设计,可以说是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课刻,掌握得不够牢固等等。
经努力过。
[1. 重庆大学出版社,2005年8月。
[2语言程序设计. 清华大学出版社,2005年月1月。
《编译原理》课程设计—预测分析法LL (1) 第21页
课 程 设 计 书
目 录
一、设计内容·····························································1 二、目的与基本要求·······················································1 三、语法分析器的功能·····················································1 四、算法分析····················································1 4.1相关理论介绍········································1 4.2设计原理····················································2 4.3构造LL(1)分析表·································3 4.4利用分析表进行预测分析的步骤······························5 4.5···································6 五、流程框图·················································6 六、函数相关说明··············································8 七、参考程序清单·············································8 八、程序运行结果···········································17 九、使用方法·················································19 十、····················································20 ···························································20
课 程 设 计 书
语 法 分 析 器
—预测分析法
一、设计内容
用预测分析法(即LL (1)分析法)构造文法G[E]:
E → E + T | T T → T * F | F
F → ( E ) | i | x | y
的预测分析程序(即语法分析器)。
二、目的与基本要求
1析的条件。
2、学会用C/C++LL (1)分析法的语法分析器; 3
4.1相关理论介绍
语法分析是编译过程的核心部分。语法分析的任务就是识别词法分析程序输出的单词序列是否为给定方法的正确句子,并确定其语法结构。尽管目前已提出很多语法分析方法,但总体上语法分析的方法可分为两大类:自顶向下的分析方法和自底向上的分析方法。
课 程 设 计 书
自底向上的分析方法就是归约的方法,即从待分析符号串出发,从底向上构造语法树,若能够造至树根(能够归约到方法开始符号),则表示该符号串是方法的句子。
自顶向下的分析法其实就是推导的方法,也就是从方法的开始符号出发,试图向下构造待分析符号串的语法树,若语法的叶结点可以构成该符号串(能够推导出该符号串),则表示这个符号串是方法的句子。自顶向下的分析方法又分为:带回溯的自顶向下分析方法和确定的自顶向下分析方法。一个文法如果要能进行确定的自顶向下分析,必须满足什么条件呢?
由可选集的定义可知,规则A →x 的可选集SELECT (A →x 推导出的下一个终结符号的集合。因此利用SELECT 据当前输入的符号有目的的选择产生式。
U →X i )(i=1,2,3,„,n ) ,求可选集。这样,U ,待输入符号为a, 且a ∈SELECT (U →X i 一定能推导出等输入符号a 。
a ∉SELECT (U (,n,i ≠j ) 。
一个非终结符A A x 1 |x2|„|xn ,满足SELECT (A →x i )⋂SELECT(A→x j )=φ„,即同一个非终结符各规则的SELECT 集两两不相交。
LL (1)分析法等, 下面详细介绍预测,的相关理论,分析表构造,预测分析过程。
4.2设计原理
所谓LL (1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。实现LL (1)分析的程序又称为LL (1)分析程序或LL (1)分析器。
我们知道一个文法要能进行LL (1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。当文法满足条件后,再分别构造文法每个非终结符的FIRST 和
课 程 设 计 书
FOLLOW 集合,然后根据FIRST 和FOLLOW 集合构造LL (1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。LL (1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:
的
4.3 构造LL(1)分析表
考查文法G[E]:
E →E+T | T
T →T*F | F
F →( E ) | i | x | y
课 程 设 计 书
我们容易看出此文法没有左公因子也没有二义性,但却存在两个直接左递归,这里我们利用引入新非终结符的方法来消除它使方法满足要求,即:
对形如:U →Ux|y的产生式(其中x,y ∈V + ,y 不以U 开头),引入一个新的非终结符U ’后,可以等价地改写成为:
U →yU ’
U ’→x U’|ε
显然改写后,U 和U ’都不是左递归的非终结符。因此文法G [E 归后可等价地写成:
E →TP
P→+TP | ε T→FQ
Q→*FQ | ε
F →( E ) | i | x | y
在构造LL(1)FIRST 和FOLLOW ①FIRST 集合的构造算法:
(1)若X ∈V T ,则FIRST ((2)若X ∈V N X a 加入到FIRST(X)中;若X →ε也是一条产生式,则把ε(3)若X →Y V N ,则把FIRST(Y)中的所有非ε-元素都加到FIRST(X)中;若Y 1Y 2k Y 1,„,Y i-1都是非终结符,而且,对于任何j ,1≤j ≤j ε(即Y 1„Y i-1*⇒ε),则把FIRST(Yj ) 中的所有非ε-FIRST(Yj ) 均含有ε,j=1,2,„,k ,则把ε加到FIRST 不再增大为止。
S ,置#于FOLLOW(S)中;
(2)若→αB β是一个产生式,则把FIRST(β)| {ε}加至FOLLOW(B)中; (3)若A →αB 是一个产生式,或A →αB β是一个产生式而β⇒ε(即ε∈FIRST(β) ),则把FOLLOW(A)加至FOLLOW(B)中。
连续使用上面的规则,直至每个集合FOLLOW 不再增大为止。
根据以上描述的算法,可以构造文法G [E ]的FIRST 和FOLLOW 集合如下:
FIRST(E) = {( , i,x ,y } FOLLOW(E) = { ) , # }
课 程 设 计 书
FIRST(P) = { + ,ε} FIRST(T) = { ( , i,x ,y } FIRST(Q) = { * , ε} FIRST(F) = { ( , i,x ,y } FOLLOW(P) = { ) , # } FOLLOW(T) = { + , ) , # } FOLLOW(Q) = { + , ) , # } FOLLOW(F) = { * , + , ) , # }
现在来构造G [E ]的LL (1)预测分析表。预测分析表M[A, a]是如下形式的一个矩阵。A 为非终结符,a 是终结符或‘#’。矩阵元素 M[A, a]中存放这一条关于A 的产
课 程 设 计 书
4.5预测分析程序的总控程序的算法描述
实现LL(1)的一种有效方法是使用一张分析表和一个栈进行联合控制。如果前面已经设计好了分析表和栈的话,那么现在就开始具体实现这个LL(1)LL(1)分析程序的算法的描述如下:
BEGIN
首先把‘#’然后把文法开始符号推进STACK 分析栈; 把第一个输入符号读进a ; FLAG = TURE; WHILE FLAG DO BEGIN
把STACK IF X∈V T THEN
a ELSE ‘ →X 1X 2„„X k } THEN 把X k-1X 1,一一推进STACK 栈 若1X k = ε,不推进什么进栈 */ 分析成功 */
五、流程框图
课 程 设 计 书
课 程 设 计 书
六、函数相关说明
分析栈可以采取许多的存储方法来设计,在这里采用的顺序栈。这里定义了一个类Stack ,将所有对栈的操作封装在Stack 类中,作为它的成员函数。
根据预测分析器模型,LL(1)分析器的实现关键在于分析栈和分析表是采用何种数据结构来实现。分析表是一个矩阵,当我们要调用分析表来分析时,就根据栈顶的非终结符和当前输入的终结符来决定执行哪种过程。具体设计思想如下:
//声明:每个Event 执行一个特定的进栈处理,Error 将抛出错误 void Event1(); void Event2(); void Event3(); void Event4(); void Event5(); void Event6(); void Event7(); void Error();
typedef void (*Action)();
// };
#if !defined(AFX_STACK_H__AA8994AF_8B3A_477C_A4CC_6F18499CA9BE__INCLUDED_)
#define AFX_STACK_H__AA8994AF_8B3A_477C_A4CC_6F18499CA9BE__INCLUDED_
#if _MSC_VER > 1000 #pragma once
课 程 设 计 书
#endif // _MSC_VER > 1000
class Stack {
public:
Stack(); ~Stack();
void push(char token); char pop(); bool isEmpty();
private:
char *_stack; int _top; int _bottom; };
#endif
// D_)
// stack
// Construction/Destruction
Stack::Stack() {
_stack=new char [InitStackSize]; _top=_bottom=-1;
课 程 设 计 书
}
Stack::~Stack() {
_top=_bottom=-1; delete _stack; }
// Attributes
void Stack::push(char token) {
if(_top>=InitStackSize-1) {
exit(1); }
_top++;
_stack[_top]=token; }
{
{
}
}
bool Stack::isEmpty() {
if(_top==_bottom) return true; else
课 程 设 计 书
return false; }
// 分析表的构造 #include "Stack.h" #include
using namespace std;
const int NonterminalNum=5; //非终结符个数 const int TerminalNum=7; //终结符个数
char nonterminal[]={'E', 'P', 'T', 'Q','F'}; //
定义终结符 Stack stack;
// 事件描述与LL (1)分析表
void Event1(); void Event2(); void Event3(); void Event4(); void Event5(); void Event6();
{Event4, Error, Error, Event4, Error, Error}, {Error, Event3, Event5, Error, Event3, Event3}, {Event6, Error, Error, Event7, Error, Error} };
// 定义事件
课 程 设 计 书
void Event1() {
stack.push('P'); stack.push('T'); };
void Event2() {
stack.push('P'); stack.push('T'); stack.push('+'); };
void Event3() { };
void Event4() {
stack.push('Q'); };
{
void Event6() {
stack.push('i'); stack.push('x'); stack.push('y'); };
课 程 设 计 书
void Event7() {
stack.push(')'); stack.push('E'); stack.push('('); };
// 出错处理
void Error() {
cerr
// 判断 Token
bool isVt(char ch) {
{
// 字符串入 Stack 分析栈
void pushTogether(char nonterminal, char terminal) {
switch(nonterminal) {
课 程 设 计 书
case 'E':
switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': ParseTable[4][3](); break; case '*': ParseTable[4][4](); break; case '(': ParseTable[4][5](); break; case ')': ParseTable[4][6](); break; case '#': ParseTable[4][7](); break; default: break; }
break;
case 'P':
switch(terminal) {
case 'i': case 'x': case 'y': switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': ParseTable[4][3](); break; case '*': ParseTable[4][4](); break;
课 程 设 计 书
case '(': case ')': case '#': default: }
break;
ParseTable[4][5](); break; ParseTable[4][6](); break; ParseTable[4][7](); break; break;
case 'Q':
switch(terminal) {
case 'i': ParseTable[4][0](); break; case 'x': ParseTable[4][1](); break; case 'y': ParseTable[4][2](); break; case '+': case '*': case '(': case ')': case '#': default: break; }
break;
case 'F':
{
ParseTable[4][2](); break; ParseTable[4][3](); break; ParseTable[4][4](); break; ParseTable[4][5](); break; case ')': ParseTable[4][6](); break; case '#': ParseTable[4][7](); break; default: break; }
break; default:
课 程 设 计 书
Error(); break; } }
// LL(1)分析程序 #include #include "Stack.h" #include "Parse.h"
using namespace std; void LL1Parse() {
stack.push('#'); stack.push('E');
char a;
cout
{
//match
Error(); {
if(X==a) //parse successfully flag=false; else
Error(); }
else //reverse, push into stack
课 程 设 计 书
pushTogether(X, a); }
if(stack.isEmpty())
cout
// 主程序
#include #include "LL1.h" using namespace std; void main() {
cout
cout
cout
cout
i+i*i#, 显示“分析成功”。
课 程 设 计 书
显示“分析失败!”。运行结果如下:
课 程 设 计 书
九、使用方法
程序在VC++6.0下调试通过。打开VC6.0执行“文件”—>“新建”, 编辑上面的源程序,完成后单击“保存”(aa.cpp ),再单击菜单栏的“编译”—>“编译 aa.cpp”或按Ctrl+F7;“编译”—>“构件 aa.exe”或按F7;“编译”—>“执行 aa.exe”或按Ctrl+F5。
当然你也可以找aa.cpp 文件所在目录的“debug 目录”aa.exe, 拷贝到别的目录下面再在DOS 下来执行它。这里我把它拷到“然后执行“Win+R”,输入“CMD ”进入DOS, 接着执行“cd\”C:\录,再执行aa 回车。如下图:
课 程 设 计 书
十、课程设计心得
本次课程设计完成了语法分析器-预测分析法(即LL (1)分析法)的算法分析到实现的全部过程,结果满足设计要求,验证无误。在整整一个星期的日子里同时做两个课程设计,可以说是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课刻,掌握得不够牢固等等。
经努力过。
[1. 重庆大学出版社,2005年8月。
[2语言程序设计. 清华大学出版社,2005年月1月。
《编译原理》课程设计—预测分析法LL (1) 第21页