逻辑表达式词法分析器分析结果的显示


上篇博客文章《简易逻辑表达式词法分析器》讲到设计了一个逻辑表达式词法分析器,这次以那个词法分析器作为后端,利用VC搭建前端界面,展示一下分析效果。


逻辑表达式词法分析器分析结果的显示

分析结果以树的形式表示:同一级节点表示具有相同的等级,参数比它的谓词的等级要高,比如Missile(x)中Missile等级为0级,x为1级。分析之后各个节点存储在Parser.list中,可以根据该链表的节点的level属性将各节点插入树种的相应位置。
分析以上逻辑表达式可知,各个节点的等级如下:
Missile x AND Owns Nono Sub x => Sells West x Nono
0 1 0 0 1 1 2 0 0 1 1 1
可见,利用堆栈来辅助将节点插入树中是最理想的方法。思路如下:将树的TVI_ROOT压栈;若当前节点的等级大于其前一个节点,将前一个节点压栈;若当前节点等级小于前一个节点,出栈前一节点等级 和 当前节点等级之差次;若当前节点等级等于前一节点等级,既不压栈也不出栈。每个当前节点的父节点为栈顶元素。

源代码如下:
逻辑表达式词法分析器分析结果的显示voidCPPageFaultLogicExpression::OnBnClickedButtonParse()
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示
//TODO:在此添加控件通知处理程序代码
逻辑表达式词法分析器分析结果的显示
UpdateData(TRUE);
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示
if(m_strLogicExpression==L"")
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示MessageBox(L
"请输入逻辑表达式!");
逻辑表达式词法分析器分析结果的显示}

逻辑表达式词法分析器分析结果的显示
else
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示m_parser.Parse((wstring)m_strLogicExpression);
//进行词法分析
逻辑表达式词法分析器分析结果的显示
m_bIsParsed=TRUE;
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
/**/////向词法分析树种添加分析结果////
逻辑表达式词法分析器分析结果的显示m_tLexer.DeleteAllItems();//清除所有节点
逻辑表达式词法分析器分析结果的显示

逻辑表达式词法分析器分析结果的显示NodeList_Itit
=m_parser.list.begin();
逻辑表达式词法分析器分析结果的显示NodeList_Ittmp_it
=it;
逻辑表达式词法分析器分析结果的显示wchar_ttmp[
128];
逻辑表达式词法分析器分析结果的显示wcscpy(tmp,it
->content.c_str());
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示stack
<HTREEITEM>st;//定义堆栈
逻辑表达式词法分析器分析结果的显示

逻辑表达式词法分析器分析结果的显示TVINSERTSTRUCTtvInsert;
逻辑表达式词法分析器分析结果的显示tvInsert.hParent
=TVI_ROOT;
逻辑表达式词法分析器分析结果的显示tvInsert.hInsertAfter
=TVI_LAST;
逻辑表达式词法分析器分析结果的显示tvInsert.item.mask
=TVIF_TEXT;
逻辑表达式词法分析器分析结果的显示tvInsert.item.pszText
=tmp;
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示HTREEITEMhcur
=TVI_ROOT;
逻辑表达式词法分析器分析结果的显示st.push(hcur);
逻辑表达式词法分析器分析结果的显示hcur
=m_tLexer.InsertItem(&tvInsert);//插入根节点
逻辑表达式词法分析器分析结果的显示

逻辑表达式词法分析器分析结果的显示HTREEITEMhprev;
逻辑表达式词法分析器分析结果的显示hprev
=hcur;
逻辑表达式词法分析器分析结果的显示
//intlevel=0,max_level=0;
逻辑表达式词法分析器分析结果的显示

逻辑表达式词法分析器分析结果的显示it
++;
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示
for(it;it!=m_parser.list.end();it++)
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示wcscpy(tmp,it
->content.c_str());
逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示
if(it->level>tmp_it->level)//当前节点深度大于前一节点时,前一节点所在的树的位置入栈
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示st.push(hprev);
逻辑表达式词法分析器分析结果的显示hcur
=m_tLexer.InsertItem(tmp,hprev,TVI_LAST);//插入新的节点
逻辑表达式词法分析器分析结果的显示

逻辑表达式词法分析器分析结果的显示}

逻辑表达式词法分析器分析结果的显示
elseif(it->level<tmp_it->level)//当前节点深度小于前一节点时,根据两节点深度之差将保存的节点出栈
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示
intlevel=tmp_it->level;
逻辑表达式词法分析器分析结果的显示
while(it->level<level--)
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示st.pop();
逻辑表达式词法分析器分析结果的显示}

逻辑表达式词法分析器分析结果的显示hprev
=st.top();
逻辑表达式词法分析器分析结果的显示hcur
=m_tLexer.InsertItem(tmp,hprev,TVI_LAST);//插入新的节点
逻辑表达式词法分析器分析结果的显示
}

逻辑表达式词法分析器分析结果的显示
elseif(it->level==tmp_it->level)//当前节点深度等于前一节点时,根据栈顶元素插入新节点
逻辑表达式词法分析器分析结果的显示逻辑表达式词法分析器分析结果的显示
...{
逻辑表达式词法分析器分析结果的显示hprev
=st.top();
逻辑表达式词法分析器分析结果的显示hcur
=m_tLexer.InsertItem(tmp,hprev,TVI_LAST);
逻辑表达式词法分析器分析结果的显示}

逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示hprev
=hcur;
逻辑表达式词法分析器分析结果的显示tmp_it
=it;
逻辑表达式词法分析器分析结果的显示}

逻辑表达式词法分析器分析结果的显示
逻辑表达式词法分析器分析结果的显示UpdateData(FALSE);
逻辑表达式词法分析器分析结果的显示}
//endofelse
逻辑表达式词法分析器分析结果的显示
}

PS1: 当初考虑到中文的支持,利用wstring定义节点内容,现在发现是个错误,在字符转换的过程中很是麻烦,耽误了不少时间,走了不少弯路。
PS2: 也许因为我对STL不是很熟悉,感觉比较麻烦,不知道如何被C++标准委员会接纳的?