
2.2 词法分析过程
词法分析从第一个字符开始遍历,识别出字符“i”,如图2-4所示。

图2-4 识别出字符“i”
根据C语言的词法规则,以字母或下划线开头的符号是标识符,所以根据“i”就可以确定当前分析的符号是一个标识符,但这个标识符的全部内容是什么现在还无法确定,需要继续向后遍历。下面识别出“n”,如图2-5所示。

图2-5 识别出字符“n”
根据词法规则,标识符的后续字符可以是字母、数字或下划线,“n”符合规则,它属于当前这个符号,继续遍历。下面识别出“t”,如图2-6所示。

图2-6 识别出字符“t”
仍然符合规则。继续遍历,识别出“空格”,如图2-7所示。

图2-7 识别出空格并确定符号“int”
它不再是字母、数字或下划线,这意味着,当前这个标识符的全部内容是“int”。下一个字符是空格,如图2-8所示。

图2-8 继续识别空格
这个空格为什么要被再次识别呢?这是因为第一次识别的空格是“int”这个标识符的后续,意味着“int”是一个标识符的完整内容。完成“int”的识别后,词法分析进入对下一个符号的识别,识别的起始位置从上一个符号的终结位置的下一个字符算起,在此就是空格,于是此时再次识别这个空格。可见,对这个空格的两次识别,性质是不一样的,分别对应着对前后两个符号的处理。对于其他可以确定前一个标识符终结的分隔符,也会进行这样的第二次处理。
根据C语言规则,空格是间隔符,不是任何符号的起始,于是跳过它,继续向后遍历,陆续识别出“f”、“u”、“n”、“(”。当发现“(”时,不再符合标识符“字母、数字、下划线”的规则,于是可以确定,“fun”是一个完整的标识符,如图2-9所示。

图2-9 识别出“(”后确定符号“fun”
继续准备识别下面的符号,对下一个字符“(”也进行了前后两次识别。这与前面我们介绍的对空格的两次识别是相同的,差异是,根据C语言词法规则,“(”是个符号,不能忽略,如图2-10所示。

图2-10 继续识别出“(”确定符号“(”
根据前面的方式继续遍历,识别出符号“int”、“a”、“int”、“b”、“)”、“;”,直到识别出“\n”,“\n”可跳过,如图2-11所示。

图2-11 识别出“\n”之前不断确定符号
继续遍历,识别出符号“int”、“m”,之后遍历到“=”,如图2-12所示。

图2-12 刚识别到“=”还不能确定符号全部内容
这时候还不能确定当前符号就是“=”,也有可能是“==”的前半部分,根据C语言的词法规则,“=”和“==”的含义是不一样的,所以还要往后遍历,发现后续字符是“1”,不是“=”,如图2-13所示。

图2-13 刚识别到“1”确定符号“=”
现在可以确定,当前符号是“=”,它是个运算符,在确定的符号“=”后继续遍历,还是刚才的字符“1”,如图2-14所示。

图2-14 识别到“1”后确定符号“=”
根据词法规则,以数字开头的符号是数字,说明当前符号是数字,继续遍历,识别到“0”,如图2-15所示。

图2-15 识别到“0”
继续遍历到“;”,如图2-16所示。

图2-16 识别到“;”后确定符号“10”
“;”不属于数字,说明前面的数字已经完结,“10”就是当前数字符号的全部。从“10”后继续遍历,也就是“;”,如图2-17所示。

图2-17 确定符号“;”
最后识别到换行符“\n”,如图2-18所示。

图2-18 识别到“\n”
跳过换行符,继续按照前面的方式对后续的字符串进行遍历,切分出符号并提取信息。这就是词法分析的大致过程。