Lex/Yacc时间格式解析器解析结果交替异常问题求助
问题分析与修复方案
核心问题
你的解析器出现交替错误/正常的现象,根源在于三个关键问题:
- Yacc在语法错误后会保持错误状态,后续调用
yyparse()会直接返回错误,不会重新初始化解析环境 - 错误地将换行符
\n当作EOF_处理,混淆了行分隔符与真正的输入结束标志 - Lex中未处理的
.规则会默默吞掉非法字符,导致解析状态混乱
具体修复步骤
1. 修改Yacc文件(.y)
调整语法规则,添加错误恢复逻辑,并移除错误的EOF_定义:
%token HOUR COLON MINUTE AM PM %% main: time_list ; // 支持多行时间解析 time_list: time | time_list time ; // 匹配合法时间格式,添加错误恢复 time: HOUR ampm { printf("The time format is correct\n\n"); } | HOUR COLON MINUTE { printf("The time format is correct\n\n"); } | HOUR COLON MINUTE ampm { printf("The time format is correct\n\n"); } | error '\n' { yyerrok; /* 强制重置错误状态 */ printf("Skipping invalid line\n\n"); } ; ampm: AM | PM ;
更新main函数,让解析器自然处理到真正的输入结束:
int main() { yyparse(); return 0; }
2. 修改Lex文件(.l)
完善词法规则,正确处理换行、空白和非法字符:
[0-9]{1,2} { printf("HOUR: %s\n", yytext); return HOUR; } : { printf("COLON\n"); return COLON; } [0-9]{2} { printf("MINUTE: %s\n", yytext); return MINUTE; } am { printf("AM\n"); return AM; } pm { printf("PM\n"); return PM; } \n { /* 换行作为行分隔符,不返回token */ } [ \t] { /* 忽略空格和制表符 */ } . { printf("Invalid character: %c\n", yytext[0]); }
修复关键点说明
- 错误状态重置:使用
yyerrok宏在解析错误后强制重置Yacc的错误标志,确保下一行解析能正常启动 - 正确区分换行与EOF:换行仅作为行分隔符处理,真正的输入结束由Lex自动识别并返回0,避免解析状态混乱
- 完善Lex规则:移除不必要的行首锚定
^,处理空白字符,对非法字符明确报错,避免输入被静默丢弃
内容的提问来源于stack exchange,提问作者Ash Ketchum
相关产品推荐
相关产品推荐

