XML文档Lexer元素值正则覆盖空白符匹配规则如何修复
XML词法分析器(Flex实现)问题解决方案
问题1:多余空ELEMENT_VALUE token修复
Flex的匹配规则遵循两个优先级逻辑:更长匹配优先,相同匹配长度下规则书写顺序靠前的优先触发,你遇到的空白被元素值规则捕获的问题,对应解决方案如下:
- 调整规则书写顺序:将空白符匹配规则放在
ELEMENT_VALUE匹配规则之前,纯空白内容直接忽略,无需返回token,规则示例:
\s+ { /* 直接吞噬所有标签间空白,不生成token */ }
- 优化
ELEMENT_VALUE匹配逻辑:你当前的正则[^<>]+/<是前瞻匹配到下一个标签起始符<为止,可在匹配动作中增加全空白判定,即使顺序错配也不会返回无效的空白内容token,示例代码:
[^<>]+/< { // 判定匹配结果是否全为空白 int all_blank = 1; for (int i = 0; i < yyleng; i++) { if (!isspace(yytext[i])) { all_blank = 0; break; } } if (all_blank) return 0; // 非空白内容正常返回ELEMENT_VALUE yylval.str = strndup(yytext, yyleng); return ELEMENT_VALUE; }
- 补充忽略规则:XML声明行、指定命名空间声明可以单独写规则放在所有规则最前面,匹配到直接跳过即可:
// 忽略XML声明 <\?xml[^?>]*\?> { } // 忽略指定命名空间,替换成你要过滤的命名空间URI即可 xmlns(:[a-zA-Z0-9_]+)?="http://your-target-ns-1" { } xmlns(:[a-zA-Z0-9_]+)?="http://your-target-ns-2" { }
问题2:移除ATTRIBUTE_VALUE外层包裹的引号
属性值的匹配规则通常是匹配被单引号或双引号包裹的内容,只需在匹配动作中截断首尾的引号即可,示例代码:
// 匹配双引号包裹的属性值 \"[^"]*\" { // 移除首尾双引号,有效内容长度为yyleng-2 yylval.str = malloc(yyleng - 1); strncpy(yylval.str, yytext + 1, yyleng - 2); yylval.str[yyleng - 2] = '\0'; return ATTRIBUTE_VALUE; } // 匹配单引号包裹的属性值 '[^']*' { yylval.str = malloc(yyleng - 1); strncpy(yylval.str, yytext + 1, yyleng - 2); yylval.str[yyleng - 2] = '\0'; return ATTRIBUTE_VALUE; }
如果项目使用GLib等工具库,也可以直接用g_strndup(yytext + 1, yyleng - 2)简化代码,无需手动处理内存和字符串结束符。
内容的提问来源于stack exchange,提问作者Roger Costello
相关产品推荐
相关产品推荐

