使用正则表达式获取字符串中Token的起止位置(C语法高亮场景)
在C语言中实现代码语法高亮:正则匹配位置与实践方案
一、用<regex.h>获取匹配位置的具体实现
要获取正则匹配在字符串中的起始和结束位置,核心是利用regexec函数的regmatch_t参数。这个结构体的rm_so字段存储匹配的起始偏移(从0开始),rm_eo字段存储匹配的结束偏移,你要的结束位置就是rm_eo的值。
以下是一个简单示例,演示如何匹配C语言的int关键字并获取其结束位置:
#include <stdio.h> #include <regex.h> #include <string.h> int main() { const char *source = "int main(int argc, char** argv) { ... }"; regex_t regex; regmatch_t match; int ret; // 编译正则:匹配独立的int关键字(避免匹配标识符中的int,比如myint) ret = regcomp(®ex, "\\bint\\b", REG_EXTENDED); if (ret != 0) { fprintf(stderr, "正则编译失败\n"); return 1; } // 执行匹配,只找第一个匹配项 ret = regexec(®ex, source, 1, &match, 0); if (ret == 0) { printf("匹配起始位置:%d\n", match.rm_so); printf("匹配结束位置:%d\n", match.rm_eo); // 这里就是你要的结束位置 // 从结束位置开始处理剩余字符串 const char *remaining = source + match.rm_eo; printf("剩余待处理字符串:%s\n", remaining); } else if (ret == REG_NOMATCH) { printf("未找到匹配\n"); } else { fprintf(stderr, "匹配出错\n"); } regfree(®ex); return 0; }
注意正则里的\b是单词边界,避免把myint这类标识符里的int误识别为关键字。
二、语法高亮的基本处理流程
基于正则的语法高亮可以按以下步骤循环处理:
- 定义不同Token的正则规则和对应颜色(比如关键字用蓝色,字符串用红色,标识符用默认色),注意规则要按优先级排序(比如字符串、注释的优先级要高于关键字,避免误匹配)
- 从当前位置开始,依次尝试匹配各规则
- 找到第一个匹配的Token后,标记该段的颜色,然后将当前位置更新为匹配的结束位置
- 重复上述步骤,直到处理完整个字符串
三、更优方案:用词法分析器生成器
纯手写正则处理C语法会遇到很多边缘情况:比如字符串中的关键字不会被高亮、多行注释的处理、预处理指令(#include、#define)的识别、字符常量与字符串的区分等,这些用纯正则很难完美处理。
更靠谱的方案是使用flex(GNU词法分析器生成器):
- flex可以定义C语言的词法规则(比如关键字、字符串、注释、标识符等的匹配规则)
- 它会自动生成词法分析代码,能准确识别各种Token,同时返回Token的类型和位置
- 你只需要在flex的规则中添加对应的颜色标记逻辑,就能轻松实现语法高亮
比如flex的规则片段:
"int" { printf("\033[34m%s\033[0m", yytext); } // 蓝色高亮int关键字 \"([^"\\]|\\.)*\" { printf("\033[31m%s\033[0m", yytext); } // 红色高亮字符串 [a-zA-Z_][a-zA-Z0-9_]* { printf("%s", yytext); } // 默认颜色显示标识符 [ \t\n] { printf("%s", yytext); } // 保留空白字符
内容的提问来源于stack exchange,提问作者trxgnyp1
相关产品推荐
相关产品推荐

