Proiectarea Si Implementarea Unui Generator de Analizoare Sintactice Bazate pe Relatii de Precedenta
=== ANEXA ===
Anexa 1
Figura 1
Pagina "Gramatica"
Figura 2
Pagina "Gramatica maodificata"
Figura 3
Pagina "Prim-Ultim"
Figura 4
Pagina "Tabela de precedenta"
Figura 5
Pagina "Sirul de ferificare"
Anexa 2
Conținutul fișierului 2.h
// 2.h: interface for the CGram class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_2_H__A62A66EB_3E97_484D_A624_CCDE75210123__INCLUDED_)
#define AFX_2_H__A62A66EB_3E97_484D_A624_CCDE75210123__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGram{
public:
CGram();
virtual ~CGram();
CString s;
int i;
CGram *urm, *prec, *prim;
void addElem(const CString &str, int i=0);
CGram* eraseElem();
void clear();
void print();
bool apartine(CGram *list);
CGram* intra(CGram *list1, CGram *list2);
CGram* intra1(CGram *list1, CGram *list2);
bool intra2(CGram *list1, CGram *list2);
bool intra3(CGram *list1, CGram *list2);
CGram* operator [](int i);
void modificare(const CString &str, int i=0);
void Replace(const CString &str, CGram *list);
bool FindRepeat();
void DeleteRepeat();
};
class CPrimUltim{
public:
CPrimUltim();
virtual ~CPrimUltim();
CString s;
CGram *grprim, *grultim;
CPrimUltim *prim, *prec, *urm;
void clear();
void addSublist(CGram *gram1=NULL,CGram *gram2=NULL);
void addElement(const CString &str);
void print();
void printAll();
};
#endif // !defined(AFX_2_H__A62A66EB_3E97_484D_A624_CCDE75210123__INCLUDED_)
Conținutul fișierului 2.h
// 2.cpp: implementation of the CGram class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Compilator.h"
#include "2.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGram::CGram(){
prim=urm=prec=NULL;
}
CGram::~CGram(){
}
void CGram::clear(){
CGram *tmp1, *tmp2;
if (prim==NULL) return;
for (tmp1=this->prim;tmp1->urm!=NULL;){
tmp2=tmp1->urm;
delete tmp1;
tmp1=tmp2;
}
delete tmp1;
}
void CGram::addElem(const CString &str,int i){
if (prim==NULL){
this->s=str;
this->i=i;
prim=this;
} else {
CGram *newElem,*tmp;
newElem = new CGram();
newElem->s=str;
newElem->i=i;
for (tmp=this->prim;tmp->urm!=NULL;tmp=tmp->urm);
tmp->urm=newElem;
newElem->prec=tmp;
newElem->prim=tmp->prim;
}
}
CGram* CGram::eraseElem(){
CGram *tmp;
if (prim==NULL) return NULL;
if (prec==NULL){
CGram *tmp2;
for (tmp2=prim->urm;tmp2->urm!=NULL;tmp2=tmp2->urm)
tmp2->prim=urm;
tmp2->prim=urm;
urm->prec=NULL;
} else
if (urm==NULL){
prec->urm=NULL;
} else {
prec->urm=urm;
urm->prec=prec;
}
if (prec!=NULL)
tmp=prec;
else
if (urm!=NULL)
tmp=urm;
else
tmp=NULL;
delete this;
return tmp;
}
void CGram::print(){
CGram *tmp;
if (prim==NULL) return;
CString str;
char cc[10];
for (tmp=this->prim;tmp->urm!=NULL;tmp=tmp->urm){
itoa(tmp->i,cc,10);
str=(CString)""+tmp->s+" _ "+cc;
AfxMessageBox(str);
}
itoa(tmp->i,cc,10);
str=(CString)""+tmp->s+" _ "+cc;
AfxMessageBox(str);
}
bool CGram::apartine(CGram *list){
if ((prim==NULL) || (list->prim==NULL)) return false;
bool b=false;
for (list=list->prim;list->urm!=NULL;list=list->urm)
if (s==list->s) b=true;
if (s==list->s) b=true;
return b;
}
CGram* CGram::intra(CGram *list1, CGram *list2){
CGram* tmp;
bool b;
list1=list1->prim;
for (tmp=list2->prim->urm;tmp->urm!=NULL;tmp=tmp->urm)
if ((tmp->s==list1->s) && (tmp->i==list1->i)){
b=true;
for (list2=tmp;;list1=list1->urm,list2=list2->urm)
if (list1->urm==NULL || list2->urm==NULL)
break;
else
if ((list2->s!=list1->s) || (list2->i!=list1->i)){
b=false;
break;
}
if ((list2->s!=list1->s) || (list2->i!=list1->i)) b=false;
if ((b==true) && (list2->urm!=NULL)) return tmp;
list1=list1->prim;
}
return NULL;
}
CGram* CGram::intra1(CGram *list1, CGram *list2){
CGram *tmp1,*tmp2,*tmp3;
bool b;
for (tmp2=list2->prim;tmp2!=NULL;tmp2=tmp2->urm){
tmp1=list1->prim;
if ((tmp1->s==tmp2->s) && (tmp1->i==tmp2->i) && ((tmp2->prec==NULL)||(tmp2->prec->i==1))){
b=false;
for (tmp3=tmp2;tmp3!=NULL;tmp3=tmp3->urm,tmp1=tmp1->urm)
if (tmp1==NULL){b=true; break;}
else
if ((tmp1->s!=tmp3->s) || (tmp1->i!=tmp3->i)) break;
if (b==true) return tmp2;
if ((tmp3==NULL) && (tmp1==NULL)) return tmp2;
}
}
return NULL;
}
void CGram::modificare(const CString &str, int i){
this->s=str;
this->i=i;
}
void CGram::Replace(const CString &str, CGram *list){
CGram *tmp1,*tmp2,*elem;
for (tmp1=this->prim;tmp1!=NULL;tmp1=tmp1->urm)
if (tmp1->s==str){
tmp1=tmp1->eraseElem();
for (tmp2=list->prim;tmp2!=NULL;tmp2=tmp2->urm){
elem=new CGram();
elem->s=list->s;
if (tmp1->urm->i!=1) elem->i=0; else elem->i=2;
elem->urm=tmp1->urm;
elem->prec=tmp1;
tmp1->urm->prec=elem;
tmp1->urm=elem;
}
}
}
bool CGram::FindRepeat(){
CGram *tmp1,*tmp2,*tmp3,*tmp4,*tmp5;
for (tmp1=this->prim;tmp1!=NULL;tmp1=tmp1->urm)
if (tmp1->i==1){
tmp2=new CGram();
for (tmp4=tmp1->urm;tmp4!=NULL;tmp4=tmp4->urm)
if (tmp4->i==1) break;
else
tmp2->addElem(tmp4->s,tmp4->i);
tmp3=new CGram();
for (tmp4=tmp1->urm->urm;tmp4!=NULL;tmp4=tmp4->urm)
tmp3->addElem(tmp4->s,tmp4->i);
if (intra2(tmp2,tmp3)==true){
tmp3->clear();
CString st=tmp1->s;
tmp1=tmp1->eraseElem();
for (tmp3=tmp1->urm;tmp3->i!=1;tmp3=tmp3->urm)
tmp3=tmp3->eraseElem();
for (tmp5=this->prim;tmp5->urm!=NULL;tmp5=tmp5->urm);
for (tmp3=this->prim;tmp3!=tmp5;tmp3=tmp3->urm)
if ((tmp3->s==st) && (tmp3->i!=1)){
for (tmp4=tmp3;tmp4->i!=1;tmp4=tmp4->prec);
tmp3->addElem(tmp4->s,tmp4->i);
for (tmp1=tmp4->urm;tmp1->i!=1;tmp1=tmp1->urm)
if (tmp1->s==st){
for (tmp4=tmp2->prim;tmp4!=NULL; tmp4=tmp4->urm)
tmp1->addElem(tmp4->s,0);
} else tmp1->addElem(tmp1->s,0);
for (tmp4=tmp1->prim;tmp4->urm!=NULL;tmp4=tmp4->urm);
tmp4->i=2;
}
tmp2->clear();
return true;
}
tmp2->clear();
tmp3->clear();
}
return false;
}
bool CGram::intra2(CGram *list1, CGram *list2){
CGram *tmp1,*tmp2,*tmp3;
bool b;
for (tmp2=list2->prim;tmp2!=NULL;tmp2=tmp2->urm){
tmp1=list1->prim;
if ((tmp1->s==tmp2->s) && (tmp1->i==tmp2->i) && ((tmp2->prec==NULL)||(tmp2->prec->i==1))){
b=false;
for (tmp3=tmp2;tmp3!=NULL;tmp3=tmp3->urm,tmp1=tmp1->urm)
if (tmp1==NULL){b=true; break;}
else
if ((tmp1->s!=tmp3->s) || (tmp1->i!=tmp3->i)) break;
if (b==true) return true;
if ((tmp3==NULL) && (tmp1==NULL)) return true;
}
}
return false;
}
bool CGram::intra3(CGram *list1, CGram *list2){
CGram *tmp1,*tmp2;
tmp1=list1->prim;
for (tmp2=list2->prim;tmp2->urm!=NULL;tmp2=tmp2->urm)
if ((tmp1->s==tmp2->s) && (tmp1->urm->s==tmp2->urm->s) && (tmp2->i!=1) && (tmp2->urm->i!=1))
return true;
return false;
}
void CGram::DeleteRepeat(){
CGram *tmp1,*tmp2,*tmp3,*tmp4;
for (tmp1=this->prim;tmp1!=NULL;tmp1=tmp1->urm)
if (tmp1->i==1){
tmp2=new CGram();
tmp2->addElem(tmp1->s,tmp1->i);
for (tmp4=tmp1->urm;tmp4!=NULL;tmp4=tmp4->urm)
if (tmp4->i==1) break;
else
tmp2->addElem(tmp4->s,tmp4->i);
tmp3=new CGram();
for (tmp4=tmp1->urm->urm;tmp4!=NULL;tmp4=tmp4->urm)
tmp3->addElem(tmp4->s,tmp4->i);
if (intra2(tmp2,tmp3)==true){
for (;tmp1->i!=2;tmp1=tmp1->urm);
AfxMessageBox(tmp1->s);
while (tmp1->i!=1) tmp1=tmp1->eraseElem();
tmp1=tmp1->eraseElem();
}
tmp2->clear();
tmp3->clear();
}
AfxMessageBox("tmp1");
this->print();
}
//////////////////////////////////////////////////////////////////////
// CPrimUltim Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPrimUltim::CPrimUltim(){
prim=prec=urm=NULL;
grprim=grultim=NULL;
}
CPrimUltim::~CPrimUltim(){
}
void CPrimUltim::addSublist(CGram *gram1,CGram *gram2){
if (gram1==NULL) goto l1;
CGram *tmp;
tmp = new CGram();
if (gram1->prim!=NULL){
for (gram1=gram1->prim;gram1->urm!=NULL;gram1=gram1->urm)
tmp->addElem(gram1->s);
tmp->addElem(gram1->s);
grprim=tmp;
}
l1: if (gram2==NULL) return;
CGram *tmp1;
tmp1 = new CGram();
if (gram2->prim!=NULL){
for (gram2=gram2->prim;gram2->urm!=NULL;gram2=gram2->urm)
tmp1->addElem(gram2->s);
tmp1->addElem(gram2->s);
grultim=tmp1;
}
}
void CPrimUltim::addElement(const CString &str){
if (prim==NULL){
this->s=str;
prim=this;
grprim=grultim=NULL;
} else {
CPrimUltim *newElem,*tmp;
newElem = new CPrimUltim();
newElem->s=str;
for (tmp=this;tmp->urm!=NULL;tmp=tmp->urm);
tmp->urm=newElem;
newElem->prec=tmp;
newElem->prim=tmp->prim;
newElem->grprim=NULL;
newElem->grultim=NULL;
}
}
void CPrimUltim::clear(){
CPrimUltim *tmp1, *tmp2;
if (prim==NULL) return;
for (tmp1=this->prim;tmp1->urm!=NULL;){
tmp2=tmp1->urm;
if (tmp1->grprim!=NULL)
tmp1->grprim->clear();
if (tmp1->grultim!=NULL)
tmp1->grultim->clear();
delete tmp1;
tmp1=tmp2;
}
if (tmp1->grprim!=NULL)
tmp1->grprim->clear();
if (tmp1->grultim!=NULL)
tmp1->grultim->clear();
delete tmp1;
prim=NULL;
}
void CPrimUltim::print(){
CPrimUltim *tmp;
if (prim==NULL) return;
for (tmp=this->prim;tmp->urm!=NULL;tmp=tmp->urm)
AfxMessageBox(tmp->s);
AfxMessageBox(tmp->s);
}
void CPrimUltim::printAll(){
CPrimUltim *tmp;
if (prim==NULL) return;
for (tmp=this->prim;tmp->urm!=NULL;tmp=tmp->urm){
AfxMessageBox(tmp->s);
AfxMessageBox("Prim");
if (tmp->grprim!=NULL)
tmp->grprim->print();
else
AfxMessageBox("NULL");
AfxMessageBox("Ultim");
if (tmp->grultim!=NULL)
tmp->grultim->print();
else
AfxMessageBox("NULL");
}
AfxMessageBox(tmp->s);
AfxMessageBox("Prim");
if (tmp->grprim!=NULL)
tmp->grprim->print();
else
AfxMessageBox("NULL");
AfxMessageBox("Ultim");
if (tmp->grultim!=NULL)
tmp->grultim->print();
else
AfxMessageBox("NULL");
}
CGram* CGram::operator [](int i){
CGram *tmp;
tmp=this;
for (tmp=tmp->prim;tmp->urm!=NULL;tmp=tmp->urm)
if (i==tmp->i) return tmp;
if (i==tmp->i) return tmp;
}
Conținutul fișierului CompilatorDlg.h
// CompilatorDlg.h : header file
//
//{{AFX_INCLUDES()
#include "msflexgrid.h"
//}}AFX_INCLUDES
#if !defined(AFX_COMPILATORDLG_H__F10CE38C_3C48_4858_9378_64C3C39F5A2E__INCLUDED_)
#define AFX_COMPILATORDLG_H__F10CE38C_3C48_4858_9378_64C3C39F5A2E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CCompilatorDlg dialog
#include "2.h"
class CCompilatorDlg : public CDialog
{
// Construction
public:
CCompilatorDlg(CWnd* pParent = NULL); // standard constructor
int My_x,My_y;
void MakeGram(const CString &s);
void MakeList();
int Corectitudinea(const CString &ss);
bool quastion,change,first,ver_sir;
CGram *gr,*sir;
CString name,first_s;
int next;
void FindVectori(const CString &ss);
// Dialog Data
//{{AFX_DATA(CCompilatorDlg)
enum { IDD = IDD_COMPILATOR_DIALOG };
CEdit m_ctrl_ambig;
CButton m_constr;
CButton m_page1_verif;
CButton m_verif_sir;
CEdit m_ctrl_sir;
CButton m_page1_save_as;
CButton m_page1_save;
CButton m_page1_load;
CEdit m_ctrl_gram1;
CEdit m_ctrl_gram2;
CTabCtrl m_tab;
CMSFlexGrid m_tab_pr_ul;
CMSFlexGrid m_tab_prec;
CString m_gram1;
CString m_gram2;
CString m_sir;
CMSFlexGrid m_vector;
CMSFlexGrid m_tab_vector;
CString m_ambig;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCompilatorDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CCompilatorDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnLoad();
afx_msg void OnVerificarea();
afx_msg void OnVerif();
afx_msg void OnConstruct();
afx_msg void OnChangeGram();
afx_msg void OnSave();
afx_msg void OnSaveAs();
virtual void OnOK();
virtual void OnCancel();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_COMPILATORDLG_H__F10CE38C_3C48_4858_9378_64C3C39F5A2E__INCLUDED_)
Conținutul fișierului CompilatorDlg.cpp
// CompilatorDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Compilator.h"
#include "CompilatorDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#include "2.h"
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCompilatorDlg dialog
CCompilatorDlg::CCompilatorDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCompilatorDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCompilatorDlg)
m_gram1 = _T("");
m_gram2 = _T("");
m_sir = _T("");
m_ambig = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CCompilatorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCompilatorDlg)
DDX_Control(pDX, IDC_AMBIGUITATE, m_ctrl_ambig);
DDX_Control(pDX, IDC_CONSTRUCT, m_constr);
DDX_Control(pDX, IDC_VERIF, m_page1_verif);
DDX_Control(pDX, IDC_VERIFICAREA, m_verif_sir);
DDX_Control(pDX, IDC_SIR, m_ctrl_sir);
DDX_Control(pDX, IDC_SAVE_AS, m_page1_save_as);
DDX_Control(pDX, IDC_SAVE, m_page1_save);
DDX_Control(pDX, IDC_LOAD, m_page1_load);
DDX_Control(pDX, IDC_GRAM, m_ctrl_gram1);
DDX_Control(pDX, IDC_NEW_GRAM, m_ctrl_gram2);
DDX_Control(pDX, IDC_TAB1, m_tab);
DDX_Control(pDX, IDC_MSFLEXGRID1, m_tab_pr_ul);
DDX_Control(pDX, IDC_MSFLEXGRID2, m_tab_prec);
DDX_Text(pDX, IDC_GRAM, m_gram1);
DDX_Text(pDX, IDC_NEW_GRAM, m_gram2);
DDX_Text(pDX, IDC_SIR, m_sir);
DDX_Control(pDX, IDC_VECTOR, m_vector);
DDX_Text(pDX, IDC_AMBIGUITATE, m_ambig);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCompilatorDlg, CDialog)
//{{AFX_MSG_MAP(CCompilatorDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1)
ON_BN_CLICKED(IDC_LOAD, OnLoad)
ON_BN_CLICKED(IDC_VERIFICAREA, OnVerificarea)
ON_BN_CLICKED(IDC_VERIF, OnVerif)
ON_BN_CLICKED(IDC_CONSTRUCT, OnConstruct)
ON_EN_CHANGE(IDC_GRAM, OnChangeGram)
ON_BN_CLICKED(IDC_SAVE, OnSave)
ON_BN_CLICKED(IDC_SAVE_AS, OnSaveAs)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCompilatorDlg message handlers
BOOL CCompilatorDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About…" menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
m_tab.InsertItem(0,"Gramatica");
m_tab.InsertItem(1,"Gramatica modificata");
m_tab.InsertItem(2,"Prim-Ultim");
m_tab.InsertItem(3,"Tabela de precedenta");
m_tab.InsertItem(4,"Sirul de verificare");
change=quastion=false;
gr=NULL;
name="";
ver_sir=false;
return TRUE; // return TRUE unless you set the focus to a control
}
void CCompilatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CCompilatorDlg::OnPaint(){
m_tab.MoveWindow(15,15,My_x-30,30);
int sel=m_tab.GetCurSel();
m_page1_load.ShowWindow(SW_HIDE);
m_page1_save.ShowWindow(SW_HIDE);
m_page1_save_as.ShowWindow(SW_HIDE);
m_ctrl_gram1.ShowWindow(SW_HIDE);
m_ctrl_gram2.ShowWindow(SW_HIDE);
m_tab_pr_ul.ShowWindow(SW_HIDE);
m_tab_prec.ShowWindow(SW_HIDE);
m_ctrl_sir.ShowWindow(SW_HIDE);
m_verif_sir.ShowWindow(SW_HIDE);
m_page1_verif.ShowWindow(SW_HIDE);
m_vector.ShowWindow(SW_HIDE);
m_constr.ShowWindow(SW_HIDE);
m_ctrl_ambig.ShowWindow(SW_HIDE);
if (sel==0){
m_page1_verif.ShowWindow(SW_SHOW);
m_page1_load.ShowWindow(SW_SHOW);
m_page1_save.ShowWindow(SW_SHOW);
m_page1_save_as.ShowWindow(SW_SHOW);
m_ctrl_gram1.ShowWindow(SW_SHOW);
m_page1_verif.MoveWindow(My_x/5-35,My_y-30,70,23);
m_page1_load.MoveWindow(My_x/5*2-35,My_y-30,70,23);
m_page1_save.MoveWindow(My_x/5*3-35,My_y-30,70,23);
m_page1_save_as.MoveWindow(My_x*4/5-35,My_y-30,70,23);
m_ctrl_gram1.MoveWindow(15,45,My_x-30,My_y-90);
} else
if (sel==1){
m_ctrl_gram2.ShowWindow(SW_SHOW);
m_ctrl_gram2.MoveWindow(15,45,My_x-30,My_y-70);
} else
if (sel==2){
m_tab_pr_ul.ShowWindow(SW_SHOW);
m_tab_pr_ul.MoveWindow(15,45,My_x-30,My_y-125);
m_vector.ShowWindow(SW_SHOW);
m_vector.MoveWindow(15,My_y-75,My_x-30,55);
} else
if (sel==3){
m_tab_prec.ShowWindow(SW_SHOW);
m_tab_prec.MoveWindow(15,45,My_x-30,My_y-70);
} else
if (sel==4){
m_ctrl_sir.ShowWindow(SW_SHOW);
m_ctrl_sir.MoveWindow(20,50,My_x-40,40);
m_ctrl_ambig.ShowWindow(SW_SHOW);
m_ctrl_ambig.MoveWindow(70,110,My_x-140,90);
m_verif_sir.ShowWindow(SW_SHOW);
m_verif_sir.MoveWindow(My_x/2+50,My_y-60,100,23);
m_constr.ShowWindow(SW_SHOW);
m_constr.MoveWindow(My_x/2-150,My_y-60,120,23);
}
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 CCompilatorDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CCompilatorDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
My_x=cx;
My_y=cy;
Invalidate();
}
void CCompilatorDlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
Invalidate();
*pResult = 0;
}
void CCompilatorDlg::MakeList(){
CGram *Vn, *Vt;
bool b1=false,b2=false;
CString temp_s;
m_ambig="";
int i,j,k=1;
while (gr->FindRepeat()==true);
Vn = new CGram();
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if (gr->i==1)
if (gr->apartine(Vn)==false)
Vn->addElem(gr->s);
Vt = new CGram();
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if (gr->apartine(Vn)==false)
if (gr->apartine(Vt)==false)
Vt->addElem(gr->s);
if (gr->apartine(Vn)==false)
if (gr->apartine(Vt)==false)
Vt->addElem(gr->s);
CPrimUltim *pu;
pu = new CPrimUltim();
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm)
pu->addElement(Vn->s);
pu->addElement(Vn->s);
CString stmp;
CGram *tmp1, *tmp2, *tmp3;
tmp1 = new CGram();
tmp2 = new CGram();
pu=pu->prim;
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm){
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->s==Vn->s) && (gr->urm->apartine(tmp1)==false))
tmp1->addElem(gr->urm->s);
l1: for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->apartine(tmp1)) && (gr->urm->apartine(tmp1)==false)){
tmp1->addElem(gr->urm->s);
goto l1;
}
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->apartine(tmp1)) && (gr->urm->apartine(tmp1)==false)){
tmp1->addElem(gr->urm->s);
goto l1;
}
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) stmp=gr->s;
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (Vn->s==stmp))
tmp2->addElem(gr->s);
}
if ((gr->apartine(tmp2)==false) && (Vn->s==stmp))
tmp2->addElem(gr->s);
l2: for (tmp2=tmp2->prim;tmp2->urm!=NULL;tmp2=tmp2->urm){
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) {tmp3 = new CGram(); tmp3->addElem(gr->s);}
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l2;
}
}
if ((gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l2;
}
tmp3->clear();
}
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) {tmp3 = new CGram(); tmp3->addElem(gr->s);}
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l2;
}
}
if ((gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l2;
}
tmp3->clear();
pu->addSublist(tmp1,tmp2);
pu=pu->urm;
tmp1->clear();
tmp2->clear();
tmp1 = new CGram();
tmp2 = new CGram();
}
//pentru ultimul Vn cautam PRIM
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->s==Vn->s) && (gr->urm->apartine(tmp1)==false))
tmp1->addElem(gr->urm->s);
l3: for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->apartine(tmp1)) && (gr->urm->apartine(tmp1)==false)){
tmp1->addElem(gr->urm->s);
goto l3;
}
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->i==1) && (gr->apartine(tmp1)) && (gr->urm->apartine(tmp1)==false)){
tmp1->addElem(gr->urm->s);
goto l3;
}
//pentru ultimul Vn cautam ULTIM
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) stmp=gr->s;
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (Vn->s==stmp))
tmp2->addElem(gr->s);
}
if ((gr->apartine(tmp2)==false) && (Vn->s==stmp))
tmp2->addElem(gr->s);
l4: for (tmp2=tmp2->prim;tmp2->urm!=NULL;tmp2=tmp2->urm){
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) {tmp3 = new CGram(); tmp3->addElem(gr->s);}
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l4;
}
}
if ((gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l4;
}
tmp3->clear();
}
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
if (gr->i==1) {tmp3 = new CGram(); tmp3->addElem(gr->s);}
if ((gr->i==2) && (gr->apartine(tmp2)==false) && (tmp3->apartine(tmp2))){
tmp2->addElem(gr->s);
tmp3->clear();
goto l4;
}
}
if ((gr->apartine(tmp2)==false)){
tmp2->addElem(gr->s);
tmp3->clear();
goto l4;
}
tmp3->clear();
pu->addSublist(tmp1,tmp2);
CGram *tab, *line;
tab = new CGram();
line = new CGram();
k=0;
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm)
line->addElem(Vn->s,k++);
line->addElem(Vn->s,k++);
for (Vt=Vt->prim;Vt->urm!=NULL;Vt=Vt->urm)
line->addElem(Vt->s,k++);
line->addElem(Vt->s,k++);
line->addElem("$",k++);
//initializarea tabelului de precedenta
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (pu->s==first_s) break;
tmp3=line->prim;
for (line=line->prim;line->urm!=NULL;line=line->urm){
for (tmp3=tmp3->prim;tmp3->urm!=NULL;tmp3=tmp3->urm)
tab->addElem("",line->i*k+tmp3->i);
if (line->apartine(pu->grultim)) tab->addElem(">",line->i*k+tmp3->i);
}
for (tmp3=tmp3->prim;tmp3->urm!=NULL;tmp3=tmp3->urm)
if (tmp3->apartine(pu->grprim))
tab->addElem("<",line->i*k+tmp3->i);
tab->addElem("",line->i*k+tmp3->i);
int i1,j1;
for (gr=gr->prim->urm;gr->urm!=NULL;gr=gr->urm)
if (gr->i==0){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->s==gr->s) i1=line->i;
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->s==gr->urm->s) j1=line->i;
(*tab)[k*i1+j1]->s="=";
// – < –
if (gr->urm->apartine(Vn)){
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (gr->urm->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grprim)){
j1=line->i;
if ((*tab)[k*i1+j1]->s.Find("<")==-1) (*tab)[k*i1+j1]->s+="<";
}
}
if (gr->urm->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grprim)){
j1=line->i;
if ((*tab)[k*i1+j1]->s.Find("<")==-1) (*tab)[k*i1+j1]->s+="<";
}
}
}
// – > –
if ((gr->apartine(Vn)) && (gr->urm->apartine(Vt))){
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
}
// – > –(Ultim>Prim)
if ((gr->apartine(Vn)) && (gr->urm->apartine(Vn))){
CPrimUltim *tmp4;
CGram *tmp_x;
for (tmp4=pu->prim;tmp4!=NULL;tmp4=tmp4->urm)
if (gr->urm->s==tmp4->s){
for (tmp_x=line->prim;tmp_x->urm!=NULL;tmp_x=tmp_x->urm)
if ((tmp_x->apartine(tmp4->grprim)) && (tmp_x->apartine(Vt))){
j1=tmp_x->i;
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
}
}
/* if (gr->urm->s==tmp4->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(tmp4->grultim))
j1=line->i;
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
if (gr->s==pu->s){
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (line->apartine(pu->grultim)){
i1=line->i;
if ((*tab)[k*i1+j1]->s.Find(">")==-1) (*tab)[k*i1+j1]->s+=">";
}
}
}*/
}
}
CString aaa;
char c1,c2;
i=0;
for (tab=tab->prim;tab->urm!=NULL;tab=tab->urm){
aaa+=" ";
if (i%k==0){c1=13;c2=10;aaa=aaa+c1+c2;}
if (tab->s=="") aaa+="_"; aaa+=tab->s;
i++;
}
// afisarea vectorului Vn si Vt
m_vector.SetRow(0);
m_vector.SetCol(0);
m_vector.SetColWidth(0,1500);
m_vector.SetText("Vectorul Neterminal");
m_vector.SetRow(1);
m_vector.SetCol(0);
m_vector.SetText("Vectorul Terminal");
j=i=1;
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm) i++;
i++;
for (Vt=Vt->prim;Vt->urm!=NULL;Vt=Vt->urm) j++;
j++;
if (i>j) m_vector.SetCols(i); else m_vector.SetCols(j);
i=0;
m_vector.SetRow(0);
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm){
m_vector.SetCol(++i);
m_vector.SetText(Vn->s);
if (Vn->s.GetLength()>10) m_vector.SetColWidth(i,Vn->s.GetLength()*100);
}
m_vector.SetCol(++i);
m_vector.SetText(Vn->s);
if (Vn->s.GetLength()>10) m_vector.SetColWidth(i,Vn->s.GetLength()*100);
i=0;
m_vector.SetRow(1);
for (Vt=Vt->prim;Vt->urm!=NULL;Vt=Vt->urm){
m_vector.SetCol(++i);
m_vector.SetText(Vt->s);
if (Vt->s.GetLength()>10) m_vector.SetColWidth(i,Vt->s.GetLength()*100);
}
m_vector.SetCol(++i);
m_vector.SetText(Vt->s);
if (Vt->s.GetLength()>10) m_vector.SetColWidth(i,Vt->s.GetLength()*100);
tmp1->clear();
tmp2->clear();
Vn->clear();
Vt->clear();
for (line=line->prim;line->urm!=NULL;line=line->urm);
int q1=line->i;
CString ss1,ss2;
for (tab=tab->prim;tab->urm!=NULL;tab=tab->urm){
if (tab->s=="<>" || tab->s=="><"){
i=tab->i/(q1+1);
j=tab->i%(q1+1);
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (i==line->i){
ss1=line->s;
}
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (j==line->i){
ss2=line->s;
}
b2=true;
goto l9;
}
}
for (tab=tab->prim;tab->urm!=NULL;tab=tab->urm){
if (tab->s=="=>" || tab->s=="=<"){
i=tab->i/(q1+1);
j=tab->i%(q1+1);
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (i==line->i){
ss1=line->s;
}
for (line=line->prim;line->urm!=NULL;line=line->urm)
if (j==line->i){
ss2=line->s;
}
b1=true;
break;
}
}
// modificarea gramaticii pe ecran
l9: c1=13;c2=10;
m_gram2=(CString)"";
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm){
m_gram2=m_gram2+'<';
m_gram2=m_gram2+gr->s;
m_gram2=m_gram2+'>';
if (gr->i==1) m_gram2=m_gram2+"->";
if (gr->i==2) m_gram2=m_gram2+';'+c1+c2;
}
m_gram2=m_gram2+'<';
m_gram2=m_gram2+gr->s;
m_gram2=m_gram2+'>';
if (gr->i==1) m_gram2=m_gram2+"->";
if (gr->i==2) m_gram2=m_gram2+';'+c1+c2;
if (b1==true){
m_ambig=(CString)""+"Intre simbolurile <"+ss1+"> si <"+ss2+"> a aparut semnul => sau =<"+c1+c2;
m_ambig=m_ambig+"Pentru rezolvarea conflictului vor fi adaugate urmatoarele rinduri:"+c1+c2;
tmp2 = new CGram();
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->s==ss1) && (gr->urm->s==ss2) && (gr->i!=1) && (gr->i!=2)){
CGram *tmp3;
tmp3=gr;
for (;gr->i!=1;gr=gr->prec);
for (;;gr=gr->urm)
if ((gr->s==tmp3->s) && (gr->i!=1)) break;
else{
gr->addElem(gr->s,gr->i);
m_ambig=m_ambig+"<"+gr->s+">";
if (gr->i==1) m_ambig+="->";
}
gr->addElem(gr->s,gr->i);
m_ambig=m_ambig+"<"+gr->s+">";
char cc[10];
itoa(next++,cc,10);
temp_s=(CString)""+"tmp"+cc;
gr->addElem(temp_s,2);
m_ambig=m_ambig+"<"+temp_s+">";
gr->addElem(temp_s,1);
m_ambig=m_ambig+";"+c1+c2+"<"+temp_s+">->";
for (gr=gr->urm;gr->i!=2;gr=gr->urm){
gr->addElem(gr->s,gr->i);
m_ambig=m_ambig+"<"+gr->s+">";
tmp2->addElem(gr->s,gr->i);
}
gr->addElem(gr->s,gr->i);
m_ambig=m_ambig+"<"+gr->s+">;"+c1+c2;
tmp2->addElem(gr->s,gr->i);
break;
}
CString s_a="";
m_ambig=m_ambig+"Si este eliminat rindul:"+c1+c2;
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if ((gr->s==ss1) && (gr->urm->s==ss2) && (gr->i!=1) && (gr->i!=2)){
for (;gr->i!=1;){
s_a="<"+gr->s+">"+s_a;
gr=gr->eraseElem();
}
s_a="<"+gr->s+">->"+s_a;
gr=gr->eraseElem();
if (gr->prec!=NULL)
gr=gr->urm;
for (;gr->i!=2;gr=gr->urm){
s_a=s_a+"<"+gr->s+">";
gr=gr->eraseElem();
}
s_a=s_a+"<"+gr->s+">;";
gr=gr->eraseElem();
m_ambig+=s_a;
break;
}
tmp1=tmp2->intra(tmp2,gr);
if (tmp1!=NULL){
for (;tmp1->i!=2;tmp1=tmp1->urm)
tmp1=tmp1->eraseElem();
tmp1->modificare(temp_s,2);
}
tmp2->clear();
b1=false;
goto l_1;
}
if (b2==true){
CString s_a="";
m_ambig=(CString)""+"Intre simbolurile <"+ss1+"> si <"+ss2+"> a aparut semnul <>"+c1+c2;
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if (ss1==gr->s){
tmp3=new CGram();
for (tmp2=gr->prim;tmp2!=NULL;tmp2=tmp2->urm)
if (tmp2->s==ss2){
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
if (tmp2->apartine(pu->grprim)){
tmp3->addElem(ss1);
tmp3->addElem(pu->s);
if (gr->intra3(tmp3,gr)==true){
goto k1;
}
tmp3->clear();
tmp3=new CGram();
}
if (tmp2->apartine(pu->grprim)){
tmp3->addElem(ss1);
tmp3->addElem(pu->s);
if (gr->intra3(tmp3,gr)==true){
goto k1;
}
tmp3->clear();
tmp3=new CGram();
}
break;
}
}
MessageBox("Torba");
goto l_1;
k1:
tmp1=tmp3->prim;
for (tmp2=gr->prim;tmp2->urm!=NULL;tmp2=tmp2->urm)
if ((tmp1->s==tmp2->s) && (tmp1->urm->s==tmp2->urm->s) && (tmp2->i!=1) && (tmp2->urm->i!=1))
break;
tmp3->clear();
m_ambig=m_ambig+"Pentru rezolvarea conflictului va fi schimbat rindul:"+c1+c2;
for (tmp3=tmp2;tmp3->i!=1;tmp3=tmp3->prec);
m_ambig=m_ambig+"<"+tmp3->s+">->";
for (tmp3=tmp3->urm;tmp3->i!=2;tmp3=tmp3->urm)
m_ambig=m_ambig+"<"+tmp3->s+">";
m_ambig=m_ambig+"<"+tmp3->s+">;"+c1+c2;
CGram *tmp4;
tmp4=new CGram();
tmp4->addElem(tmp2->s,2);
tmp2=tmp2->prec;
for (;tmp2->i!=1;){
tmp4->addElem(tmp2->s,0);
tmp2=tmp2->eraseElem();
}
tmp2=tmp2->urm;
m_ambig=m_ambig+"Cu urmatoarele rinduri:"+c1+c2;
char cc[10];
itoa(next++,cc,10);
temp_s=(CString)""+"tmp"+cc;
tmp2->modificare(temp_s);
for (tmp3=tmp2;tmp3->i!=1;tmp3=tmp3->prec);
m_ambig=m_ambig+"<"+tmp3->s+">->";
for (tmp3=tmp3->urm;tmp3->i!=2;tmp3=tmp3->urm)
m_ambig=m_ambig+"<"+tmp3->s+">";
m_ambig=m_ambig+"<"+tmp3->s+">;"+c1+c2;
gr->addElem(temp_s,1);
m_ambig=m_ambig+"<"+temp_s+">->";
for (tmp4=tmp4->prim;tmp4->urm!=NULL;tmp4=tmp4->urm);
tmp2=new CGram();
for (;tmp4->prec!=NULL;tmp4=tmp4->prec){
m_ambig=m_ambig+"<"+tmp4->s+">";
gr->addElem(tmp4->s,tmp4->i);
tmp2->addElem(tmp4->s,tmp4->i);
}
m_ambig=m_ambig+"<"+tmp4->s+">;";
gr->addElem(tmp4->s,tmp4->i);
tmp2->addElem(tmp4->s,tmp4->i);
tmp1=tmp2->intra(tmp2,gr);
if (tmp1!=NULL){
for (;tmp1->i!=2;tmp1=tmp1->urm)
tmp1=tmp1->eraseElem();
tmp1->modificare(temp_s,2);
}
tmp4->clear();
tmp2->clear();
goto l_1;
}
l_1:i=1;
for (line=line->prim;line->urm!=NULL;line=line->urm)
i++;
i++;
m_tab_prec.SetCols(i);
m_tab_prec.SetRows(i);
int len0=0,len1=0,len2=0;
m_tab_prec.SetCol(0);
int ii=0;
for (line=line->prim;line->urm!=NULL;line=line->urm){
m_tab_prec.SetRow(++ii);
m_tab_prec.SetText(line->s);
if (len0<line->s.GetLength()) len0=line->s.GetLength();
}
m_tab_prec.SetRow(++ii);
m_tab_prec.SetText(line->s);
if (len0<line->s.GetLength()) len0=line->s.GetLength();
if (len0>10) m_tab_prec.SetColWidth(0,len0*100);
m_tab_prec.SetRow(0);
ii=0;
for (line=line->prim;line->urm!=NULL;line=line->urm){
m_tab_prec.SetCol(++ii);
m_tab_prec.SetText(line->s);
if (line->s.GetLength()>10)
m_tab_prec.SetColWidth(ii,line->s.GetLength()*100);
}
m_tab_prec.SetCol(++ii);
m_tab_prec.SetText(line->s);
if (line->s.GetLength()>10)
m_tab_prec.SetColWidth(ii,line->s.GetLength()*100);
for (tab=tab->prim;tab->urm!=NULL;tab=tab->urm){
m_tab_prec.SetRow(tab->i/(i-1)+1);
m_tab_prec.SetCol(tab->i%(i-1)+1);
m_tab_prec.SetText(tab->s);
}
j=2;
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm)
j++;
m_tab_pr_ul.SetRows(j);
m_tab_pr_ul.SetCols(3);
j=0;
m_tab_pr_ul.SetRow(0);
m_tab_pr_ul.SetCol(1);
m_tab_pr_ul.SetText("Prim");
m_tab_pr_ul.SetRow(0);
m_tab_pr_ul.SetCol(2);
m_tab_pr_ul.SetText("Ultim");
CString s1;
len0=0;len1=0;len2=0;
for (pu=pu->prim;pu->urm!=NULL;pu=pu->urm){
m_tab_pr_ul.SetRow(++j);
m_tab_pr_ul.SetCol(0);
m_tab_pr_ul.SetText(pu->s);
if (len0<pu->s.GetLength()) len0=pu->s.GetLength();
s1=(CString)"";
tmp1=pu->grprim;
for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
s1=s1+"<"+tmp1->s+">";
s1=s1+"<"+tmp1->s+">";
m_tab_pr_ul.SetCol(1);
m_tab_pr_ul.SetText(s1);
if (len1<s1.GetLength()) len1=s1.GetLength();
s1=(CString)"";
tmp1=pu->grultim;
for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
s1=s1+"<"+tmp1->s+">";
s1=s1+"<"+tmp1->s+">";
m_tab_pr_ul.SetCol(2);
m_tab_pr_ul.SetText(s1);
if (len2<s1.GetLength()) len2=s1.GetLength();
}
m_tab_pr_ul.SetRow(++j);
m_tab_pr_ul.SetCol(0);
m_tab_pr_ul.SetText(pu->s);
if (len0<pu->s.GetLength()) len0=pu->s.GetLength();
s1=(CString)"";
tmp1=pu->grprim;
for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
s1=s1+"<"+tmp1->s+">";
s1=s1+"<"+tmp1->s+">";
m_tab_pr_ul.SetCol(1);
m_tab_pr_ul.SetText(s1);
if (len1<s1.GetLength()) len1=s1.GetLength();
s1=(CString)"";
tmp1=pu->grultim;
for (tmp1=tmp1->prim;tmp1->urm!=NULL;tmp1=tmp1->urm)
s1=s1+"<"+tmp1->s+">";
s1=s1+"<"+tmp1->s+">";
m_tab_pr_ul.SetCol(2);
m_tab_pr_ul.SetText(s1);
if (len2<s1.GetLength()) len2=s1.GetLength();
if (len0>10) m_tab_pr_ul.SetColWidth(0,len0*100);
if (len1>10) m_tab_pr_ul.SetColWidth(1,len1*100);
if (len2>10) m_tab_pr_ul.SetColWidth(2,len2*100);
UpdateData(FALSE);
if (m_ambig==""){
ver_sir=true;
m_ambig=(CString)"Lucrul s-a terminat."+c1+c2;
m_ambig+="Puteti verifica sirul.";
MessageBox(m_ambig);
m_ambig=(CString)"";
} else ver_sir=false;
pu->clear();
tab->clear();
line->clear();
}
void CCompilatorDlg::OnLoad()
{
// TODO: Add your control notification handler code here
if (change==true){
int x=MessageBox("Grammatica era modificata. Vreti sa solvati?","Save file",MB_ICONQUESTION|MB_YESNOCANCEL);
if (x==IDYES)
OnSave();
else
if (x==IDCANCEL) return;
}
CFileDialog fd(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Fisiere cu gramatica (*.grm)|*.grm|*.*|*.*||");
CFile f;
int dwread;
m_gram1="";
if (IDOK==fd.DoModal()){
CString s=fd.GetPathName();
char c;
f.Open(s,CFile::modeRead);
do{
dwread=f.Read(&c,1);
if (c!=0)
m_gram1=(CString)""+m_gram1+c;
c=0;
}while (dwread>0);
UpdateData(FALSE);
quastion=true;
first=true;
next=0;
change=false;
ver_sir=false;
name=fd.GetPathName();
f.Close();
}
}
void CCompilatorDlg::OnVerificarea(){
// TODO: Add your control notification handler code here
char c1=13,c2=10;
UpdateData();
if (ver_sir==true){
CGram *tmp1,*tmp2,*tmp3,*tmp4;
tmp3=NULL;
sir=new CGram();
sir->addElem("$",2);
sir->addElem("",1);
CString s2;
int i,j;
m_sir+=" ";
for (i=0;i<m_sir.GetLength();i++){
s2="";
if (m_sir[i]=='<'){
for (j=++i;;j++,i++)
if (m_sir[j]=='>')
if (m_sir[j+1]!='>') break;
else {
s2+=">>";
j++;
}
else s2+=m_sir[j];
sir->addElem(s2,0);
sir->addElem("",1);
}
}
CString sss;
for (i=0;i<m_sir.GetLength()-1;i++)
sss+=m_sir[i];
m_sir=sss;
sir->addElem("$",2);
m_ambig=(CString)"";
l2: bool b1,b2;
CString xx="Sirul este incorect.\n";
int n=m_tab_prec.GetCols();
for (tmp1=sir->prim->urm->urm;tmp1->urm!=NULL;tmp1=tmp1->urm->urm){
b1=b2=false;
for (i=1;i<n;i++){
m_tab_prec.SetCol(0);
m_tab_prec.SetRow(i);
if (m_tab_prec.GetText()==tmp1->prec->prec->s){
b1=true;
break;
}
}
for (j=1;j<n;j++){
m_tab_prec.SetCol(j);
m_tab_prec.SetRow(0);
if (m_tab_prec.GetText()==tmp1->s){
b2=true;
break;
}
}
if (b1 && b2){
m_tab_prec.SetCol(j);
m_tab_prec.SetRow(i);
if (m_tab_prec.GetText()==""){
xx=xx+"Nu exista relatie intre "+tmp1->prec->prec->s+" si "+tmp1->s+".";
MessageBox(xx);
tmp1->prec->s=m_tab_prec.GetText();
goto l3;
} else {
tmp1->prec->s=m_tab_prec.GetText();
if (m_tab_prec.GetText()==">") break;
}
} else{
if (b1==false) xx=xx+"Nu exista simbol "+tmp1->prec->prec->s;
else xx=xx+"Nu exista simbol "+tmp1->s;
MessageBox(xx);
goto l3;
}
}
b1=b2=false;
for (i=1;i<n;i++){
m_tab_prec.SetCol(0);
m_tab_prec.SetRow(i);
if (m_tab_prec.GetText()==tmp1->prec->prec->s){
b1=true;
break;
}
}
for (j=1;j<n;j++){
m_tab_prec.SetCol(j);
m_tab_prec.SetRow(0);
if (m_tab_prec.GetText()==tmp1->s){
b2=true;
break;
}
}
if (b1 && b2){
m_tab_prec.SetCol(j);
m_tab_prec.SetRow(i);
if (m_tab_prec.GetText()==""){
xx=xx+"Nu exista relatia intre "+tmp1->prec->prec->s+" si "+tmp1->s+".";
MessageBox(xx);
tmp1->prec->s=m_tab_prec.GetText();
goto l3;
} else tmp1->prec->s=m_tab_prec.GetText();
} else{
if (b1==false) xx=xx+"Nu exista simbol "+tmp1->prec->prec->s;
else xx=xx+"Nu exista simbol "+tmp1->s;
MessageBox(xx);
goto l3;
}
for (tmp1=sir->prim->urm->urm;tmp1->urm!=NULL;tmp1=tmp1->urm->urm){
if (tmp1->urm->s==">")
break;
else
if (tmp1->prec->s=="<") tmp2=tmp1;
}
if (tmp1->prec->s=="<") tmp2=tmp1;
tmp3=new CGram();
for (tmp1=tmp2;tmp1->urm->s!=">";tmp1=tmp1->urm->urm){
tmp3->addElem(tmp1->s,0);
}
tmp3->addElem(tmp1->s,2);
tmp4=sir->intra1(tmp3,gr);
for (tmp1=sir->prim;tmp1!=NULL;tmp1=tmp1->urm)
if (tmp1->i==1)
m_ambig=m_ambig+tmp1->s;
else
m_ambig=m_ambig+" '"+tmp1->s+"' ";
m_ambig=m_ambig+c1+c2;
if (tmp4==NULL){
if (sir->prim->urm->urm->s==first_s && sir->prim->urm->urm->urm->urm->s=="$"){
MessageBox("Sirul este corect.");
goto l3;
}
xx="Sirul este incorect."+c1+c2;
xx+="Nu se reduce ultima combinatia";
MessageBox(xx);
goto l3;
}
for (tmp1=tmp2;tmp1->urm->s!=">";){
tmp1=tmp1->eraseElem();
tmp1=tmp1->urm;
tmp1=tmp1->eraseElem();
tmp1=tmp1->urm;
}
tmp1->modificare(tmp4->prec->s,0);
if (sir->prim->urm->urm->s==first_s && sir->prim->urm->urm->urm->urm->s=="$")
MessageBox("Sirul este corect.");
else
goto l2;
l3: for (tmp1=sir->prim;tmp1!=NULL;tmp1=tmp1->urm)
if (tmp1->i==1)
m_ambig=m_ambig+tmp1->s;
else
m_ambig=m_ambig+" '"+tmp1->s+"' ";
m_ambig=m_ambig+c1+c2;
if (tmp3!=NULL) tmp3->clear();
if (sir!=NULL) sir->clear();
} else MessageBox("Nu-s construite toate tabelele pina la capat.");
UpdateData(FALSE);
}
int CCompilatorDlg::Corectitudinea(const CString &ss){
CString s;
int i;
s=ss;
int pos=0;
for (i=0;i<s.GetLength();i++)
switch (pos){
case 0 :
{
if (s[i]==10 || s[i]==13 || s[i]==' ') break;
if (s[i]!='<') {MessageBox("Lipseste '<'0");return i;} else {pos=1; break;}
}
case 1 : if (s[i]=='<') {pos=2; break;} else
if (s[i]=='>') {pos=3; break;} else {pos=1; break;}
case 2 : if (s[i]!='<') {MessageBox("Lipseste '<'2"); return i;} else {pos=1; break;}
case 3 :
{
if (s[i]==10 || s[i]==13 || s[i]==' ') break;
if ((s[i]!='>') && (s[i]!='-')) {MessageBox("Se asteapta '>' sau '-'3"); return i;} else
if (s[i]=='>') {pos=1; break;}else
if (s[i]=='-') {pos=5; break;}
}
case 5 : if (s[i]!='>') {MessageBox("Lipseste '>'5"); return i;} else {pos=6; break;}
case 6 :
{
if (s[i]==10 || s[i]==13 || s[i]==' ') break;
if (s[i]!='<') {MessageBox("Lipseste '<'6"); return i;} else {pos=7; break;}
}
case 7 : if (s[i]=='<') {pos=8;break;} else
if (s[i]=='>') {pos=9;break;} else {pos=7; break;}
case 8 : if (s[i]!='<') {MessageBox("Se asteapta '<'8"); return i;} else {pos=7; break;}
case 9 :
{
if (s[i]==10 || s[i]==13 || s[i]==' ') break;
if ((s[i]!='>') && (s[i]!=';') && (s[i]!='<')) {MessageBox("Lipseste '>' sau ';'9"); return i;} else
if ((s[i]=='>') || (s[i]=='<')) {pos=7; break;} else
if (s[i]==';') {pos=10; break;}
}
case 10: if ((s[i]!='<') && (s[i]!=13) && (s[i]!=10)) {MessageBox("Lipseste '<'10"); return i;} else
if (s[i]=='<') {pos=1; break;}else
if ((s[i]==10) || (s[i]==13) || (s[i]==' ')) {pos=10; break;}
}
if (pos!=10) {MessageBox("Regulile nu-s terminate"); return s.GetLength();}
return -1;
}
void CCompilatorDlg::OnVerif(){
// TODO: Add your control notification handler code here
UpdateData();
int n=Corectitudinea(m_gram1);
if (n==-1){
FindVectori(m_gram1);
MessageBox("\tGramatica este corecta.\nVn si Vt puteti vedea pe pagina 'Prim-Ultim'.");
m_ctrl_gram1.SetSel(0,0);
}
else
m_ctrl_gram1.SetSel(n,n+1);
m_ctrl_gram1.SetFocus();
}
void CCompilatorDlg::OnConstruct(){
// TODO: Add your control notification handler code here
UpdateData();
int n=Corectitudinea(m_gram1);
if (n==-1){
MakeGram(m_gram1);
MakeList();
} else {
m_tab.SetCurSel(0);
Invalidate();
m_ctrl_gram1.SetSel(n,n+1);
m_ctrl_gram1.SetFocus();
}
}
void CCompilatorDlg::OnChangeGram(){
// TODO: Add your control notification handler code here
quastion=true;
first=true;
ver_sir=false;
next=0;
change=true;
}
void CCompilatorDlg::MakeGram(const CString &ss){
if (quastion==true){
int i,j,k=1;
CString s,s2;
bool b=false;
for (i=0;i<ss.GetLength();i++){
if (ss[i]=='<')
if (ss[i+1]=='<') {s+='<';i++;}
else b=true;
if (ss[i]=='>')
if (ss[i+1]=='>') {s+='>';i++;}
else b=false;
if (!(b==false && ((ss[i]==' ') || (ss[i]==13) || (ss[i]==10)))) s+=ss[i];
}
if (gr!=NULL) gr->clear();
gr = new CGram();
quastion=false;
for (i=0;i<s.GetLength();i++){
s2="";
if (s[i]=='<'){
for (j=++i;;j++,i++)
if (s[j]=='>'){
if (s[j+1]=='>'){
s2+=">>";
j++; i++;
} else break;
} else s2+=s[j];
if (s[j+1]==';'){
gr->addElem(s2,2);
i=j+1;
} else gr->addElem(s2,k);
k=0;
}
if (s[i]==';') k=1;
}
first_s=gr->prim->s;
}
}
void CCompilatorDlg::OnSave(){
// TODO: Add your control notification handler code here
change=false;
CFile f;
if (name!=""){
UpdateData(TRUE);
f.Open(name,CFile::modeReadWrite|CFile::modeCreate);
for (int i=0;i<m_gram1.GetLength();i++){
char c=m_gram1[i];
f.Write(&c,1);
}
f.Close();
} else OnSaveAs();
}
void CCompilatorDlg::OnSaveAs(){
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CFileDialog fd(FALSE,"grm",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Fisiere cu gramatica (*.grm)|*.grm|*.*|*.*||");
if (fd.DoModal()==IDOK){
change=false;
CFile f;
name=fd.GetPathName();
f.Open(name,CFile::modeReadWrite|CFile::modeCreate);
for (int i=0;i<m_gram1.GetLength();i++){
char c=m_gram1[i];
f.Write(&c,1);
}
f.Close();
}
}
void CCompilatorDlg::OnOK(){
// TODO: Add extra validation here
if (change==true){
int x=MessageBox("Grammatica era modificata. Vreti sa solvati?","Save file",MB_ICONQUESTION|MB_YESNOCANCEL);
if (x==IDYES)
OnSave();
else
if (x==IDCANCEL) return;
}
if (gr!=NULL) delete gr;
CDialog::OnOK();
}
void CCompilatorDlg::OnCancel(){
// TODO: Add extra cleanup here
if (change==true){
int x=MessageBox("Grammatica era modificata. Vreti sa solvati?","Save file",MB_ICONQUESTION|MB_YESNOCANCEL);
if (x==IDYES)
OnSave();
else
if (x==IDCANCEL) return;
}
if (gr!=NULL) delete gr;
CDialog::OnCancel();
}
void CCompilatorDlg::FindVectori(const CString &ss){
CGram *gr;
int i,j,k=1;
CString s,s2;
bool b=false;
for (i=0;i<ss.GetLength();i++){
if (ss[i]=='<')
if (ss[i+1]=='<') {s+='<';i++;}
else b=true;
if (ss[i]=='>')
if (ss[i+1]=='>') {s+='>';i++;}
else b=false;
if (!(b==false && ((ss[i]==' ') || (ss[i]==13) || (ss[i]==10)))) s+=ss[i];
}
gr = new CGram();
for (i=0;i<s.GetLength();i++){
s2="";
if (s[i]=='<'){
for (j=++i;;j++,i++)
if (s[j]=='>'){
if (s[j+1]=='>'){
s2+=">>";
j++; i++;
} else break;
} else s2+=s[j];
if (s[j+1]==';'){
gr->addElem(s2,2);
i=j+1;
} else gr->addElem(s2,k);
k=0;
}
if (s[i]==';') k=1;
}
CGram *Vn,*Vt;
Vn = new CGram();
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if (gr->i==1)
if (gr->apartine(Vn)==false)
Vn->addElem(gr->s);
Vt = new CGram();
for (gr=gr->prim;gr->urm!=NULL;gr=gr->urm)
if (gr->apartine(Vn)==false)
if (gr->apartine(Vt)==false)
Vt->addElem(gr->s);
if (gr->apartine(Vn)==false)
if (gr->apartine(Vt)==false)
Vt->addElem(gr->s);
// afisarea vectorului Vn si Vt
for (i=0;i<m_vector.GetCols();i++){
m_vector.SetRow(0);
m_vector.SetCol(i);
m_vector.SetText("");
m_vector.SetRow(1);
m_vector.SetText("");
}
m_vector.SetRow(0);
m_vector.SetCol(0);
m_vector.SetColWidth(0,1500);
m_vector.SetText("Vectorul Neterminal");
m_vector.SetRow(1);
m_vector.SetCol(0);
m_vector.SetText("Vectorul Terminal");
j=i=1;
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm) i++;
i++;
for (Vt=Vt->prim;Vt->urm!=NULL;Vt=Vt->urm) j++;
j++;
if (i>j) m_vector.SetCols(i); else m_vector.SetCols(j);
i=0;
m_vector.SetRow(0);
for (Vn=Vn->prim;Vn->urm!=NULL;Vn=Vn->urm){
m_vector.SetCol(++i);
m_vector.SetText(Vn->s);
if (Vn->s.GetLength()>10) m_vector.SetColWidth(i,Vn->s.GetLength()*100);
}
m_vector.SetCol(++i);
m_vector.SetText(Vn->s);
if (Vn->s.GetLength()>10) m_vector.SetColWidth(i,Vn->s.GetLength()*100);
i=0;
m_vector.SetRow(1);
for (Vt=Vt->prim;Vt->urm!=NULL;Vt=Vt->urm){
m_vector.SetCol(++i);
m_vector.SetText(Vt->s);
if (Vt->s.GetLength()>10) m_vector.SetColWidth(i,Vt->s.GetLength()*100);
}
m_vector.SetCol(++i);
m_vector.SetText(Vt->s);
if (Vt->s.GetLength()>10) m_vector.SetColWidth(i,Vt->s.GetLength()*100);
gr->clear();
Vt->clear();
Vn->clear();
}
Componenta ActiveX MSFlexGrid 6.0:
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++
// NOTE: Do not modify the contents of this file. If this class is regenerated by
// Microsoft Visual C++, your modifications will be overwritten.
#include "stdafx.h"
#include "font.h"
/////////////////////////////////////////////////////////////////////////////
// COleFont properties
CString COleFont::GetName()
{
CString result;
GetProperty(0x0, VT_BSTR, (void*)&result);
return result;
}
void COleFont::SetName(LPCTSTR propVal)
{
SetProperty(0x0, VT_BSTR, propVal);
}
CY COleFont::GetSize()
{
CY result;
GetProperty(0x2, VT_CY, (void*)&result);
return result;
}
void COleFont::SetSize(const CY& propVal)
{
SetProperty(0x2, VT_CY, &propVal);
}
BOOL COleFont::GetBold()
{
BOOL result;
GetProperty(0x3, VT_BOOL, (void*)&result);
return result;
}
void COleFont::SetBold(BOOL propVal)
{
SetProperty(0x3, VT_BOOL, propVal);
}
BOOL COleFont::GetItalic()
{
BOOL result;
GetProperty(0x4, VT_BOOL, (void*)&result);
return result;
}
void COleFont::SetItalic(BOOL propVal)
{
SetProperty(0x4, VT_BOOL, propVal);
}
BOOL COleFont::GetUnderline()
{
BOOL result;
GetProperty(0x5, VT_BOOL, (void*)&result);
return result;
}
void COleFont::SetUnderline(BOOL propVal)
{
SetProperty(0x5, VT_BOOL, propVal);
}
BOOL COleFont::GetStrikethrough()
{
BOOL result;
GetProperty(0x6, VT_BOOL, (void*)&result);
return result;
}
void COleFont::SetStrikethrough(BOOL propVal)
{
SetProperty(0x6, VT_BOOL, propVal);
}
short COleFont::GetWeight()
{
short result;
GetProperty(0x7, VT_I2, (void*)&result);
return result;
}
void COleFont::SetWeight(short propVal)
{
SetProperty(0x7, VT_I2, propVal);
}
short COleFont::GetCharset()
{
short result;
GetProperty(0x8, VT_I2, (void*)&result);
return result;
}
void COleFont::SetCharset(short propVal)
{
SetProperty(0x8, VT_I2, propVal);
}
/////////////////////////////////////////////////////////////////////////////
// COleFont operations
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++
// NOTE: Do not modify the contents of this file. If this class is regenerated by
// Microsoft Visual C++, your modifications will be overwritten.
#include "stdafx.h"
#include "picture.h"
/////////////////////////////////////////////////////////////////////////////
// CPicture properties
long CPicture::GetHandle()
{
long result;
GetProperty(0x0, VT_I4, (void*)&result);
return result;
}
long CPicture::GetHPal()
{
long result;
GetProperty(0x2, VT_I4, (void*)&result);
return result;
}
void CPicture::SetHPal(long propVal)
{
SetProperty(0x2, VT_I4, propVal);
}
short CPicture::GetType()
{
short result;
GetProperty(0x3, VT_I2, (void*)&result);
return result;
}
long CPicture::GetWidth()
{
long result;
GetProperty(0x4, VT_I4, (void*)&result);
return result;
}
long CPicture::GetHeight()
{
long result;
GetProperty(0x5, VT_I4, (void*)&result);
return result;
}
/////////////////////////////////////////////////////////////////////////////
// CPicture operations
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++
// NOTE: Do not modify the contents of this file. If this class is regenerated by
// Microsoft Visual C++, your modifications will be overwritten.
#include "stdafx.h"
#include "msflexgrid.h"
// Dispatch interfaces referenced by this interface
#include "Font.h"
#include "Picture.h"
#include "rowcursor.h"
/////////////////////////////////////////////////////////////////////////////
// CMSFlexGrid
IMPLEMENT_DYNCREATE(CMSFlexGrid, CWnd)
/////////////////////////////////////////////////////////////////////////////
// CMSFlexGrid properties
/////////////////////////////////////////////////////////////////////////////
// CMSFlexGrid operations
long CMSFlexGrid::GetRows()
{
long result;
InvokeHelper(0x4, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRows(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x4, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetCols()
{
long result;
InvokeHelper(0x5, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCols(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x5, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetFixedRows()
{
long result;
InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFixedRows(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x6, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetFixedCols()
{
long result;
InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFixedCols(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x7, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
short CMSFlexGrid::GetVersion()
{
short result;
InvokeHelper(0x1, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, NULL);
return result;
}
CString CMSFlexGrid::GetFormatString()
{
CString result;
InvokeHelper(0x2, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFormatString(LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_BSTR;
InvokeHelper(0x2, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
lpszNewValue);
}
long CMSFlexGrid::GetTopRow()
{
long result;
InvokeHelper(0x8, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetTopRow(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x8, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetLeftCol()
{
long result;
InvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetLeftCol(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x9, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetRow()
{
long result;
InvokeHelper(0xa, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRow(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xa, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetCol()
{
long result;
InvokeHelper(0xb, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCol(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xb, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetRowSel()
{
long result;
InvokeHelper(0xc, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRowSel(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xc, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetColSel()
{
long result;
InvokeHelper(0xd, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetColSel(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xd, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
CString CMSFlexGrid::GetText()
{
CString result;
InvokeHelper(0x0, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetText(LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_BSTR;
InvokeHelper(0x0, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
lpszNewValue);
}
unsigned long CMSFlexGrid::GetBackColor()
{
unsigned long result;
InvokeHelper(DISPID_BACKCOLOR, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetBackColor(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(DISPID_BACKCOLOR, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetForeColor()
{
unsigned long result;
InvokeHelper(DISPID_FORECOLOR, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetForeColor(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(DISPID_FORECOLOR, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetBackColorFixed()
{
unsigned long result;
InvokeHelper(0xe, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetBackColorFixed(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xe, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetForeColorFixed()
{
unsigned long result;
InvokeHelper(0xf, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetForeColorFixed(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xf, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetBackColorSel()
{
unsigned long result;
InvokeHelper(0x10, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetBackColorSel(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x10, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetForeColorSel()
{
unsigned long result;
InvokeHelper(0x11, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetForeColorSel(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x11, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetBackColorBkg()
{
unsigned long result;
InvokeHelper(0x12, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetBackColorBkg(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x12, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
BOOL CMSFlexGrid::GetWordWrap()
{
BOOL result;
InvokeHelper(0x13, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetWordWrap(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x13, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
COleFont CMSFlexGrid::GetFont()
{
LPDISPATCH pDispatch;
InvokeHelper(DISPID_FONT, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL);
return COleFont(pDispatch);
}
void CMSFlexGrid::SetRefFont(LPDISPATCH newValue)
{
static BYTE parms[] =
VTS_DISPATCH;
InvokeHelper(DISPID_FONT, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms,
newValue);
}
float CMSFlexGrid::GetFontWidth()
{
float result;
InvokeHelper(0x54, DISPATCH_PROPERTYGET, VT_R4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFontWidth(float newValue)
{
static BYTE parms[] =
VTS_R4;
InvokeHelper(0x54, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
CString CMSFlexGrid::GetCellFontName()
{
CString result;
InvokeHelper(0x4d, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontName(LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_BSTR;
InvokeHelper(0x4d, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
lpszNewValue);
}
float CMSFlexGrid::GetCellFontSize()
{
float result;
InvokeHelper(0x4e, DISPATCH_PROPERTYGET, VT_R4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontSize(float newValue)
{
static BYTE parms[] =
VTS_R4;
InvokeHelper(0x4e, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
BOOL CMSFlexGrid::GetCellFontBold()
{
BOOL result;
InvokeHelper(0x4f, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontBold(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x4f, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
BOOL CMSFlexGrid::GetCellFontItalic()
{
BOOL result;
InvokeHelper(0x50, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontItalic(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x50, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
BOOL CMSFlexGrid::GetCellFontUnderline()
{
BOOL result;
InvokeHelper(0x51, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontUnderline(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x51, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
BOOL CMSFlexGrid::GetCellFontStrikeThrough()
{
BOOL result;
InvokeHelper(0x52, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontStrikeThrough(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x52, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
float CMSFlexGrid::GetCellFontWidth()
{
float result;
InvokeHelper(0x53, DISPATCH_PROPERTYGET, VT_R4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellFontWidth(float newValue)
{
static BYTE parms[] =
VTS_R4;
InvokeHelper(0x53, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
long CMSFlexGrid::GetTextStyle()
{
long result;
InvokeHelper(0x14, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetTextStyle(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x14, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetTextStyleFixed()
{
long result;
InvokeHelper(0x15, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetTextStyleFixed(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x15, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
BOOL CMSFlexGrid::GetScrollTrack()
{
BOOL result;
InvokeHelper(0x16, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetScrollTrack(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x16, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
long CMSFlexGrid::GetFocusRect()
{
long result;
InvokeHelper(0x17, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFocusRect(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x17, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetHighLight()
{
long result;
InvokeHelper(0x18, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetHighLight(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x18, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
BOOL CMSFlexGrid::GetRedraw()
{
BOOL result;
InvokeHelper(0x19, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRedraw(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x19, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
long CMSFlexGrid::GetScrollBars()
{
long result;
InvokeHelper(0x1a, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetScrollBars(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x1a, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetMouseRow()
{
long result;
InvokeHelper(0x1b, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetMouseCol()
{
long result;
InvokeHelper(0x1c, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetCellLeft()
{
long result;
InvokeHelper(0x1d, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetCellTop()
{
long result;
InvokeHelper(0x1e, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetCellWidth()
{
long result;
InvokeHelper(0x1f, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetCellHeight()
{
long result;
InvokeHelper(0x20, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
long CMSFlexGrid::GetRowHeightMin()
{
long result;
InvokeHelper(0x21, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRowHeightMin(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x21, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetFillStyle()
{
long result;
InvokeHelper(0xfffffe01, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetFillStyle(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0xfffffe01, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetGridLines()
{
long result;
InvokeHelper(0x22, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetGridLines(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x22, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetGridLinesFixed()
{
long result;
InvokeHelper(0x23, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetGridLinesFixed(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x23, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
unsigned long CMSFlexGrid::GetGridColor()
{
unsigned long result;
InvokeHelper(0x24, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetGridColor(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x24, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetGridColorFixed()
{
unsigned long result;
InvokeHelper(0x25, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetGridColorFixed(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x25, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetCellBackColor()
{
unsigned long result;
InvokeHelper(0x26, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellBackColor(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x26, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
unsigned long CMSFlexGrid::GetCellForeColor()
{
unsigned long result;
InvokeHelper(0x27, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellForeColor(unsigned long newValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x27, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
short CMSFlexGrid::GetCellAlignment()
{
short result;
InvokeHelper(0x28, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellAlignment(short nNewValue)
{
static BYTE parms[] =
VTS_I2;
InvokeHelper(0x28, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetCellTextStyle()
{
long result;
InvokeHelper(0x29, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellTextStyle(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x29, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
short CMSFlexGrid::GetCellPictureAlignment()
{
short result;
InvokeHelper(0x2b, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetCellPictureAlignment(short nNewValue)
{
static BYTE parms[] =
VTS_I2;
InvokeHelper(0x2b, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
CString CMSFlexGrid::GetClip()
{
CString result;
InvokeHelper(0x2d, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetClip(LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_BSTR;
InvokeHelper(0x2d, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
lpszNewValue);
}
void CMSFlexGrid::SetSort(short nNewValue)
{
static BYTE parms[] =
VTS_I2;
InvokeHelper(0x2e, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetSelectionMode()
{
long result;
InvokeHelper(0x2f, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetSelectionMode(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x2f, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetMergeCells()
{
long result;
InvokeHelper(0x30, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetMergeCells(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x30, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
BOOL CMSFlexGrid::GetAllowBigSelection()
{
BOOL result;
InvokeHelper(0x33, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetAllowBigSelection(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0x33, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
long CMSFlexGrid::GetAllowUserResizing()
{
long result;
InvokeHelper(0x34, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetAllowUserResizing(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x34, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetBorderStyle()
{
long result;
InvokeHelper(DISPID_BORDERSTYLE, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetBorderStyle(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(DISPID_BORDERSTYLE, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetHWnd()
{
long result;
InvokeHelper(DISPID_HWND, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
BOOL CMSFlexGrid::GetEnabled()
{
BOOL result;
InvokeHelper(DISPID_ENABLED, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetEnabled(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(DISPID_ENABLED, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
long CMSFlexGrid::GetAppearance()
{
long result;
InvokeHelper(DISPID_APPEARANCE, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetAppearance(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(DISPID_APPEARANCE, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
long CMSFlexGrid::GetMousePointer()
{
long result;
InvokeHelper(0x35, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetMousePointer(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x35, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
CPicture CMSFlexGrid::GetMouseIcon()
{
LPDISPATCH pDispatch;
InvokeHelper(0x36, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL);
return CPicture(pDispatch);
}
void CMSFlexGrid::SetRefMouseIcon(LPDISPATCH newValue)
{
static BYTE parms[] =
VTS_DISPATCH;
InvokeHelper(0x36, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms,
newValue);
}
long CMSFlexGrid::GetPictureType()
{
long result;
InvokeHelper(0x32, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetPictureType(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x32, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
CPicture CMSFlexGrid::GetPicture()
{
LPDISPATCH pDispatch;
InvokeHelper(0x31, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL);
return CPicture(pDispatch);
}
CPicture CMSFlexGrid::GetCellPicture()
{
LPDISPATCH pDispatch;
InvokeHelper(0x2a, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL);
return CPicture(pDispatch);
}
void CMSFlexGrid::SetRefCellPicture(LPDISPATCH newValue)
{
static BYTE parms[] =
VTS_DISPATCH;
InvokeHelper(0x2a, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms,
newValue);
}
CString CMSFlexGrid::GetTextArray(long index)
{
CString result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x37, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetTextArray(long index, LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_BSTR;
InvokeHelper(0x37, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, lpszNewValue);
}
short CMSFlexGrid::GetColAlignment(long index)
{
short result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x38, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetColAlignment(long index, short nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I2;
InvokeHelper(0x38, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
long CMSFlexGrid::GetColWidth(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x39, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetColWidth(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x39, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
long CMSFlexGrid::GetRowHeight(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x3a, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetRowHeight(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x3a, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
BOOL CMSFlexGrid::GetMergeRow(long index)
{
BOOL result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x3b, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetMergeRow(long index, BOOL bNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_BOOL;
InvokeHelper(0x3b, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, bNewValue);
}
BOOL CMSFlexGrid::GetMergeCol(long index)
{
BOOL result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x3c, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetMergeCol(long index, BOOL bNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_BOOL;
InvokeHelper(0x3c, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, bNewValue);
}
void CMSFlexGrid::SetRowPosition(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x3d, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
void CMSFlexGrid::SetColPosition(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x3e, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
long CMSFlexGrid::GetRowData(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x3f, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetRowData(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x3f, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
long CMSFlexGrid::GetColData(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x40, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetColData(long index, long nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x40, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
CString CMSFlexGrid::GetTextMatrix(long Row, long Col)
{
CString result;
static BYTE parms[] =
VTS_I4 VTS_I4;
InvokeHelper(0x41, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, parms,
Row, Col);
return result;
}
void CMSFlexGrid::SetTextMatrix(long Row, long Col, LPCTSTR lpszNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I4 VTS_BSTR;
InvokeHelper(0x41, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
Row, Col, lpszNewValue);
}
void CMSFlexGrid::AddItem(LPCTSTR Item, const VARIANT& index)
{
static BYTE parms[] =
VTS_BSTR VTS_VARIANT;
InvokeHelper(0x42, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
Item, &index);
}
void CMSFlexGrid::RemoveItem(long index)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x43, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
index);
}
void CMSFlexGrid::Clear()
{
InvokeHelper(0x44, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}
void CMSFlexGrid::Refresh()
{
InvokeHelper(DISPID_REFRESH, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}
CRowCursor CMSFlexGrid::GetDataSource()
{
LPDISPATCH pDispatch;
InvokeHelper(0x4c, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&pDispatch, NULL);
return CRowCursor(pDispatch);
}
void CMSFlexGrid::SetDataSource(LPDISPATCH newValue)
{
static BYTE parms[] =
VTS_DISPATCH;
InvokeHelper(0x4c, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
newValue);
}
BOOL CMSFlexGrid::GetRowIsVisible(long index)
{
BOOL result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x55, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, parms,
index);
return result;
}
BOOL CMSFlexGrid::GetColIsVisible(long index)
{
BOOL result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x56, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, parms,
index);
return result;
}
long CMSFlexGrid::GetRowPos(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x57, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
long CMSFlexGrid::GetColPos(long index)
{
long result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x58, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,
index);
return result;
}
short CMSFlexGrid::GetGridLineWidth()
{
short result;
InvokeHelper(0x59, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetGridLineWidth(short nNewValue)
{
static BYTE parms[] =
VTS_I2;
InvokeHelper(0x59, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
short CMSFlexGrid::GetFixedAlignment(long index)
{
short result;
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x5a, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, parms,
index);
return result;
}
void CMSFlexGrid::SetFixedAlignment(long index, short nNewValue)
{
static BYTE parms[] =
VTS_I4 VTS_I2;
InvokeHelper(0x5a, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
index, nNewValue);
}
BOOL CMSFlexGrid::GetRightToLeft()
{
BOOL result;
InvokeHelper(0xfffffd9d, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetRightToLeft(BOOL bNewValue)
{
static BYTE parms[] =
VTS_BOOL;
InvokeHelper(0xfffffd9d, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
bNewValue);
}
long CMSFlexGrid::GetOLEDropMode()
{
long result;
InvokeHelper(0x60f, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
return result;
}
void CMSFlexGrid::SetOLEDropMode(long nNewValue)
{
static BYTE parms[] =
VTS_I4;
InvokeHelper(0x60f, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,
nNewValue);
}
void CMSFlexGrid::OLEDrag()
{
InvokeHelper(0x610, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}
Anexa 3
Graful rețea pentru generator de analizoare sintactice
=== RAM1 ===
Cuprins
INTRODUCERE 5
INSTRUMENTARIU 7
ANALIZA SINTACTICĂ. STRATEGIA ASCENDENTĂ 15
Analiza sintactică 15
Mașina “deplasează-reduce” 18
GRAMATICI DE PRECEDENȚĂ SIMPLĂ 21
ALGORITME DE CONSTRUIRE A RELAȚIILOR DE PRECEDENȚĂ 26
Algoritmul de construire a mulțimilor PRIM și ULTIM 26
Algoritmul de construire a relațiilor de precedență 27
GRAMATICI DE PRECEDENȚĂ SLABĂ 29
Stratificarea – o soluție pentru eliminarea conflictelor 29
Gramatici de precedență slabă 32
AUTOMATIZAREA CONSTRUIRII ANALIZOARELOR “DEPLASEAZĂ-
REDUCE” BAZATE PE RELAȚII DE PRECEDENȚĂ 34
Implementarea unei MDR valabile pentru o gramatică de precedență simplă 34
Construirea și codificarea gramaticii independente de context 36
Construirea tabelelor 41
Crearea analizorului sintactic 49
Exemple 51
PARTEA ECONOMICĂ 59
Planificarea rețea 59
Evaluarea economică a proiectului 66
PROTEC”IA MUNCII 70
Aprecierea pericolului la monitor 70
Calcularea iluminatului natural 73
Analiza condițiilor de muncă 75
Cerințele ergonomice privind locul de muncă 76
Condiționarea aerului 78
Cerințele securității tehnice la începutul lucrării 79
Cerințele securității tehnice în timpul de lucru 80
Acțiuni în cazuri fatale 80
Securitatea antiincendiară 80
Cazurile apariției incendiilor 81
Securitatea antiincendiară în sălile de clcul 82
CONCLUZII 84
BIBLIOGRAFIE 85
ANEXE 86
=== RAM2 ===
PROTEC”IA MUNCII 70
Aprecierea pericolului la monitor 70
Calcularea iluminatului natural 73
Analiza condițiilor de muncă 75
Cerințele ergonomice privind locul de muncă 76
Condiționarea aerului 78
Cerințele securității tehnice la începutul lucrării 79
Cerințele securității tehnice în timpul de lucru 80
Acțiuni în cazuri fatale 80
Securitatea antiincendiară 80
Cazurile apariției incendiilor 81
Securitatea antiincendiară în sălile de clcul 82
CONCLUZII 84
BIBLIOGRAFIE 85
ANEXE 86
Anexa 1 86
Anexa 2 89
Anexa 3 135
=== TEORIA_F1 ===
Introducere
Analizorul sintactic este o componentă obligatorie pentru orice compilator. Pentru a obține un product soft (program) trebuie să creăm un program executabil. Pentru aceasta avem nevoie de un limbaj de programare, de exemplu, un limbaj destul de răspândit ca C++. Într-o fereastră obișnuită poate fi scris un cod în pseudolimbaj care va fi tratat și prelucrat. Pentru a înțelege propozițiile scrise avem nevoie de un vocabular și reguli cu ajutorul cărora vor fi tratate cuvintele introduse de programator. Aceasta se realizează cu ajutorul analizoarelor sintactice.
Rolul analizei sintactice constă în transformarea șirului de atomi lexicali într-o descriere structurală a șirului, dacă șirul este corect, sau generarea unui mesaj de eroare, dacă șirul nu este corect. Descrierea structurală este de obicei un echivalent al arborelui de derivare.
O situație des întâlnită este cea în care analizorul sintactic în loc să construiască în mod explicit arborele de derivare, pentru fiecare pas în construcția arborelui, declanșează anumite acțiuni asupra bazei de date prin intermediul procedurilor semantice.
În principiu, există două strategii de construire a arborelui de derivare: strategia descendentă în care arborele este construit de la rădăcină spre frunze și strategia ascendentă în care arborele este construit de la frunze spre rădăcină. În ambele cazuri construcția este ghidată de șirul de la intrare. Corespunzător acestor strategii vom avea analizoare sintactice descendente și, respectiv, analizoare sintactice ascendente.
O altă clasificare a analizoarelor sintactice este bazată pe existența revenirilor. Deoarece modelul sintaxei limbajelor de programare este gramatica independentă de context, modelul analizorului sintactic va fi automatul push-down nedeterminist. Este normal deci ca în simularea funcționării acestuia în cadrul unui program, să prevedem posibilitatea încercării tuturor alternativelor de continuare a analizei. Abandonarea unei alternative necesită revenirea la situația anterioară încercării ei. Asigurarea în orice moment a unei singure posibilități de continuare a analizei sintactice permite realizarea de analizoare fără reveniri, deci analizoare eficiente.
Pentru analiza sintactică se utilizează gramatica independentă de context – gramatica , toate producțiile gramaticii sunt de forma: , unde , . În lucrarea prezentată se utilizează gramatica independentă de context fără -producții (-producții).
Presupunem că există o gramatică cu un număr de reguli respectiv mic. Atunci construirea analizorului sintactic poate fi nu atât de grea. De obicei numărul producțiilor este destul de mare și construirea manuală a analizorului este practic imposibilă. De exemplu, în limbajul C++ sau Pascal numărul cuvintelor este mai mult de 1000, iar al regulilor este mai mult de 5000.
În acest caz apare necesitatea automatizării construirii analizoarelor sintactice. Cum s-a menționat mai sus pot fi utilizate 2 metode: analizoare sintactice descendente și analizoare sintactice ascendente. În lucrarea dată este elaborat un generator de analizoare sintactice ascendente bazate pe relații de precedență. Această metoda nu este cea mai avansată, dar oferă posibilitatea construirii automate a analizorului și în același timp este ușoară și înțeleasă.
Dezavantajul acestei metode în comparație cu alte metode mai avansate constă în faptul că nu în toate cazurile poate fi efectiv tratată eroarea. Adică la apariția erorii nu întotdeauna poate fi găsit locul și denumirea ei. Un alt dezavantaj al acestei metode constă în folosirea irațională a memoriei calculatorului pentru tabela relațiilor de precedență.
Avantajele acestei metode sunt rapiditatea construirii analizorului și verificarea șirului de simboluri. Al doilea avantaj constă în ușurința (în comparație cu alte metode) construirii analizorului.
Instrumentariu
Construirea generatorului analizoarelor sintactice este realizată utilizând limbajul de programare Visual C++. Acest limbaj dă posibilități avansate programatorului, deoarece el este orientat spre obiect și în același timp este orientat spre eveniment. Folosind componentele standarde și nestandarde este elaborată o interfață foarte comodă pentru utilizatori.
Programul dat dă posibilitatea de a obține o informație fără greutăți, deoarece în orice moment de timp utilizatorul poate obține informația necesară despre corectitudinea gramaticii introduse, despre vectorii terminali și neterminali, poate arăta conținutul tabelelor “PRIM-ULTIM” sau de precedență. Pentru a obține comoditatea aceasta sunt utilizate clase standarde CDialog (Fereastră de dialog), CEdit (Edit Box), CButton (Buton), CTabCtrl (Tab Control – pagini speciale) și componenta care nu intră în pachetul standard Visual C++ 6.0 – componenta ActiveX MSFlexGrid destinată afișării tabelelor. Această componentă utilizează clase adăugătoare CRowCursor, COleFont și CPicture (sursele acestor clase ale componentei ActiveX ale puteți vedea în anexă).
Pentru păstrarea informației despre gramatica inițială și modificată, despre vectorii terminali și neterminali, despre șirul destinat verificării și diferite tabele este elaborată o clasă specială care are denumirea CGram. Pentru păstrarea conținutului tabelului Prim-Ultim este elaborată o clasă aparte care poartă denumirea CPrimUltim.
Limbajul Visual C++ este unul din cele mai avansate limbaje de programare destinate elaborării aplicațiilor sub Windows. Cu ajutorul Wizard-ului se elaborează o fereastră standard de tip dialog pe care putem amplasa diferite butoane, ferestre pentru editarea textelor și alte componente vizuale ale programului.
Partea principală vizuală a programului o constituie paginile în care puteți vedea diferite elemente destinate afișării datelor necesare. Pentru a utiliza “Tab Control” este necesar să se declare o variabilă a clasei CTabCtrl. Această clasă se bazează pe clasa CWnd și afară de avantajele clasei bazice are și metode proprii. Ca orice clasă CTabCtrl are constructor și încă o metodă pentru construirea paginilor. Inițial numărul paginilor este egal cu 0. Pentru a adăuga o pagină se utilizează funcția InsertItem ce întoarce valoarea true – dacă adăugarea s-a petrecut fără erori și -1 – în cazul unei erori. Parametrul principal al clasei este adresa unui string (denumirea paginii) dar sunt posibili alți parametri începând cu diferite constante și terminând cu diferite imagini care pot fi prezentate lângă denumirea paginii. Numerotarea paginilor se începe cu 0. Pentru a distruge o pagină se utilizează funcția DeleteItem. La începutul programului variabila clasei CTabCtrl se asociază cu Tab Control care poate fi modificată cu ajutorul masterului. Pentru a recunoaște numărul paginii utilizate la momentul dat se folosește funcția GetCurSel care întoarce numărul paginii selectate. Există și funcția inversă care dă posibilitatea alegerii unei ferestre din interiorul programului: SetCurSel cu parametrul care arată numărul paginii selectate. În cadrul programului (clasei CCompilatorDlg) este adăugată o funcție care se apelează numai atunci când utilizatorul alege altă fereastră. Există încă un set de metode în cadrul clasei date, dar care se utilizează mai rar.
Deoarece limbajul Visual C++ este orientat spre eveniment există posibilitatea de a efectua orice operațiune în orice moment de timp (conform dorinței utilizatorului). Această posibilitate poate fi îndeplinită utilizând o tastă. Pentru a salva, a încărca, a modifica etc. utilizatorul în orice moment poate apăsa butonul respectiv și se vor efectua operațiunile necesare. Pentru efectuarea unei comenzi este necesar de a utiliza variabila clasei CButton, sau a unor operațiuni orientate spre eveniment, sau și a clasei și a operațiunii în același timp. Clasa CButton se bazează pe clasa CWnd și are metode moștenite de clasă părinte. La început clasa dată se asociază cu butonul plasat pe fereastra de dialog. Clasa CButton ca și orice altă clasă în C++ are constructor și diferite funcții (metode). Majoritatea metodelor acestei clase se referă la schimbarea formei, culorii, mărimii tastei respective sau la obținerea informației despre aceste caracteristici (GetIcon, SetIcon, GetBitmap, SetBitmap, GetButtonStyle etc.). Există încă funcția care întoarce poziția cursorului referitor la taste, adică pe ce tasta se află cursorul (GetCursor), și metoda inversă (SetCursor). Pentru a îndeplini diferite operațiuni la apăsarea tastei se utilizează funcția creată cu ajutorul masterului utilizând efectul BN_CLICKED. Funcția dată se bazează în corpul clasei CCompilatorDlg.
Figura 1.1
Fereastră de dialog a clasei CFileDlg
De exemplu, pentru încărcarea sau salvarea gramaticii este necesar să se utilizeze o fereastră de dialog standard Windows cu ajutorul căreia se alege locul și denumirea fișierului cu gramatică (vezi figura 1.1). Pentru inițializarea ferestrei date se utilizează clasa CFileDialog. Această clasă este destinată alegerii fișierelor atât pentru salvare, cât și pentru încărcare. Pentru a alege modul de funcționare a clasei este necesar să transmitem constructorului parametrul necesar. De asemenea se transmitem constructorului alți parametri necesare pentru inițializarea corectă a variabilei clasei date. În primul rând, aceasta este extensiunea fișierelor destinate prelucrării, adică ce fișiere vor fi arătate în fereastra de dialog. În al doilea rând, este parametrul necesar pentru adăugarea extensiunii la sfârșitul fișierului în cazul salvării. Mai există încă diferite fanioane destinate afișării fișierelor cu parametrii ReadOnly ș.a.
Pentru a vizualiza fereastra de dialog inițializată în constructor este necesar de a apela la funcția DoModal. Metoda dată întoarce valoarea IDOK în cazul apăsării tastei “Open” (“Save”) și IDCANCEL – dacă era apăsata tasta “Cancel”. Pentru a cunoaște drumul complet și denumirea fișierului ales se apelează funcția GetPathName care întoarce un string. De obicei se utilizează funcția dată, dar există și alte funcții care întorc sau numai extensiunea fișierului, sau numai denumirea lui, sau calea de acces la fișierul dat etc. Clasa curentă conține și alte funcții care nu erau utilizate în programul prezentat.
Presupunem că utilizatorul a ales un fișier cu gramatica necesară, atunci această gramatică apare pe ecran în fereastra respectivă. Pentru a copia datele din fișier în fereastră sunt utilizate 2 clase: CFile și CString. Cu ajutorul variabilei clasei CFile citim datele din fișier în variabila clasei CString unde ele se păstrează, sau invers din string copiem datele în fișier.
Presupunem că conținutul fișierului este deja copiat. Atunci pentru vizualizarea acestui string avem nevoie de o fereastră (Edit Box). Pentru a asocia variabila de tip CString se utilizează Wizard-ul. Folosind funcția UpdateData cu parametrul true sau false putem transfera datele de la variabilă la fereastră și respectiv invers. Există și altă posibilitate pentru utilizarea ferestrei. Pentru aceasta avem nevoie de variabila de tip CEdit.
Mai întâi variabila clasei se creează și se asociază cu fereastra plasată pe fereastra de dialog. Clasa CEdit este bazată pe clasa CWnd. Funcțiile principale ale clasei sunt: Cut, Copy, Clear, Undo și Paste. Ele sunt aceleași ca și în Windows. Pentru a recunoaște este posibil sau nu apelarea funcției Undo trebuie să fie utilizată metoda CanUndo care întoarce sau true sau false. Se mai admite o posibilă prelucrare a liniilor aparte (GetLine) sau ferestrei totale. Pot fi utilizate funcții pentru selectarea unui text – SetSel. Ea transmite 3 parametri 1 – începutul selectării (nr. caracterului), 2 – sfârșitul selectării (nr. caracterului), 3 – parametrul cu ajutorul căruia se afișează cursorul în fereastră.
Figura 1.2
Lista clasei CGram
Una din principalele clase utilizate pentru păstrarea informației este clasa CGram. Cu ajutorul acestei clase se formează o listă în care poate fi păstrată gramatica independentă de context, diferiți vectori și tabele necesare. Pentru a inițializa un element sau o listă de elemente este necesar să se apeleze la constructor. Lista este dublu înlanțuită și adresa arată spre primul element al listei (vezi figura 1.2). Există încă 2 variabile în care se păstrează informația de bază, adică un string – elementul gramaticii și un număr ajutător.
Pentru a adăuga un element în listă se utilizează funcția addElement care are 2 parametri: string – denumirea elementului din gramatica curentă și un număr întreg a cărui valoare este 0. Această metodă adaugă un element în listă pe ultimul loc la lista curentă. Iar pentru a elimina un element din listă poate fi apelată funcția eraseElem care nu conține nici un parametru, dar întoarce o adresă. Această funcție alocă memoria care arată elementul curent și întoarce adresa elementului precedent. Numai în cazul dacă elementul curent era primul în listă se întoarce adresa elementului următor. Mai există posibilitatea de a distruge toată listă folosind metoda clear, ea n-are nici un parametru și nu întoarce nici o valoare. După apelarea funcției date lista este complet ștearsă, adică orice apelare la ea duce la eroare.
O funcție importantă la elaborarea programului se numește print. Ea joacă un rol important la începutul lucrului, deoarece la început nu există posibilitatea de a obține orice informație despre listă în afară de metoda dată. Ea afișează lista curentă cu ajutorul funcției AfxMessageBox și nu întoarce nici o valoare. La sfârșit utilizarea funcției brusc se reduce, deoarece apar alte metode pentru a afișa conținutul listei.
Funcția verifică aparține sau nu un element altei liste și întoarce valoarea true în caz pozitiv și false în caz contrar. Ea conține un singur parametru și lucrează în felul următor: în lista dată ca parametru se caută elementul care are același element al gramaticii, iar numărul suplimentar nu se verifică. Neajunsul funcției date constă în căutarea unui singur element în altă listă, dar apare nevoia de a cauta și o sublistă într-o listă. Pentru aceasta sunt adăugate încă 4 funcții care se numesc intra, intra1, intra2 și intra3. Ele îndeplinesc aproximativ aceleași funcții, dar sunt și careva diferențe. Metoda intra este destinată căutării unei liste mai mici în altă listă. Ca parametri vin 2 liste: list1 căutăm în list2. Deosebirea principală a funcției date constă în faptul că se verifică nu numai elementele gramaticilor păstrate într-o listă, dar și numere ajutătoare menționate în elementele respective ale lstei și sunt verificate numai părțile drepte a producțiilor. În caz dacă prima listă nu intră în lista numărul doi, atunci se întoarce valoarea NULL, în caz contrar se întoarce adresa începutului sublistei în lista numărul doi. Deosebirea principală a metodei intra1 de metoda precedentă constă în faptul că se verifică o regulă, iar nu numai partea dreaptă a producției. Ca și în cazul precedent se întoarce adresa sublistei sau NULL.
Funcția intra2 aproximativ coincide cu metoda intra1, dar și aici sunt excepții. Necoincidența principală constă în întoarcerea valorii, adică în cazul funcției intra1 s întoarce adresa, iar în alt caz se întoarce numai valoarea true sau false. Există încă o diferență în algoritmul căutării sublistei în listă. Metoda intra3 întoarce valoarea true sau false ca și în metoda precedentă, dar deosebirea principală constă în faptul că list1 constă din 2 elemente și pentru a întoarce valoarea true este necesar căutarea numai în partea dreaptă a producțiilor.
O funcție importantă pentru lucrarea corectă a analizorului sintactic este funcția FindRepeat care n-are nici un parametru și întoarce valoarea true dacă sunt coincideri în partea dreaptă a gramaticii. Dacă părțile drepte sunt diferite, atunci se întoarce valoarea false. Dacă este găsită o repetare (repetare completă a părții drepte) aceasta înseamnă că avem gramatică nu de precedență simplă și trebuie să fie modificată conform regulelor. De exemplu:
<R><S>;
<S><A>;
<S><(><L>;
<L><S><)>;
<L><S><L>;
<A><i>;
<L><i>;
<A><n>;
<R><S>;
<S><A>;
<S><(><L>;
<L><S><)>;
<L><S><L>;
<A><i>;
<A><n>;
<S><(><i>;
<L><S><i>;
Există și alte funcții (modificare, DeleteRepeat) nu așa de importante, care sunt de asemenea utilizate în construirea analizorului lexical.
Pentru a păstra informația despre tabelul Prim-Ultim este necesar o altă clasă CPrimUltim. Deosebirea principală (construcție) a acestei clase față de clasa CGram constă în faptul că aici se adaugă 2 liste: grprim și grultim (vezi figura 1.3).
Figura 1.3
Lista clasei CPrimUltim
Listele grprim și grultim sunt listele bazate pe clasa CGram și este evident că ele conțin toate proprietățile și structura acestei clase.
Pentru completarea unui element este necesar să se apeleze la 2 funcții: addElement și addSublist. Prima funcție coincide cu funcția CGram::addElement, iar metoda addSublist este destinată adăugării listelor grprim și grultim deja completate. Aceste 2 subliste vin ca parametrii funcției. Pentru a șterge lista clasei date din memorie se apelează la metoda clear. La început ea distruge listele grprim și grultim și după aceasta eliberează memoria, care era ocupată de elementul curent.
Ca și în clasa precedentă aici sunt 2 funcții pentru afișarea conținutului listei. Funcția print este destinată afișării numai elementelor listei curente, iar funcția printAll afișării elementelor listei și a sublistelor grprim și grultim.
Pentru vizaulizarea tabelei Prim-Ultim și tabelei de precedență este necesar utilizarea componentei ActiveX Microsoft FlexGrid Control versiunea 6.0. Adăugând această componentă cu ajutorul masterului noi obținem sursele necesare pentru crearea tabelelor. Sunt create trei clase aparte: CMSFlexGrid, COleFont, CPicture și CRowCursor. Clasa CMSFlexGrid conține mai mult de 150 metode și se bazează pe clasa CWnd.
Una din cele mai importante funcții ale clasei este SetCols și SetRows. Ele sunt destinate pentru modificarea mărimii tabelelor și ambele funcții au un parametru: numărul liniilor și a coloanelor. Aceste funcții nu întorc nici o valoare. Există încă 2 funcții inverse cu ajutorul cărora putem recunoaște mărimea tabelului.
De obicei lungimea și înălțimea unei celule inițiale este definită implicit. Dar apar cazurile când înălțimea literelor este mai mare de cât înălțimea celulei sau lungimea șirului de litere este mai mare decât lungimea celulei, atunci acești parametri trebuie să fie măriți. Pentru a modifica lungimea unei celule se utilizează funcții SetColWidth. În calitate de parametri se transfer numărul rândului și lungimea lui. Pentru a modifica înălțimea rândului se utilizează metoda SetRowHeight.
Pentru a înscrie o informație într-o celula concretă trebuie să fie utilizate 3 funcții: SetCol, SetRow și SetText. Trebuie de spus că numărarea rândurilor și coloanelor se începe cu 0. Ca parametri primele 2 funcții au numere întregi nu mai mari decât numărul coloanelor –1 sau rândurilor –1. După alegerea celulei putem scrie orice text care se transmite ca parametrul funcției SetText. Evident că pentru a citi o informație din tabel trebuie să alegem rândul și coloana și după aceasta vom citi informația cu ajutorul funcției GetText. Metoda dată întoarce șirul de litere utilizând clasa CString.
S-a menționat mai sus situația când înălțimea literelor poate fi mai mare de cât înălțimea celulei. Inițial aceasta situație este imposibilă și poate apărea numai în 2 cazuri:
înălțimea rândului este modificată (SetRowHeight);
fontul este schimbat.
Pentru modificarea fontului pot fi utilizate diferite funcții începând cu crearea textului înclinat sau cu altă culoare și terminând cu alegerea fontului TimesNewRoman sau Arial. Afară de font poate fi modificat și fonul celulei. De exemplu, pentru a modifica culoarea fonului se apelează funcția SetBackColor (ca parametru vine numărul culorii alese). Evident că aproape fiecare funcție are o funcție inversă. De exemplu, pentru metoda SetBackColor există și metoda inversă GetBackColor, care întoarce culoarea utilizată în celula respectivă.
Pentru a modifica fontul tabelei este necesar utilizarea altei clase din componenta ActiveX – COleFont. Această clasă dă posibilitatea de a modifica fontul întregului tabel în orice moment. De obicei fiecare metodă pentru a modifica ceva utilizează funcția SetProperty cu diferiți parametri.
Există încă un moment important. El constă în faptul că pentru utilizarea clasei CMSFlexGrid este necesar asocierea cu FlexGrid Contol vizualizată măcar odată. Dacă variabila clasei este asociată cu componenta nevizualizată, atunci apare o eroare când se va executată o încercare de a modifica ceva. Această eroare este datorită declarării dinamice a clasei CMSFlexGrid.
Mai există și posibilitatea de a afișa înăuntrul celulei o imagine păstrată cu ajutorul clasei CPicture. Pentru aceasta se folosește funcția SetPictureType sau SetRefCellPicture.
Este clar că toate clasele care răspund de diferite obiecte vizuale sunt bazate pe clasa CWnd. Ea răspunde de vizualizarea componentelor ca butoane, tabele, ferestre etc. Clasa aceasta conține mai mult de 300 de funcții și parametrii dintre care mai mult de 100 sunt publici și pot fi apelați din exteriorul clasei. Deoarece programul conține butoane “minimize” și “maximize” și componentele ferestrei de dialog pot fi deplasate (din interiorul programului), trebuie să fie apelate funcțiile speciale, de exemplu MoveWindow. Funcția dată transmite ca parametri 4 variabile de tip întreg: coordonatele punctului (left-top), lungime, înălțimea obiectului (buton, fereastră). În cazul modificării putem recunoaște mărimea nouă a ferestrei de dialog cu ajutorul metodei private OnSize. Ca parametri se consideră lungimea și înălțimea ferestrei.
Deoarece în program este utilizat Tab Control, pentru a afișa pe pagina curentă numai componentele necesare se folosește subrutina ShowWindow cu parametrii SW_HIDE sau SW_SHOW. Sunt posibili și alți parametrii ai funcției date. Dacă se transmite parametrul SW_SHOW, atunci obiectul asociat cu variabila curentă apare pe fereastra de dialog și invers, dacă transmitem constanta SW_HIDE.
Folosind metodele clasei curente poate fi modificat fonul și fontul utilizat în fereastra de dialog curentă. Pot fi schimbate culorile, pozițiile în spațiu, mărimile, poziția cursorului sau mouse-ului etc.
Avantajul clasei constă în faptul că unele obiecte ca Scroll Bar, Menu Bar, Tab Control etc. pot fi create în interiorul clasei, adică pe parcursul îndeplinirii programului. Orice acțiune poate fi asociată cu timpul, adică folosind funcțiile SetTimer, KillTimer și OnTimer pot fi îndeplinite diferite manipulări vizuale sau înăuntru clasei cu variabile. Tot din interiorul clasei programul poate fi oprit și închis ori deschisă o copie sau un alt program.
Analiza sintactică. Strategia ascendentă.
Analiza sintactică
Fie dată gramatica:
S bAcBe
A Aa|a
B d
și cuvântul baacde din limbajul generat de gramatică. Vom încerca să refacem drumul parcurs de un analizor cu strategie ascendentă care pleacă de la șirul baacde și găsește în final neterminalul S. Pe parcurs vom evidenția problemele mai deosebite ale acestui tip de analiză.
Prototipul analizei sintactice ascendente este automatul “push-down” extins. După cum se știe, el poate simula în funcționarea sa derivarea dreaptă într-o gramatică independentă de context, derivare parcursă însă în ordinea inversă. Automatul “push-down” extins identifică pentru aceasta în vârful stivei părți drepte ale producțiilor pe care le “reduce” la neterminalul părții stângi corespunzătoare. În vederea completării părții drepte, automatul își aduce pe rând în stivă simbolurile de la intrare. Șirul este acceptat dacă au fost “consumate” toate simbolurile de la intrare, iar în stivă a rămas doar simbolul de început.
În cazul exemplului considerat, un analizor sintactic ascendent va căuta părți dreapta ale producțiilor în șirul de intrare. Le găsește sub forma: a și d. Desigur, analizând în mod natural, de la stânga la dreapta, după depășirea lui b, va prefera înlocuirea primului a cu A, rezultând șirul bAacde. În termenii arborilor de derivare subșirul analizat se prezintă ca în figura 2.1.
După cum vom vedea în continuare, un analizor ascendent creează o “pădure” de arbori pe care încearcă să-i reunească în final într-un unic arbore. În cazul nostru, el a creat un arbore format dintr-un nod etichetat b și un arbore ca în figura 2.2.
A A
b a a
figura 2.1 figura 2.2
Încercând în continuare să găsească părți dreapta (de această dată în bAacde) analizorul va găsi, în ordine: Aa, a și d. Ordinea de analiză de la stânga la dreapta a intrării impune de data aceasta două posibilități: Aa și a. Ambele se reduc la A, dar nu sunt totuși la fel de bune. Într-adevăr, reducerea lui a la A conduce la șirul de bAAcde care apoi prin reducerea lui d la B conduce la bAAcBe în care analizorul nu mai poate recunoaște nici o parte dreaptă și analiza pe această cale eșuează, fiind necesară revenirea la decizia reducerii lui a. Dacă se alege reducerea lui Aa la A se obține șirul bAcde și corespunzător “pădurea” din figura 2.3.
După adăugarea lui c și d la pădure, singurul șir de redus este d. După reducerea lui obținem bAcBe și pădurea din figura 4.
În fine, adăugând și ultimul simbol la pădurea de arbori, se observă că noul șir, ca și rădăcinile arborilor pădurii, alcătuiesc partea dreaptă a primei producții, deci putem reduce la S, adică ajungem la arborele de derivare din figura 2.5.
A A
A A B
b a a b a a c d
figura 2.3 figura 2.4
S
A
A B
b a a c d e
figura 2.5
Concluzia este, desigur, acceptarea șirului.
Să observăm că analiza a refăcut în ordine inversă derivarea dreapta:
prin reduceri:
baacde bAacde bAcde bAcBe S
În aceste transformări, subșirul redus joacă un rol esențial. El trebuie mai întâi identificat și apoi înlocuit cu un neterminal. Acest subșir este întotdeauna cel mai din stânga subșir dintr-o formă propozițională dreapta care poate fi redus astfel încât să se refacă în sens invers un pas într-o derivare dreapta. El poartă numele de capăt.
Definiția 2.1. Capătul unei forme propoziționale dreapta este șirul dacă în gramatica respectivă există derivarea:
În cazurile concrete capătul este dat printr-o producție și poziția lui în (adică limitele lui din stânga și din dreapta).
În arborele de derivare asociat unei forme propoziționale capătul apare ca cel mai din stânga subarbore complet (format deci dintr-un nod-rădăcină și toți descendenții săi).
Utilizând noțiunea de capăt, analiza ascendentă apare ca un proces de formare și identificare a capetelor formelor propoziționale dreapta obținute și de reducere a lor la neterminale.
Exemplul 2.1.
Fie gramatica:
L L,E
L E
E id
E id(L)
și șirul de intrare id1,id2(id3,id4) în care am evidențiat diferitele apariții ale termenului id.
Reducerea șirului la neterminalul L are loc în următoarele etape:
Se observă că secvența reducerilor este exact inversa secvenței derivărilor dreapta.
Din prezentarea de mai sus remarcăm faptul că un analizor sintactic ascendent este confruntat cu două probleme principale: identificarea capătului în forma propozițională dreapta și alegerea producției cu care să facă reducerea.
În ceea ce privește identificarea capătului, se poate arăta că într-o parcurgere de la stânga la dreapta a șirului de intrare însoțită de reduceri succesive ale capătului fiecărei forme propoziționale dreapta, la un moment dat, analizorul sintactic nu trebuie să se întoarcă oricât în pădurea de arbori deja formată pentru a căuta capătul, ci acesta apare în mod natural în vecinătatea imediată a punctului de analiză.
Mai precis, să considerăm cele două posibilități de apariție a capătului. Fie mai întâi derivarea:
în care s-au folosit producțiile și . Se observă că în șirul s-a evidențiat neterminalul cel mai din dreapta.
Pornind în sens invers, de la șirul de terminale, analizorul sintactic ascendent a prelucrat parțial șirul de intrare aducându-l la forma: , și rămânându-i de parcurs șirul yu. Este momentul în care el trebuie să depisteze capătul și să-l reducă la B, șirul prelucrat devine , iar cel neanalizat rămânând yu. Se vede că în șirul , deci la stânga lui B, capătul nu poate apare, B fiind cel mai din dreapta neterminal. Singura posibilitate este ca noul capăt să se completeze prin aducerea de terminale din yu. Această operație de adăugare de către analizor din șirul de intrare a noi terminale la porțiunea deja prelucrată a formei propoziționale se numește deplasare. Adăugând y obținem By în care moment se identifică un capăt By, ce se reduce la A. (y poate fi chiar șirul vid; atunci fără a se face vreo deplasare, după reducerea lui la B se face reducerea lui B la A.)
O altă posibilitate de derivare dreapta o constituie secvența:
în care s-au folosit producțiile și .
Lucrând în sens invers, analizorul construiește șirul în care moment găsește că este capăt și îl reduce la B. Din nou, capătul nu are ce căuta în stânga lui B, deci se vor adăuga de la intrare noi simboluri până la formarea șirului în care moment se delimitează capătul y și se reduce la A.
Din observarea celor două cazuri posibile de localizare a capătului, constatăm că orice capăt este format din cele mai recente simboluri prelucrate, reduse sau deplasate.
Deci șirul deja analizat alcătuiește o listă LIFO a cărei implementare se poate face cu o memorie stivă.
În afara stivei, algoritmul de analiză va avea acces la șirul de intrare pentru a-și deplasa terminale în stivă. De asemenea, va trebui să depună la ieșire informații privind analiza efectuată. Algoritmul, pe baza informației de la intrare și a conținutului stivei, va decide asupra următoarei acțiuni ce poate fi: reducere, deplasare, eroare, acceptare.
Mașina “deplasează-reduce”
Un asemenea algoritm de analiză poartă numele “deplasează-reduce”. Analizorul “deplasează-reduce” are, după cum ușor se poate observa, ca model matematic, automatul “push-down” extins. Ca și la analiza descendentă vom încerca să definim un model fizic al analizei ascendente ce lucrează prin deplasări și reduceri: mașina “deplasează-reduce”, pe scurt MDR.
Din punct de vedere al structurii MDR este similară mașinii de analiză predicativă, MAP. Operațiile primitive sunt aceleași cu cele ale MAP cu excepția operației de comparație a subșirurilor din stivă, necesară în identificare capetelor din vârfuri stivei. În termenii acestor operații, efectele acțiunilor MDR sunt următoarele:
Reducere cu ():
se șterg din vârful stivei simboluri,
se depune în vârful stivei simbolul ,
se depune pe banda de ieșire numărul i.
Deplasare:
se depune simbolul curent de la intrare în vârful stivei,
se avansează banda de intrare.
Eroare:
Se semnalizează eroarea prin modificarea stării procesorului.
Acceptare (are loc la întâlnirea marcajului ‘$’ pe banda de intrare și a șirului $Z0 în stivă, ):
se semnalează acceptarea pin modificarea stării procesorului.
Starea mașinii este sintetizată către configurația sa (, x$, ), unde este conținutul stivei cu vârful X reprezentat spre dreapta, x$ este șirul de intrare cu marcajul $ și este șirul numerelor de producții cu care s-au făcut reducerile.
Configurația inițială este ($, x$, ), unde x este șirul de analizat, iar configurațiile finale sunt de forma ($Z0, $, ).
Reducerea cu (, A, i) determină o mișcare a mașinii de forma:
Deplasarea determină mișcarea:
Eroarea întrerupe șirul mișcărilor ceea ce notăm astfel:
? eroare.
Acceptarea de asemenea întrerupe evoluția mașinii:
? acceptare.
Relația de mișcare se poate extinde la închiderea ei tranzitivă și reflexivă .
MDR poate fi privită și ea ca un translator ce definește o traducere astfel:
Definiția 2.2. O MDR este valabilă pentru o gramatică G dacă:
pentru orice , dacă , atunci .
Exemplul 2.2.
Fie gramatica GL de mai sus și șirul de intrare id, id. Considerăm și Z0=L. Atunci există următoarea secvență de mișcări ale MDR (pentru a nu se confunda cu virgula folosită în descrierea configurației, terminalul ‘,’ a fost “prins” între apostrofuri).
– ? acceptare.
Principala problemă în proiectarea unei MDR valabile pentru o anumită gramatică o prezintă algoritmul de conducere al mașinii. El trebuie să decidă când mașina face o reducere, o deplasare, când semnalează eroare sau acceptare, care este capătul, cu ce producție se face reducerea. Pentru toate aceste decizii este de dorit ca algoritmului să-i fie suficient un context al analizei cât mai limitat, alcătuit, de exemplu, din simbolul curent de la intrare (în cazuri mai complicate și din alte câteva care îi urmează) precum și simbolul din vârful stivei (eventual și alte câteva de sub acestea). La baza unui asemenea algoritm vor exista tabele care, pentru toate combinațiile de simboluri ce pot apărea în vârful stivei și la intrare, să indice o unică acțiune.
Modul corect în care se construiesc asemenea tabele reprezintă subiectul următoarelor paragrafe. Astfel, vom prezenta proiectarea analizoarelor sintactice bazate pe relații de precedență între simbolurile gramaticii. În toate cazurile vom urmări modul în care se stabilesc regulile referitoare la:
delimitarea capătului prin precizarea limitei dreapta și apoi a celei stânga ale acestuia,
stabilirea producției cu care se face reducerea .
Gramatici de precedență.
Ideea analizei bazată pe relații de precedență constă în posibilitatea depistării limitei dreapta și a celui stânga ale capătului folosind relații între simbolurile ce alcătuiesc forma propozițională. Relațiile, trei la număr, sunt notate de obicei cu <, =, >. În cazul precedenței simple, într-o derivare dreapta de forma:
capătul Xk…X2X1 este delimitat prin cele trei relații astfel:
la dreapta: X1>a,
la stânga: Xk+1<Xk,
în interiorul capătului: Xi+1=Xi pentru i=1,2,…,k-1. De asemenea, între simbolurile consecutive din avem relații < sau =.
Presupunând că între două simboluri oarecare din gramatică există cel mult o relație, depistarea capătului de către MDR este unic determinată. Problema care rămâne este cea a alegerii producției cu care se face reducerea. Pentru a înlătura această nedeterminare vom presupune că gramatica folosită este unic invertibilă, adică în cadrul producțiilor ei nu există două părți drepte identice. Cele de mai sus sunt formal introduse prin următoarele definiții:
Definiția 3.1. Se numesc relații de precedență Wirth-Weber relațiile:
, ,
definite astfel pentru și :
X<Y dacă există a.î. ,
X=Y dacă există ,
X>a dacă există a.î. și .
La acestea se adaugă relațiile ce implică marcajul ‘$’:
$<X dacă există o derivare
X>$ dacă există o derivare .
În ciuda asemănării lor ca notația cu relațiile <, =, > din algebră, relațiile Wirth-Weber nu au proprietățile acestora. Reprezentarea cea mai folosită pentru relațiile Wirth-Weber este cea tabelară.
Definiția 3.2. O gramatică independentă de context este proprie dacă nu are simboluri inutile, dacă nu există derivări de forma pentru și dacă nu are -producții în afara, eventual, a producției în care caz S nu apare în nici o parte dreapta a vreunei producții. O gramatică independentă de context, proprie, fără -producții, în care între orice două simboluri există cel mult o relație de precedență Wirth-Weber, se numește gramatică de precedență. Dacă este, în plus, și unic invertibilă, ea se numește gramatică de precedență simplă.
Exemplul 3.1.
Fie gramatica G1:
Mulțimea perechilor R= este ușor de construit: se caută în părțile dreapta ale producțiilor toate perechile de simboluri consecutive:
R=={(b,A), (A,A), (A,c), (S,a)}.
Pentru calculul mulțimii R< se pornește cu ea vidă și cu o mulțime M inițializată cu R=. Se caută în M perechi de forma (X,B); în exemplul nostru ele sunt: (b,A) și (A,A). Pentru fiecare B din aceste perechi căutăm în părțile dreapta ale B-producțiilor primul simbol. Fie el Y. Se adaugă (X,Y) la mulțimea R< și dacă se adaugă și la M. În exemplu, din (b,A) obținem: (b,a) și (b,S). Ambele se adaugă la R<, dar (b,S) se adaugă și la M. Calculul R< se încheie când nu mai există în M nici o pereche (X,B) netratată. Se adaugă, în fine, perechile ($,Y), unde . În cazul nostru, ($,b).
În final, relația R< devine:
R<={(b,a), (b,S), (b,b), (A,a), (A,S), (A,b), ($,b)}
Pentru calculul perechilor din mulțimea R> o vom considera inițial vidă. Fie o mulțime M inițializată cu R=. În M vom căuta perechi de forma (B,Y). În exemplul nostru ele sunt: (A,A), (A,a), (S,a). Se calculează PRIM(Y). Apoi, pentru fiecare B-producții, se ia ultimul simbol al părții dreapta, fie el X. Se adaugă la R> toate perechile (X,a) cu , iar la mulțimea M perechile (X,a) cu . În exemplul nostru, pentru (A,A) avem: PRIM(A)={a,b}, iar ultimul simbol al părții dreapta este a. Deci perechile adăugate la R> sunt: (a,a) și (a,b). Mulțimea R> rezultată este:
R>={(a,a), (a,b), (a,c), (c,a), (c,$)}
Tabelul relațiilor de precedență este prezentat în tabelul 3.1.
Tabelul 3.1
Tabelul relațiilor de precedență
Deoarece în fiecare intrare a tabelului există cel mult o relație de precedență, gramatica este de precedență simplă.
La baza analizei limbajelor generate de gramatici de precedență stă următoarea teoremă:
Teorema 3.1.
Fie o gramatică proprie fără -producții și fie o derivare dreapta în această gramatică a șirului $S$:
Atunci:
pentru k<i<p, Xi+1<Xi sau Xi+1=Xi;
Xk+1<Xk;
pentru , Xi+1=Xi;
X1>a1.
Demonstrație.
Folosim metoda inducției pentru numărul de pași în derivare. Dacă derivarea este într-un pas: , unde , atunci din definiția 2.1 avem: $<Xk, Xi=Xi+1 pentru și X1>$. Deci cerințele teoremei sunt îndeplinite.
Să considerăm afirmațiile teoremei adevărate pentru n pași în derivare, n>0, și fie derivarea dreapta în n+1 pași:
în care, în ultimul pas, Xj() a fost înlocuit cu Yq…Y1, deci Xj-1,…,X1 sunt terminale (dacă j=1, avem Xj-1…X1=).
Din ipoteza inductivă avem: Xj+1<Xj sau Xj+1=Xj, precum și: Xi+1<Xi sau Xi+1=Xi pentru p<i<j (condiția a).
Se poate arăta ușor că:
.
Atunci avem: Xj+1<Yq (condiția b).
Deoarece: avem:
Y1>Xj-1 sau, pentru j=1, Y1>a (condiția d).
De asemenea, Yl+1=Yl pentru , Yq…Y1, fiind o parte dreapta a unei producții (condiția c).
Corolarul 3.1.
Dacă G este gramatică de precedență atunci concluziile a) – d) ale teoremei 2.1 devin:
pentru k<i<p fie Xi+1<Xi, Xi+1=Xi;
Xk+1<Xk;
pentru , Xi+1<Xi;
X1>a1;
între orice două simboluri din șirul Xp…X1a1 nu mai există nici o altă relație în afara celor precizate în a) – d).
Demonstrație.
Demonstrație este evidentă, datorită definiției 2.2.
Relațiile de precedență pot fi reprezentate sub forma unei matrici, dimensiunea căreia este NN, unde N=card(VNVT{$}) cum puteți vedea în tabelul 3.1.
Să considerăm gramatica independentă de context:
G2=(VN ,VT, P, S), VN ={S ,L}, VT ={a, [, ]},
P={
S(L
Sa
L(La)
Laa)
}
Limbajul L(G2) conține șirurile (aa), ((aa)a), (((aa)a)a), ((((aa)a)a)a),…. Pentru această gramatică în figura 4.3 este reprezentată matricea relațiilor de precedență. Semnul $ se folosește în calitate de marcher pentru începutul și sfârșitul șirului.
Să examinăm în continuare șirul $((aa)a)$. Să inserăm între simbolurile adiacente relațiile respective de precedență:
$<(<(<a=a =)>a=)>$
Capătul, după cum am menționat mai sus, va fi <a=a=)>. Așa cum gramatica conține producția 4. Laa), putem reveni la penultima formă propozițională, în care simbolul neterminal L a fost substituit cu șirul aa).
Obținem $((La)$. Inserăm din nou relațiile de precedență între simbolurile șirului:
$<(<(=L=a=)>$.
De data aceasta capătul va fi:
< (=L=a=) >.
Aplicând producția 3. L→(La) și reducând șirul (La) la simbolul L obținem o nouă formă sentențială: $ (L $.
Continuăm șă inserăm relațiile între simbolurile șirului:
$ <(=L > $.
Capătul nou este (L și, aplicând producția 1. S→(L, în rezultatul reducerii obținem $ S $.
În așa mod, urmărind în ordine inversă toate reducerile efectuate, obținem derivarea dreaptă:
S ( L ((La) ((aa)a)
a șirului inițial. Aceasta ne demonstrează, că acest șir este sintactic corect, adică aparține limbajului L(G2).
Pe de altă parte, pentru șirul $ (a) $ obținem:
$ < (<a=) > $.
Capătul evidențiat este a). Intrucât nu avem nici o producție, partea dreaptă a căreia să fie a), concludem, că acest șir nu aparține limbajului L(G2).
Analogic, dacă încercăm să analizăm șirul $ (a)(a) $ observăm, că între simbolurile ) și ( nu este nici o relație de precedență. Concluzia este aceiași – acest șir este eronat, nu aparține limbajului L(G2). Acest exemplu ne permite să formulăm următoarea concluzie: pătrățelele necompletate ale matricei indică că simbolurile respective nu pot apărea alături în nici o formă sentențială și deci toate aceste cazuri vor fi interpretate ca erori.
Algoritmii de construire a relațiilor de precedență simplă.
Pentru a construi matricea de precedență sunt necesare unele construcții preliminare. Pentru orice simbol neterminal U construim mulțimile PRIM(U) și ULTIM(U).
Simbolul A(VN VT) aparține mulțimii PRIM(U), dacă din U este posibilă derivarea .
Adică poate fi derivat un șir, care începe cu simbolul A. Respectiv, ULTIM(U), dacă este posibilă derivarea U* A.
Fie avem gramatica G3 independentă de context :
P = {
E T
E E+T
T F
T T*F
F a
F (E)
}
Algoritmul de construire a mulțimilor PRIM și ULTIM
PR(A):={}; UL(A):= {}; Pentru toți .
PRIM(A):=PR(A);ULTIM(A):=UL(A); pentru toți .
Pentru toate producțiile din P: PR(A):=PR(A){X1}; UL(A):=UL(A) {Xk}.
Dacă există pentru care PR(A)PRIM(A) UL(A)ULTIM(A), atunci salt la 2.
Stop.
Rezultatul unei iterații a algoritmului este prezentat în tabelul 4.1. Rezultatul final – în tabelul 4.2.
Tabelul 4.1
Tabelul Prim-Ultim pentru G3 după o iterație
Tabelul 4.2
Tabel Prim-Ultim final pentru gramatica G3
În continuare vom construi matricea relațiilor de precedență. Vom nota prin X1 , X2 simbolurile arbitrare din VNVT, iar prin șiruri arbitrare, posibil vide.
Algoritmul de construire a relațiilor de precedență
1. Dacă U1X1X22 este producție din P, atunci X1X2
2. Dacă U1X1Y2 este producție din P , YVN, atunci X1<X2 pentru toți X2PRIM(Y).
3. a) Dacă U1YX22 este producție din P, YVN, X2VT, atunci X1>X2 pentru toți X1ULTIM(Y).
b) Dacă U1YZ2 este producție din P, YVN, Z VN, atunci X1>X2 pentru toți X1ULTIM(Y), X2PRIM(Z)VT.
Aplicând acest algoritm construim matricea relațiilor de precedență pentru gramaticile G2 (tabelul 4.3) și G3 (tabelul 4.4).
Tabelul 4.3
Tabel de precedență pentru gramatica G2
Tabelul 4.4
Tabel de precedență pentru gramatica G3
Gramatica G3 nu este de precedență simplă, deoarece apar ambiguități la definirea relațiilor dintre simbolurile (, E și +, T. Pentru aceste simboluri se obține (=E, +=T, dar și (<E, +<T.
Acest fapt este o consecință a faptului, că metoda relațiilor de precedență simplă utilizează un context minimal pentru evidențierea capătului: se examinează doar două simboluri vecine din forma sentențială.
Frecvent aceste ambiguități pot fi eliminate efectuând transformări echivalente asupra gramaticii.
Gramatici de precedență slabă.
Stratificarea – o soluție pentru eliminarea conflictelor
Mai întâi sunt prezentați câteva transformări care ar putea elimina ambiguitățile ce apar în rezultatul construirii matricei relațiilor de precedență.
1. În rezultatul construirii relațiilor de precedență obținem și . Aceasta se datorează:
existenței producțiilor , (se generează ) , și
existenței producțiilor j=1,2,…,s, si (se generează )
În acest caz introducem un simbol neterminal nou , , și producțiile ,
Producțiile le substituim cu . Daca în P avem producții de forma , atunci le substituim prin .
În rezultatul acestor transformări gramatica modificata rămâne echivalentă gramaticii inițiale , iar relația în noua gramatica nu mai apare.
2. Cazul si se examinează în mod analogic .
3. Dacă simbolurile X1 și X2 satisfac relațiile X1<X2 și X1>X2 , atunci gramatica conține producțiile:
Ui X1Zii, X2PRIM(Zi) i=1,2,…,r (generează X1 <X2 ) și producțiile
VjjYjX2j , X2VT sau/și
VjjYjWjj , X1 ULTIM(Yj),
X2PRIM(Wj)∩VT , j=1,2,…,t.
Pentru a elimina ambiguitatea X1<X2, X1>X2 introducem simboluri neterminale noi Ai și producții AiiX1, I=1,2,…,r. Substituim producțiile UiiX1Ziβi prin UiAiZiβi i=1,2,…, r. Dacă gramatica conținea producții BiXi ,atunci le substituim prin BAi , i=1,2,…,r. Aceste transformări echivalente asupra gramaticii elimină relația X1<X2.
Dacă în rezultatul transformărilor mai apar ambiguități, repetăm aceste transformări. Apare întrebarea: cu ajutorul acestor transformări este posibilă transformarea oricărei gramatici independente de context într-o gramatică de precedență?
Răspunsul la această întrebare este negativ. Cu toate acestea, pentru majoritatea limbajelor de programare se poate construi o gramatică independentă de context, de precedență simplă.
Să aplicăm transformările expuse mai sus la eliminarea ambiguităților gramaticii G1.Relațiile (E și (<E se obțin din producțiile F(E), deoarece EPRIM (E). Introducem un simbol neterminal nou T1 și producția T1E). Producția F(E) o substituim prin F(T1.
Relațiile + = T și + < T se obțin din producția EET, deoarece T PRIM (E). Introducem un simbol neterminal nou T2 și producția T2T, iar producția EET o substituim prin ET2. În rezultatul acestor transformări obținem o gramatică nouă G4, echivalentă cu G3 . Producțiile gramaticii G4 sunt:
E→T2
2. E→E + T2
T2→T
T→F
T→T * F
F→a
F→( T1
T1→E )
Mulțimile PRIM și ULTIM pentru G4 sunt reprezentate în tabelul 5.1, iar matricea relațiilor de precedență în tabelul 5.2:
Tabelul 5.1
Tabelul Prim-Ultim pentru gramatica G4
Tabelul 5.2
Tabelul de precedență pentru gramatica G4
Clasa gramaticilor de precedență simplă este relativ restrânsă. Adesea, încercând să determinăm relațiile de precedență Wirth-Weber pentru o gramatică vom găsi cazuri de conflicte, adică perechi de simboluri care se află în două relații de precedență, ceea ce exclude gramatica din clasa amintită. Uneori, putem transforma aceste gramatici în gramatici echivalente, dar de precedență simplă. Un procedeu des folosit este cel al stratificării. Să presupunem cazul a două simboluri X și Y pentru care și . X=Y înseamnă că există producții de forma . Vom elimina această relație modificând gramatica astfel:
înlocuim pe X în producțiile respective cu un neterminal nou, B; adică producția devine ;
adăugăm la producțiile existente producția .
Modificările elimină conflictul, dar rămâne de văzut dacă în condițiile adăugării producției , unic-invertibilitatea, absolut necesară în analiză, se mai păstrează.
Soluții asemănătoare se pot aplica și în cazul celorlalte tipuri de conflicte.
Exemplul 5.1.
În gramatica:
avem: E=) și E>). Dacă facem în înlocuirea: și adăugăm , conflictul dispare. În schimb nouă gramatică:
nu mai este unic invertibilă: producțiile și au aceeași parte dreapta.
Observație. O soluție mai bună în cazul gramaticii de mai sus constă în evitarea relației E>) datorită L=) astfel:
Acum peste tot avem de asemenea: (=E și (<E, conflict rezolvat și el prin stratificarea cu neterminalul A. Mai avem și alte conflicte cum ar fi: (=L și (<L etc.
În cazul fericit că transformările gramaticii inițiale rezolvă conflictele, ele conduc la o gramatică mai complexă sau mai puțin naturală în descriere decât gramatica inițială.
Gramatica de precedența slabă
O soluție mai convenabilă în proiectarea analizoarelor sintactice bazate pe relațiile de precedență o reprezintă gramatica de precedență slabă. Ea permite, în anumite condiții, apariția conflictelor < și =. Astfel, clasa gramaticilor de precedență slabă conține, ca submulțime clasa gramaticilor de precedență simplă. Totuși, se poate arăta că pentru orice gramatică de precedență slabă unic invertibilă, există o gramatică de precedență simplă echivalentă (probabil cu mai multe neterminale și producții), ceea ce înseamnă că mulțimile limbajelor generate de cele două clase de gramatici sunt identice.
Definiția 5.1. O gramatică este de precedență slabă dacă:
este proprie, fără -producții,
existând două producții și în P, nu avem X<B sau X=B.
Dintre cele trei condiții, c) necesită explicații suplimentare. Fie șirul în stivă la momentul unei reduceri, unde și X<Y. Atunci, conform celor cunoscute, vom putea face reducerea cu (ceea ce înseamnă că X<B și X=B). Dacă în plus, există în P producția având ca sufix partea dreaptă a producției înseamnă că putem face o reducere și cu această producție. Pentru a evita ambiguitatea se interzic în asemenea situație relațiile X<B și X=B, deci reducerea cu producția mai scurtă. În acest fel, dintre cele două producții cu care aparent s-ar putea face reducerea (în vârful stivei se regăsesc ambele lor părți dreapta), se va alege automat cea care are parte dreapta mai lungă.
Exemplul 5.2.
Fie gramatica proprie, fără -producții:
Ea nu este gramatica de precedență simplă deoarece în urma construirii tabelei relațiilor de precedență (vezi tabelul 5.3) observăm că:
(=E și (<E
+=T și +<T
iar pentru toate celelalte perechi de simboluri există cel mult o relație de precedență. Rezultă că primele două condiții din definiție sunt îndeplinite. Să vedem dacă este îndeplinită condiția c). Trebuie să analizăm perechile de producții, și , în care a doua producție are partea dreapta sufix al părții dreapta a primei producții și să vedem relațiile care există între + și E și, respectiv, * și T. Din tabelă observăm că simbolurile căutate nu se găsesc în nici o relație. Deci gramatica este de precedență slabă.
Tabelul 5.3
Tabelul relațiilor de precedență
Pentru a proiecta analizoare sintactice bazate pe acest tip de gramatici mai trebuie să impunem gramaticilor și condiția de unic invertibilitate. În aceste condiții algoritmul de analiză de tip “deplasează-reduce” pentru o astfel de gramatică rămâne aceleași cu cel prezentat pentru gramaticile de precedență simplă, în afara unor mici modificări datorate schimbării structurii tabelului TRED.
Se observă din definiția și comentarea condiției c) că odată determinată limita dreaptă a capătului este suficient să căutăm în stivă cea mai lungă parte dreapta a unei producții care se poate aplica, indiferent de simbolul ce o precede în stivă.
De aceea tabela TRED pentru gramatici de precedență slabă va conține câte o parte dreapta a producțiilor în câmpul Sir al fiecărei intrări. Părțile dreapta sunt astfel ordonate încât pentru orice două producții și șirul va preceda șirul .
Automatizarea construirii analizoarelor “deplasează-reduce” bazate pe relații de precedență.
Implementarea unei MDR valabile pentru o gramatică de precedență simplă
Corolarul 3.1 ne permite să imaginăm pentru o gramatică de precedență simplă o MDR valabilă. Proiectarea MDR constă în stabilirea algoritmului de comandă a procesorului mașinii. Pentru simplificarea prezentării vom presupune că pentru gramatica dată avem: . În caz contrar, în cadrul algoritmului de analiză vor apărea mici modificări care afectează doar eficiența algoritmului. Condiția poate fi evitată complet dacă se consideră o gramatica îmbogățită a lui G (Gramatica îmbogățită a lui este ).
În centrul algoritmului de comandă a procesorului plasăm două tabele ce conțin toate informațiile necesare algoritmului:
tabela acțiunilor, TACT și
tabela reducerilor, TRED.
TACT reprezintă o aplicație:
iar TRED o relație:
unde .
Pentru deducerea celor două tabele sunt necesare producțiile gramaticii și tabela relațiilor de precedență, TRP.
Figura 6.1
Pseudocod al algoritmului de construire a tabelei TACT
În figura 6.1 se prezintă în pseudocod algoritmul de construire a tabelei TACT pe baza tabelei relațiilor de precedență TRP și folosind doar coloanele corespunzătoare terminalelor și simbolului ‘$’.
Conform algoritmului, o intrare din TACT conține: a) ‘RED’ dacă valoarea intrării corespunzătoare din TRP este >, b) ‘DEPL’ dacă valoarea intrării din TRP este < sau =, с) ‘ACCEPT’ doar pentru intrarea (S, $) și d) ‘ER’ în restul intrărilor.
Exemplul 6.1.
Pentru gramatica din exemplul 3.1 având TRP din tabelul 3.1, tabela TACT construită conform algoritmului din figura 6.1 este prezentată în tabelul 6.1.
Tabelul 6.1
Tabelul TACT
În vederea stabilirii tabelei TRED, primul pas îl constituie determinarea unei mulțimi de șiruri M definită astfel: . Șirurile din M sunt părți dreapta ale producțiilor din P precedate de toate simbolurile din care sunt în relație < cu primul simbol al părții dreapta.
Tabelul TRED se formează astfel încât: dacă și . Algoritmul de construire a tabelei TRED este banal.
Exemplul 6.2.
Pentru TRP gramatica din exemplul 3.1 având TRP în figura 3.1, TRED este prezentată în tabelul 6.2.
Tabelul 6.2
TRED
Coloana net este redundantă dacă analizorul dispune de o tabelă a producțiilor. La TRED s-a adăugat o coloană “lungimea șirului”, redundantă și ea, dar utilă în implementare, coloană în care se ține lungimea capătului.
Deoarece operațiile primitive ale MDR sunt similare clor ale mașinii MAP, putem folosi implementările lor prezentate în anexă. Pentru mașina MDR operația de reducere apare mai complexă ca efect și de aceea vom insista asupra implementării ei. Să reamintim că odată luată decizia de reducere, în vârful stivei se află un șir de simboluri ce constituie capătul de redus. Șirul se găsește cu siguranță printre șirurile aflate în coloana sir a tabelei, conform teoremei 4.1 și definiției tabelei TRED. Pentru implementare, căutarea poate fi simplificată dacă se cunoaște lungimea șirului de căutat în stivă. Operația de căutare o vom include într-o procedură CAUTA ce întoarce indexul liniei șirului identificat. Odată găsit șirul , sufixul reprezintă exact capătul și trebuie șters din stivă. O vom face cu o procedură STGSIR. Apoi în vârful stivei se depune neterminalul din coloana net a tabelei TRED. Folosim procedura DEPUNE. La ieșire se tipărește numărul de producție aflat pe coloana prod a liniei șirului identificat.
Căutarea, ștergerea simbolurilor din stivă, depunerea neterminalului și tipărirea numărul producției sunt cele patru operații primitive din care este alcătuită procedura RED de simulare a reducerii.
Implementarea algoritmului de comandă propriu-zis se reduce astfel (ca și în cazul mașinii MAP) la un ciclu în care se alege, pe baza simbolului din vârful stivei și al celui de la intrare, acțiunea de urmat. Ciclarea se termină fie la depistarea unei erori, fie la acceptare.
Implementarea în PASCAL a algoritmului de comandă împreună cu procedurile aferente este prezentată în anexă.
Construirea și codificarea gramaticii independente de context
Una din componentele principale ale analizorului sintactic este modul de introducere, codificare și prelucrare a gramaticii. Pentru a utiliza și a înțelege o gramatică, ea trebuie să corespundă unor anumite reguli. În primul rând orice element al gramaticii trebuie să fie cuprins între simbolurile “<” și “>”. Aceasta este necesar deoarece separarea elementelor se petrece în mod automat și metacompilatorul trebuie să înțeleagă șirul de litere introdus de utilizator.
Pentru a scrie măcar o producție avem nevoie de mai multe elemente ale gramaticii, de unde rezultă regula următoare: orice producție se termină cu simbolul “;” (punct și virgulă). De obicei gramatica se reprezintă în felul următor:
A Bc
B bA | a
unde A și B sunt simboluri neterminali, iar a, b și c sunt simboluri terminali. În program gramatica aceasta va avea forma:
<A> -> <B><c>;
<B> -> <b><A>;
<B> -> <a>;
Evident că după primul element al producției în gramatica independentă de context trebuie să fie scrisă săgeata (minus și semnul mai mare) cum este arătat.
Sfârșitul producției este marcat prin punct și virgulă. Pentru comoditate toate regulile încep din rând nou, dar aceasta nu are nici o importanță și toate regulile utilizatorul le poate scrie într-un singur rând. De exemplu:
<A> -> <B><c>; <B> -> <b><A>; <B> -> <a>;
Figura 6.2
Automatul pentru verificarea unei gramatici
Pentru descrierea unui element al gramaticii poate fi folosit un șir de simboluri nelimitat. Adică utilizatorul poate folosi simbolurile și “<” și “>”. Atunci apare întrebarea: în ce constă diferența dintre simbolul “>” și sfârșitul unui element al gramaticii. Evident că pentru a insera într-un element semnul “>” avem nevoie de o combinație. Pentru a prezenta simbolul “>” vom folosi “>>”. Analogic putem scrie și “<<”. Eroarea în gramatică poate aparea din cauza scrierii literelor în afara elementului gramaticii (excepție: “->” și “;”).
Codificarea gramaticii se efectuează folosind clasa CGram descrisă în instrumentariu. Dar pentru a înscrie fiecare element în listă trebuie să știm că gramatica introdusă este corectă, adică sunt respectate toate regulile necesare. Pentru verificarea gramaticii este elaborată subrutina “Corectitudinea”, care se apelează în 2 cazuri:
apăsarea tastei “Verificare” pe pagina “Gramatica”,
apăsarea tastei “Construirea tabelelor” pe pagina “Șirul de verificare”.
Această funcție întoarce valoarea –1 dacă gramatica introdusă este corectă, sau în caz contrar. Acest număr arată poziția simbolului greșit.
Pentru a verifica gramatica independentă de context care trebuie să corespundă anumitor reguli a fost construit un automat finit determinist prezentat în figura 6.2.
Tabelul 6.3.
Tabel pentru verificare unei gramatici
Sub x vom înțelege orice simbol afară de “<”, “>”, “;” și “–”. Unica deosebire a acestui automat determinist de automatul real care verifică gramatica independentă de context constă în faptul că după orice stare qi, unde poate urma spațiu sau simbolurile cu cod ASCII 13 și 10 (trecerea la un rând nou). Această modificare este efectuată pentru comoditatea utilizatorului. Presupunem că este dată gramatica:
<program>-><secventa de numere>;
<secventa de numere>-><numar>;
<secventa de numere>-><numar><separator><secventa de numere>;
<separator>-><+>;
<separator>-><blanc><separator>;
<separator>-><separator><blanc>;
În cazul dat toate producțiile nu depășesc mărimea paginii, dar producția 3 este relativ lungă. Sunt posibile cazuri când producția nu încape, atunci măcar ultimul element al producției este invizibil sau parțial invizibil. Desigur programul dat prevede situația aceasta, dar pentru a recunoaște elementul gramaticii trebuie să mișcăm un ScrolBar. Dar există și altă posibilitate care este mai comodă pentru utilizatori: separarea elementelor folosind tasta “spațiu” și “enter” (rândul nou). Atunci gramatica poate fi prezentată în felul următor:
<program> -> <secventa de numere>;
<secventa de numere> -> <numar>;
<secventa de numere> ->
<numar> <separator> <secventa de numere> ;
<separator> -> <+>;
<separator> -> <blanc> <separator>;
<separator>-><separator><blanc>;
Posibilii pași ai automatului prezentat în figura 6.2 și posibilele erori ale gramaticii introduse sunt prezentate în tabelul 6.3.
Erorile care pot apărea la verificarea gramaticii și prezentate în tabelul 6.3:
err_1 – se așteaptă simbolul “<”;
err_2 – se așteaptă simbolul “–”;
err_3 – se așteaptă simbolul “>”;
err_4 – se așteaptă simbolul “<” sau “;”.
Eroarea nr.1 poate apărea în cazurile următoare:
primul element al șirului nu este semnul mai mic, adică începutul gramaticii;
înăuntru elementului este afișat simbolul “<” incorect, adică semnul mai mic se arată cu ajutorul semnului dublu “<<”;
după săgeată trebuie să meargă “<”.
Eroarea nr.2 poate apărea într-un singur caz când după primul element al gramaticii utilizatorul n-a pus semnul minus (componenta săgeții: ->).
Eroarea nr.3 este asemănătoare erorii nr.2, fiindcă pentru a arăta o săgeată este necesar să se scrie mai întâi semnul minus și după aceasta semnul mai mare. Dacă după primul element al unei producții urmează simbolul “–”, atunci în continuare trebuie să urmeze simbolul “>”.
Eroarea nr.4 poate apărea într-un singur caz când după unul din elemente în partea dreapta a producției nu apare simbolul “<” (începutul elementului nou) sau “;” (sfârșitul producției).
Gramatica se consideră corectă, dacă la terminarea șirului de simboluri propus pentru verificare nodul curent este q10, în caz contrar gramatica se consideră neterminată. Adică pe parcursul verificării șirului n-a apărut nici o eroare. Această posibilitate poate fi utilizată pentru verificarea textului unei gramatici în timpul introducerii.
Dacă gramatica este corectă, atunci poate fi apelată subrutina MakeGram care construiește lista cu gramatica respectivă. Ca parametru al funcției se utilizează un string, iar ca rezultat se obține o listă. Pentru construirea listei se folosește un automat asemănător cu cel prezentat în figura 6.2. Unica deosebire constă în salvarea elementelor gramaticii și absența verificării erorilor.
Elementul clasei CGram constă din 2 subelemente: șirul de simboluri și un număr. Acest șir este destinat pentru păstrarea denumirii elementului, iar numărul întreg poate avea 3 valori: 1 – începutul regulii, 2 – ultimul element al regulii și 0 – alte elemente care se află între primul și ultimul element (posibil că într-o regula nu va exista nici un element cu i=0). Această notație oferă diferite posibilități în determinarea vectorului terminal și neterminal, ajută în căutarea perechilor de elemente necesare, etc.
În primul rând după introducerea gramaticii trebuie să fie construiți vectorul neterminal (VN), vectorul terminal (VT) și stabilită axioma. Vectorul neterminal este prezentat în partea stângă a producțiilor, adică primul element al producției aparține acestui vector. Folosind numărul adăugător în listă putem ușor determina elementele acestui vector (i=1). Vectorul terminal conține toate elementele gramaticii ce nu sunt păstrate în VN. Putem ușor determina elementele acestea. Pentru aceasta sunt luate la rând toate elementele gramaticii și verificte cu ajutorul funcției “apartine” aparține sau nu acest element vectorului neterminal. Dacă funcția întoarce valoarea false, atunci el se înscrie în vectorul VT. Ca axiomă este luat primul element al primii producții.
De exemplu:
<X> -> <Y> <separator> <X>;
<X> -> <Y>;
<Y> -> <litera>;
atunci VN = {X, Y}, VT = {separator, litera} și axioma este X.
Algoritmul de construire a listei gramatica:
toate spațiile, și simbolurile cu cod ASCII 13 și 10 sunt șterse din stringul destinat construirii gramaticii,
se alocă memorie pentru elementul gramaticii și se verifică șirul de simboluri,
simbolurile se adaugă la un string, inițial vid până nu se depistează simbolul “>”,
dacă după acest simbol urmează încă un simbol “>”, atunci stringul curent se mărește mai departe, în caz contrar elementul gramaticii este determinat,
dacă simbolul următor este o săgeată, atunci numărul i=1, dacă “;”, atunci i=2, iar dacă simbolul “<”, atunci i=0,
dacă poziția simbolului următor este ultima, atunci algoritmul se termină, în caz contrar salt la pasul 2.
Trebuie de spus că utilizatorul analizorului lexical trebuie să fie atent la introducerea gramaticii, deoarece este diferența între simbolurile mari și mici. Pentru verificare se utilizează vectorii terminal și neterminal prezentați pe pagina “Prim-Ultim”.
Utilizatorul poate utiliza orice combinație de simboluri pentru descrierea elementelor cu excepția simbolul “$”, care marchează începutul și sfârșitul șirului de verificate. De asemenea este interzisă combinația de simboluri tmpi, unde i este un indece care primește valori 0, 1, 2, …
Construirea tabelelor
Pentru a verifica un șir de simboluri trebuie să fie construită tabela de precedență, cu ajutorul căreia vor fi stabilite relațiile dintre elementele dintr-un șir. Pentru construirea tabelei de precedență sunt necesare tabela “Prim-Ultim” și regulile descrise mai sus. În cazul dacă în tabela de precedență apare măcar o ambiguitate, atunci gramatica curentă trebuie să fie modificată și construirea tabelelor se repetă.
Pentru construirea tabelei “Prim-Ultim” avem nevoie de vectori terminal, neterminal și gramatica proprie. Pentru păstrarea acestei tabele în memoria calculatorului a fost elaborată o clasă CPrimUltim, care ca elemente ale listei principale are vectorul neterminal. În comparație cu CGram există încă 2 referințe speciale destinate păstrării coloanelor “Prim” și “Ultim”.
Algoritmul construirii tabelei “Prim-Ultim”:
se alocă memoria sub elementele listei (numărul elementelor este egal cu numărul elementelor păstrat în VN);
se copie elementele vectorului neterminal în lista prim-ultim;
se inițializează o variabila booleană b (inițial valoarea true);
luăm un element din lista dată și determinăm producțiile în care elementul din partea stângă a producției coincide cu elementul curent;
pentru prima coincidere a elementului din lista prim-ultim și gramatică sunt construite 2 liste: l-prim și l-ultim, b atribuie valoarea false (deoarece lista este modificată) și primul element al producției din partea dreaptă (gr->urm) se adaugă la lista prim, iar ultimul element al producției curente (gr->i==2) se adaugă la lista ultim;
în cazul existenței listei l-prim și l-ultim și coinciderii elementului curent cu orice parte stângă sunt luate primul și ultimul element al producției (partea dreaptă) și cu ajutorul funcției apartine se verifică aparținerea fiecărui element listelor l-prim și l-ultim corespunzător. În caz negativ aceste elemente se adaugă în lista respectivă și b atribuie false;
se atribuie valoarea true variabilei b și este luat primul element din lista prim-ultim;
pentru orice element al listei prim-ultim sunt luate toate elementele listelor l-prim și l-ultim. Pentru fiecare element din aceste liste sunt căutate conform algoritmul dat (punctele 4-6) elementele prim și ultim corespunzător și în cazul apariției unui element nou în lista respectivă (l-prim sau l-ultim) b atribuie valoarea false;
dacă b==false (a apărut o modificare), atunci salt la pasul 7;
dacă b==true, atunci tabela Prim-Ultim este construită, STOP.
Conform acestui algoritm poate fi abținută tabela Prim-Ultim pentru orice gramatica independentă de context. Fiecare linie a tabelului corespunde elementului general al listei prim-ultim, iar elementele coloanelor Prim și Ultim coincid cu listele l-prim și l-ultim.
Presupunem că există gramatica:
ET
EE + T
TF
TT * F
Fa
F( E )
atunci rezultatele intermediare și rezultatul final conform algoritmului prezentat mai sus le puteți vedea în tabela 6.4.
Tabelul 6.4
Tabelele Prim-Ultim
Conform regulilor descrise în subcapitol 4.2 putem completa tabelul relațiilor de precedență pentru orice gramatica independentă de context. Inițial tabela se păstrează tot într-o listă (clasa CGram) în care numărul ajutător arată coordonatele în tabelul real. Numărul liniilor și coloanelor se determină știind numărul elementelor în vectorul terminal și neterminal plus simbolul “$”. Inițial toată listă nu conține nici un element și poate fi numită vidă.
Algoritmul construirii unui tabel al relațiilor de precedență:
Se formează o listă (line) care constă mai întâi din vectorul neterminal, vectorul terminal și ultimul element este “$”. Fiecare element al listei are un număr de la 1 și până la n, unde n – numărul total de elemente.
Mai întâi sunt examinate toate producțiile la determinarea semnului “=”. Pentru aceasta se verifică toată gramatica la determinarea regulilor de formă: .
După determinarea producției necesare în lista line găsim numere respective (pentru X și Y) și aflăm poziția (numărul poziției) în tabel de precedență. Linia pentru elementul X, iar coloana pentru Y.
Stringul se verifică la conținerea simbolului “=” în această celulă și în caz negativ înscriem acest semn în “celula” dată.
După determinarea tuturor egalităților vine rândul pentru semnul “<”. Se examinează toată gramatica în căutarea producției de forma: , unde X aparține VT sau VN, iar Y aparține numai VN.
Atunci în lista line determinăm linia în care se află elementul X. Pentru a determina o coloană (coloane) se folosește tabela Prim-Ultim în modul următor: pentru toate elementele listei l-prim luate din nodul Y se determină coloana respectivă.
Dacă “celula” determinată nu conține semnul mai mic, atunci el se adaugă la sfârșitul stringului.
Pentru determinarea pozițiilor destinate semnului “>” este utilizatăregulă nr.3 din subcapitolul 4.2. Pentru toată gramatica sunt determinate producții de formă: , unde X aparține vectorului neterminal, iar Y – vectorului terminal.
Pentru a găsi numărul coloanei trebuie de luat numărul respectiv din lista line.
Pentru determinarea unei linii (unor linii) se examinează lista l-ultim din lista prim-ultim cu nodul X și ca final determină poziția celulei respective.
După determinarea poziției se verifică la existența semnului mai mare în celula dată și dacă acest simbol n-a fost înscris în ea, atunci el se adaugă la sfârșit.
Semnul “>” poate apărea în cazul, dacă în producția X și Y aparțin vectorului neterminal.
Pentru a găsi linia (liniile) respectivă se examinează toate elementele listei l-ultim din nodul X a listei prim-pltim.
Pentru fiecare element obținut la pasul 12 se determină o coloană (niște coloane) folosind l-prim pentru Y.
După determinarea unei perechi de elemente se află numărul elementului din lista destinată memorării temporare a tabelului și se înscrie simbolul “>”.
Pentru a găsi semnele “>” și “<” între “$” și alte simboluri în tabela de precedență sunt utilizate aceleași reguli numai că se examinează lista l-prim și l-ultim numai pentru axiomă.
La sfârșit lista temporară line este ștersă.
Utilizând acest algoritm putem construi tabela de precedență pentru orice gramatică. Luăm de exemplu gramatica prezentată în subcapitolul curent și construim tabelul. Rezultatul este reprezentat în tabelul 6.5.
Tabelul 6.5
Tabelul relațiilor de precedență
Cum puteți vedea în tabelul 6.5 există în afară de simboluri pure și combinații de simboluri “=<” între elementele ( și E, + și T. În alte gramatici sunt posibile și alte combinații de simboluri: “<>” și “=>”. Aceste trei combinații de simboluri se numesc ambiguități.
În exemplul dat ambiguitatea între elementele + și T a apărut deoarece există regulile următoare:
semnul egal: EE+T (<E><E><+>=<T>)
semnul “<”: EE+T (<E><E><+> < PRIM(<T>))
Dacă în tabela de precedență a apărut măcar o ambiguitate, atunci această tabelă nu poate fi utilizată pentru verificarea unui șir. Aceasta se întâmplă, deoarece noi nu știm ce semn să punem între două simboluri ale gramatici de precedență simplă. Acest fapt este prevăzut în gramatica de precedență slabă și se rezolvă cu ajutorul anumitor reguli și metode. Această nedeterminare poate fi rezolvată și în cazul nostru. Pentru aceasta trebuie fi modificată gramatica conform regulilor descrise în subcapitolul 5.1.
Folosind aceste reguli gramatica se modifică și folosind producțiile noi, apare posibilitatea verificării șirului introdus. Pentru aceasta este necesar determinarea ambiguităților și a producțiilor, care sunt “vinovate” în apariția ambiguităților. Ambiguitățile pot fi divizate în două categorii:
ambiguități “<=” sau “>=”
ambiguități “<>”
deoarece ele se rezolvă prin diferite metode și la apariția nedeterminării “<>” în același rând de obicei apare și altă ambiguitate. Rezolvând ambiguitatea de categoria 2 se rezolvă (dispare) și altă ambiguitatea (dacă există).
Din aceasta reiese că mai întâi trebuie să fie rezolvate ambiguitățile de tipul “<>”.
Algoritmul pentru modificarea gramaticii în cazul apariției nedeterminării “<>”:
Mai întâi se determină locul ambiguității “<>” în tabela de precedență și elementele între care a apărut această combinație de simboluri (presupunem X <> Y).
Pentru a rezolva o ambiguitate este necesar să se determine o regulă care are forma următoare: , unde X – orice simbol, iar Z aparține vectorului neterminal, deoarece această producție propune simbolul “<”. Apare încă o condiție pentru elementul gramaticii Z: .
Se începe un ciclu pentru toate elementele listei l-prim pentru Z.
Se verifică toată gramatica în căutarea perechii de elemente <X><PRIM(Z)> cu ajutorul funcției intra3.
Când combinația aceasta este găsită în gramatică, atunci ieșim din ambele cicluri (punctele 3 și 4).
Pentru a afișa pe ecran această ambiguitate și rezolvarea ei, mai întâi se păstrează într-un string elementele regulii respective.
Pointer care arată la lista cu gramatică arată și la elementul X. Atunci se alcătuiește încă o listă temporară pentru păstrarea elementelor șterse din producția curentă.
Se începe un ciclu cu poziția curentă a listei cu gramatică și se termină când pointer arată la primul element al părții dreapta (se termină când gr->prec->i==1).
În ciclul dat sunt îndeplinite următoarele operațiuni:
copierea elementului în lista temporară
eliminarea elementului
La terminarea ciclului primul element al părții dreapta se copie în lista temporară, iar după aceasta nu se șterge, ci se modifică și se atribuie valoarea tmpi, unde i este un număr care arată cât de mult era adăugat elementelor suplimentare.
Elementele șterse dintr-o regulă trebuie să fie adăugate în altă regulă. Ele se păstrează în lista temporară în ordinea inversă. Pentru a începe regula nouă adăugăm elementul tmpi cu parametrul adăugător 1.
Luăm toate elementele listei temporare și în ordinea inversă le adăugăm la listă cu gramatică.
Stop.
Algoritmul pentru modificarea gramaticii în cazul apariției nedeterminărilor “<=” sau “>=”:
În cazul dacă nu este găsită nici o ambiguitate de tip “<>”, atunci se găsește de alt tip. Prima găsită este examinată.
Se determină în primul rând elementele între care există ambiguitate.
Pentru a rezolva o ambiguitate este necesar să se determine o producție care are forma următoare: , unde X și Y – simboluri arbitrare. Ca rezultat al acestei reguli apare semnul “=” între X și Y.
Se verifică toată gramatica în căutarea combinației de elemente XY.
Când această pereche este găsită programul iese din ciclu. Pointer arată spre elementul X.
Conform regulilor elementele trebuie să fie înlocuite cu un simbol neterminal tmpi. Toate elementele necesare sunt înscrise în mod necesar într-un string pentru afișarea pe ecran.
Se adaugă la gramatică o regulă care începe cu elementul tmpi.
Se începe un ciclu cu elementul Y și se termină cu ultimul element al producției modificate.
Toate elementele acestei reguli sunt adăugate la sfârșitul gramaticii (se formează o producție nouă) și după aceasta sunt șterse în afară de ultimul element. Ultimul element se modifică și are denumirea tmpi.
Împreună cu copierea elementelor la sfârșitul gramaticii aceste elemente se adaugă la o listă temporară.
Stop.
Efectuând aceste transformări se obține o gramatica nouă care poate conține diferite probleme apărute ca rezultat al modificărilor.
Luăm ca exemplu gramatica următoare
ET
EE+T
TF
TT*F
Fa
F(E)
și efectuăm operațiile descrise în al doilea algoritm și obținem:
ET;
TF;
TT*F;
Fa;
F(E);
EE+tmp0;
tmp0T;
Cum puteți vedea regula 1 și 7 au partea dreapta identică ce este interzis pentru gramatica de precedență simplă. Conform algoritmului descris în subcapitolul 5.1 prima regulă trebuie modificată în Etmp0. Tot așa se poate întâmpla și în rezultatul rezolvării altor ambiguități. Pentru a efectua operația necesară este alcătuit algoritmul următor:
Lista temporară care a fost alcătuită la algoritmii precedenți conține elementele părții dreaptă a producției adăugate.
Folosind funcția intra putem obține un pointer care arată la începutul producției necesare. Această funcție se utilizează numai odată, fiindcă această parte dreaptă poate fi întâlnită numai odată.
Se începe un ciclu de la începutul părții drepte și până la ultimul element al producției.
Fiecare element se elimină afară de ultimul.
Ultimul element se modifică și poartă denumirea nouă tmpi.
Stop. Se distruge lista temporară.
Conform acestui algoritm putem obține gramatica următoare:
Etmp0;
TF;
TT*F;
Fa;
F(E);
EE+tmp0;
tmp0T;
În realitate acești algoritmi puțin se modifică, se includ în program diferite variabile temporare etc. Realizarea lor este prezentată în anexă.
În programul prezentat pentru a obține tabelul relațiilor de precedență, tabelul Prim-Ultim comentariile necesare în cazul apariției unor ambiguități este necesar să introduceți gramatica respectivă și pe pagina “Sirul de verificare” să apăsați butonul “Construirea tabelelor”. După apăsarea acestei taste în primul rând se verifică era introdusă gramatica nouă sau a rămas gramatica veche. În al doilea rând se verifică corectitudinea gramaticii noi. Și numai în cazul gramaticii corecte și noi se apelează funcția MakeGram destinată construirii listei cu gramatică (gramatica veche se șterge).
După aceasta se alocă memoria sub liste legate de vectorul terminal și vectorul neterminal. Ambii vectori se completează conform algoritmilor descriși în subcapitolul precedent. Acum avem tot pentru a construi tabelul Prim-Ultim. După construirea tabelului o putem afișa pe pagina “Prim-Ultim”. Tot aici prezentăm conținutul vectorilor VN și VT.
La afișarea tabelelor se verifică lungimea stringului introdus într-o celulă și lungimea celulei în realitate. În caz dacă celula este mai mică de cât șirul de simboluri, atunci lungimea ei se mărește în proporție 1 simbol – 100 unități (puncte). Aceasta dă posibilitatea de a arăta stringul complet. Aceste operații se efectuează indiferent de tabela utilizată, deoarece toate tabelele se bazează pe componenta ActiveX MSFlexGrid 6.0.
Determinând tabelul Prim-Ultim putem afla și altă tabel – tabelul de precedență. El se determină conform algoritmului descris mai sus. După construirea luii într-o listă el trebuie să fie prezentat pe pagina “Tabelul de precedenta”. În cazul apariției măcar unei ambiguități se începe modificarea gramaticii. Este verificată toată gramatica rând la rând în căutarea nedeterminării “<>” și dacă ea există, atunci căutarea se termină și se începe realizarea algoritmului de schimbare a gramaticii, în caz contrar va fi căutată prima ambiguitatea de tip “<=” sau “>=”.
Prima ambiguitatea găsită va fi rezolvată conform uneia din metodele prezentate mai sus în subcapitolul curent. În timpul modificării gramaticii este completat un string ce conține o soluție care este prezentată în fereastra respectivă. De exemplu:
Figura 6.3
Conținutul ferestrei ce afișează erori
La apariția unei ambiguități gramatica se modifică ceea ce înseamnă că există posibilitatea apariției altor nedeterminări. De aceea o variabilă booleană atribuie valoarea false (variabila dă posibilitatea apelării analizorului sintactic și a verificării unui șir). Ea ia valoarea true numai în cazul absenței ambiguităților (poate fi verificat un șir de simboluri).
În cazul dacă gramatica nu este modificată (adică nu este schimbată în fereastră de dialog), atunci ea rămâne în starea curentă și facem apel la toți algoritmii necesari pentru construirea tabelei de precedență. Aceasta se continuă până la construirea tabelei fără nedeterminări. În acest caz variabila booleană respectivă atribuie valoarea true și poate fi utilizat algoritmul de controlare a unui șir. La rândul său apăsarea tastei “Construirea Tabelelor” n-are rost, deoarece toate tabelele sunt construite și de aceea la funcția respectivă nu se apelează.
Există încă un caz în care apăsarea tastei “Construirea Tabelelor” n-are nici un sens: gramatica nu e introdusă sau ea este incorectă. Aceasta se verifică cu ajutorul procedurii Corectitudinea după schema descrisă în subcapitol 6.2 și conform automatului prezentat în figura 6.2.
Dacă gramatica nu e de precedență simplă, adică gramatica conține două sau mai multe reguli cu partea dreapta identică, atunci ea nu poate fi utilizată la verificarea șitului respectiv. De aceea până la aplicarea algoritmilor respectivi este necesară o verificare a acestor situații. Pentru a efectua căutarea și modificarea se utilizează metoda FindRepeat. Ea este o funcție booleană și întoarce valoarea true în cazul existenței repetărilor. După modificare acest neajuns dispare, dar nu este evident că în cazul dat n-a apărut o altă situație asemănătoare. De aceea această funcție se apelează până la obținerea valorii false, adică nu există repetare.
Crearea analizorului sintactic
Analizorul sintactic este destinat verificării oricărui șir de simboluri după o gramatică independentă de context. Pentru controlarea unui string el are nevoie de un metocompilator pentru șirul respectiv, gramatica independentă de context și tabelul relațiilor de precedență.
Un metocompilator reprezintă prin sine un automat ce transformă un string într-o listă ce conține elementele unei gramatici. El folosește următoarele reguli:
Toate elementele sunt scrise între simbolurile “<” și “>” (<…>).
Pentru a arăta simbolul mai mic sau mai mare se utilizează semnele duble (“<<” sau “>>”).
Se admit spațiile între simboluri.
Algoritmul destinat transformării unui șir de simboluri într-o listă:
Se inițializează o listă destinată păstrării unui șir de simboluri.
Se adaugă primul element al listei: “$”.
Într-un ciclu sunt determinate toate elementele scrise în stringul respectiv.
La găsirea unui element la listă se adaugă 2 elemente: un element vid și elementul găsit. Elementul vid va fi utilizat pentru păstrarea simbolului între două elemente vecine a stringului.
După terminarea șirului de simboluri se adaugă încă două elemente: elementul vid și simbolul “$”.
Stop. Ca rezultat a apărut o listă cu 2n+3 elemente, unde n – este numărul elementelor introduse pentru verificarea.
Acest și următoarele algoritme pot fi folosite numai în cazul construirii tuturor tabelelor necesare. Pentru a verifica aceasta se folosește variabilă de tip boolean, care este globală și conține parametrul true (tabelele sunt construite) sau false (tabelele nu-s construite).
Mai departe este prezentat algoritmul destinat completării elementelor libere din lista:
Începem un ciclu de la primul element până la ultimul element al listei.
În tabelul de precedență se determină rândul în care se află același element ca și elementul curent din lista.
În tabela de precedență se găsește coloana în care denumirea elementului coincide cu elementul următor din șir (list->urm->urm).
Dacă la intersecția liniei și a coloanei nu există nici un element, atunci apare eroarea “Între elementele X și Y nu există relații”.
Dacă linia sau coloana nu este determinată, atunci unul din elemente nu aparțin gramaticii curente. În acest caz tot apare o eroare.
Dacă simbolul este determinat, atunci el este înscris în lista (list->urm).
Dacă acest element este “>”, atunci Stop – ieșim din ciclu.
Dacă obținem din tabel “<” sau “=”, atunci verificăm următoarele 2 elemente. Adică list atribuie valoarea list->urm->urm (Salt la 2).
Conform algoritmul dat se stabilesc semnele între elemente luate din șirul de simboluri. Pentru a modifica lista respectivă conform metodei de reducere este utilizat algoritmul următor.
Algoritmul reducerii:
Se începe ciclul de la primul element al listei și până la ultimul element.
În cazul găsirii semnului “<” această poziție se marchează cu un pointer.
În cazul găsirii simbolului “>” ieșim din ciclu.
Este obținută o sublistă destinată reducerii (capăt).
În gramatică se determină o producție în care capătul coincide cu partea dreaptă. Această operație se efectuează cu ajutorul funcției intra3.
În cazul absenței producției, pe ecran apare o comunicare.
În caz contrar sublista respectivă este înlocuită cu elementul producției ce se afla în partea stângă a producției. Aceasta se petrece în modul următor:
se începe un ciclu de la elementul marcat și până la penultimul element din subistă;
se elimină elementul curent;
ultimul element se modifică cu ajutorul metodei modificare.
Stop.
La construirea programului ultimii doi algoritmi se vor repeta până când lista nu va conține numai trei elemente: “$” “Z” “$”, unde “Z” este axiomă. Numai în cazul dat șirul se consideră corect. Pentru a vizualiza lucrul care se efectuează în fereastra de pe pagină “Sirul de verificare” este afișat conținutul listei după fiecare pas. Trebuie de spus că în fereastră dată elementele sunt luate nu în semnele mai mic și mai mare, dar în apostrofe. Acest lucru se întâmplă din cauză că între elementele sunt plasate simbolurile “<”, “>” și “=”.
În cazul apariției unei erori apare mesajul respectiv și în fereastră la fel se afișează informația despre reducerea șirului. Numai în cazul dat această informație va prezenta derivarea șirului până apariția erorii.
Exemple
Pentru a prezenta toate posibilitățile acestui program sunt luate două exemple. Pentru gramatici propuse vor fi construite toate tabelele necesare (tabelul cu vectorul terminal și neterminal, tabelul Prim-Ultim, tabelul de precedență), vor fi prezentate toate mesajele respective etc.
De exemplu luăm gramatica următoare:
R( L )
Li
Li S L
S, S
S,
Construirea tabelelor.
Pasul 1.
Intre simbolurile <S> si <i> a aparut semnul <>
Pentru rezolvarea conflictului va fi schimbat rindul:
<L>-><i><S><L>;
Cu urmatoarele rinduri:
<L>-><tmp0><L>;
<tmp0>-><i><S>;
Pasul 2.
Intre simbolurile <L> si <)> a aparut semnul => sau =<
Pentru rezolvarea conflictului vor fi adaugate urmatoarele rinduri:
<R>-><(><L><tmp1>;
<tmp1>-><)>;
Si este eliminat rindul:
<R>-><(><L><)>;
Pasul 3.
Intre simbolurile <L> si <)> a aparut semnul <>
Pentru rezolvarea conflictului va fi schimbat rindul:
<R>-><(><L><tmp1>;
Cu urmatoarele rinduri:
<R>-><tmp2><tmp1>;
<tmp2>-><(><L>;
Pasul 4.
Deoarece tabelul de precedență nu conține nici o ambiguitate, atunci nu apare nici o comunicare și pot fi verificate șirurile necesare. Gramatica nouă:
Li
Ltmp0 L
S, S
S,
tmp0i S
Rtmp2 tmp1
tmp1)
tmp2( L
Verificarea șirului.
<(><i><)>
Șirul este corect.
'$' < '(' < 'i' > ')' '$'
'$' < '(' = 'L' > ')' '$'
'$' < 'tmp2' < ')' > '$'
'$' < 'tmp2' = 'tmp1' > '$'
'$' < 'R' > '$'
<(><i><,><i><)>
Șirul este corect.
'$' < '(' < 'i' < ',' > 'i' ')' '$'
'$' < '(' < 'i' = 'S' > 'i' ')' '$'
'$' < '(' < 'tmp0' < 'i' > ')' '$'
'$' < '(' < 'tmp0' = 'L' > ')' '$'
'$' < '(' = 'L' > ')' '$'
'$' < 'tmp2' < ')' > '$'
'$' < 'tmp2' = 'tmp1' > '$'
'$' < 'R' > '$'
<(><i><,><)>
Șirul este incorect. Nu există relație între , și ).
'$' < '(' < 'i' < ',' ')' '$'
<(><i>
Șirul este incorect. Nu există relație între i și $.
'$' < '(' < 'i' '$'
Cu părere de rău nu pentru orice gramatica poate fi construit tabelul de precedență și de aceea verificat un șir la corectitudinea gramaticii date. Luăm, de exemplu, o gramatică care puțin se deferă de gramatica precedentă:
R( L )
Li
Li S L
Sc S
SS c
S,
Construirea tabelelor.
Pasul 1.
Intre simbolurile <S> si <i> a aparut semnul <>
Pentru rezolvarea conflictului va fi schimbat rindul:
<L>-><i><S><L>;
Cu urmatoarele rinduri:
<L>-><tmp0><L>;
<tmp0>-><i><S>;
Pasul 2.
Intre simbolurile <c> si <c> a aparut semnul <>
Pentru rezolvarea conflictului va fi schimbat rindul:
<S>-><c><S>;
Cu urmatoarele rinduri:
<S>-><tmp1><S>;
<tmp1>-><c>;
Pasul 3.
Intre simbolurile <S> si <c> a aparut semnul <>
Pentru rezolvarea conflictului va fi schimbat rindul:
<S>-><S><tmp1>;
Cu urmatoarele rinduri:
<S>-><tmp2><tmp1>;
<tmp2>-><S>;
La momentul curent gramatica poate avea forma (dacă sunt efectuate recomandările făcute):
R( L )
Li
Ltmp0 L
Stmp1 tmp2
Stmp2 tmp1
S,
tmp0i S
tmp1c
tmp2S
Evident că dacă această se petrece mai departe nu vom atinge tabelul de precedență fără ambiguități. Această s-a întâmplat deoarece în gramatica există recursia stânga și recursia dreapta cu aceleași elemente.
Partea economică a proiectului.
Planificarea rețea
Proiectele tehnologice contemporane sunt caracterizate de următoarele particularități:
tehnica nouă utilizată este foarte complexă și este construită utilizând ultimele elaborări științifice.
accelerării vitezei de elaborare a proiectelor.
proiectele referitoare la complexele tehnicii de calcul și softului sunt supuse uzurii morale foarte rapide.
necesitatea proiectării de sistemă la elaborarea softului și sistemelor tehnice.
Toate acestea au dus la necesitatea de creare a noi metode de planificare. Una din aceste metode prezintă modelarea procesului de elaborare, adică prezentarea legăturilor și caracteristicilor lucrărilor în procesul elaborării proiectului.
Metodele tradiționale de planificare presupun utilizarea celor mai simple modele de construirea a diagramelor de tip consecutive și ciclice.
Prima dată graficele rețea au fost folosite în procesul de proiectare a rachetelor “POLARIS” 1957. În 1964 e folosită în URSS pentru proiectarea stației hidro în Ucraina (Borsiscov). În procesul de planificare la pregătire și proiectare a tehnicilor noi, în raport cu cea clasică, numită calendaristică avantajele planificării în rețea:
Toate planurile în rețea constau din două elemente: lucrări prezentate prin săgeți și evenimente prezentate prin circumferințe.
Lucrarea înregistrează direcția și efortul depus pentru realizarea evenimentului numit.
Evenimentul înregistrează momentul când a fost realizată lucrarea.
Avantajele planificării în rețea:
Graficele rețea sunt mai compacte.
În graf rețea se văd bine legăturile de interacțiune între lucrări și evenimente (ce lucrare e preconizată pentru a atinge evenimentul anumit.
Modelele rețea pot fi revăzute, reconstruite, reoptimizate.
E posibilă schimbarea topografiei grafului.
Pot fi schimbate duratele de timp pentru efectuarea lucrărilor.
E posibilă paralelizarea diferitor ramuri, segmente ale grafului rețea, care tot reduc timpul total de efectuare a proceselor tehnologice.
Apreciază valoarea lucrărilor (reale și fictive). Lucrarea reală – linie ne întreruptă; Lucrare fictivă, secundară – linie întreruptă. Lucrarea se efectuează dar nu necesită pierdere de timp.
Graficele sunt mai citabile, receptive, comparativ cu graficele calendaristice.
Sistemele de planificare și gestiune în rețea prezintă un complex de metode grafice și de calcul, metode de control și de organizare, care asigură modelarea, analiza și reconstruirea dinamică a planului de executare a proiectelor complexe.
Sistemele de planificare și gestiune în rețea este o metodă cibernetică creată pentru gestiunea cu sisteme dinamice complexe cu scopul asigurării condiției de optim pentru careva indicatori. Așa indicatori, în dependență de condițiile concrete, pot fi:
timpul minim pentru elaborarea întregului complex de lucrări;
costul minim al elaborării proiectului;
economia maximală a resurselor.
Particularitățile sistemului de planificare și gestiune în rețea în general sunt următoarele:
Crearea posturilor automatizate de lucru a specialiștilor la PC în regimul funcționării rețelei electronice locale.
Crearea BAZEI DE DATE.
Elaborarea unui set de programe “Centralizarea raporturilor statistice și de evidență contabilă”.
Elaborarea unui set de programe “Analiza indicelor economico-financiari a activității sistemului în ansamblu și întreprinderilor în parțial”.
Culegerea, vizionarea și salvarea datelor (documentelor) să se efectueze conform algoritmului, meniului prin intermediul resurselor tehnice ale calculatorului și sistemului operațional.
Posibilitatea extragerii din baza de date a indicilor (documentelor) date prin acționare minimale de taste sau prin intermediul mouse-lui.
Posibilitatea modificării unor indici, date anterior culese (salvate).
Prevederea securității datelor.
Totalizarea datelor economico-financiari, reflectarea lor la ecran și imprimantă.
Analiza indicelor pe baza activității economice financiare a sistemului în ansamblu și a organizațiilor în parțial după un algoritm comparându-le cu pronosticul și perioadele precedente.
Reflectarea lor la ecran și imprimantă.
Acces limitat la baza de date a utilizatorilor cu drept de modificare (ne modificare) a datelor.
Documentul de bază în sistemul de planificare și gestiune în rețea este graful-rețea (modelul rețea), care prezintă modelul informațional-dinamic, în care sunt prezentate legăturile și rezultatele tuturor lucrărilor, necesare pentru atingerea scopului final.
Tabelul 7.1
Tabelul evenimentelor și lucrărilor efectuate în procesul elaborării softului
Tabelul 7.2
Durata efectuării lucrărilor.
În figura 7.1 este prezentată schema reprezentării grafice a grafului-rețea :
Figura 7.1.
Structura grafului-rețea.
unde: cercul – un eveniment;
săgeata – o lucrare;
tij – durata lucrului ij;
Rlij – rezerva liberă de timp a lucrului ij;
Rdij – rezerva deplină de timp a lucrului ij;
Tdi – timpul devreme de începere a evenimentului i;
Tli – timpul târziu de terminare a evenimentului i;
Ri – rezerva liberă de timp a evenimentului i;
Ni – numărul evenimentului i;
Tdj – timpul devreme de începere a evenimentului j;
Tlj – timpul târziu de terminare a evenimentului j;
Rj – rezerva liberă de timp a evenimentului j;
Nj – numărul evenimentului j.
Parametrii calculați ai grafului rețea sunt prezentați în tabelul 7.3.
Tabelul 7.3.
Calculele parametrilor grafului rețea
Figura 7.2
Graful rețea pentru generator de analizoare sintactice
Evaluarea economică a proiectului
Din graful rețea vedem că realizarea proiectului durează 57 de zile (săptămâna cu 5 zile lucrătoare a câte 8 ore lucrătoare). Salariul lucrătorilor este reprezentat în tabelul 7.3.
Tabelul 7.3
Salariul săptămânal al lucrătorilor
Tabelul 7.4
Calculul timpului lucrat de calculatoare și de lucrători
Calculul energiei electrice consumate de calculatoare:
Având la dispoziție 2 calculatoare putem calcula numărul zilelor lucrate conform rezultatelor luate din tabelul 7.4. Numărul total de ore lucrate este 42 ore. Știind că 1kW/h costă 0,65 lei și că într-o zi lucrătoare conține 8 ore putem calcula cheltuielile pentru energie electrică: 0,67*42*8=218,82 lei.
Calculul energiei electrice consumate de calculatoare:
Știind solariile lucrătorilor pe zi, luate din tabelul 7.3 și zile lucrate putem calcula salariul de bază și solariul auxiliar (20%) a fiecărui lucrător.
Șeful proiectului: 19*90=1710 lei.
Programatorul 1: 54*85=4590 lei.
Programatorul 2: 17*60=1020 lei.
Solariul total: 1710+4590+1020=7320 lei.
Necesitățile în materiale, soft și hard sunt prezentate în tabelele 7.5 și 7.6.
Tabelul 7.5
Costul hardului și softului procurat
Tabelul 7.6
Costul materialelor utilizate
Deoarece procurarea hardului și a softului în domeniul Tehnologiilor Informaționale este considerată investiție de capital, vom amortiza aceste cheltuieli timp de 2 ani – termen in care totul din acest domeniu se uzează moral:
X=[S/(A*365)]*Z
unde: S – suma ce trebuie de amortizat, A – perioada de amortizare în ani, Z – perioada proiectului în zile.
X=[22950/(2*365)]*57 = 1791,98 lei
Pentru studierea domeniilor noi a fost procurată literatură în sumă de 325 lei.
Tabelul 7.7
Calculul prețului de livrare a proiectului
Calculul costului pe unitate de produs:
Deoarece acest program poate fi utilizat în proiectarea programelor destul de voluminoase și complicate, el poate fi cumpărat de către persoane juridice (firme) legate de programare și proiectare. De ce firme comerciale vor cumpăra acest soft? El ușurează lucrul programatorului, mărește eficiența lui și eliberează mult timp. Numărul firmelor care au nevoie de acest program aproximativ 100. Evident că nu toate firme vor cumpăra acest program, dar reieșind din faptul că va cumpăra numai 10% și câte 2 copii, putem calcula numărul copiilor: 100*0,1*2 = 20 copii.
Acest program poate fi utilizat de către universități în timpul învățării studenților de a programa. Presupunând că există aproximativ 10 universități care sunt ocupați cu programare (Tehnologii informaționale, Informatica aplicativă) și va fi instalat acest soft măcar în 4 săli de calculatoare câte 10 computere, atunci putem calcula numărul copiilor necesare: 10*10*4 = 400 copii.
În cazurile sus numite programatorii și studenții va dori să cumpere aceste programe și le va instala acasă. Presupunem că numărul doritorilor este aproximativ 500, iar va cumpăra 10% câte o copie, atunci iasă că numărul copiilor necesare sete: 500*0,1*1=50 copii.
Acum putem calcula costul unității: 23106/(20+400+50)=49,16 lei (aproximativ 50 lei/copie).
Protecția muncii
8.1 Aprecierea pericolului la monitor
Odată cu dezvoltarea tehnicii de calcul tot mai mult se atrage atenția asupra problemelor protecției utilizatorilor, оn special acelor care lucrează la calculator, adică lвngă monitor. Principalii factori dăunători, care influențează asupra sănătății omului, cвnd acesta lucrează lвngă monitor sunt:
radiația sau iradieri ionizate;
câmpul electrostatic;
câmpul electromagnetic, etc.
Iradieri Ionizate reprezintă iradierea electro-magnetică cu o capacitate de ionizare a moleculelor. Dacă se provoacă ionizarea moleculelor organismului uman, atunci legăturile între molecule se distruge și ca rezultat apar diferite boli. Capacitatea de ionizare o au următoarele particule: a, b, X, g – iradieri, fluxul de electroni, substanțele radioactive.
În cazul monitoarelor cel mai semnificativ tip de iradiere ionizată este b – iradiere, care însă este foarte mică, de obicei nu depășește normele biologice. Celelalte tipuri de iradieri pot fi neglijate deoarece greu pot fi depistate.
b – iradierea apare în urma ciocnirii electronilor cu atomii substanței luminofore sau cu atomii ecranului din sticlă.
Pentru a micșora iradierea ionizată a monitoarelor moderne, pe suprafața lor se aplică o foaie metalică străvezie, care atenuează fluxul de iradiere. O altă cale de apărare împotriva iradierii ionizate este procurarea unui ecran protector, care se instalează pe monitor și are același efect ca și foaia metalică străvezie.
În genere iradierea ionizată asupra omului poate provoca următoarele acțiuni:
locale – acțiuni de scurtă durată cu doze mari, care aduce la traume locale: îmbolnăvirea pieii, pierderea pieii, pierderea unghiilor, defectarea oaselor, cancer;
totale – reprezintă iradieri îndelungate cu doze mici, aduce la îmbolnăvirea sângelui (leucemie).
Câmpul electrostatic, care apare pe ecranul monitorului este rezultatul bombardării permanente a monitorului cu fascicolul de electroni emis de catod. Astfel sarcina electrică, case se acumulează pe suprafață monitorului, formează câmpul electrostatic. Fenomenul electrizării statice este legat și de starea aerului din mediu. În condiții normale aerul se caracterizează cu proprietăți izolatorii înalte, însă sub acțiunea razelor solare și celor cosmice, radiației materialelor radioactive a scoarței pământului și a altor factor ionizatori, moleculele neutrale a aerului se ionizează, formând ioni pozitivi și negativi – purtători ai sarcinii electrice. Dacă intensitatea câmpului electric, format de materialele, de dispozitivele de curent continuu și de obiectele, care ușor se electrizează, este mare, atunci ionii liberi obțin energie cinetică suficientă pentru a forma ioni noi la ciocnirea lor cu moleculele neutre. În urma ionizării aerul își pierde proprietatea sa de izolator (devine conductibil) și descărcarea electrică latentă se transformă într-o descărcare sferică, adică are loc o străpungere electrică a aerului.
Descărcarea electricității statice poate provoca o explozie, incendiu și alte accidente. La unele оntreprinderi, care produc substanțe sintetice, polimeri și produse din aceste substanță, și care posedă proprietăți dielectrice оnalte, electrizarea micșorează productivitatea muncii și este unul din motive care duc la scăderea calității producției.
Influența sistematică a câmpului electrostatic de intensitate înaltă asupra corpului omului poate duce la unele dereglări funcționale a sistemului central nervos, a sistemului cardio-vascular și a altor organe. Din aceste motive, intensitatea maxim-admisibilă a câmpului electric la locurile de muncă este normată:
Tabelul 8.1
Intensitatea maxim-admisibilă a câmpului electric la locurile de muncă
Intensitățile admisibile a câmpului electrostatic sînt indicate fără a lua în considerație influența asupra omului a descărcărilor electrice. Normele indicate pentru intensitatea câmpului electrostatic mai mare de 20 kW/m se utilizează numai cu condiția, restul timpului a zilei de lucru intensitatea nu întrece 20 kW/m. Dacă intensitatea câmpului electrostatic întrece valorile indicate, atunci se aplică unele măsuri de micșorare a ei.
Măsurile principale de micșorare a intensității câmpului electric în zona de lucru sânt:
îndepărtarea surselor a câmpurilor electrostatice din zona personalului care deservește aparatura;
ecranarea sursei câmpului sau a locului de muncă;
utilizarea neutralizatorilor de sarcini electrice statice;
umezirea materialului care se electrizează;
schimbarea materialelor, care ușor se electrizează cu materiale ce nu se electrizează;
alegerea suprafețelor care contactează conform condițiilor de electrizare minimă;
modificarea procesului tehnologic în așa mod ca să se micșoreze nivelul de electrizare;
alegerea materialelor și suprafețelor care greu electrizează alte corpuri sau le electrizează cu sarcini de polaritate diferită;
instalarea în toate încăperile, unde se află oameni, a podelelor care conduc curentul electric.
Оn calitate de măsură de protecție individuală a omului de la electricitatea electrostatică poate servi оncălțămintea ce conduce curentul electric, albituri, halat, etc. adică tot ce asigură legătura electrică a corpului omului cu pămвntul.
În majoritatea monitoarelor moderne problema câmpului electrostatic este parțial rezolvată prin introducerea tehnologiei antistatice. Datorită acestei tehnologii câmpul electrostatic se micșorează până la 10% din intensitatea inițială a acestuia. În afară de această majoritatea ecranelor protectoare, care micșorează iradierea ionizată, mai sigură și atenuarea considerabilă a câmpului electrostatic.
Câmpul electromagnetic creat de monitor este de asemenea un factor dăunător sănătății omului.
Influența câmpurilor electromagnetice de mare intensitate asupra omului constă în absorbția de către țesuturile corpului uman a energiei, însă influența principală îi revine câmpului electric. Nivelul de influență a câmpurilor electromagnetice asupra omului depinde de frecvență, de puterea emisiei, de durata acțiunii, de regimul de emisie (prin impulsuri sau continuu), și de asemenea de proprietățile individuale ale organismului. Influența câmpului electric de frecvență joasă provoacă dereglări în activitatea funcțională a sistemului cardio-vascular, și chiar la schimbări privind componența sângelui.
Influența câmpului electromagnetic de frecvență înaltă se reflectă sub forma efectului termic, care duce la ridicarea temperaturii corpului, la supraîncălzirea locală a țesuturilor corpului și a organelor cu o termoreglare slabă. Ca rezultat unii lucrători suferă din cauză insomniei, simt dureri în regiunea inimii, dureri de cap, ușor obosesc.
Pentru a micșora puterea de emisie a sursei câmpului electromagnetic pot fi utilizate următoarele mijloace tehnice:
utilizarea unui astfel de regim de lucrul, în care dispozitivul lucrează cu o putere mai mică decât cea proiectată;
lichidarea locurilor de emisie suplimentară;
micșorarea undelor reflectate prin ajustarea sarcinilor, etc.
Alegerea corectă a regimului de lucru a personalului și a utilajului permite micșorarea prezenței omului în zona de acțiune a câmpurilor electromagnetice.
Utilizarea sistemelor de dirijare la distanță cu utilajul permite personalului să-și îndeplinească funcțiile în afara zonei de acțiune a câmpurilor electromagnetice.
Procesul de ecranare, des utilizat cu scopul de micșora influența câmpurilor electromagnetice, utilizează fenomenul de absorbție și reflectare a energiei câmpului electromagnetic. Pentru confecționarea ecranului se utilizează materiale cu o conductibilitate electrică înaltă (aluminiu, cupru, oțel), și cu proprietăți de absorbție și reflectare sub formă de foi și plasă. Ecranele obligatoriu se unesc la pământ.
Eficacitatea acțiunii de ecranare a materialului se caracterizează prin adâncimea infiltrării câmpului electromagnetic în ecran, care depinde de materialul de confecționare.
Adâncimea infiltrării câmpului electromagnetic, la care acest câmp scade de 2,718 ori:
unde
m – permeabilitatea magnetică relativă a materialului ecranului, Hn/m;
s – conductibilitatea relativă a materialului ecranului, cm/m;
f – frecvența câmpului electromagnetic Hz.
Adâncimea infiltrării a frecvențelor înalte și supraînalte în ecran de obicei nu întrece un milimetru, astfel grosimea ecranului se alege din considerente constructive.
8.2 Calcularea Iluminatorului Natural
Iluminarea suficientă a locurilor de muncă este o condoție principală a lucrului productiv și stării normale a sănătății omului. Iluminarea locului de mincă poate fi naturală, artificială și combinată.
Iluminatorul natural se batorează energiei solare. Regulamentul cere ca în încăperile de lucru să fie obligatoriu iluminatul natural pate fi lateral (prin ferestre), de sus (prin prin felinare) și mixt.
Iluminatorul natural poate fi neuniform.
Iluminarea locurilor de muncă să corespundă următoarei condiții:
nivelul de iluminare a suprafeței de lucru trebuie să corespundă normelor igienice pentru lucrul de tipul dat;
trebuie să fie asigurată omagenitatea și stabilitatea nivelului de iluminat în încăpere, lipsa contrastelor între iluminarea suprafeței de lucru și spațiului înconconjurător;
sursele de lumină și alte obiecte nu trebuie să genereze reflecții în cîmpul de vedere;
iluminul artificial după spectrul său trebuie să apropie de spectrul iluminatorului natural.
O mare importanță pentru asigurarea capacității înalte de muncă și bunei dispoziții are iluminarea optimă a locului de lucru. Iluminatorul poate fi natural (se folosește energia solară), artificial (cu ajutorul becurilor incandescente sau fluorescente) și susprapus.
Calcularea iluminatorului natural constă în calcularea ariei totale a ferestrelor, felinarelor m2 .
unde
Sf – suprafața ferestrei la iluminatul lateral;
Sn – suprafața podelei în încăpere a 12 m2 ;
En – valoarea normală a calculării iluminatorului artificial (CIN);
En4=En3*m*c,
unde
En3 – valoarea CIN; En3=2.0.
m – coeficientul zonei climatice; m=0.9
c – coeficientul zonei solare; că0.95.
Ks – coeficientul suplimentar; Ks=1.2
Nf – caracteristica de lumină a ferestrei la iluminatul natural; Nf=7.5
Kcl – coeficientul care ține cont de întunecare a ferestrelor de late clădiri; Kcl=1
– coeficient complex de pătrundere a luminii, sedetermină după formula:
0*1*2*3*4*5, unde
1 – coeficient de trecere a luminii pentru materialele date; 1=0.8
2 – coeficient care ține cont de pierderi ale luminii la trecere prin ferestre; 2=0.75
3 – coeficient care ține cont de pierderi ale luminii în condiții de bază; 3=1.0
4 – coeficient care ține cont de pierderi ale luminii în intervalele de slăbire a luminii; 4=0.65
5 – coeficient care ține cont de pierderi de lumină în plasă de protecție a felinarelor: =0.5
0=0.8*0.1*0.75*0.65*0.9=0.04
r1 – coeficient care țime cont de majorarea CIN al iluminatorului natural, datorită luminii încăperii; r1 =2.25
Sf=8.46 m2
8.3 Analiza condițiilor de muncă.
Factorii dăunători și periculoși la locul de lucru
Analiza condițiilor de lucru și aprecierea factorilor dăunători se efectuiază conform cerinceșor și standartelor elaborate special de comisiile pentru Tehnica Securității care sunt ca criterii de bază pentru analiza condițiilor la locul de lucru. Analiza se efectuiază conform SRAS 12.1.05
Tabelul 8.2
Factorii dăunători și periculoși la locul de lucru
8.4 Cerințele ergonomice privind locul de muncă
Ergonomica și estetica procesului de producere sunt părți componente ale culturii procesului de producere, adică complexului măsurilor de organizare a muncii îndreptate spre crearea condițiilor de lucru prielnice.La baza ridicării culturii de muncă stau cerințele organizării științifice a procesului de muncă. Cultura procesului de muncă poate fi atinsă prin organizarea corectă a procesului de muncă și a relațiilor între coloboratori, organizarea locurilor de muncă, transformarea estetică a mediului înconjurător. Pentru crearea condițiilor de muncă plăcute este necesar de a considera particularitățile psihofiziologice a omului și condițiile igienice generale.
Iluminarea rațională a încăperilor de lucru stă la baza ridicării eficacității de lucru, preîntîmpină oboseala generală și a văzului, crează condiții psihologice optimale și determină dispoziția bună. Iluminarea naturală suficientă crează simțul de legătură directă cu mediul inconjurător. Este necesar de subliniat acțiunea biologică binevenită a razelor solare. Deaceea este necesar de amplasat locurile de muncă în așa mod încît ele să nimerească în zona atingerii razelor solare. În dependență de condițiile de muncă și partucularitățile lucrului îndeplinit, pentru iluminarea artificială pot fi folosite instalațiile de iluminat, generale și locale, cu o anumită caracteristică de lumină. Lămpile de lumină directă au fost folosite limitate din cauza creării umbrelor abrupte. Lămpile de lumină reflectată pot fi folosite în cazuri cînd este necesitatea de a lumină omogenă și slabă. Lămpi de lumină semireflectată ce sunt echipate cu abajur din sticlă mată, care posedă proprietăți de a dispersa lumina se află pe masa de lucru. În calitate de instalație de iluminat general este recomandabil de folosit lămpi cu lumina dispersată. Lămpile de iluminare locală trebuie să fie mobile și la necesitate să asigure shimbarea direcției luminii. Fiecare loc de muncă, indiferent de amplasarea lui față de ferestre trebuie să aibă și instalație de lumină locală. Este recomandabil de folosit lămpi luminiscente, spectrul luminii cărora aproape coincide cu cel al luminii naturale. Pentru a exlude reflectarea razelor directe ale luminii de pe ecranul monitorului instalațiile de iluminare se aranjază pe ambele părți de la locul de muncă, paralel cu direcția văzului operatorului, și peretele cu ferestre (figura 8.1)
O astfel de amplasare a instalațiilor de iluminat permite de a le conecta consecutiv în dependență de mărimea iluminatului natural și exclude iritarea ochilor de către linii alterate de lumină și umbră, care apare la amplasare lor paralelă.
Oformare cu culori a încăperilor și înverzirea lor nu numai micșorează tensiunea nervoasă dar și permanent susține buna dispoziție a lucratorilor și inspirația creativă în lucru.
Figura 8.1.
Amplasarea instalațiilor de iluminat general față de locurile de muncă ale operatorilor
ferestre; 2 – instalațiile de iluminat; 3 – locul de muncă;
Culoarea încăperilor de lucru influențează esențial asupra iluminării, stării psihofiziologice a omului, ansamblului arhitectutal al încăperii. Este cunoccut că nuanțele întunecate au proprietatea de a consuma o parte mare a luminii și prin aceasta micșorează iluminarea încăperii. Pentru oformarea cu culori a încăperilor se propune de a folosi în primul rînd acele culori care reflectă cel puțin 40-50% de lumină care cade pe o suprafață. Culorile pentru oformare a încăperilor trebuie să fie alese în conformitate cu condițiile climaterice.Culorile galben-verzi și verde-albastru influențiază în mod liniștitor, pe cînd culorile albastru deschis, albastru, violet pot influența în mod depresiv. La oformare cu culori a încăperilor trebuie de luat seamă de amplasarea ferestrelor, particularitățile arhitecturale ale încăperilor. Pentru asigurarea condițiilor de lucru optimale, oformarea cu culoare trebuie să fie alese ținînd cond de culorile monitorului. În cazul paletei monocrone, peretele înaintea operatorului trebuie să fie vopsite cu culoarea verde deshisă sau bej, iar în cazul paletei colorate – culoarea bej.
Un rol important îl joacă organizarea locului de muncă, care trebuie să satisfacă cerințele comoditații a efectuării lucrului și economisirii energiei și a timpului operatorului și utilizării raționale ale suprafetelor de lucru. Este necesar de stabilit zonele de atingere a mîinelor operatorului de display-ul, imprimantă și alte dispozitive periferice.Zonele date sunt stabilite pe baza datelor antropometrice ale corpului uman, permit de a amplasa corect elementele de dirijare.
Mișcările lucrătorului trebuie să fie de așa fel, ca grupurule de mușchi ale lui vor fi încărcate omogen, iar mișcările neproductive vor fi excluse.
Locurile de muncă trebuie să fie aranjate tot în conformitate cu cerințele comodității lucrului și optimizării mișcării. Locul de muncă de obicei este constituit dintr-un birou, scaun, o poliță pentru literatura profesională des folosită. Distanțele între componentele menționate trebuie sî fie optimale, care nu limitează mișcările și în acelaș timp nu provoacă mișcări de prisos.
8.5 Condiționarea aerului
Parametrii ncesari al microclimei în încăperile de producție se asigură prin diferite metode. Pentru menținerea normelor aflării substanțelor dăunătoare în aer la locul de lucru se iau măuri spre izolarea izvoarelor de substanțe dăunătoare, limitarea timpului de aflare a oamenilor în încăperile cu conținutul atmosferic dăunător, folosirea tehnologiilor avansate pentru micșorarea conținutului de substanțe dăunătoare în aer.
Una din tehnicile de folosire în procesul de producție pentru eliminarea substanțelor dăunătoare din aerul zonei de lucru este ventilarea. Sistemele de ventilare asigură parametrii necesari ai microclimei în aerul de lucru. Ventilarea este divizată în două categorii în dependență de natura acestea: ventilarea naturală și ventilare aertificială.
La ventilarea artificială schimbul de aer se efectuiază cu ajutorul ventilatorului prin sisitemele de cannale cu aer. Reeșind din principiul de lucru a ventilatorului, ventilarea artificială se clasifică în următoarele categorii: de tragere, de extragere, de tragere-extragere. În sistemele de ventilare artificială aerul tras în încăperea de lucru poate fi uscat, umezit, răcit. Adică parametrii aerului tras, la ventilarea artificială pot fi schimbați.
În prezent pentru asigurarea normativelor de ventilare a aerului zonei de lucru sunt folosite dispozitive de condiționare a aerului. Cu ajutorul dispozitivului de condiționare aerul poate fi uscat, umezim, ozonat, dezodorat, răcit sau încălzit.
Conform normativelor sanitar-igienice fiecărui lucrător trebuie de-i asigurat de la 20 m3/oră pînî la 30 m3/oră. Raportul între volumul încăperii și numărul de persoane care lucrează în această încăpere nu trebuie să fie mai mic decît 20 m3.
În lipsa substanțelor dăunătoare în încăpere, dacă volumul de aer pentru un lucrător e mai mare de 40 m3, normativele de ventilare nu sunt reglamentate.
Deoarece sala laboratorului catedrei intră în categoria I – raportul volumului de aer din laborator și numărul de persoane care se află în laborator în timpul lucrărilor este mai mic decît 20 m3 pentru o persoană, aerul zonei laboratorului trebuie ventilat. Volumul de aer care trebuie să fie tras să fie în diapazonul de 20m3/oră pentru o persoană pînă la 30 m3/oră. Deci trebuie de ales un așa tip de dispozitiv de condiționare care ar asigura cerințele expuse mai sus.
Un așa tip de aparat poate servi dispozitivul de tip BK – 1000, care are următorii parametrii tehnici:
Volumul de aer tras – 1000 m3/oră;
Tensiunea de alimentare 220 V, 50 Hz
Schema de lucru a unui dispozitiv de condiționare tipic este arătată în desenul de mai jos:
Figura 8.2
Schema de lucru a unui dispozitiv de condiționare tipic
1 – canalul aerului din afară
2 – canalul aerului recirculant
3 – filtrul
4,7 – încălzitoare de aer
5 – injectoare
6 – separatorul de picături
8 – aerul condiționat
8.6 Cerințele securității tehnice la începutul lucrului
Pînă la începutul propriu zis a lucrului practic în laborator, studenții sunt obligați să studieze locul său de lucru: dislocația dispozitivelor aflate sub tensiune, a întreprinderilor de curent, caracteristica tehnică a utilajului, instrucțiunile de exploatare a dispozitivelor folosite la efectuarea lucrărilor de laborator. Trebuie de studiat principiul de lucru a echipamentului și metodele de operare inifensive în timpul lucrului.
8.7 Cerințele securității tehnice în timpul de lucru
Este interzisă cuplarea cuplarea echipamentului la rețea fără permisiunea persoanei responsabile de lucrări; cuplarea în rețea a echipamentului care în timpul efectuării lucrării de laborator nu este folosit.
Studenții neatestați de lector nu sunt admiși la lucrări de laborator.
În prosesul efectuării lucrării de laborator se interzice categoric:
abaterea de la subiect cît și atragerea altora;
părăsirea locului de lucru lăsînd utilajul sub tensiune;
efectuarea lucrului de reparație a utilajului aflat sub tensiune.
Dacă înprocesul delucru apar cazuri ieșite din comun (miros de izolație arsă, fum) utilajul se decuplează, urgent de la rețea informînd despre acesta dirigintele de lucrări sau responsabilul de laborator.
8.8 Acțiuni în cazuri fatale
Dacă vre-o persoană nimerește sub tensiune, este nesesar de urgență de decuplat tensiunea, despre ce se informează dirigintele de lucrări.
Dacă persoana în cauză a rămas în conștiință trebuie să-i creăm condiții de liniște și odihnă. Apoi în caz de necesitate chemăm medicul. Dacă individul a pierdut cunoștința și nu respiră este necesar de a-i face respirație artificială, chemînd totodată salvarea. Respirația artificială se aplică pînă vine medicul sau pănă se restabilește respirația.
Pentru toate cazurile fatale se fac procese verbale conform regulamentului.
8.9 Securitatea antiincendiară
Incendiu se numește procesul necontrolat de ardere în afara unui loc de ardere special amenajat, ce aduce daune materiale.
În cadrul oricărei organizații, sau întreprinderi trebuie să existe mijloace de anunțare, de apel rapid la serviciile orășenești antiincendiare în cazul apariției incendiului. Pentru obiectele de o importanță majoră sau periculoase, este recomandată posibilitatea legăturii telefonice directe cu secția antiincendiară orășenească. Semnalizarea antiincendiară se execută cu ajutorul diferitor sisteme. Pentru a anunța despre incendiu se utilizează legătura telefonică, legătura radio, sirena, semnalizarea cu ajutorul clopotelor etc. Mijloacele de anunțare despre incendiu trebuie să fie disponibile toate 24 ore.
Semnalizarea incendiului se execută de diferite sisteme. Cel mai simplu și mai des utilizat este semnalizatorul manual, care se activează prin apăsarea butonului. Așa semnalizatoare se instalează pe scări, în paliere și sînt vopsite în culoarea roșie.
În timpul de față larg se utilizează semnalizatoarele automate, care conform principiului de lucru se împart în cele termice, de fum, combinate și optice.
Semnalizatoarele termice de acțiune maximă acționează la deformarea unei plăci bimetalice, la încălzirea ei până la 60, 80, 100 °C în dependență de reglaj.
În semnalizatoarele termice semiconductoare, în calitate de elemente sensibile sânt termorezistențele, din cauza cărora se schimbă curentul în rețea la încălzirea lor.
Termosemnalizatoarele diferențiale reacționează la ridicarea rapidă a temperaturii (la 30°C timp de 7 secunde), iar în calitate de element sensibil se folosește elementul la încălzirea căruia apare termo-FEM.
În semnalizatoarele de fum în calitate de element sensibil se utilizează camera de ionizare, în care sub acțiunea izotopului radioactiv (plutoniu-239) apare un curent de ionizare. Apariția fumului în cameră mărește consumul de raze ceea ce cauzează micșorarea curentului de ionizare.
În semnalizatoarele combinate se folosește interconectarea semnalizatorului de fum cu cel termic. La camera de ionizare se mai conectează în plus încă o termorezistență.
Semnalizatoarele combinate reacționează atât la apariția fumului, cât și la schimbarea temperaturii. Semnalizatoarele optice reacționează la razele ultraviolete ale spectrului flăcării, deoarece elementul sensibil reprezintă contoarele de fotoni. Semnalizatoarele de diferite tipuri pot controla suprafețe de la 15 până la 100 m2.
Semnalizatoarele de fum și cele combinate nu se instalează în încăperi umede și prăfuite, sau în încăperi în care se conțin vapori de acizi, baze, sau unde temperatura este mai mare decât 80 °C, deoarece în așa locuri poate avea loc acționarea falsă ale semnalizatoarelor.
8.10 Cauzele apariției incendiilor
Procesul de ardere este posibil în cazul când este prezentă substanța arzătoare, sursa de aprindere și oxidantul, care în cele mai dese cazuri este oxigenul, ce se conține în aer. La reducerea concentrației oxigenului din aer până la 12-14% arderea majorității substanțelor se oprește. Procesul de ardere este posibil și în lipsa oxigenului – deoarece hidrogenul, stibiul și unele metale ard în clor. Unele substanțe (turba, cărbunele, funinginea, cârpele uleioase), numite piriforme pot să se autoinflameze la contactul cu aerul. Auto-aprinderea acestor substanțe are loc în urma proceselor chimice, termice sau microbiologice. Substanțele se încălzesc sub acțiunea căldurii ce vine din afară, ce se elimină în timpul reacțiilor chimice, și de asemenea în rezultatul acțiunii micro-organismelor.
În procesul de producție, incendiul poate apare în urma unor cauze de ordin electric sau ne electric. La cauzele de ordin ne electric se referă:
funcționarea proastă a instalațiilor de producție și dereglarea procesului tehnologic; comportarea iresponsabilă sau ne atentă cu focul (fumatul, lăsarea fără supraveghere a dispozitivelor de încălzire);
construcția incorectă sau dereglarea sistemului de ventilare;
autoinflamarea materialelor.
La cauzele de ordin electric se referă:
scurtcircuitul;
supraîncărcarea conductoarelor;
rezistența mare de trecere;
scânteierea;
electricitatea statică și descărcarea fulgerului;
arcul electric ce apare în timpul sudării electrice și în timpul operațiilor greșite cu aparatajul de comutare;
instabilitatea tensiunii electrice din rețea – ca rezultat se aprind unele circuite integrate din calculator, sau monitor, etc.
8.11 Securitatea antiincendiară în sălile de calcul
Pentru a analiza nivelul securității incendiare a locurilor de muncă, a zonelor de producție, a sălilor de calcul se folosește următoarea clasificare :
1.Clasificarea materialelor de construcție și construcțiilor după nivelul de inflamabilitate:
ne inflamabile;
greu inflamabile;
inflamabile;
2. Clasificarea construcțiilor după nivelul rezistență la incendiu (limita nivelului de rezistența la incendiu – timpul în ore din momentul începerii incendiului până la momentul apariției crăpăturilor).
3. Clasificarea încăperilor după RCIE ("Regulile de Construcție a Instalațiilor Electrice"):
cu pericol de explozie;
cu pericol de inflamare.
Criteriile de apreciere:
Conținutul de substanțe inflamabile;
Regimul termic de prelucrare.
4. Clasificarea proceselor de producție după pericolul incendiar:
cu pericol de explozie;
cu pericol de explozie și inflamare;
cu pericol de inflamare;
fără pericol de inflamare;
Conform primei clasificări (clasificarea materialelor de construcție și construcțiilor după nivelul de inflamabilitate) sala de calcul este ne inflamabilă deoarece sînt prevăzute multe măsuri de prevenire a incendiului cum ar fi: sisteme de semnalizare, podele din metal, mese metalice, pereții în sala de calcul se acoperă cu substanțe ne arzătoare.
După clasificarea a doua (clasificarea construcțiilor după nivelul rezistență la incendiu), de obicei sălile de calcul se află în clădiri construite sau din beton armat sau coteleț (pentru instituțiile de învățământ). Ambele materiale de construcție au o rezistență la incendiu mare – pereții în sala de calcul se acoperă cu substanțe ne arzătoare.
După clasificarea a treia (după Regulile de Construcție a Instalațiilor Electrice), luând în considerație conținutul mic de substanțe inflamabile și regimul termic de prelucrare, sălile de calcul pot fi caracterizate – cu pericol mic de inflamare.
Sălile de calcul după pericolul incendiar a proceselor de producție se referă la categoria celor cu pericol de inflamare ceea ce se explică prin faptul, că în încăpere se găsesc substanțe inflamabile: de obicei, aceste săli sînt echipate cu utilaj care conține masă plastică, care totuși arde. Trebuie însă de menționat, în ultimul timp masa plastică utilizată la fabricarea tehnicii de calcul are o astfel de componență chimică, care nu arde sau care se autostinge după primele secunde de ardere. În sala de calcul de obicei lipsesc așa atribute cum ar fi : covoare, obiecte din lemn, dulapuri cu cărți, etc. Reiese că, cu toate că pericolul de inflamare există, el este foarte mic.
Securitatea antiincendiară poate fi asigurată prin măsuri de profilaxie antiincendiară și prin respectarea regulilor de prevenire a incendiului. Noțiunea de profilaxie antiincendiară include un complex întreg de măsuri, necesare pentru preîntâmpinarea apariției incendiului sau reducerea urmărilor lui.
Concluzii
În lucrarea de licență dată este cercetată tema “Analiza sintactică ascendentă” și este elaborat un generator de automate sintactice. Acest generator prezintă prin sine un sistem integrat care dă posibilitatea construirii analizoarelor sintactice în regim automat, având la intrare numai gramatică.
Generatorul sintactic cuprinde un metolimbaj elaborat special pentru proiectarea păstrarea gramaticii independente de context, un metocompilator care transformă un șir de simboluri într-o listă și îl verifică la erori sintactice. O altă componenta principală este constructorul tabelului “Prim-Ultim” și al tabelului relațiilor de precedență. Aceste constructori pot fi utilizate pentru orice gramatică independentă de context și în cazurile unor erori pot o modifica. Pentru a verifica un șir de simboluri avem nevoie de tabelul relațiilor de precedență care conține numai anumite simboluri. În cazul apariției unui simbol inaccesibil (ambiguitate) este apelat algoritmul transformării gramaticii. Una din componentele principale ale generatorului de analizoare sintactice este însuși analizor sintactic. Folosind relațiile de precedență păstrate în tabelul respectiv, el transformă șirul introdus într-o listă și o verifică la corectitudinea (se reduce șirul sau nu).
Folosind proprietățile limbajului Visual C++ 6.0 era elaborată interfața comodă pentru utilizator care dă posibilitatea obținerii unei informații foarte repede și ușor. Programul este divizat pe pagini ce ușurează acces la datele necesare. Avantajul acestui sistem integrat constă în faptul că utilizatorul observă tot ce se întâmplă în sistem și poate îl opri și modifica în orice moment. Această legătură între om și generator dă posibilități avansate în construirea analizoarelor sintactice.
Generatorul prezentat poate fi utilizat în procesul studierii cursului universitar “Limbaje formale și compilatoare”, fiindcă metoda analizei sintactice, utilizând relații de precedență, este una din cele mai ușoare și înțelese de studenți. Încă acest sistem integrat poate fi utilizat ca un program ajutător în construirea altor programe ce au necesitatea de un compilator simplu.
Bibliografie
Harrison M.A. Introduction to formal language theory. Reading, Mass.: Addison-Wesley, 1978.
Șerbănați L.D. “Limbaje de programare și compilatoare”. /București. Editura Academiei Republicii Socialiste România. – 1987.
Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции – М.: Мир, 1978, т.2.
Бржезовский А.В., Корсакова Н.В., Фильчаков В.В. Лексический и синтаксический анализ. Формальные языки и грамматики – Л.: ЛИАП, 1990.
Грис Д. Конструирование компиляторов для цифровых вычислительных машин – М.: Мир, 1975.
Коровинский В.В., Жаков В.И., Фильчаков В.В. Синтаксический анализ и генерация кода – СПб.: ГААП, 1993.
Льюис Ф. и др. Теоретические основы построения компиляторов – М.: Мир, 1979.
Рейуорд-Смит В. Теория формальных языков. Вводный курс – М.: Радио и связь, 1988.
Кушнер Б. А. Лекции по конструктивному математическому анализу. – М., 1973.
Вирт Н. Алгоритмы и структуры данных. – М.: Мир, 1989.
Круглински Д. Основы Visual C++. – M.: Мир, 1996.
Маккиман У. Генератор Компиляторов. – М.: Статистика, 1980.
Страуструп Б. Язык программирования C++, 3-е изд./Пер. с англ. – СПб.; М.: "Невский Диалект" – "Издательство БИНОМ", 1999.
Фостер Дж. Автоматический синтаксический анализ. – М.: Мир, 1975.
http://vega.unitbv.ro/~galmeanu/lfc
http://apolo.cs.pub.ro/~dict/compilatoare/compilatoare.html
http://www.eltech.ru
http://www.softcraft.ru/translat/lect/content.shtml
http://www.mnu.samara.ru/depart/K_info/compiler.htm
http://dept.aanet.ru/homepages/Molchanov/labFI-97.htm
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Proiectarea Si Implementarea Unui Generator de Analizoare Sintactice Bazate pe Relatii de Precedenta (ID: 161082)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
