Lex/yacc 只检测到一个令牌

Lex/yacc only detecting one token

我正在尝试使用 lex 和 yacc 编写 LaTeX 解析器,但我很挣扎。这是我的词法分析器:

%{
#include "y.tab.h"
#include <stdio.h>
%}

%%
^\begin\{.*\} {return BEG;}
%%

int yywrap() {
    return 1;
}

这是我的解析器:

%{
#include <stdio.h>
#include <stdlib.h>

void yyerror(char *s);
int yylex();
extern FILE *yyin;
%}

%token BEG

%%
beg: BEG {printf("Hello world\n");}
%%

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 代码段上使用这个

\begin{document}
\begin{equation}
    x = 3
\end{equation}
\end{document}

我明白了

Hello world

syntax error

解析器似乎只看到一个 \begin 模式,而不是两个。这是为什么?我真的不明白为什么。提前谢谢你。

编辑:我试过

lines: line
     | lines line
     ;
line: beg '\n'
    | ID '\n'
    ;
beg: BEG {printf("Hello world\n");}
   ;

其中 ID 对应于正则表达式 .*,但我得到相同的错误。

词法分析器:

%{
#include "y.tab.h"
#include <stdio.h>
#include <string.h>
%}

%%
^\begin\{.*\} {return BEG;}
\n {
        return  *yytext;
    }
%%

int yywrap() {
    return 1;
}

解析器:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void yyerror(char *s);
int yylex();
extern FILE *yyin;
%}

%token BEG
%start beg
%%
beg: BEG '\n' {printf("Hello world\n");}
%%

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;
}

上面的代码是我所能记住的,而且我还建议您首先记下您期望的标记类型以及基于您实际想要对这些标记执行的操作的语法。

语法如下:

lines: line
     | lines line
     ;
line: beg '\n'
    | ID '\n'
    ;
beg: BEG {printf("Hello world\n");}
   ;

lines是起始变量,有一组非终结符如lines、line、beg,以及终结符(tokens)ID、BEG、'\n'。尽管此语法没有任何意义,因为它基于您的词法分析器,因为您的词法分析器也应该 return 这些标记。

以下语法意味着您有一个起始标记 beg,您将获得一个标记 BEG 和一个标记 '\n'。您正在打印 'Hello World'。虽然我真的不知道这将如何进行。

beg: BEG '\n'  {printf("Hello world\n");}