原创:一个简单的句法分析程序,界面还算漂亮

来源:互联网 发布:ubuntu查看串口设备 编辑:程序博客网 时间:2024/04/28 23:59

程序一般,但是界面绝对体现我对美术天生的感觉^_^,题外话:决心远离这个行业,太BT,没人情味,就是一堆机器在操纵另一堆机器,太冷酷,不适合我

以后可能还会写程序,但仅仅作为爱好了

核心部分JCODER.H

#include "stdafx.h"
char *reserved[]  =  { "if","then",
        "while","do",
        "+","-","*","/",":=",
        "=",">=","<=","<>",">","<",
        ";","(",")","#",
        "begin","end"
      };//total 21 tokens
//note index128 for variable
//note index256 for numbers
class error
{
public:
 int offset;
 char *reason;
}err;

class File
{
public:
 static char *ReadFromFile(char *FileName);
public:
 static char *writeToFile(char *FileName,char *buf);
};

class Number
{
public:
 static int allNum(char *str,int len);
};

class Token
{
private:
 int index;
 char content[8];
 Token *next;
 Token *past;
 int offset;
public:
 void CreateNextToken(int index,char *content,int offset);
 Token *getNext();
 Token *getPast();
 char *getContent();
 int getIndex();
 void setOffset(int offset);
 int getOffset();
};

class JCoder
{
//<程序>::=begin <语句串> end
//<语句串>::=<语句>{;<语句>}
//<语句>::=<赋值语句>
//<赋值语句>::=ID:= <表达式>
//<表达式>::=<项>{+<项>|-<项>}
//<项>::=<因子>{*<因子>|/<因子>}
//<因子>::=ID | NUM | (<表达式>)
private:
 static int getWord(char *source,int *index);
 static Token *program(Token *First);
 static Token *Lines(Token *First);
 static Token *Sentence(Token *First);
 static Token *Expression(Token *First);
 static Token *ShortExpressions(Token *First);
 static Token *Atom(Token *First);
public:
 static Token *CreateTokens(char *source);
 static bool Parse(Token *First);
};
////////////////////////////////for class File/////////////////////////////////
char *File::ReadFromFile(char *FileName)
{
 HANDLE hFile;
 char *buf;
 hFile=CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
 if(hFile==INVALID_HANDLE_VALUE)
  return (char *)0;
 else
 {
  unsigned long numDone;
  buf=new char[(sizeof(char)*GetFileSize(hFile,0)+16)];
  ZeroMemory(buf,sizeof(char)*GetFileSize(hFile,0)+16);
  ReadFile(hFile,buf,GetFileSize(hFile,0),&numDone,0);
  FlushFileBuffers(hFile);
  CloseHandle(hFile);
  return buf;
 }
}

char *File::writeToFile(char *FileName,char *buf)
{
 HANDLE hFile;
 hFile=CreateFile(FileName,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
 if(hFile==INVALID_HANDLE_VALUE)
  return (char *)0;
 else
 {
  unsigned long numDone;
  WriteFile(hFile,buf,strlen(buf),&numDone,0);
  FlushFileBuffers(hFile);
  CloseHandle(hFile);
  return buf;
 }
}
////////////////////////////////for class Number///////////////////////////////
int Number::allNum(char *str,int len)
{
 while(len!=0)
 {
  if(!(*(str+len-1)>='0' && *(str+len-1)<='9'))
  {
   return -1;
  }
  len--;
 }
 return 1;
}
////////////////////////////////for class JCoder///////////////////////////////
int JCoder::getWord(char *source,int *len)
{
 char *buf,*Bptr;
 int i;
 Bptr=buf=new char[strlen(source)+2];
 ZeroMemory(Bptr,strlen(source)+2);
 while(*(source)!=0 && *(source)!=' ' && *(source)!='/n' && *(source)!='/r')
 {
  *(buf)=*(source);
  for(i=0;i<=20;i++)
  {
   if(strcmp(Bptr,reserved[i])==0)
   {
    //for remove the bug,">=,<=,==,!=,&&,||"
    if(!strcmp(reserved[i],">") && *(source+1)=='=')
    {
     delete []Bptr;
     return 10;
    }
    else if(!strcmp(reserved[i],"<") && *(source+1)=='=')
    {
     delete []Bptr;
     return 11;
    }
    else if(!strcmp(reserved[i],"<") && *(source+1)=='>')
    {
     delete []Bptr;
     return 12;
    }
    else
    {
     delete []Bptr;
     return i;
    }
   }
   else
   {
    if(strstr(Bptr,reserved[i])!=NULL)
    {
     if((Number::allNum(Bptr,buf-Bptr)==1))
     {
      *(len)=strlen(Bptr)-strlen(reserved[i]);
      delete []Bptr;
      return 256;
     }
     else
     {
      if(!(*(Bptr)>='0' && *(Bptr)<='9'))
      {
       *(len)=strlen(Bptr)-strlen(reserved[i]);
       delete []Bptr;
       return 128;
      }
      else
      {
       delete []Bptr;
       return -1;
      }
     }
    }
   }
  }
  buf+=1;
  source+=1;
 }
 if(Number::allNum(Bptr,buf-Bptr)==1)return 256;
 if((*(Bptr)>='a' && *(Bptr)<='z')||(*(Bptr)>='A' && (*(Bptr)<='Z')))
 {
  delete []Bptr;
  return 128;
 }
 else
 {
  delete []Bptr;
  return -1;
 }
}

Token *JCoder::CreateTokens(char *source)
{
 int flag,len;
 char buffer[32];
 Token *Theader=new Token();
 Token *Tptr;
 Tptr=Theader;
 char *sptr=source;
 while((*(source)==' ' || *(source)=='/r' || *(source)=='/n'||*(source)=='/t') && *(source)!=0 )
   source++;
 if(*(source)==0){delete Theader;return 0;};
 while ((flag=getWord(source,&len))>=0)
 {
  if(flag<=20)
   Tptr->CreateNextToken(flag,reserved[flag],source-sptr);
  else
  {
   ZeroMemory(buffer,32);
   strncpy(buffer,source,len);
   Tptr->CreateNextToken(flag,buffer,source-sptr);
  }
  Tptr=Tptr->getNext();
  if(flag==128 || flag==256)
   source+=len;
  else
   source+=strlen(reserved[flag]);
  while((*(source)==' ' || *(source)=='/r' || *(source)=='/n'||*(source)=='/t') && *(source)!=0 )
   source++;
  if(*(source)==0)break;
 }
 if(flag!=-1)//-1 for a nomally end
  return Theader;
 else
 {
  err.offset=source-sptr;
  err.reason="Word Parse Error";
  Tptr=Theader;
  while(Theader!=NULL)
  {
   Tptr=Theader->getNext();
   delete Theader;
   Theader=Tptr;
  }
  return 0;
 }
}

Token *JCoder::Atom(Token *First)
{
 Token *ptr=First;
 if(ptr->getIndex()==128 || ptr->getIndex()==256)
 {
  return ptr->getNext();
 }
 else
 {
  if(ptr->getIndex()==16)
  {
   if(ptr->getNext()==0)
   {
    err.reason="Expression Expected";
    err.offset=ptr->getOffset();
    return 0;
   }
   ptr=JCoder::Expression(ptr->getNext());
   if(ptr==0)return 0;
   else
   {
    if(ptr->getIndex()==17)
     return ptr->getNext();
    else
    {
     err.reason="/")/" Expected";
     err.offset=ptr->getOffset();
     return 0;
    }
   }
  }
  else
   return 0;
 }
}

Token *JCoder::ShortExpressions(Token *First)
{
 Token *ptr;
 ptr=JCoder::Atom(First);
Atom:
 if(ptr==0)return 0;
 if(ptr->getIndex()==15)
  return ptr;
 if(ptr->getIndex()==17)
  return ptr;//(b+a)
 else
 {
  if(ptr->getIndex()==6 || ptr->getIndex()==7)
  {
   if(ptr->getNext()==0)
   {
    err.reason="Expression Expected";
    err.offset=ptr->getOffset();
    return 0;
   }
   else
    ptr=JCoder::Atom(ptr->getNext());
   goto Atom;
  }
  else
  {
   if(ptr->getIndex()==4 || ptr->getIndex()==5)
    return ptr;
   else
   {
    err.reason="Operator expected";
    err.offset=ptr->getOffset();
    return 0;
   }
  }
 }
}

Token *JCoder::Expression(Token *First)
{
 Token *ptr;
 ptr=JCoder::ShortExpressions(First);
ShortExpression:
 if(ptr==0)
  return 0;
 if(ptr->getIndex()==15)return ptr;
 if(ptr->getIndex()==17)return ptr;
 else
 {
  if(ptr->getIndex()==4 || ptr->getIndex()==5)
   if(ptr->getNext()==0)
   {
    err.reason="Expression Expected";
    err.offset=ptr->getOffset();
    return 0;
   }
   else
    ptr=JCoder::ShortExpressions(ptr->getNext());
  goto ShortExpression;
 }
}

Token *JCoder::Sentence(Token *First)
{
 Token *ptr;
 if(First->getIndex()==128)
 {
  ptr=First->getNext();
  if(ptr->getIndex()!=8)
  {
   err.offset=ptr->getOffset();
   err.reason="/":=/" Required,Syntax Error";
   return 0;
  }
  ptr=ptr->getNext();
  if(ptr==0)
  {
   err.offset=ptr->getOffset();
   err.reason="Right Value Required";
   return 0;
  }
  ptr=JCoder::Expression(ptr);
  return ptr;
 }
 else
 {
  err.offset=First->getOffset();
  err.reason="Left Value Required";
  return 0;
 }
}

Token *JCoder::Lines(Token *First)
{
 Token *ptr;
 ptr=JCoder::Sentence(First);
 if(ptr==0)return 0;
SentenceLoop:
 if(ptr->getIndex()==15)
 {
  if(ptr->getNext()==0)
  {
   err.offset=ptr->getOffset();
   err.reason="Begin Without End";
   return 0;
  }
  else if(ptr->getNext()->getIndex()==20)return ptr->getNext();
  ptr=JCoder::Sentence(ptr->getNext());
  if(ptr==0)return 0;
  goto SentenceLoop;
 }
 else
 {
  if(ptr->getIndex()==16 || ptr->getIndex()==17)
  {
   err.offset=ptr->getOffset();
   err.reason="Syntax Error,( and ) should be matched";
   return 0;
  }
  else
  {
   err.offset=ptr->getOffset();
   err.reason="Sentence should be ended with /";/"";
   return 0;
  }
 }
}

bool JCoder::Parse(Token *First)
{
 Token *ptr;
 if(First->getIndex()==19)
 {
  ptr=JCoder::Lines(First->getNext());
  if(ptr==0)return false;
  if(ptr->getIndex()==20 && ptr->getNext()==0)return true;
  else
  {
   err.offset=ptr->getOffset();
   err.reason="Begin Without End";
   return false;
  }
 }
 else
 {
  err.offset=0;
  err.reason="Code With Out Begin";
  return false;
 }
}
////////////////////////////////for class Token////////////////////////////////
void Token::CreateNextToken(int index,char *content,int offset)
{
 this->next=new Token();
 this->next->setOffset(offset);
 this->next->index=index;
 strcpy(this->next->content,content);
 this->next->next=0;
 this->next->past=this;
}

void Token::setOffset(int offset)
{
 this->offset=offset;
}

int Token::getOffset()
{
 return this->offset;
}

Token *Token::getNext()
{
 return this->next;
}

Token *Token::getPast()
{
 return this->past;
}

char *Token::getContent()
{
 return this->content;
}

int Token::getIndex()
{
 return this->index;
}
//usage:
 //Token *t;
 //bool result;
 //t=JCoder::CreateTokens(File::ReadFromFile("test1.pas"));
 //result=JCoder::Parse(t->getNext());

界面:

 // JCoder.cpp : Defines the entry point for the application.
//
//关键字:begin end if then while do
//运算符、界符::=   +   -   *   /   <   <=  >   >=  =   <>   ;  (   )    #
//标识符和整形常数:
//ID= letter (letter | digit )*
//NUM= digit digit *
//Letter= a|b|c…|z
//Digit=0|1|2…|9
#include "stdafx.h"
#include "JCoder.h"
#include "commctrl.h"
#include <commdlg.h>
#include "resource.h"
#include "stdlib.h"
HWND hListView;
HWND hCodeText;
HWND hErrorText;
Token *t;
char *fileBuf;
int openFlag;

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("JCODER") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
  InitCommonControls();
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (hInstance,MAKEINTRESOURCE(IDI_MAINICON)) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH) ;
     wndclass.lpszMenuName  = 0;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     hwnd = CreateWindow (szAppName,                  // window class name
                          TEXT ("JCODER"), // window caption
                          WS_MINIMIZE | WS_MINIMIZEBOX | WS_BORDER | WS_SYSMENU,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          800,              // initial x size
                          400,              // initial y size
                          NULL,                       // parent window handle
                          LoadMenu(hInstance,MAKEINTRESOURCE(IDM_MENU)),                       // window menu handle
                          hInstance,                  // program instance handle
                          NULL) ;                     // creation parameters
    
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
    
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  static LVCOLUMN lvc;
  static OPENFILENAME ofn ;
  static int menuCmd;
  static char fileName[2560]={0};
  static TCHAR szFilter[] =TEXT ("SudoPascal Files (*.pas)/0*.pas/0/0") ;
  static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH] ;
  char error[256];
  char textBuf[256];
  char *fileBuffer;
  LVITEM lvi;
  Token *ptr;
  NMHDR *lpNMHDR;
  int i;
     switch (message)
     {
     case WM_CREATE:
   {
    hListView=CreateWindowEx(WS_EX_CLIENTEDGE,"SysListView32",NULL,WS_CHILD | WS_VISIBLE | LVS_SHAREIMAGELISTS | LVS_REPORT,1,1,300,348,hwnd,NULL,GetModuleHandle(NULL),0);
          hCodeText=CreateWindowEx(WS_EX_CLIENTEDGE,"edit",NULL,WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,303,1,490,300,hwnd,NULL,GetModuleHandle(NULL),0);
    hErrorText=CreateWindowEx(WS_EX_CLIENTEDGE,"static",NULL,WS_CHILD | WS_VISIBLE | WS_BORDER,303,303,490,49,hwnd,NULL,GetModuleHandle(NULL),0);
    SendMessage(hListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_SUBITEMIMAGES | LVS_EX_GRIDLINES);
    SendMessage(hListView, LVM_SETTEXTCOLOR, 0, 0x00ffff00);
          SendMessage(hListView, LVM_SETBKCOLOR, 0, 0x00aaaaaa);
          SendMessage(hListView, LVM_SETTEXTBKCOLOR, 0, 0x00aaaaaa);
    lvc.mask=LVCF_TEXT|LVCF_FMT|LVCF_WIDTH;
    lvc.fmt=LVCFMT_CENTER;
    lvc.cx=100;
    lvc.pszText="词法成分";
    ListView_InsertColumn(hListView,0,&lvc);
    lvc.pszText="序号";
    ListView_InsertColumn(hListView,1,&lvc);
    lvc.pszText="位置";
    ListView_InsertColumn(hListView,2,&lvc);
    return 0 ;
         }
     case WM_DESTROY:
   {
          PostQuitMessage (0) ;
          return 0 ;
   }
  case WM_NOTIFY:
   {
   lpNMHDR=(NMHDR *)lParam;
   if(lpNMHDR->hwndFrom==hListView)
   {
    if(lpNMHDR->code==LVN_ITEMACTIVATE)
    {
     i=SendMessage(hListView,LVM_GETNEXTITEM,0,MAKELPARAM((UINT)LVNI_SELECTED,0));
     if(i==-1)i=0;
     lvi.mask=LVIF_TEXT;
     lvi.iItem=i;
     lvi.iSubItem=2;
     lvi.pszText=textBuf;
     lvi.cchTextMax=255;
     SendMessage(hListView,LVM_GETITEM,0,(long)&lvi);
     i=atoi(lvi.pszText);
     lvi.iSubItem=0;
     SendMessage(hListView,LVM_GETITEM,0,(long)&lvi);
     SendMessage(hCodeText,EM_SETSEL,i,strlen(lvi.pszText)+i);
     SetFocus(hCodeText);
    }
   }
   }
  case WM_COMMAND:
   {
    menuCmd=wParam;
    menuCmd=menuCmd & 0x0000ffff;
    if(menuCmd==IDM_OPEN)
    {
   ofn.lStructSize       = sizeof (OPENFILENAME) ;
   ofn.hwndOwner         = hwnd ;
   ofn.hInstance         = NULL ;
   ofn.lpstrFilter       = szFilter ;
   ofn.lpstrCustomFilter = NULL ;
   ofn.nMaxCustFilter    = 0 ;
   ofn.nFilterIndex      = 0 ;
   ofn.nMaxFile          = MAX_PATH ;
   ofn.nMaxFileTitle     = MAX_PATH ;
   ofn.lpstrInitialDir   = NULL ;
   ofn.lpstrTitle        = NULL ;
   ofn.Flags             = 0 ;             // Set in Open and Close functions
   ofn.nFileOffset       = 0 ;
   ofn.nFileExtension    = 0 ;
   ofn.lpstrDefExt       = TEXT ("pas") ;
   ofn.lCustData         = 0L ;
   ofn.lpfnHook          = NULL ;
   ofn.lpTemplateName    = NULL ;
      ofn.hwndOwner         = hwnd ;
   ofn.lpstrFile         = szFileName;
   ofn.lpstrFileTitle    = szTitleName;
   ofn.Flags             = OFN_HIDEREADONLY | OFN_CREATEPROMPT ;
   if(GetOpenFileName (&ofn))
   {
    if(fileBuf)
    {
     delete []fileBuf;
     fileBuf=0;
    }
    openFlag=1;
    SetWindowText(hErrorText,"File Selected,Let's make a try!");
    SetWindowText(hCodeText,(fileBuf=File::ReadFromFile(ofn.lpstrFile)));
   }
   else
   {
    SetWindowText(hErrorText,"Please Specify a file");
    openFlag=0;
   }
   return 0;
    }
   }
   if(menuCmd==IDM_WORD)
   {
    if(t)
    {
     while(t->getNext())
     {
      t=t->getNext();
      delete t->getPast();
     }
     delete t;
     t=0;
    }
    if(openFlag==1)
    {
     fileBuffer=new char[64*1024];
     ZeroMemory(fileBuffer,64*1024);
     GetWindowText(hCodeText,fileBuffer,64*1024);
     t=JCoder::CreateTokens(fileBuffer);
     if(!t)
     {
    wsprintf(error,"error at %d,%s",err.offset,err.reason);
    SetWindowText(hErrorText,error);
    SendMessage(hCodeText,EM_SETSEL,err.offset,err.offset+1);
    SetFocus(hCodeText);
     }
     else
     {
      ptr=t->getNext();
      SendMessage(hListView,LVM_DELETEALLITEMS,0,0);
      i=0;
      while(ptr)
      {
       lvi.mask=LVIF_TEXT;
       lvi.iItem=i;
       lvi.iSubItem=0;
       lvi.pszText=ptr->getContent();
       SendMessage(hListView,LVM_INSERTITEM,0,(long)&lvi);
       lvi.iSubItem=1;
       wsprintf(textBuf,"%d",ptr->getIndex());
       lvi.pszText=textBuf;
       SendMessage(hListView,LVM_SETITEM,0,(long)&lvi);
       lvi.iSubItem=2;
       wsprintf(textBuf,"%d",ptr->getOffset());
       lvi.pszText=textBuf;
       SendMessage(hListView,LVM_SETITEM,0,(long)&lvi);     
       i++;
       ptr=ptr->getNext();
      }
      SetWindowText(hErrorText,"Word Parse Ok");
     }
     delete []fileBuffer;
    }
   }
   if(menuCmd==IDM_PARSE)
   {
     if(t)
     {
    if(!JCoder::Parse(t->getNext()))
    {
       SendMessage(hCodeText,EM_SETSEL,err.offset,err.offset+1);
       SetFocus(hCodeText);
       wsprintf(error,"error at %d,%s",err.offset,err.reason);
       SetWindowText(hErrorText,error);
    }
    else
    {
       SetWindowText(hErrorText,"all is ok");
       MessageBox(hwnd,"分析成功","提示",MB_OK);
    }
     }
   }
   if(menuCmd==IDM_SAVE)
   {
    fileBuffer=new char[64*1024];
    ZeroMemory(fileBuffer,64*1024);
    GetWindowText(hCodeText,fileBuffer,64*1024);
    File::writeToFile(ofn.lpstrFile,fileBuffer);
    delete []fileBuffer;
   }
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

 

原创粉丝点击