词法分析


目录
  • 1. 正则表达式
    • 正则表达式定义
    • 正则语言
    • RE的代数定律
    • 正则文法与正则表达式等价
  • 2. 正则定义(Regular Definition)
  • 3. 有穷自动机
    • FA的经典例子
    • FA模型
    • FA的表示
    • FA定义(接收)的语言
    • 最长子串匹配原则(Longest String Matching Principle)
  • 3. 有穷自动机的分类
    • 确定的有穷自动机(DFA)
    • 非确定的有穷自动机(NFA)
    • DFA和NFA的等价性
    • 带有"ε-边的NFA"
    • 带有和不带有"ε-边"的NFA的等价性
    • DFA的算法实现
  • 4. 从正则表达式到有穷自动机
    • 根据RE构造NFA
  • 5. NFA到DFA的转换
    • 子集构造法
    • 计算 ε-closure(T)
  • 6. 识别标识符的DFA
    • 识别无符号数的NFA
    • 识别无符号数的DFA
    • 识别各进制无符号整数的DFA
    • 识别注释的DFA
    • 识别Token的DFA
  • 7. 词法分析阶段的错误处理
    • 错误恢复策略
  • 8. 词法分析器的实现
    • 定义种别码
    • 对所有单词进行编码
    • 实现词法分析
    • 实现代码(长)

1. 正则表达式

image-20211106172413933

正则表达式定义

image-20211106172537809

例:

image-20211106173224015

image-20211107093037159

正则语言

可以用

RE定义的语言叫做正则语言(regular language)或正则集合(regular set)

RE的代数定律

image-20211107093304079

正则文法与正则表达式等价

image-20211107093414687

2. 正则定义(Regular Definition)

image-20211107093625388

例:

image-20211107093937887

image-20211107094036584

3. 有穷自动机

image-20211107094104832

FA的经典例子

image-20211107094305231

FA模型

image-20211107094426011

FA的表示

image-20211107095059207

FA定义(接收)的语言

image-20211107095247596

最长子串匹配原则(Longest String Matching Principle)

image-20211107095344304

3. 有穷自动机的分类

  • 确定的FA(Deterministic finite automata, DFA)
  • 非确定的FA(Nondeterministic finite automata, NFA)

确定的有穷自动机(DFA)

image-20211107095630458

沿着一条边只能到达一个确定的状态, 且不允许有ε边

例:

image-20211107095734185

非确定的有穷自动机(NFA)

image-20211107095827342

例:

image-20211107095857221

DFA和NFA的等价性

image-20211107100007628

例:

image-20211107100041437

带有"ε-边的NFA"

image-20211107100327847

带有和不带有"ε-边"的NFA的等价性

image-20211107100427731

DFA的算法实现

image-20211107100512197

4. 从正则表达式到有穷自动机

image-20211107101552361

根据RE构造NFA

image-20211107101709041

image-20211107101835459

image-20211107101918081

5. NFA到DFA的转换

image-20211107101948410

image-20211107102013727

子集构造法

image-20211107102111672

计算 ε-closure(T)

image-20211107102233678

6. 识别标识符的DFA

image-20211107103703970

image-20211107102307448

识别无符号数的NFA

image-20211107102349053

识别无符号数的DFA

image-20211107102505340

识别各进制无符号整数的DFA

image-20211107102607050

识别注释的DFA

image-20211107102710039

识别Token的DFA

image-20211107102801402

7. 词法分析阶段的错误处理

image-20211107102909227

image-20211107103021426

错误恢复策略

image-20211107103052802

8. 词法分析器的实现

定义种别码

image-20211107104836982

对所有单词进行编码

image-20211107104924240

实现词法分析

image-20211107104958488

实现代码(长)

测试代码:

#include 
int main(int argc, char const *argv[])
{
	char *str = "String123";
	int num1=0x45f7,num2=0187,num3=0x1g35;//num3 16进制错误  num2 8进制错误
	//This is comment
	/**
	printf("NULL\n");
	*/
	int floatnum = 123.456;@ //不能识别字符@
	int num4 = 45.58e-10;
	if(6.4 <= 5.8)
		printf("Yes");	
	if(floatn>5) //floatn 暂不考虑
		printf("No");
	for(int i=1;i<6;i++){
		num2+=10;	//识别+=
		num2-=10;	//识别-=
		num2*=10;	//识别*=
		num2/=10;	//识别/=
		printf("%d",num2);
	}
	/*测试注释符号未匹配
	printf("NULL\n");
	
	return 0;
}$

主程序:

// Lexical_Analysis.cpp : 定义控制台应用程序的入口点。
//
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "windows.h"
#include 
#include 
#include 
using namespace std;

HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//词法分析程序
//首先定义种别码
/*
第一类:标识符   letter(letter | digit)*  无穷集
第二类:常数    (digit)+  无穷集
第三类:保留字(32)
auto       break    case     char        const      continue
default    do       double   else        enum       extern
float      for      goto     if          int        long
register   return   short    signed      sizeof     static
struct     switch   typedef  union       unsigned   void
volatile    while

第四类:界符  ‘/*’、‘//’、 () { } [ ] " "  '
第五类:运算符 <、<=、>、>=、=、+、-、*、/、^、

对所有可数符号进行编码:
<$,0>

...

<+,33>
<-,34>
<*,35>

<<,37>
<<=,38>
<>,39>
<>=,40>
<=,41>
<==,42>

<;,44>
<(,45>
<),46>
<^,47>
<,,48>
<",49>
<',50>
<#,51>
<&,52>
<&&,53>
<|,54>
<||,55>
<%,56>
<~,57>
<<<,58>左移
<>>,59>右移
<[,60>
<],61>
<{,62>
<},63>
<\,64>
<.,65>
<?,66>
<:,67>

<+=,69>
<-=,70>
<*=,71>

"[","]","{","}"
<十进制整数99, 数值>
<标识符100, 标识符指针>
<十进制浮点数101, 数值>
<八进制整数102, 数值>
<八进制浮点数103, 数值>
<十六进制整数104, 数值>
<十六进制浮点数105, 数值>
*/

/****************************************************************************************/
//全局变量,行号
static int index_line = 0;
//全局变量,列号
static int index_col = 0;
//全局变量,保留字表
static char reserveWord[32][20] = {
    "auto", "break", "case", "char", "const", "continue",
    "default", "do", "double", "else", "enum", "extern",
    "float", "for", "goto", "if", "int", "long",
    "register", "return", "short", "signed", "sizeof", "static",
    "struct", "switch", "typedef", "union", "unsigned", "void",
    "volatile", "while"};
//界符运算符表,根据需要可以自行增加
static char operatorOrDelimiter[40][10] = {
    "+", "-", "*", "/", "<", "<=", ">", ">=", "=", "==",
    "!=", ";", "(", ")", "^", ",", "\"", "\'", "#", "&",
    "&&", "|", "||", "%", "~", "<<", ">>", "[", "]", "{",
    "}", "\\", ".", "\?", ":", "!", "+=", "-=", "*=", "/="};

static char IDentifierTbl[1000][50] = {""}; //标识符表
static int count_id = 0;
/****************************************************************************************/

/********查找是否是保留字*****************/
/* 找到返回索引,未找到返回-1(猜的) */
int searchReserve(char reserveWord[][20], char s[])
{ //自己实现
    for (int i = 0; reserveWord[i][0] != '\0'; i++)
    {
        if (strcmp(reserveWord[i], s) == 0)
            return i + 1;
    }
    return -1;
}
/********查找保留字*****************/

/********查找是否是标识符*****************/
/* 找到返回索引,未找到返回-1(猜的) */
int searchID(char reserveWord[][50], char s[])
{ //自己实现
    for (int i = 0; reserveWord[i][0] != '\0'; i++)
    {
        if (strcmp(reserveWord[i], s) == 0)
            return i + 1;
    }
    return -1;
}
/********查找标识符*****************/

/*********************判断是否为字母********************/
bool IsLetter(char letter)
{ //注意C语言允许下划线也为标识符的一部分可以放在首部或其他地方
    if (letter >= 'a' && letter <= 'z' || letter >= 'A' && letter <= 'Z' || letter == '_')
    {
        return true;
    }
    else
    {
        return false;
    }
}
/*********************判断是否为字母********************/

/*****************判断是否为数字************************/
bool IsDigit(char digit)
{
    if (digit >= '0' && digit <= '9')
    {
        return true;
    }
    else
    {
        return false;
    }
}
/*****************判断是否为数字************************/

/*****************判断是否为数字************************/
bool Is0Digit(char digit)
{
    if (digit >= '0' && digit <= '7')
    {
        return true;
    }
    else
    {
        return false;
    }
}
/*****************判断是否为数字************************/

/*****************判断是否为十六进制数字************************/
bool Is0xDigit(char digit)
{
    if (digit >= '0' && digit <= '9' || digit >= 'a' && digit <= 'f')
    {
        return true;
    }
    else
    {
        return false;
    }
}
/*****************判断是否为十六进制数字************************/

/********************输出带行号的代码**********************/
void printResourceWithIndex(char r[], int pProject)
{
    int count = 1;
    cout << setw(5) << left << count++;
    for (int i = 0; i <= pProject; i++)
    {
        if (r[i] == '\n')
        {
            cout << endl;
            cout << setw(5) << left << count++;
        }
        else
        {
            cout << r[i];
        }
    }
    cout << endl;
}
/********************输出带行号的代码**********************/

/********************输出带行号的代码**********************/
void printWithIndex(char r[])
{
    int count = 1;
    cout << setw(5) << left << count++;
    for (int i = 0;; i++)
    {
        if (r[i] == '$')
        {
            break;
        }

        if (r[i] == '\n')
        {
            cout << '\n';
            cout << setw(5) << left << count++;
        }
        else
        {
            cout << r[i];
        }
    }
    cout << endl;
}
/********************输出带行号的代码**********************/

/********************编译预处理,取出无用的字符和注释**********************/
void filterResource(char r[], int pProject)
{
    char tempString[10000];

    int count = 0;
    int index_line_anotation = 0;
    int index_col_anotation = 0;

    index_col = 0;
    index_line = 1;
    int i = 0;
    while (i < pProject)
    {
        index_col++;
        if (r[i] == '\n')
        {
            index_col = 1;
            index_line++;
            tempString[count++] = r[i++];
        }
        else if (r[i] == '/' && r[i + 1] == '*')
        {
            index_line_anotation = index_line;
            index_col_anotation = index_col;
            i += 2;
            index_col += 2;

            int flag_matched = 1;   // 标志是否匹配
            while (r[i] != '*' || r[i + 1] != '/')
            {
                if (r[i] == '$')
                {
                    flag_matched = 0;
                    SetConsoleTextAttribute(hConsole, 0xC);
                    cout << index_line_anotation << "行," << index_col_anotation << "列:"
                         << "error: 注释未配对" << endl;
                    SetConsoleTextAttribute(hConsole, 0xF);
                    tempString[count++] = r[i++];   // 依旧把$添加进入
                    
                    tempString[count] = '\0';
                    strcpy(r, tempString);
                    return;
                }
                else if (r[i] == '\n')
                {
                    index_col = 1;
                    index_line++;
                    tempString[count++] = r[i++];
                }
                else if (r[i] == '\t')
                {
                    index_col += 8;
                    tempString[count++] = r[i++];
                }
                else
                {
                    i++;
                }
            }
            if (flag_matched)
            {
                i += 2;
            }
        }
        else if (r[i] == '/' && r[i + 1] == '/')
        {
            while (r[i] != '\n')
            {
                i++;
            }
            tempString[count++] = r[i++];
            index_col = 1;
            index_line += 1;
        }
        else if (r[i] == '\t')
        {
            index_col += 8;
            tempString[count++] = r[i++];
        }
        else
        {
            tempString[count++] = r[i++];
        }
    }

    tempString[count] = '\0';

    strcpy(r, tempString);
}
/********************编译预处理,取出无用的字符和注释**********************/

/****************************分析子程序,算法核心***********************/
void GetToken(int &syn, char resourceProject[], char token[], int &pProject)
{                     //根据DFA的状态转换图设计
    int i, count = 0; //count用来做token[]的指示器,收集有用字符
    char ch;          //作为判断使用
    ch = resourceProject[pProject];

    while (ch == '\r' || ch == ' ' || ch == '\n' || ch == '\t')
    { //过滤没有识别码的符号,防止程序因识别不了而结束
        if (ch == '\r')
        {
            index_col = 1;
            pProject++;
        }
        else if (ch == ' ')
        {
            pProject++;
            index_col++;
        }
        else if (ch == '\n')
        {
            index_col = 1;
            index_line++;
            pProject++;
        }
        else if (ch == '\t')
        {
            index_col += 8;
            pProject++;
        }

        ch = resourceProject[pProject];
    }

    // while (ch == '$')
    // {
    //     pProject++;
    //     ch = resourceProject[pProject];
    // }
    for (i = 0; i < 20; i++)
    { //每次收集前先清零
        token[i] = '\0';
    }
    if (IsLetter(resourceProject[pProject]))
    {
        token[count++] = resourceProject[pProject];
        pProject++;
        index_col++;
        while (IsLetter(resourceProject[pProject]) || IsDigit(resourceProject[pProject]))
        {
            token[count++] = resourceProject[pProject];
            pProject++;
            index_col++;
        }
        token[count] = '\0';
        syn = searchReserve(reserveWord, token);

        if (syn == -1)
        {
            syn = searchID(IDentifierTbl, token);
            if (syn == -1)
            {
                strcpy(IDentifierTbl[count_id++], token);
            }
            syn = 100;
        }
        return;
    }
    else if (IsDigit(resourceProject[pProject]))
    { //首字符为数字(包括浮点数)(十、八、十六)
        if (resourceProject[pProject] != '0')
        { //十进制
            while (IsDigit(resourceProject[pProject]))
            {                                               //后跟数字
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                index_col++;
            } //多读了一个字符既是下次将要开始的指针位置
            if (resourceProject[pProject] == '.')
            {
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                index_col++;
                while (IsDigit(resourceProject[pProject]))
                {                                               //后跟数字
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                } //多读了一个字符既是下次将要开始的指针位置
                if (resourceProject[pProject] == 'e')
                {//科学记数法
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                    if (resourceProject[pProject] == '+' || resourceProject[pProject] == '-')
                    {
                        token[count++] = resourceProject[pProject]; //收集
                        pProject++;
                        index_col++;
                    }
                    while (IsDigit(resourceProject[pProject]))
                    {                                               //后跟数字
                        token[count++] = resourceProject[pProject]; //收集
                        pProject++;
                        index_col++;
                    } //多读了一个字符既是下次将要开始的指针位置
                }
                token[count] = '\0';
                syn = 101; //十进制浮点数种别码
                return;
            }
            if (resourceProject[pProject] == 'e')
            {//科学记数法
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                index_col++;
                if (resourceProject[pProject] == '+' || resourceProject[pProject] == '-')
                {
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                }
                while (IsDigit(resourceProject[pProject]))
                {                                               //后跟数字
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                } //多读了一个字符既是下次将要开始的指针位置
            }

            token[count] = '\0';
            syn = 99; //十进制整数种别码
            return;
        }
        else
        {
            if (resourceProject[pProject + 1] == 'x' || resourceProject[pProject + 1] == 'X')
            {                                               // 十六进制
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                index_col += 2;
                while (Is0xDigit(resourceProject[pProject]))
                {                                               //后跟数字
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                } //多读了一个字符既是下次将要开始的指针位置
                if (resourceProject[pProject] == '.')
                {
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                    while (Is0xDigit(resourceProject[pProject]))
                    {                                               //后跟数字
                        token[count++] = resourceProject[pProject]; //收集
                        pProject++;
                        index_col++;
                    } //多读了一个字符既是下次将要开始的指针位置

                    if (IsLetter(resourceProject[pProject]))
                    {
                        SetConsoleTextAttribute(hConsole, 0xC);
                        cout << index_line << "行," << index_col << "列:"
                             << "error: 十六进制格式错误\n";
                        SetConsoleTextAttribute(hConsole, 0xF);
                    }

                    token[count] = '\0';
                    syn = 105; //十六进制浮点数种别码
                    return;
                }

                if (IsLetter(resourceProject[pProject]))
                {
                    SetConsoleTextAttribute(hConsole, 0xC);
                    cout << index_line << "行," << index_col << "列:"
                         << "error: 十六进制格式错误\n";
                    SetConsoleTextAttribute(hConsole, 0xF);
                }
                token[count] = '\0';
                syn = 104; //十六进制整数种别码
                return;
            }
            else
            {
                //八进制
                token[count++] = resourceProject[pProject]; //收集
                pProject++;
                index_col++;
                while (Is0Digit(resourceProject[pProject]))
                {                                               //后跟数字
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                } //多读了一个字符既是下次将要开始的指针位置
                if (resourceProject[pProject] == '.')
                {
                    token[count++] = resourceProject[pProject]; //收集
                    pProject++;
                    index_col++;
                    while (Is0Digit(resourceProject[pProject]))
                    {                                               //后跟数字
                        token[count++] = resourceProject[pProject]; //收集
                        pProject++;
                        index_col++;
                    } //多读了一个字符既是下次将要开始的指针位置

                    if (IsLetter(resourceProject[pProject]) || resourceProject[pProject] == '8' || resourceProject[pProject] == '9')
                    {
                        SetConsoleTextAttribute(hConsole, 0xC);
                        cout << index_line << "行," << index_col << "列:"
                             << "error: 八进制格式错误\n";
                        SetConsoleTextAttribute(hConsole, 0xF);
                    }

                    token[count] = '\0';
                    syn = 103; //八进制浮点数种别码
                    return;
                }

                if (IsLetter(resourceProject[pProject]) || resourceProject[pProject] == '8' || resourceProject[pProject] == '9')
                {
                    SetConsoleTextAttribute(hConsole, 0xC);
                    cout << index_line << "行," << index_col << "列:"
                         << "error: 八进制格式错误\n";
                    SetConsoleTextAttribute(hConsole, 0xF);
                }

                token[count] = '\0';
                syn = 102; //八进制整数种别码
                return;
            }
        }
    }
    else if (ch == ';' || ch == '(' || ch == ')' || ch == '^' || ch == ',' || ch == '\"' || ch == '\'' || ch == '~' || ch == '#' || ch == '%' || ch == '[' || ch == ']' || ch == '{' || ch == '}' || ch == '\\' || ch == '.' || ch == '\?' || ch == ':')
    { //若为运算符或者界符,查表得到结果
        token[0] = resourceProject[pProject];
        token[1] = '\0'; //形成单字符串
        for (i = 0; i < 36; i++)
        { //查运算符界符表
            if (strcmp(token, operatorOrDelimiter[i]) == 0)
            {
                syn = 33 + i; //获得种别码,使用了一点技巧,使之呈线性映射
                break;        //查到即推出
            }
        }
        pProject++; //指针下移,为下一扫描做准备
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '+')
    {               // +=
        pProject++; //后移,超前搜索
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 69;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 33;
        }
        pProject++; //指针下移
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '-')
    {               // +=
        pProject++; //后移,超前搜索
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 70;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 34;
        }
        pProject++; //指针下移
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '*')
    {               // +=
        pProject++; //后移,超前搜索
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 71;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 35;
        }
        pProject++; //指针下移
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '/')
    {               // +=
        pProject++; //后移,超前搜索
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 72;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 36;
        }
        pProject++; //指针下移
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '<')
    {               //<,<=,<<
        pProject++; //后移,超前搜索
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 38;
        }
        else if (resourceProject[pProject] == '<')
        { //左移
            pProject--;
            index_col--;
            syn = 58;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 37;
        }
        pProject++; //指针下移
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '>')
    { //>,>=,>>
        pProject++;
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 40;
        }
        else if (resourceProject[pProject] == '>')
        {
            syn = 59;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 39;
        }
        pProject++;
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '=')
    { //=.==
        pProject++;
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 42;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 41;
        }
        pProject++;
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '!')
    { //!,!=
        pProject++;
        index_col++;
        if (resourceProject[pProject] == '=')
        {
            syn = 43;
        }
        else
        {
            syn = 68;
            pProject--;
            index_col--;
        }
        pProject++;
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '&')
    { //&,&&
        pProject++;
        index_col++;
        if (resourceProject[pProject] == '&')
        {
            syn = 53;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 52;
        }
        pProject++;
        index_col++;
        return;
    }
    else if (resourceProject[pProject] == '|')
    { //|,||
        pProject++;
        index_col++;
        if (resourceProject[pProject] == '|')
        {
            syn = 55;
        }
        else
        {
            pProject--;
            index_col--;
            syn = 54;
        }
        pProject++;
        index_col++;
        return;
    }
        else if (resourceProject[pProject] == '$')
    {            //结束符
        syn = 0; //种别码为0
    }
    else
    { //不能被以上词法分析识别,则出错。
        SetConsoleTextAttribute(hConsole, 0xC);
        cout << index_line << "行," << index_col << "列:"
             << "error:there is no exist " << ch << endl;
        SetConsoleTextAttribute(hConsole, 0xF);

        pProject++;
    }
}

int main()
{
    //打开一个文件,读取其中的源程序
    char *resourceFile = "C:\\Users\\46855\\Desktop\\c\\lex\\testHard.c";
    char *outputCompile = "C:\\Users\\46855\\Desktop\\c\\lex\\test_compile.txt";
    char resourceProject[10000];
    char token[20] = {0};
    int syn = -1, i;  //初始化
    int pProject = 0; //源程序指针
    FILE *fp, *fp1;
    if ((fp = fopen(resourceFile, "r")) == NULL)
    { //打开源程序
        cout << "can't open this file";
        exit(0);
    }
    resourceProject[pProject] = fgetc(fp); //读取一个字符
    while (resourceProject[pProject] != EOF)
    { //将源程序读入resourceProject[]数组
        pProject++;
        resourceProject[pProject] = fgetc(fp);
    }
    resourceProject[++pProject] = '\0';
    fclose(fp);
    cout << endl
         << "\n源程序为:\n";
    printResourceWithIndex(resourceProject, pProject);
    //对源程序进行过滤
    filterResource(resourceProject, pProject);
    cout << endl
         << "\n过滤之后的程序:" << endl;
    // cout << resourceProject << endl;
    printWithIndex(resourceProject);
    pProject = 0; //从头开始读
    index_line = 1;
    index_col = 0;
    if ((fp1 = fopen(outputCompile, "w+")) == NULL)
    { //打开编译输出文件
        cout << "can't open this file";
        exit(0);
    }

    cout << "\nTocken序列:\n";
    while (syn != 0)
    {
        //启动扫描
        GetToken(syn, resourceProject, token, pProject);
        printf("%d行,%d列:", index_line, index_col);
        fprintf(fp1, "%d行,%d列:", index_line, index_col);
        if (syn == 100)
        { //标识符
            printf("(标识符, %s)\n", token);
            fprintf(fp1, "(标识符, %s)\n", token);
        }
        else if (syn >= 1 && syn <= 32)
        { //保留字
            printf("(%s, --)\n", reserveWord[syn - 1]);
            fprintf(fp1, "(%s, --)\n", reserveWord[syn - 1]);
        }
        else if (syn == 99)
        { //十进制整数
            printf("(十进制整数, %s)\n", token);
            fprintf(fp1, "(十进制整数, %s)\n", token);
        }
        else if (syn >= 33 && syn <= 72)
        {
            printf("(%s , --)\n", operatorOrDelimiter[syn - 33]);
            fprintf(fp1, "(%s, --)\n", operatorOrDelimiter[syn - 33]);
        }
        else if (syn == 101)
        { //十进制浮点数
            printf("(十进制浮点数, %s)\n", token);
            fprintf(fp1, "(十进制浮点数, %s)\n", token);
        }
        else if (syn == 102)
        { //八进制整数
            printf("(八进制整数, %s)\n", token);
            fprintf(fp1, "(八进制整数, %s)\n", token);
        }
        else if (syn == 103)
        { //八进制浮点数
            printf("(八进制浮点数, %s)\n", token);
            fprintf(fp1, "(八进制浮点数, %s)\n", token);
        }
        else if (syn == 104)
        { //十六进制整数
            printf("(十六进制整数, %s)\n", token);
            fprintf(fp1, "(十六进制整数, %s)\n", token);
        }
        else if (syn == 105)
        { //十六进制浮点数
            printf("(十六进制浮点数, %s)\n", token);
            fprintf(fp1, "(十六进制浮点数, %s)\n", token);
        }
    }

    cout << "\n\n标识符序列:\n";
    for (i = 0; i < count_id; i++)
    { //插入标识符表中
        printf("第%d个标识符:  %s\n", i + 1, IDentifierTbl[i]);
        fprintf(fp1, "第%d个标识符:  %s\n", i + 1, IDentifierTbl[i]);
    }
    fclose(fp1);
    system("pause");
    return 0;
}

运行结果:

源程序为:
1    #include 
2    int main(int argc, char const *argv[])
3    {
4       char *str = "String123";
5       int num1=0x45f7,num2=0187,num3=0x1g35;//num3 16进制错误  num2 8进制错误
6       //This is comment
7       /**
8       printf("NULL\n");
9       */
10      int floatnum = 123.456;@ //不能识别字符@
11      int num4 = 45.58e-10;
12      if(6.4 <= 5.8)
13              printf("Yes");
14      if(floatn>5) //floatn 暂不考虑
15              printf("No");
16      for(int i=1;i<6;i++){
17              num2+=10;       //识别+=
18              num2-=10;       //识别-=
19              num2*=10;       //识别*=
20              num2/=10;       //识别/=
21              printf("%d",num2);
22      }
23      /*测试注释符号未匹配
24      printf("NULL\n");
25
26      return 0;
27   }$
23行,11列:error: 注释未配对


过滤之后的程序:
1    #include 
2    int main(int argc, char const *argv[])
3    {
4       char *str = "String123";
5       int num1=0x45f7,num2=0187,num3=0x1g35;
6
7
8
9
10      int floatnum = 123.456;@ 
11      int num4 = 45.58e-10;
12      if(6.4 <= 5.8)
13              printf("Yes");
14      if(floatn>5)
15              printf("No");
16      for(int i=1;i<6;i++){
17              num2+=10;
18              num2-=10;
19              num2*=10;
20              num2/=10;
21              printf("%d",num2);
22      }
23
24
25
26
27

Tocken序列:
1行,1列:(# , --)
1行,8列:(标识符, include)
1行,10列:(< , --)
1行,15列:(标识符, stdio)
1行,16列:(. , --)
1行,17列:(标识符, h)
1行,18列:(> , --)
2行,4列:(int, --)
2行,9列:(标识符, main)
2行,10列:(( , --)
2行,13列:(int, --)
2行,18列:(标识符, argc)
2行,19列:(, , --)
2行,24列:(char, --)
2行,30列:(const, --)
2行,32列:(* , --)
2行,36列:(标识符, argv)
2行,37列:([ , --)
2行,38列:(] , --)
2行,39列:() , --)
3行,2列:({ , --)
4行,13列:(char, --)
4行,15列:(* , --)
4行,18列:(标识符, str)
4行,20列:(= , --)
4行,22列:(" , --)
4行,31列:(标识符, String123)
4行,32列:(" , --)
4行,33列:(; , --)
5行,12列:(int, --)
5行,17列:(标识符, num1)
5行,18列:(= , --)
5行,24列:(十六进制整数, 0x45f7)
5行,25列:(, , --)
5行,29列:(标识符, num2)
5行,30列:(= , --)
5行,32列:error: 八进制格式错误
5行,32列:(八进制整数, 01)
5行,34列:(十进制整数, 87)
5行,35列:(, , --)
5行,39列:(标识符, num3)
5行,40列:(= , --)
5行,43列:error: 十六进制格式错误
5行,43列:(十六进制整数, 0x1)
5行,46列:(标识符, g35)
5行,47列:(; , --)
10行,12列:(int, --)
10行,21列:(标识符, floatnum)
10行,23列:(= , --)
10行,31列:(十进制浮点数, 123.456)
10行,32列:(; , --)
10行,32列:error:there is no exist @
10行,32列:(; , --)
11行,12列:(int, --)
11行,17列:(标识符, num4)
11行,19列:(= , --)
11行,29列:(十进制浮点数, 45.58e-10)
11行,30列:(; , --)
12行,11列:(if, --)
12行,12列:(( , --)
12行,15列:(十进制浮点数, 6.4)
12行,18列:(<= , --)
12行,22列:(十进制浮点数, 5.8)
12行,23列:() , --)
13行,23列:(标识符, printf)
13行,24列:(( , --)
13行,25列:(" , --)
13行,28列:(标识符, Yes)
13行,29列:(" , --)
13行,30列:() , --)
13行,31列:(; , --)
14行,11列:(if, --)
14行,12列:(( , --)
14行,18列:(标识符, floatn)
14行,19列:(> , --)
14行,20列:(十进制整数, 5)
14行,21列:() , --)
15行,23列:(标识符, printf)
15行,24列:(( , --)
15行,25列:(" , --)
15行,27列:(标识符, No)
15行,28列:(" , --)
15行,29列:() , --)
15行,30列:(; , --)
16行,12列:(for, --)
16行,13列:(( , --)
16行,16列:(int, --)
16行,18列:(标识符, i)
16行,19列:(= , --)
16行,20列:(十进制整数, 1)
16行,21列:(; , --)
16行,22列:(标识符, i)
16行,23列:(< , --)
16行,24列:(十进制整数, 6)
16行,25列:(; , --)
16行,26列:(标识符, i)
16行,27列:(+ , --)
16行,28列:(+ , --)
16行,29列:() , --)
16行,30列:({ , --)
17行,21列:(标识符, num2)
17行,23列:(+= , --)
17行,25列:(十进制整数, 10)
17行,26列:(; , --)
18行,21列:(标识符, num2)
18行,23列:(-= , --)
18行,25列:(十进制整数, 10)
18行,26列:(; , --)
19行,21列:(标识符, num2)
19行,23列:(*= , --)
19行,25列:(十进制整数, 10)
19行,26列:(; , --)
20行,21列:(标识符, num2)
20行,23列:(/= , --)
20行,25列:(十进制整数, 10)
20行,26列:(; , --)
21行,23列:(标识符, printf)
21行,24列:(( , --)
21行,25列:(" , --)
21行,26列:(% , --)
21行,27列:(标识符, d)
21行,28列:(" , --)
21行,29列:(, , --)
21行,33列:(标识符, num2)
21行,34列:() , --)
21行,35列:(; , --)
22行,10列:(} , --)
27行,1列:

标识符序列:
第1个标识符:  include
第2个标识符:  stdio
第3个标识符:  h
第4个标识符:  main
第5个标识符:  argc
第6个标识符:  argv
第7个标识符:  str
第8个标识符:  String123
第9个标识符:  num1
第10个标识符:  num2
第11个标识符:  num3
第12个标识符:  g35
第13个标识符:  floatnum
第14个标识符:  num4
第15个标识符:  printf
第16个标识符:  Yes
第17个标识符:  floatn
第18个标识符:  No
第19个标识符:  i
第20个标识符:  d
请按任意键继续. . .