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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值