You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Lex/Yacc编写LaTeX解析器仅识别单个token报错求助

问题原因分析
  • 第一版语法规则设计错误:初始语法仅允许单个BEG token作为有效输入,匹配到第一个\begin{document}后,语法解析器已到达接受状态,后续输入内容无匹配规则,直接触发语法错误。
  • 词法分析器规则缺失:修改语法支持多行后,词法层仍存在两个核心问题:
    1. 仅定义了\begin行的匹配规则,换行符、普通文本、第二个\begin等其余输入无对应匹配规则,Lex默认会将未匹配字符直接输出到标准输出,不会返回给语法解析器,导致语法层收不到完整token流。
    2. 未定义换行符的返回逻辑,语法规则中用'\n'作为行结束标识,但词法层不会返回换行符token,永远无法匹配行规则。
  • 正则匹配逻辑缺陷:尝试添加的.*正则为贪婪匹配,若行内存在其他内容会被全部吞噬,且未在词法中定义ID token的返回规则,语法层的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 07:24:01