在编译原理中,词法分析是第一步,它负责将源代码中的字符流转换为有意义的“单词”(称为记号或Token)。而实现词法分析最常用、最直观的方法之一就是使用状态机。本文将带你从零开始,用通俗易懂的方式理解 C 语言词法分析状态机的工作原理,并手写一个简单的状态机框架。

想象你正在读一段 C 语言代码:
int main() { int a = 10; return 0;}词法分析器的任务就是把这段字符序列拆分成如下记号(Token):
int → 关键字(KEYWORD)main → 标识符(IDENTIFIER)( → 左括号(LPAREN)) → 右括号(RPAREN){ → 左花括号(LBRACE)a → 标识符(IDENTIFIER)= → 赋值符号(ASSIGN)10 → 整数字面量(INTEGER_LITERAL); → 分号(SEMICOLON)这个过程就像“分词”——把一串连续的字符按语法规则切分成有意义的单元。
因为词法规则具有“阶段性”和“上下文依赖性”。例如:
i,可能是标识符的开始;n、t,就变成了关键字 int;d,比如 id,那就是普通标识符。这种“根据当前字符决定下一步行为”的逻辑,正是有限状态自动机(Finite State Machine, FSM)的强项。
我们以识别整数和标识符为例,构建一个极简的状态机。
| 当前状态 | 输入字符 | 下一状态 | 动作 |
|---|---|---|---|
| START | 数字(0-9) | IN_INT | 开始记录整数 |
| START | 字母或 '_' | IN_ID | 开始记录标识符 |
| IN_INT | 数字 | IN_INT | 继续追加数字 |
| IN_ID | 字母/数字/'_' | IN_ID | 继续追加字符 |
| IN_INT / IN_ID | 非合法字符(如空格、符号) | DONE | 输出 Token,回到 START |
下面是一个简化版的 C 语言词法分析状态机核心逻辑:
#include <stdio.h>#include <ctype.h>#include <string.h>enum State { START, IN_INT, IN_ID, DONE };void tokenize(char *input) { enum State state = START; char buffer[100]; int pos = 0; for (int i = 0; input[i] != '\0'; i++) { char c = input[i]; switch (state) { case START: if (isdigit(c)) { buffer[pos++] = c; state = IN_INT; } else if (isalpha(c) || c == '_') { buffer[pos++] = c; state = IN_ID; } // 忽略空格等无关字符 break; case IN_INT: if (isdigit(c)) { buffer[pos++] = c; } else { buffer[pos] = '\0'; printf("INTEGER: %s\n", buffer); pos = 0; state = START; i--; // 回退一个字符,重新处理 } break; case IN_ID: if (isalnum(c) || c == '_') { buffer[pos++] = c; } else { buffer[pos] = '\0'; // 简化:不区分关键字和普通标识符 printf("IDENTIFIER: %s\n", buffer); pos = 0; state = START; i--; } break; } } // 处理最后一个 token if (pos > 0) { buffer[pos] = '\0'; if (state == IN_INT) printf("INTEGER: %s\n", buffer); else if (state == IN_ID) printf("IDENTIFIER: %s\n", buffer); }}int main() { char code[] = "int count = 42;"; tokenize(code); return 0;}运行这段代码,你会看到输出:
IDENTIFIER: intIDENTIFIER: countINTEGER: 42
虽然简单,但它已经体现了C语言词法分析和状态机实现的核心思想!
通过本文,你已经掌握了:
这为你学习更复杂的词法分析器(如 Flex 工具生成的)打下了坚实基础。如果你是刚接触编译原理的小白,建议动手改写上面的代码,尝试加入对关键字(如 if、while)、运算符(+、==)的支持,这是提升编程基础的绝佳练习!
记住:每一个编译器,都始于一个小小的词法分析器。现在,轮到你了!
本文由主机测评网于2025-12-03发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025122283.html