Flex/Bison Markdown 到 HTML 程序

Flex/Bison Markdown to HTML Program

这是家庭作业。我自己编辑的唯一代码是定义、规则和标记。到目前为止,我已经成功编译,但是当我尝试在降价文件 (.md) 上 运行 时出现分段错误,因此 HTML 输出只是一个空白文件。

%{
#define YYSTYPE char *
#include <string.h>
#include "miniMD2html.tab.h"
extern YYSTYPE yylval;
%}
%option yylineno

/* Flex definitions */
whitespace [ \t]+
newline [\n]+|{whitespace}[\n]+
textword [a-zA-Z:/.\-,\']+
integer [0-9]+
header #|##|###|####|#####

%%
{header} { return T_HEADER; }
{integer} { return T_INTEGER; }
{textword} { return T_TEXTWORD; }
{whitespace} { return T_BLANK; }
{newline} { return T_NEWLINE; }
%%

生成函数在另一个文件中给出。大部分只接受char*,generate_header函数接受一个int和char*,generate_image函数接受两个char*和两个int。语法可能看起来很奇怪,但这是作业中给出的内容。

%{
#include "global.h"
#include "stdlib.h"
#include "stdio.h"
#define YYSTYPE char *
extern int yylex();
int yywrap();
int yyerror(const char*);
int yyparse();
extern FILE *yyin;
Html_Doc *html_doc;
%}

/* Define tokens here */
%token T_BLANK T_NEWLINE
%token T_HEADER T_INTEGER T_TEXTWORD

%% /* Grammar rules and actions follow */
s: mddoc;
mddoc: /*empty*/ | mddoc paragraph;
paragraph: T_NEWLINE {add_linebreak(html_doc);} 
        | pcontent T_NEWLINE {add_element(html_doc, ); free();} ;
pcontent: header
        | rftext {generate_paragraph();}
header: T_HEADER T_BLANK rftext {generate_header(strlen(), );}
rftext: rftext T_BLANK rftextword {strappend(, );}
        | rftext rftextword {strappend(, );}
        | rftextword
rftextword: textnum | image | format
image: "![" text "](" text '=' T_INTEGER '@' T_INTEGER ')' {generate_image(, , atoi(), atoi());}
format: "**" text "**" {generate_bold();}
        | '_' text '_' {generate_italic();}
        | "**" format "**" {generate_bold();}
        | '_' format '_' {generate_italic();}
text: text T_BLANK textnum {strappend(, );}
        | text textnum {strappend(, );}
        | textnum
textnum: T_TEXTWORD | T_INTEGER
%%

int main(int argc, char *argv[]) {
    // yydebug = 1;

    FILE *fconfig = fopen(argv[1], "r");
    // make sure it is valid
    if (!fconfig) {
        printf("Error reading file!\n");
        return -1;
    }
    html_doc = new_html_doc();
    // set lex to read from file
    yyin = fconfig;
    int ret = yyparse();
    output_result(html_doc);
    del_html_doc(html_doc);
    return ret;
}

int yywrap(){
    return 1;
}

int yyerror(const char* s){
    extern int yylineno;
    extern char *yytext;
    printf("error while parsing line %d: %s at '%s', ASCII code: %d\n", yylineno, s, yytext, (int)(*yytext));
    return 1;
}

None 的 flex 规则曾经设置 yylval 的值,因此它将始终为 NULL。语法中对语义值 ($n) 的所有引用也是如此。由于大多数采用 char* 的函数都假定它是一个有效的字符串,因此很可能其中一个函数很快就会尝试检查字符串值,而指针为 NULL 的事实肯定会导致段错误。

此外,您的语法中同时包含单个字符和带引号的字符串标记,none 可以由您的扫描器生成。因此,一旦在输入中遇到其中一个非单词字符,解析器很可能会因语法错误而停止。

在 bison 文件中,每个标记应由 ;

分隔
s: mddoc;
mddoc: /*empty*/ | mddoc paragraph;
paragraph: ...

注意

;

在 mmdoc 段落之后。

这是正确的,但以下标记没有很好地分开。

另外,正如@Rockcat所说,在flex文件中,你应该添加

yylval = strdup(yytext);

在将您的令牌返回到 bison 文件之前。