1. 总体设计思想
整个词法分析器有一张预测分析表,一个先进后出的分析栈和一个总控程序组成。主控程序控制整个分析的过程,分析过程中从用户输入的程序源码中利用词法分析器从程序源码缓冲区中取出字符(满足语法规则的单词),然后根据分析栈中的内容,通过查找预测分析表,根据通过的返回结果执行不同的操作,出现错误则直接返回报错,否则知道将整个源码程序分析完为止。
2. 详细算法设计
(1).文法转换:
<表达式> ::=<项>{+<项>|-<项>}
<项> ::= <因子>{*<因子>|/<因子>}
<因子> ::=ID|num|(<表达式>)
改为:
S->AB
A->CD
B->+AB|-AB |ε
C->ID|num|(S)
D->*CD| /CD |ε
构造预测分析表:
| ID | num | ( | ) | + | - | * | / | # |
S | S->AB | S->AB | S->AB |
|
|
|
|
|
|
A | A->CD | A->CD | A->CD |
|
|
|
|
|
|
B |
|
|
| B->ε | B->+AB | B->-AB |
|
| B->ε |
C | C->ID | C->num | C->(S) |
|
|
|
|
|
|
D |
|
|
| D->ε | D->ε | D->ε | D->*CD | D->/CD | D->ε |
(2)分析栈为S,从源码缓冲区读出的字符存放变量a
下面是伪码:
push(S,’#‘); //‘#’为结束符
push(S,’S’); //‘S‘为文法开始符号
X=pop(S) //X存放从分析栈pop出的字符
while(true)
{
if(X∈Vt)
{
if(X=a)
{
a= scanner(codeBuffer); //将下一个字符读入a
}
else
{
error();
}
}
else
{
if(X=’#’)
{
if(X=a)
{
break; //结束
}
else
{
error();
}
}
else
{
if(search(M[X,a]))
{
push(YnYn-1...Y2Y1);//如果找到规则X->Y1Y2…Yn,右侧逆序入栈,空不入 }
else
{
error();
}
}
}
}
3. 流程框图
下面是主控程序的流程框图:
4. 函数相关说明
int AnalysisStack[ANALYSIS_STACK_LEN]; //分析堆栈
int stackTop; //堆栈顶部指针
charbufferToken[TOKEN_LENGTH]; //从缓冲区中取出的字符串
int stackToken;// 从分析堆栈取出的字符
bool startGrammarAnalysis(constchar codeBuffer[]); //开始语法分析
Morphology morphology; //词法分析器,实现词法分析功能
bool isTerminalCh(int Xcode,intteminalChTable[]);//判断是否为终结字符
bool serachPreMatrix(int Xcode,int Avalue,int &stackTop); //查表函数
void pushStack(intAnalysisStack[],int &stackTop,int object);
5.输入与输出
输入:以#号结束所给文法的源程序字符串
输出:success或者error
例如:输入:x+1
输出:success(语法正确)
输入:x=1
输出:error(语法错误)
6. 程序运行结果
样例1:a++1.27e+18#
样例2:--20+-124. e+137.246e+#
样例3:/* this test program*/
x
+
1-36*x#
7. 程序源码
/*
*功能:语法分析器
*作者:KDF5000
*时间:2013.10
*/
#include "grtammarAnalysis.h"
#include <stdio.h>
#include <string.h>
#include "Complier.h"
int teminalChTable[] = {IDENTIFIER,DIGIT,PLUS,SUB,STAR,SLASH,KUOHAO_L,KUOHAO_R};
grammarAnalysis::grammarAnalysis(void)
{
}
grammarAnalysis::~grammarAnalysis(void)
{
}
bool grammarAnalysis::startGrammarAnalysis(const char codeBuffer[])
{
int returnCode; //每次识别字符串的code
int startPosition = 0; //每次读出字符的起始位置
morphology.setPreIsOp(true);//初始化操作符信号
double num = 0; //记录scanner扫描到数字的数值
do{
returnCode = morphology.scaner(codeBuffer,startPosition,bufferToken);
if(returnCode == DIGIT)
{
Complier::strToNumber(bufferToken,num);
printf("(%d,%g)\n",returnCode,num);
}
else if(returnCode == ERROR)
{
printf("('%s')不能有该文法生成!\n",bufferToken);
}
else if(returnCode==NOTE)
{
//
}
else
{
printf("(%d,'%s')\n",returnCode,bufferToken);
}
}while(returnCode!=END_JINGHAO);
startPosition=0;
returnCode=0;
stackTop = 0; //指向栈顶
morphology.setPreIsOp(true);
AnalysisStack[stackTop++] = END_JINGHAO; //
AnalysisStack[stackTop] = S_NTERMINAL;//S作为文法的其实字符
returnCode = morphology.scaner(codeBuffer,startPosition,bufferToken);
while(returnCode==NOTE)
{
returnCode = morphology.scaner(codeBuffer,startPosition,bufferToken);
}
//语法分析
while(true)
{
//将栈顶字符取出
stackToken = AnalysisStack[stackTop--];
//如果stackToken是非终结符(x属于Vt)
if(isTerminalCh(stackToken,teminalChTable))
{
//X=a
if(stackToken != returnCode)
{
return false;
}
else
{
do
{
returnCode = morphology.scaner(codeBuffer,startPosition,bufferToken);
}while(returnCode==NOTE);
}
}
else
{
//X = '$'
if(stackToken == END_JINGHAO)
{
if(stackToken == returnCode )
{
return true;
}
else
{
return false;
}
}
// X!=‘$'
else
{
if(!serachPreMatrix(stackToken,returnCode,stackTop))
{
return false;
}
}
}
}
}
//判断是否为终结符
bool grammarAnalysis::isTerminalCh(int Xcode,int terminalT[])
{
for(int i=0;i<sizeof(teminalChTable)/sizeof(teminalChTable[0]);i++)
{
if(Xcode==teminalChTable[i])
{
return true;
}
}
return false;
}
/* | ID | num | ( | ) | + | - | * | / | #
S |S->AB |S->AB |S->AB | | | | | |
A |A->CD |A->CD |A->CD | | | | | |
B | | | |B->ε |B->+AB |B->-AB | | | B->ε
C |C->ID |C->num |C->(S) | | | | | |
D | | | |D->ε |D->ε |D->ε |D->*CD |D->/CD| D->ε
_____________________________________________________________________________*/
//查找预测矩阵
bool grammarAnalysis::serachPreMatrix(int Xcode ,int Avalue,int &stackTop)
{
switch(Xcode)
{
case S_NTERMINAL:
switch(Avalue)
{
case IDENTIFIER:
case DIGIT:
case KUOHAO_L:
pushStack(AnalysisStack,stackTop,B_NTERMINAL);
pushStack(AnalysisStack,stackTop,A_NTERMINAL);
return true;
default:
return false;
}
break;
case A_NTERMINAL:
switch(Avalue)
{
case IDENTIFIER:
case DIGIT:
case KUOHAO_L:
pushStack(AnalysisStack,stackTop,D_NTERMINAL);
pushStack(AnalysisStack,stackTop,C_NTERMINAL);
return true;
default:
return false;
}
break;
case B_NTERMINAL:
switch(Avalue)
{
case PLUS:
pushStack(AnalysisStack,stackTop,B_NTERMINAL);
pushStack(AnalysisStack,stackTop,A_NTERMINAL);
pushStack(AnalysisStack,stackTop,PLUS);
return true;
case SUB:
pushStack(AnalysisStack,stackTop,B_NTERMINAL);
pushStack(AnalysisStack,stackTop,A_NTERMINAL);
pushStack(AnalysisStack,stackTop,SUB);
return true;
case KUOHAO_R:
case END_JINGHAO:
return true;
default:
return false;
}
break;
case C_NTERMINAL:
switch(Avalue)
{
case IDENTIFIER:
pushStack(AnalysisStack,stackTop,IDENTIFIER);
return true;
case DIGIT:
pushStack(AnalysisStack,stackTop,DIGIT);
return true;
case KUOHAO_L:
pushStack(AnalysisStack,stackTop,KUOHAO_R);
pushStack(AnalysisStack,stackTop,S_NTERMINAL);
pushStack(AnalysisStack,stackTop,KUOHAO_L);
return true;
default:
return false;
}
break;
case D_NTERMINAL:
switch(Avalue)
{
case PLUS:
case SUB:
case KUOHAO_R:
case END_JINGHAO:
return true;
case STAR:
pushStack(AnalysisStack,stackTop,D_NTERMINAL);
pushStack(AnalysisStack,stackTop,C_NTERMINAL);
pushStack(AnalysisStack,stackTop,STAR);
return true;
case SLASH:
pushStack(AnalysisStack,stackTop,D_NTERMINAL);
pushStack(AnalysisStack,stackTop,C_NTERMINAL);
pushStack(AnalysisStack,stackTop,SLASH);
return true;
default:
return false;
}
break;
default:
return false;
}
}
//
void grammarAnalysis::pushStack(int AnalysisStack[],int &stackTop,int object)
{
//缺少判断堆栈是否已满
AnalysisStack[++stackTop]= object;
}