yacc如何生成.y文件来恢复.c文件?

时间:2013-11-27 02:09:48

标签: c parsing compiler-construction yacc

我最近下载了一个名为re1(Goggle)的开源项目,因为我目前的研究课题是关于与nfa和dfa匹配的正则表达式。 re1是一个非常非常简单的小项目,但有一个parse.y文件,但我从未见过。谷歌之后,我知道它是由yacc(又一个编译器编译器)生成的。还有一个makefile,所以我可以在Linux中运行它,但现在我想在Visual Studio(Windows)中运行它,因为我需要逐步调试(F5,F10,F11等非常有用)。但是现在它无法在VS中构建,因为VS无法识别它的.y文件,有很多“错误LNK2019:未解析的外部符号”。 我不知道如何解决它,我可以将其转换或恢复为.c文件吗?怎么做?

以下是parse.y的一部分:

%{
#include "regexp.h"

static int yylex(void);
static void yyerror(char*);
static Regexp *parsed_regexp;
static int nparen;

%}

%union {
    Regexp *re;
    int c;
    int nparen;
}

%token  <c> CHAR EOL
%type   <re>    alt concat repeat single line
%type   <nparen> count

%%

line: alt EOL
    {
        parsed_regexp = $1;
        return 1;
    }

alt:
    concat
|   alt '|' concat
    {
        $$ = reg(Alt, $1, $3);
    }
;

concat:
    repeat
|   concat repeat
    {
        $$ = reg(Cat, $1, $2);
    }
;

repeat:
    single
|   single '*'
    {
        $$ = reg(Star, $1, nil);
    }
|   single '*' '?'
    {
        $$ = reg(Star, $1, nil);
        $$->n = 1;
    }
|   single '+'
    {
        $$ = reg(Plus, $1, nil);
    }
|   single '+' '?'
    {
        $$ = reg(Plus, $1, nil);
        $$->n = 1;
    }
|   single '?'
    {
        $$ = reg(Quest, $1, nil);
    }
|   single '?' '?'
    {
        $$ = reg(Quest, $1, nil);
        $$->n = 1;
    }
;

count:
    {
        $$ = ++nparen;
    }
;

single:
    '(' count alt ')'
    {
        $$ = reg(Paren, $3, nil);
        $$->n = $2;
    }
|   '(' '?' ':' alt ')'
    {
        $$ = $4;
    }
|   CHAR
    {
        $$ = reg(Lit, nil, nil);
        $$->ch = $1;
    }
|   '.'
    {
        $$ = reg(Dot, nil, nil);
    }
;

%%

static char *input;
static Regexp *parsed_regexp;
static int nparen;
int gen;

static int
yylex(void)
{
    int c;

    if(input == NULL || *input == 0)
        return EOL;
    c = *input++;
    if(strchr("|*+?():.", c))
        return c;
    yylval.c = c;
    return CHAR;
}

void
fatal(char *fmt, ...)
{
    va_list arg;

    va_start(arg, fmt);
    fprintf(stderr, "fatal error: ");
    vfprintf(stderr, fmt, arg);
    fprintf(stderr, "\n");
    va_end(arg);
    exit(2);
}

static void
yyerror(char *s)
{
    fatal("%s", s);
}


Regexp*
parse(char *s)
{
    Regexp *r, *dotstar;

    input = s;
    parsed_regexp = nil;
    nparen = 0;
    if(yyparse() != 1)
        yyerror("did not parse");
    if(parsed_regexp == nil)
        yyerror("parser nil");

    r = reg(Paren, parsed_regexp, nil); // $0 parens
    dotstar = reg(Star, reg(Dot, nil, nil), nil);
    dotstar->n = 1; // non-greedy
    return reg(Cat, dotstar, r);
}

我尝试删除这些符号,如%,token和type,但我不知道如何解析规则(%%),当然它不起作用,我怎么能在VS中做,VS支持yacc ?

2 个答案:

答案 0 :(得分:0)

而不是 Yacc ,寻找 Bison ,这是旧Yacc程序的GNU免费实现。 Yacc / Bison不会生成 parse.y 文件,但它是输入文件。

某些Unix和类Unix系统,例如某些Linux发行版,已经安装了Bison。在Windows上,您必须单独下载并安装它们。您可以下载然后安装Bison for Windows

然后使用.y文件作为输入运行Bison。它会生成一个C文件,然后您可以在Visual Studio中进行编译。

答案 1 :(得分:0)

有两种工具可以携手并进。

Flex和Bison,GNU团队“Lex和Yacc”。

有一本名为“Flex and Bison”的好书和另一本名为“Lex and Yacc”的书,他们真的值得一读,你可以用二手拿起它们几便士。

Flex和Bison是我所知道的两件最不被重视的事情。不断重新实施。

了解已经发生的工作非常重要。不要尝试阅读Flex的输出,这是程序创建的优化结果,不供人类消费!相反,当你知道它的作用时,请阅读Flex的源代码。

GPL许可授予您阅读其源代码的权利。享受它:))

BTW Unix的东西,unix哲学,告诉我们编写为我们编写其他程序的程序,用人类可读的文本进行交谈,只做一份工作和一份工作,但做得很好。

Flex和Bison是这方面的主要例子。

另一个着名的雷蒙德引述:“为未来做好准备,因为它会比你想象的更早到来”,两者仍然在这里,仍然非常好。