⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 C语言词法分析器 实现简单的词法分析
💻 CPP
字号:

#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#include "commendef.h"

void GetProgramFile(HWND);
BOOL CALLBACK DlgWndProc(HWND,UINT,WPARAM,LPARAM);
void WordAnalyse(HWND,HWND);
void InitOutputList(HWND hList);

bool RecogniseString(char** pStr,RECOG_RESULT* pResult);
bool RecogniseOtherChar(char** pStr,RECOG_RESULT* pResult);
bool RecogniseOperator(char** pStr,RECOG_RESULT* pResult);
bool RecogniseNumber(char** pStr,RECOG_RESULT *pResult);
bool RecogniseIdentifier(char** pStr,RECOG_RESULT *pResult);
bool IsValidOperatorChar(char ch);

extern STACK_NODE* g_pStackTop;

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpCmdLine,int nShowCmd)
{
	DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DlgWndProc);		
	return 0;
}

BOOL CALLBACK DlgWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	HICON hIcon;	
	switch(msg)
	{
	case WM_INITDIALOG:
		hIcon = LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
		SendMessage(hwnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
		SendMessage(GetDlgItem(hwnd,IDC_EDIT1),WM_SETFONT,
			                   (WPARAM)GetStockObject(SYSTEM_FIXED_FONT),FALSE);
		return FALSE;
	case WM_COMMAND:
		if (LOWORD(wParam) == IDC_OPEN)// 打开程序文件
			GetProgramFile(GetDlgItem(hwnd,IDC_EDIT1));  
		else if (LOWORD(wParam) == IDC_ANALYSE) // 词法分析
			WordAnalyse(GetDlgItem(hwnd,IDC_EDIT1),GetDlgItem(hwnd,IDC_LIST1));
		return TRUE;
	case WM_CLOSE:
		EndDialog(hwnd,0);
		return TRUE;
	}
	return FALSE;
}

// 取得源程序文件名(显示打开文件对话框)
BOOL GetProgramFileName(HWND hwnd,LPTSTR pstrFileName,LPTSTR pstrTitleName)
{
	 OPENFILENAME ofn ;
	 TCHAR szFilter[] = TEXT ("C程序(*.c)\0*.c\0C++程序(*.cpp)\0*.cpp\0");

     ofn.lStructSize       = sizeof (OPENFILENAME) ;     
     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        = TEXT("打开程序文件");     
     ofn.nFileOffset       = 0 ;
     ofn.nFileExtension    = 0 ;
     ofn.lpstrDefExt       = TEXT (".c") ;
     ofn.lCustData         = 0L ;
     ofn.lpfnHook          = NULL ;
     ofn.lpTemplateName    = NULL ;

	 ofn.hwndOwner         = hwnd ;
	 ofn.lpstrFile         = pstrFileName ;          
	 ofn.lpstrFileTitle    = pstrTitleName ;          
	 ofn.Flags             = 0 ;          
	 return GetOpenFileName(&ofn);
}

// 读取程序文件到编辑控件中
void GetProgramFile(HWND hEdit)
{
	TCHAR   szFileName[MAX_PATH],szTitleName[MAX_PATH];
	HANDLE  hFile;
	TCHAR*  pText;
	DWORD   dwSize,dwSizeHigh;
	
	ZeroMemory(szFileName,sizeof(TCHAR) * MAX_PATH);
	ZeroMemory(szTitleName,sizeof(TCHAR) * MAX_PATH);
	if (GetProgramFileName(hEdit,szFileName,szTitleName))
	{
		hFile = CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,
						   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
		if (hFile != INVALID_HANDLE_VALUE)
		{
			dwSize = GetFileSize(hFile,&dwSizeHigh);
			pText  = (TCHAR *)GlobalAlloc(GPTR,dwSize + 2);
			ZeroMemory(pText,dwSize + 2);
			if (pText == NULL)
			{
				MessageBox(hEdit,TEXT("内存不足,无法完成操作!"),TEXT("错误"),MB_OK | MB_ICONWARNING);
				CloseHandle(hFile);
			}
			else
			{
				if (ReadFile(hFile,pText,dwSize,&dwSizeHigh,NULL) && dwSizeHigh == dwSize)
				{
					SetWindowText(hEdit,pText);
					GlobalFree(pText);					
					CloseHandle(hFile);
				}
				else
				{
					GlobalFree(pText);
					MessageBox(hEdit,TEXT("读文件过程中发生错误!"),TEXT("错误"),MB_OK | MB_ICONWARNING);
					CloseHandle(hFile);
				}
			}			
		}
		else		
			MessageBox(hEdit,TEXT("打开文件失败!"),TEXT("错误"),MB_OK | MB_ICONWARNING);
	}		
}

// 初始化输出列表
void InitOutputList(HWND hList)
{
	LVCOLUMN  colinfo;	
	int       count;	
	HWND      hHead;	
	// 清除所有内容和表头
	ListView_DeleteAllItems(hList);
	hHead = ListView_GetHeader(hList);
	count = Header_GetItemCount(hHead);
	if (count == 0)
	{	
		colinfo.mask = LVCF_TEXT | LVCF_WIDTH;		
		colinfo.cx   = 0;
		colinfo.pszText = TEXT("");
		ListView_InsertColumn(hList,0,&colinfo);
	}
	else 
	{
		for(int i = 0; i < count - 1; i++)
			ListView_DeleteColumn(hList,1);
	}
	// 设置表头
	colinfo.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;		
	colinfo.fmt  = LVCFMT_CENTER;
	colinfo.cx   = 75;
	colinfo.pszText = TEXT("单词类型");
	ListView_InsertColumn(hList,1,&colinfo);

	colinfo.cx   = 130;
	colinfo.pszText = TEXT("值");
	ListView_InsertColumn(hList,2,&colinfo);

	colinfo.cx   = 75;
	colinfo.pszText = TEXT("说明");
	ListView_InsertColumn(hList,3,&colinfo);
    //  Windows XP 才支持
	//ListView_SetSelectedColumn(hList,1);    
}

// 添加一个分析结果到输出列表中
void AddWordToList(HWND hList,RECOG_RESULT Result)
{
	RECOG_RESULT* pWord;
	TCHAR   szType[MAX_PATH];
	TCHAR   szValue[MAX_PATH];
	TCHAR   szNote[MAX_PATH];
	LVITEM  item;
	int     count;

	count = ListView_GetItemCount(hList);		
	pWord = &Result;
	
	ZeroMemory(szType,sizeof(TCHAR) * MAX_PATH);
	ZeroMemory(szValue,sizeof(TCHAR) * MAX_PATH);
	ZeroMemory(szNote,sizeof(TCHAR) * MAX_PATH);

	switch(pWord->WordType)
	{
	case WORD_ID: 
		wsprintf(szType,TEXT("标识符"));
		wsprintf(szValue,TEXT("%s"),pWord->Value.Identifier);
		wsprintf(szNote,(pWord->ChildType == CHILD_KEYWORD) ? TEXT("关键字") : TEXT("用户标识符"));
		break;

	case WORD_NUM:
		wsprintf(szType,TEXT("常数"));
		if (pWord->ChildType == CHILD_INT)
			wsprintf(szValue,TEXT("%d"),pWord->Value.IntValue);
		else
			wsprintf(szValue,TEXT("%e"),pWord->Value.RealValue);
		wsprintf(szNote,(pWord->ChildType == CHILD_INT) ? TEXT("整数") : TEXT("浮点数"));
		break;

	case WORD_STR:			
		wsprintf(szType,TEXT("字符常量"));
		wsprintf(szValue,TEXT("%s"),pWord->Value.String);
		if (pWord->ChildType == CHILD_ESC)
			wsprintf(szNote,TEXT("转义字符"));
		else if (pWord->ChildType == CHILD_CHAR)
			wsprintf(szNote,TEXT("单字符"));
		else
			wsprintf(szNote,TEXT("字符串"));		
		break;

	case WORD_OP:
		wsprintf(szType,TEXT("运算符"));
		wsprintf(szValue,TEXT("%s"),pWord->Value.Operator);			
		break;

	case WORD_OTHER:
		wsprintf(szType,TEXT("其它符号"));
		wsprintf(szValue,TEXT("%s"),pWord->Value.OtherSymbol);
		break;
	}
	// 增加列表项
	item.mask     = LVIF_TEXT;
	item.iItem    = count;
	item.iSubItem = 0;		
	item.pszText  = TEXT("");		
	ListView_InsertItem(hList,&item);

	item.iSubItem = 1;		
	item.pszText  = szType;		
	ListView_SetItem(hList,&item);

	item.iSubItem = 2;		
	item.pszText  = szValue;		
	ListView_SetItem(hList,&item);

	item.iSubItem = 3;		
	item.pszText  = szNote;		
	ListView_SetItem(hList,&item);	
}

// 对编辑控件 hEdit 中的程序进行词法分析,分析结果放到 hList 列表控件中
void WordAnalyse(HWND hEdit,HWND hList)
{	
	int    Len;
	bool   AllRight;
	char   *pInput,*pText,ch;
	RECOG_RESULT  RegResult;
	
	Len = GetWindowTextLengthA(hEdit);
	pText = (char *)GlobalAlloc(GPTR,sizeof(char) * (Len + 1));
	if (pText == NULL)
	{
		MessageBox(hList,TEXT("内存不足,无法完成操作!"),TEXT("错误"),MB_OK | MB_ICONWARNING);
		return;
	}
	ZeroMemory(pText,sizeof(char) * (Len + 1));
	GetWindowTextA(hEdit,pText,Len + 1);
	InitOutputList(hList);	

	pInput = pText;
	AllRight = true;
	while(*pInput && AllRight)
	{		
		ch = *pInput;                 //    回车            换行               Tab
		while (*pInput && (ch == ' ' || ch == RETURN || ch == NEWLINE || ch == TAB)) 
			ch = *(++pInput);
		if (*pInput == NULL) continue;

		if (ch == '_' || IsAlpha(ch))
			RecogniseIdentifier(&pInput,&RegResult);
		else if (IsDigit(ch))
			RecogniseNumber(&pInput,&RegResult);
		else if (IsValidOperatorChar(ch))
			RecogniseOperator(&pInput,&RegResult);
		else if (ch == '\'' || ch == '\"')  // 单双引号
			RecogniseString(&pInput,&RegResult);
		else 
			RecogniseOtherChar(&pInput,&RegResult);
		
		if (RegResult.Right)
		{
			if (RegResult.WordType != WORD_REMARK)
				AddWordToList(hList,RegResult);
		}
		else AllRight = false;
	}

	GlobalFree(pText);	
	if (AllRight)
	{
		if (g_pStackTop == NULL) 
			MessageBox(hList,TEXT("程序通过词法分析!"),
					   TEXT("词法分析"),MB_OK | MB_ICONINFORMATION);
		else
			MessageBox(hList,TEXT("括号不匹配!"),TEXT("词法分析"),MB_OK | MB_ICONWARNING);		
	}
	else
		MessageBox(hList,TEXT("程序存在词法错误!"),TEXT("词法分析"),MB_OK | MB_ICONWARNING);				
	// 释放堆栈内存
	STACK_NODE*   pNode;
	while(g_pStackTop != NULL)
	{
		pNode = g_pStackTop->next;
		delete g_pStackTop;
		g_pStackTop = pNode;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -