使用Lex/Yacc编写LaTeX解析器仅识别单个token报错求助
问题原因分析
- 第一版语法规则设计错误:初始语法仅允许单个
BEGtoken作为有效输入,匹配到第一个\begin{document}后,语法解析器已到达接受状态,后续输入内容无匹配规则,直接触发语法错误。 - 词法分析器规则缺失:修改语法支持多行后,词法层仍存在两个核心问题:
- 仅定义了
\begin行的匹配规则,换行符、普通文本、第二个\begin等其余输入无对应匹配规则,Lex默认会将未匹配字符直接输出到标准输出,不会返回给语法解析器,导致语法层收不到完整token流。 - 未定义换行符的返回逻辑,语法规则中用
'\n'作为行结束标识,但词法层不会返回换行符token,永远无法匹配行规则。
- 仅定义了
- 正则匹配逻辑缺陷:尝试添加的
.*正则为贪婪匹配,若行内存在其他内容会被全部吞噬,且未在词法中定义IDtoken的返回规则,语法层的ID标识无对应输入来源。
修复方案
1. 修正词法分析器逻辑
补充完整的token返回规则,替换贪婪匹配为安全的括号匹配:
%{ #include "y.tab.h" #include <stdio.h> %} %% ^\\begin\{[^{}]*\} { return BEG; } \n { return '\n'; } . { return ID; } %% int yywrap() { return 1; }
2. 修正语法分析器逻辑
补充ID token声明,完善普通行的匹配规则:
%{ #include <stdio.h> #include <stdlib.h> void yyerror(char *s); int yylex(); extern FILE *yyin; %} %token BEG ID %% lines: line | lines line ; line: beg '\n' | content '\n' ; beg: BEG { printf("Hello world\n"); } ; content: ID | content ID ; %% void yyerror(char *s) { fprintf(stderr, "%s\n", s); } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Wrong number of arguments provided\n"); exit(1); } yyin = fopen(argv[1], "r"); if (!yyin) { fprintf(stderr, "Not a valid filename\n"); exit(1); } yyparse(); return 0; }
效果验证
使用提供的LaTeX测试用例运行修复后的程序,会输出两次Hello world,无语法错误,两个\begin指令都能被正确识别。
内容的提问来源于stack exchange,提问作者fresh
相关产品推荐
相关产品推荐

