词法分析
目录
- 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. 正则表达式
正则表达式定义
例:
正则语言
可以用
RE定义的语言叫做正则语言(regular language)或正则集合(regular set)
RE的代数定律
正则文法与正则表达式等价
2. 正则定义(Regular Definition)
例:
3. 有穷自动机
FA的经典例子
FA模型
FA的表示
FA定义(接收)的语言
最长子串匹配原则(Longest String Matching Principle)
3. 有穷自动机的分类
- 确定的FA(Deterministic finite automata, DFA)
- 非确定的FA(Nondeterministic finite automata, NFA)
确定的有穷自动机(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. 词法分析器的实现
定义种别码
对所有单词进行编码
实现词法分析
实现代码(长)
测试代码:
#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
请按任意键继续. . .