C14-词法分析器,扫描文本提却词义


两个断点定位问题
用两个断点,不断缩少出现bug范围,定位错误位置.
方块为中文字符占2个字符

对于上次方块占位的时候,有空心方块
解决的方案是:以前是合起来,再分开避免的问题
现在直接用 showbrick 直接不画空心方块 就不做什么就可以了
这样直接ShowBackground ShowBrick 就可以了

对于词法分析器我们先从 单词数量开始.

如何统计一段文字中的单词个数

这是一道平时很常见的习题或者面试题

Hello World. I love you.

对以上文本(以空格作为单词分隔),统计单词个数
下面比较简单的版本:

#include"stdafx.h"
#include<stdio.h>
#include<string.h>

int WordNum(char *str)
{
 int nCount = 0;
 while (*str != 0)
 {
  if (*str == ' ')
  {
   nCount++;
  }
    
  str++;
 }
 return ++nCount;
}
int main(void)
{
char nArry[] = "Hello    World. I love you.   ";
 printf("%d\r\n",WordNum(nArry) );
 return 0;
}

这个版本是有bug的 :比如中间加空格,后面加空格都会影响结果。
所以就知道,不能仅仅以空格为评判标准
就像我们怎么知道这是一个单词,以人的直观角度去判断
那就是遇到空格前面是什么状态 如果是非空格 那么计数加一,如果是空格那么不计数
讲一下算法:

  • 分为两种状态,分为空格,非空格状态;
  • 由非空格到空格那么计数加一
  • 其他情况不计数
    用图解释:
    在这里插入图片描述

然后根据图去写程序:
多余结束的时候我就图示舍去了
判断结束是否要加上1 就是判断‘\0’前面是否为非空格如果是那么计数加一

#include"stdafx.h"
#include<stdio.h>
#include<string.h>

#define STATE_START 0
#define STATE_BLANK 1
#define STATE_NONSPACE 2

int WordNum(char *pszContent)
{
 int nState = STATE_START;
 int nCount = 0;
 while (*pszContent != '\0')
 {
  if (nState == STATE_START)
  {
   if (*pszContent == ' ')
   {
    nState = STATE_BLANK;
   }
   else
   {
    nState = STATE_NONSPACE;
   }
  }
  else if (nState == STATE_BLANK)
  {
   if (*pszContent != ' ')
   {
    nState = STATE_NONSPACE;
   }
  }
  else if (nState == STATE_NONSPACE)
  {
   if (*pszContent == ' ')
   {
    nState = STATE_BLANK;
    nCount++;
   }
  }
  pszContent++;

 }
 if (nState==STATE_NONSPACE)
 {
  if (*pszContent == '\0')
  {
   nCount++;
  }
 }
 return nCount;
}
int main(void)
{
 char nArry[] = "Hello       World. I    love   you.        ";
 printf("%d\r\n",WordNum(nArry) );
 return 0;
}

以上就是状态机(又称自动机,有限状态的自动机)
常常用于词法分析过程制作词法分析器

初级版本的词法分析器

词法分析就是将单词分类。比如C语言的字符,由多种分类:

  • 标识符:以字母下划线开头,后面接字母,下划线,数字。
  • 数字:以数字开头,后面接任意数字
  • 分隔符号:\n \r \t ’ ’ 等

当然有人会说0x1234 分隔符号还有其他等问题 ,今天讲的初级版本就不涉及了。
我们可以将以上版本同时用状态机器表达出来

对应程序如下
如果不用彩色的化 将printf解锁,将wirtchar注释掉就可以了
在这里插入图片描述

#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#include"setdisplay.h"

#define STATE_START 0
#define STATE_ID 1
#define STATE_NUM 2
#define STATE_DELM 3
#define STATE_EOF 4

int g_nCount = 0;
char* g_szWord = "int nValue1 = 1234;\nint nValue2 =5678;\n";
int IsDeline(char* pszContent)
{
 if (*pszContent == '_')
 {
  return 1;
 }
 else
 {
  return 0;
 }
}
int IsNum(char* pszContent)
{

 if ((*pszContent >= '1'&&*pszContent <= '9'))
 {
  return 1;
 }
 else
 {
  return 0;
 }
}
int IsID(char* pszContent)
{
 if ((*pszContent >= 'a'&&*pszContent <= 'z') ||
  (*pszContent >= 'A'&&*pszContent <= 'Z'))
 {
  return 1;
 }
 else
 {
  return 0;
 }
}
int IsDelimter(char* pszContent)
{
 if (*pszContent == ' '
  || *pszContent == '\n'
  || *pszContent == '\r'
  || *pszContent == '\t'
  || *pszContent == ';')
 {
  return 1;
 }
 else
 {
  return 0;
 }
}
void ShowIt(char* pszContent1, char* pszContent2)
{
 for (size_t i = 0; i < pszContent2 - pszContent1; i++)
 {
  printf("%c", *(pszContent1 + i));
 }
	
 printf("\r\n");
 pszContent1 = pszContent2;
}
void Lexer(char *pszContent)
{

 char* pStartContent = NULL;//开始指针
 int nState = STATE_START;
 while (*pszContent != '\0')
 {
  char* pszNextContent = pszContent;
  if (nState == STATE_START)
  {
   if (IsID(pszNextContent) || IsDeline(pszNextContent))
   {
    pStartContent = pszContent;//记录开始标识
    nState = STATE_ID;
   }
   else if (IsNum(pszNextContent))
   {
    pStartContent = pszContent;
    nState = STATE_NUM;
   }
   else if (IsDelimter(pszNextContent))
   {
    nState = STATE_DELM;
   }
  }
  else if (nState == STATE_ID)
  {
   if (IsDelimter(pszNextContent))
   {
    WriteChar(g_nCount, 0, "找到一个变量", SetConsoleColor(COLOR_LIGHTBLUE, COLOR_BLACK));
    g_nCount++;
   /*	printf("找到一个变量");*/
    ShowIt(pStartContent, pszContent);
    nState = STATE_DELM;
   }
   else
   {

   }
  }
  else if (nState == STATE_NUM)
  {

   if (IsDelimter(pszNextContent))
   {
   
    WriteChar(g_nCount, 0, "找到一个数字", SetConsoleColor(COLOR_THIN_LIGHT_GREEN, COLOR_BLACK));
          /*printf("找到一个数字");*/
    g_nCount++;//坐标加1
    ShowIt(pStartContent, pszContent);
    nState = STATE_DELM;
   }
   else
   {

   }

  }
  else if (nState == STATE_DELM)
  {
   if (IsID(pszNextContent))
   {
    pStartContent = pszContent;
    nState = STATE_ID;
   }
   else if (IsNum(pszNextContent) || IsDeline(pszNextContent))
   {
    pStartContent = pszContent;
    nState = STATE_NUM;
   }
  }
  pszContent++;

 }
}
int main(void)
{
 Lexer(g_szWord);
 return 0;
}
词法分析// TranslationDlg.cpp : 实现文件 // #include "stdafx.h" #include "Translation.h" #include "TranslationDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CTranslationDlg 对话框 CTranslationDlg::CTranslationDlg(CWnd* pParent /*=NULL*/) : CDialog(CTranslationDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CTranslationDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_EDIT2, content); DDX_Control(pDX, IDC_EDIT1, result); } BEGIN_MESSAGE_MAP(CTranslationDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON1, &CTranslationDlg::OnBnClickedButton1) END_MESSAGE_MAP() // CTranslationDlg 消息处理程序 BOOL CTranslationDlg::OnInitDialog() { CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 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); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 CAboutDlg dlgAbout; dlgAbout.DoModal(); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CTranslationDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CTranslationDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 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; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CTranslationDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CTranslationDlg::SplideFrontSpc (CString &str) { int i = 0; for(i;str[i]==' ';) {str.Delete (0);}//MessageBox (_T("ok")); } void CTranslationDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 CString code ,temp ,output; //CString word[8] = ; CString flag[3][10] = {{_T("if"),_T("int"),_T("for"),_T("while"),_T("do"),_T("return"),_T("break"),_T("continue")}, {_T("+"),_T("-"),_T("*"),_T("/"),_T("="),_T(">"),_T("<"),_T("<="),_T(">="),_T("!=")}, { _T(","),_T(";"),_T("{"),_T("}"),_T("("),_T(")")}}; content.GetWindowTextW (code); code.Replace (_T("\r\n"),_T("")); code.Append (_T(" ")); while(!code.IsEmpty ()) { temp.Empty (); int i,j; int isfind = 0;//是否找到,找到了代表其类型 SplideFrontSpc(code); //temp = code.Left (code.Find (_T(","))); //code.Delete (0,2);//temp = code[0]; //截取下一个单词 temp = code.Left (code.Find (_T(" "))); code.Delete (0,code.Find (_T(" "))); //对比单词类型 for(i=0;!isfind&&i<3;i++) for(j=0;j<10;j++) if(temp == flag[i][j]) { if(i==0) isfind = 1; else if(i==1) isfind = 4; else isfind = 5; break; } if(isfind==0) { int isnum = temp[0]-'0'; if(isnum>-1||isnum<10) isfind = 3; else isfind = 2; } CString cnum; cnum.Format (_T("%d"),isfind); if(!temp.IsEmpty ()) temp = _T("(") + cnum + _T(", \"") + temp + _T("\")"); else temp = _T("词法分析完毕!\r\n"); output = output + temp + _T("\r\n"); } //output = _T("asdjfk\r\naksdjfl\nasldkfj\n"); result.SetWindowTextW (output); } BOOL CTranslationDlg::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 return CDialog::PreTranslateMessage(pMsg); } void CTranslationDlg::OnOK() { // TODO: 在此添加专用代码和/或调用基类 CDialog::OnOK(); }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值