Пример разбора предложения
Пример: a:=-(a+a)*a/a;
{a:=-(a+a)*a/a;⊥K; ⊥H; λ} {;⊥K; ⊥H a:=E/a; 9 9 2 8 9 4}
{:=-(a+a)*a/a;⊥K; ⊥H a; λ} {;⊥K; ⊥H a:=E /E; 9 9 2 8 9 4 9}
{ -(a+a)*a/a;⊥K; ⊥H a:=; λ} {;⊥K; ⊥H a:=E; 9 9 2 8 9 4 9 5}
{ (a+a)*a/a;⊥K; ⊥H a:=-; λ} {⊥K; ⊥H a:=E; ; 9 9 2 8 9 4 9 5}
{ a+a)*a/a;⊥K; ⊥H a:=-(; λ} {⊥K; ⊥ H E; 9 9 2 8 9 4 9 5 1}
{ +a)*a/a;⊥K; ⊥H a:=-(a; λ}
{ +a)*a/a;⊥K; ⊥H a:=-(E; 9}
{ a)*a/a;⊥K; ⊥H a:=-(E+; λ}
{)*a/a;⊥K; ⊥H a:=-(E+a; λ}
{)*a/a;⊥K; ⊥H a:=-(E+E; 9 9}
{)*a/a;⊥K; ⊥H a:=-(E; 9 9 2}
{*a/a;⊥K; ⊥H a:=-(E); 9 9 2}
{*a/a;⊥K; ⊥H a:=E; 9 9 2 8}
{a/a;⊥K; ⊥H a:=E*; 9 9 2 8}
{ /a;⊥K; ⊥H a:=E*a; 9 9 2 8}
{ /a;⊥K; ⊥H a:=E*E; 9 9 2 8 9}
{ /a;⊥K; ⊥H a:=E; 9 9 2 8 9 4}
{ a;⊥K; ⊥H a:=E/; 9 9 2 8 9 4}
Листинг программы
// LabSPODlg.cpp : implementation file
//
#include "stdafx.h"
#include "LabSPO.h"
#include "LabSPODlg.h"
#include "MyLab2_func.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CLabSPODlg dialog
CLabSPODlg::CLabSPODlg(CWnd* pParent /*=NULL*/)
: CDialog(CLabSPODlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CLabSPODlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CLabSPODlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CLabSPODlg)
DDX_Control(pDX, IDC_LIST_ABOUT_TREE, m_AbTr);
DDX_Control(pDX, IDC_TREE1, m_TreeOut);
DDX_Control(pDX, IDC_LIST_SYN_ERR, m_SynErr);
DDX_Control(pDX, IDC_LIST_LT_PROP, m_ListProp);
DDX_Control(pDX, IDC_LIST_LT_ID, m_ListID);
DDX_Control(pDX, IDC_LIST_RULE, m_RuleList);
DDX_Control(pDX, IDC_LIST_ERR, m_MsgErr);
DDX_Control(pDX, IDC_MY_LIST, m_List);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CLabSPODlg, CDialog)
//{{AFX_MSG_MAP(CLabSPODlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(ID_GEN_OUT, OnGenOut)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CLabSPODlg message handlers
BOOL CLabSPODlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CLabSPODlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CLabSPODlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CLabSPODlg::OnGenOut()
{
// TODO: Add your control notification handler code here
UpdateData();
char ch, ID[64][40], buffer[64][40];
char Del[1][20]={'d','e','l','i','m','e','t','e','r'};
char Oper[1][20]={'o','p','e','r','a','t','i','o','n',' ','s','i','g','n'};
char Brack[1][20]={'b','r','a','c','k','e','t'};
char Cons[1][20]={'c','o','n','s','t'};
char Sl[1][40]; for(int i=0; i<40; i++) Sl[0][i]=NULL; Sl[0][0]='/';
char Appr[1][20]={'a','p','p','r','o','p','r','i','a','t','i','o','n'};
char Identi[1][20]={'i','d','e','n','t','i','f','i','e','r'};
for (int j=0; j<64; j++)
{for (int i=0; i<64; i++) buffer[j][i]=NULL;}
Table TLex(64); int codeEr=0;
bool errlex=false, errsynt=false;
enum State { STATE_A, STATE_B, STATE_M, STATE_N, STATE_D, STATE_E, STATE_O, STATE_V,
STATE_W, STATE_H, STATE_S, STATE_C, STATE_C1, STATE_C2};
char FileName[7]={'e','x','.','t','x','t'};
ifstream ReadFromFile(FileName);
State St; St=STATE_H; int d=0, e=0;
while (ReadFromFile.get(ch))
{
if (St==STATE_E){ if(ch!=' ') continue;
else {St=STATE_H;for(i=0; i<40; i++) buffer[d][i]=NULL;e=0;continue;}};
if (ch!=' ') {if(ch!='\r'){if(ch!='\n') {if(ch!='/') {if(St!=STATE_C)
{if(St!=STATE_C1) {if (St!=STATE_C2)
{buffer[d][e]=ch; e++;};}}}}}}
switch (St)
{
case (STATE_H):
{
switch(ch){
case 'a':St=STATE_V; break; case 'b':St=STATE_V; break;
case 'c':St=STATE_V; break; case 'd':St=STATE_V; break;
case 'e':St=STATE_V; break; case 'f':St=STATE_V; break;
case 'g':St=STATE_V; break; case 'h':St=STATE_V; break;
case 'i':St=STATE_V; break; case 'j':St=STATE_V; break;
case 'k':St=STATE_V; break; case 'l':St=STATE_V; break;
case 'm':St=STATE_V; break; case 'n':St=STATE_V; break;
case 'o':St=STATE_V; break; case 'p':St=STATE_V; break;
case 'q':St=STATE_V; break; case 'r':St=STATE_V; break;
case 's':St=STATE_V; break; case 't':St=STATE_V; break;
case 'u':St=STATE_V; break; case 'v':St=STATE_V; break;
case 'w':St=STATE_V; break; case 'x':St=STATE_V; break;
case 'y':St=STATE_V; break; case 'z':St=STATE_V; break;
case (':'): St=STATE_A; break;
case '*' : St=STATE_O; break; case '-' : St=STATE_O; break;
case '+' : St=STATE_O; break; case '=' : St=STATE_O; break;
case '0' : St=STATE_N; break; case '1' : St=STATE_N; break;
case '2' : St=STATE_N; break; case '3' : St=STATE_N; break;
case '4' : St=STATE_N; break; case '5' : St=STATE_N; break;
case '6' : St=STATE_N; break; case '7' : St=STATE_N; break;
case '8' : St=STATE_N; break; case '9' : St=STATE_N; break;
case 'A': St=STATE_N; break; case 'B': St=STATE_N; break;
case 'C': St=STATE_N; break; case 'D': St=STATE_N; break;
case 'E': St=STATE_N; break; case 'F': St=STATE_N; break;
case '(' : St=STATE_M; break; case ')': St=STATE_M; break;
case ';' : St=STATE_D; break;
case '/' : St=STATE_C; break; case ' ': St=STATE_H;break;
default: errlex=true;codeEr=1;St=STATE_E;break;}; break;
};break;
case (STATE_D): if(ch==' ') {m_ListID.AddString(buffer[d]); m_ListProp.AddString(Del[0]);
TLex.createRec(d, buffer[d], Del[0] );d++; e=0; St=STATE_H; break; }
else {errlex=true;codeEr=2;St=STATE_E; break;}; break;
case (STATE_V):
{
switch(ch){
case 'a':St=STATE_V; break; case 'b':St=STATE_V; break;
case 'c':St=STATE_V; break; case 'd':St=STATE_V; break;
case 'e':St=STATE_V; break; case 'f':St=STATE_V; break;
case 'g':St=STATE_V; break; case 'h':St=STATE_V; break;
case 'i':St=STATE_V; break; case 'j':St=STATE_V; break;
case 'k':St=STATE_V; break; case 'l':St=STATE_V; break;
case 'm':St=STATE_V; break; case 'n':St=STATE_V; break;
case 'o':St=STATE_V; break; case 'p':St=STATE_V; break;
case 'q':St=STATE_V; break; case 'r':St=STATE_V; break;
case 's':St=STATE_V; break; case 't':St=STATE_V; break;
case 'u':St=STATE_V; break; case 'v':St=STATE_V; break;
case 'w':St=STATE_V; break; case 'x':St=STATE_V; break;
case 'y':St=STATE_V; break; case 'z':St=STATE_V; break;
case '0' : St=STATE_W; break; case '1' : St=STATE_W; break;
case '2' : St=STATE_W; break; case '3' : St=STATE_W; break;
case '4' : St=STATE_W; break; case '5' : St=STATE_W; break;
case '6' : St=STATE_W; break; case '7' : St=STATE_W; break;
case '8' : St=STATE_W; break; case '9' : St=STATE_W; break;
case ' ' : TLex.createRec(d, buffer[d], Identi[0]);
m_ListID.AddString(buffer[d]); m_ListProp.AddString(Identi[0]);
d++;e=0;St=STATE_H; break;
default: errlex=true;codeEr=3;St=STATE_E;break;}
} ;break;
case (STATE_A): if(ch=='=') { St=STATE_B; break;} else {St=STATE_E;break;}
case (STATE_B): if(ch==' ') {TLex.createRec(d, buffer[d], Appr[0]);
m_ListID.AddString(buffer[d]); m_ListProp.AddString(Appr[0]);
e=0;d++; St=STATE_H;break;}
else {errlex=true;codeEr=4;St=STATE_E; break;}
case (STATE_W):
{
switch(ch){
case '0' : St=STATE_W; break; case '1' : St=STATE_W; break;
case '2' : St=STATE_W; break; case '3' : St=STATE_W; break;
case '4' : St=STATE_W; break; case '5' : St=STATE_W; break;
case '6' : St=STATE_W; break; case '7' : St=STATE_W; break;
case '8' : St=STATE_W; break; case '9' : St=STATE_W; break;
case ' ': TLex.createRec(d, buffer[d], Identi[0] );
m_ListID.AddString(buffer[d]); m_ListProp.AddString(Identi[0]);
d++; e=0;St=STATE_H; break;
default: errlex=true;codeEr=3;St=STATE_E;break;}
}; break;
case (STATE_N):
{
switch(ch){
case '0' : St=STATE_N; break; case '1' : St=STATE_N; break;
case '2' : St=STATE_N; break; case '3' : St=STATE_N; break;
case '4' : St=STATE_N; break; case '5' : St=STATE_N; break;
case '6' : St=STATE_N; break; case '7' : St=STATE_N; break;
case '8' : St=STATE_N; break; case '9' : St=STATE_N; break;
case 'A' : St=STATE_N; break; case 'D' : St=STATE_N; break;
case 'B' : St=STATE_N; break; case 'E' : St=STATE_N; break;
case 'C' : St=STATE_N; break; case 'F' : St=STATE_N; break;
case ' ': TLex.createRec(d, buffer[d], Cons[0] ); m_ListID.AddString(buffer[d]); m_ListProp.AddString(Cons[0]);
d++; e=0;St=STATE_H; break;
default: errlex=true;codeEr=5;St=STATE_E;}
}; break;
case (STATE_O): if(ch==' ') {TLex.createRec(d, buffer[d], Oper[0] );
m_ListID.AddString(buffer[d]); m_ListProp.AddString(Oper[0]);
d++;e=0;St=STATE_H; break;}
else {errlex=true;codeEr=4;St=STATE_E; break;}
case (STATE_M): if(ch==' ') {TLex.createRec(d, buffer[d], Brack[0] );
m_ListID.AddString(buffer[d]); m_ListProp.AddString(Brack[0]);
d++;e=0;St=STATE_H; break;}
else {errlex=true;codeEr=4;St=STATE_E;break;}
case (STATE_S): break;
case (STATE_C):
{switch(ch){
case '*': St=STATE_C1; break;
case ' ': TLex.createRec(d, Sl[0], Oper[0] );d++;e=0;St=STATE_H; break;
default: errlex=true;codeEr=6;St=STATE_E; break;}
}; break;
case (STATE_E): St=STATE_H; break;
case (STATE_C1): if (ch=='*') {St=STATE_C2; break;} else {St=STATE_C1; break;}
case (STATE_C2): if (ch=='/')
{St=STATE_H; break;}
else {St=STATE_C1; break;}
default: St=STATE_E; break;
}
}
ReadFromFile.close();
CString msgNE("Lex errors are absent in file"); CString msg1("Error lex");CString msg2("Error delimiter");
CString msg3("Error identifier");CString msg4("Error sign");CString msg5("Error const");
CString msg6("Error comment");
if (errlex==false) {m_MsgErr.AddString(msgNE);}
else
{switch(codeEr)
{
case 1: m_MsgErr.AddString(msg1); break;
case 2: m_MsgErr.AddString(msg2); break;
case 3: m_MsgErr.AddString(msg3); break;
case 4: m_MsgErr.AddString(msg4); break;
case 5: m_MsgErr.AddString(msg5); break;
case 6: m_MsgErr.AddString(msg6); break;
}
}
//////////////////////////синтаксический анализатор////////////////////////////
bool vi=true;
char Inp_Str[64], Stack[64];
CString msgNSE("Syntax errors are absent in file."),
msgSE("Syntax error occured!");
for( e=0; e<64; e++) Inp_Str[e]=NULL; for( e=0; e<64; e++) Stack[e]=NULL;
int r=0; char SeqRule[20]; for(e=0; e<20; e++) SeqRule[e]=NULL; int sch=0;
char sign, strBuff[10]; for(e=0; e<10; e++) strBuff[e]=NULL;
while(TLex.GetRecEF(sch)==false) {sch++;}
for(e=0; e<sch;e++)
{
if(TLex.GetRecProp(e)[0]=='c' ||TLex.GetRecProp(e)[0]=='i') Inp_Str[e] = 'a';
else Inp_Str[e] = TLex.GetRecId(e)[0];
//во входную строку записываю вх.цепочку,заменяя идент-ры и константы на а
}
Inp_Str[sch]='L';//заносим в конец вх.цепочки маркер конца строки
Stack[0]='F';
int t=0; // t-указатель на текущий анализируемый символ во вх.цепочке
int s=0; //счетчик символов в стеке
int k=0, y=0;
do
{
m_List.AddString(Stack);
if(Stack[0]!='E') sign=OPM(Stack[0], Inp_Str[t]);
else sign=OPM(Stack[1], Inp_Str[t]);
if(sign==' ') { vi=false; break;}
if(sign=='<' || sign == '=') // сдвиг
{
for(e=s; e>=0; e--) {Stack[e+1]=Stack[e]; s++;};
Stack[0]=Inp_Str[t];
t++;
} //конец сдвига
if(sign=='>') // свертка
{
if (Stack[0]=='E')
{ y=0;
while(Stack[y]=='E') y++; //если в вершине стека нетермю символ, то ищем
strBuff[0]=Stack[y-1]; //след. терм.
strBuff[1]=Stack[y];
strBuff[2]=Stack[y+1];
y=3;
}
else
{
j=0; y=0;
strBuff[j]=Stack[0]; j++;
while(true)
{
if(Stack[y+1]=='E') y=y+2; else y++;
if(OPM(Stack[y], strBuff[j-1]) == '=')
{
for(e=1; e<10; e++) strBuff[e]=NULL;
for(e=1; e<=y; e++) strBuff[e]=Stack[e];
j=y+1;
}
else break;
}
}
r=Grammar(strBuff);
if ( r>='1' && r<='9' ){
SeqRule[k]=r; k++;
for(e=0;e<y;e++) Stack[e]=NULL;
Stack[y-1]='E';
while(Stack[0]==NULL) for(e=0; e<=s; e++) {Stack[e]=Stack[e+1]; Stack[e+1]=NULL; s--;}}
else {vi=false; break;}
}
for(e=0; e<10; e++) {strBuff[e]=NULL;};
Inp_Str[t-1]=NULL;
}while(Stack[1]!='F' || Inp_Str[t]!='L');
if(vi!=false)
{
m_List.AddString(Stack);
m_RuleList.AddString(SeqRule); m_SynErr.AddString(msgNSE);
}
else {m_SynErr.AddString(msgSE);}
///////////////////////////////вывод дерева/////////////////////////////////////////////////
if (vi!=false)
{
CString q1(" This tree was built:"); m_AbTr.AddString(q1);
TVINSERTSTRUCT myTree;
HTREEITEM ParStore[20];
int a=0, pPS=0; k--;
myTree.hParent=TVI_ROOT;
myTree.hInsertAfter=TVI_LAST;
myTree.item.mask=TVIF_TEXT;
myTree.item.pszText="E";
ParStore[pPS]=m_TreeOut.InsertItem(&myTree);
char numRul=SeqRule[k];//номер правила
myTree.hParent=ParStore[pPS];
for(e=k;e>=0;e--)
{
myTree.hParent=ParStore[pPS];//сделать родителем текущий эл-т стека
pPS++; ParStore[pPS]=0;//поставить разделитель м/у уровнями
numRul=SeqRule[e]; a=0;
while(Output(SeqRule[e])[a]!=NULL)
{
CString S1=Output(SeqRule[e])[a];
LPSTR S2=S1.GetBuffer(S1.GetLength());
myTree.item.pszText=S2;
//если в правиле Е,то этот узел будет родителем
if(S1=="E")
{
pPS++;
ParStore[pPS]=m_TreeOut.InsertItem(&myTree);
}
else
{
m_TreeOut.InsertItem(&myTree);
}
a++;
}
while(pPS)
{
if(ParStore[pPS]==0)
{
ParStore[pPS]=0; pPS--;
ParStore[pPS]=0; pPS--;
}
else {break;}
}
}
}
else {CString q("Tree can't be built because of error!"); m_AbTr.AddString(q);}
}