优信二手车:“优”无品质 “信”失归途
2025-11-07
<prog> → program <id>;<block>
<block> → [<condecl>][<vardecl>][<proc>]<body>
<condecl> → const <const>{,<const>}
<const> → <id>:=<integer>
<vardecl> → var <id>{,<id>}
<proc> → procedure <id>(<id>{,<id>});<block>{;<proc>}
<body> → begin <statement>{;<statement>}end
<statement> → <id> := <exp>
|if <lexp> then <statement>[else <statement>]
|while <lexp> do <statement>
|call <id>[(<exp>{,<exp>})]
|<body>
|read (<id>{,<id>})
|write (<exp>{,<exp>})
<lexp> → <exp> <lop> <exp>|odd <exp>
<exp> → [+|-]<term>{<aop><term>}
<term> → <factor>{<mop><factor>}
<factor>→<id>|<integer>|(<exp>)
<lop> → =|<>|<|<=|>|>=
<aop> → +|-
<mop> → *|/
<id> → l{l|d} (注:l表示字母)
<integer> → d{d}
注释:
<prog>:程序 ;<block>:块、程序体 ;<condecl>:常量说明 ;<const>:常量; <vardecl>:变量说明 ;<proc>:分程序 ; <body>:复合语句 ;<statement>:语句; <exp>:表达式 ;<lexp>:条件 ;<term>:项 ; <factor>:因子 ;<aop>:加法运算符; <mop>:乘法运算符; <lop>:关系运算符 odd:判断表达式的奇偶性。下面我们先来看看词法及语法分析器的设计与实现。词法分析采用循环分支方法实现,语法分析采用递归下降来实现。它们的程序流程图如下:

class CCompiler
{
public:
CCompiler();
virtual ~CCompiler();
public:
void Compile(char *szFile);//编译,公共接口
vector<SYNTAXERR> GetSyntaxErr(){return m_vectorSyntaxErr;};//得到语法错误
protected:
bool LexAnalysis(char *szStr); //词法分析
bool IsOprSym(char *szStr); //是否为运算符
bool IsBndSym(char *szStr); //是否为界符
bool IsKeyWord(char *szStr); //是否为关键字
bool IsInSymbolTab(char *szStr); //是否已在符号表中
char* JumpNoMatterChar(char *szStr);//跳过空格,回车,换行符,Tab
void OutSymbolTab(char *szFile);//输出符号表到文件
void SyntaxAnalysis();//语法分析
void SyntaxAnalysis_Prog();
bool SyntaxAnalysis_Mop();
bool SyntaxAnalysis_Integer();
bool SyntaxAnalysis_Aop();
bool SyntaxAnalysis_Lop();
int SyntaxAnalysis_Id();
int SyntaxAnalysis_Block();
int SyntaxAnalysis_Body();
int SyntaxAnalysis_Factor();
int SyntaxAnalysis_Term();
int SyntaxAnalysis_Lexp();
int SyntaxAnalysis_Exp();
int SyntaxAnalysis_Statement();
int SyntaxAnalysis_Const();
int SyntaxAnalysis_Proc();
int SyntaxAnalysis_Vardecl();
int SyntaxAnalysis_Condecl();
protected:
int m_iVecotrSymbolSize; //符号表大小
int m_iCurPointer; //符号表中当前指针
vector<LEXPROPERTYVS> m_vectorSymbol;//符号表
vector<SYNTAXERR> m_vectorSyntaxErr; //语法错误代码
};
其中:函数bool LexAnalysis(char *szStr);是对输入字符串szStr采用循环分支方法进行词法分析,分析出来的符号放在符号表m_vectorSymbol中,这个符号表采用向量这个数据结构来表示。词法分析得出符号表后,即进入语法分析阶段,语法分析由函数void SyntaxAnalysis();完成。下面这些函数是各非终结符对应的递归子程序。
bool SyntaxAnalysis_Mop(); bool SyntaxAnalysis_Integer(); bool SyntaxAnalysis_Aop(); bool SyntaxAnalysis_Lop(); int SyntaxAnalysis_Id(); int SyntaxAnalysis_Block(); int SyntaxAnalysis_Body(); int SyntaxAnalysis_Factor(); int SyntaxAnalysis_Term(); int SyntaxAnalysis_Lexp(); int SyntaxAnalysis_Exp(); int SyntaxAnalysis_Statement(); int SyntaxAnalysis_Const(); int SyntaxAnalysis_Proc(); int SyntaxAnalysis_Vardecl(); int SyntaxAnalysis_Condecl();
以上我介绍了词法及语法分析核心的设计实现,下面我简单介绍下IDE的实现和IDE与分析核心之间的通信。本系统的IDE与分析核心之间采用管道通信,代码如下:
DWORD dwThreadID; ::CreateThread(0,0,CompileThread,this,0,&dwThreadID);//创建进程
进程创建后调用进程函数,
//进程函数
DWORD WINAPI CompileThread(LPVOID pParam)
{
CCompileSysView *pView=(CCompileSysView*)pParam;
pView->GetCompileResult();
return 0;
}
进程函数调用类的自身函数GetCompileResult();得到分析核心的输出结果,这个函数的实现如下:
void CCompileSysView::GetCompileResult()
{
SECURITY_ATTRIBUTES sa;
HANDLE hRead,hWrite;
CString strFile;
CString strOut;
strFile.Format("..\\pl\\pl.exe ");//指定分析核心程序的路径
//当前文件作为参数传给分析核心程序,防止这个文件名中含有空格,故用双引号""将文件名括住
strFile=strFile+(char)34+m_szCurFile+(char)34;
sa。nLength=sizeof(SECURITY_ATTRIBUTES);
sa。lpSecurityDescriptor=NULL;
sa。bInheritHandle=TRUE;
if(!CreatePipe(&hRead,&hWrite,&sa,0))//创建管道进行通信
{
MessageBox("Error On CreatePipe()");
return;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
si。cb=sizeof(STARTUPINFO);
GetStartupInfo(&si);
si。hStdError=hWrite;
si。hStdOutput=hWrite;//输出重定向到文件
si。wShowWindow=SW_HIDE;
si。dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建进程启动分析核心程序
if(!CreateProcess(NULL,(LPSTR)(LPCTSTR)strFile,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
{
MessageBox("Error on CreateProcess()");
return;
}
CloseHandle(hWrite);
char buffer[4096]={0};
DWORD bytesRead;
while(true)
{
if(!ReadFile(hRead,buffer,4095,&bytesRead,NULL))
break;
strOut+=buffer;
m_pwndOutBar->SetColorRichEditText(strOut);//将输出结果显示出来
Sleep(500);
}
}
这样就完成了整个分析系统的设计与实现。下面我们来看看整个系统是怎样运行的。我们先来看看这个系统的运行界面:
评论 {{userinfo.comments}}
{{child.content}}



{{question.question}}
提交