Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing Lex&;Yacc解析器输出值?_Parsing_Yacc_Lex - Fatal编程技术网

Parsing Lex&;Yacc解析器输出值?

Parsing Lex&;Yacc解析器输出值?,parsing,yacc,lex,Parsing,Yacc,Lex,因此,对于我正在进行的项目,我使用Lex和Yacc解析FTP配置文件。配置文件如下所示: global { num_daemons = 10 etc = /etc/ftpd }; host "ftp-1.foobar.com" { ftproot = /var/ftp/server1 max_out_bandwidth = 20.7 }; host "ftp-2.foobar.com" { ftproot = /var/ftp/server2

因此,对于我正在进行的项目,我使用Lex和Yacc解析FTP配置文件。配置文件如下所示:

global {
    num_daemons = 10
    etc = /etc/ftpd
};

host "ftp-1.foobar.com" {
    ftproot = /var/ftp/server1
    max_out_bandwidth = 20.7
};

host "ftp-2.foobar.com" {
    ftproot = /var/ftp/server2
    exclude = /var/ftp/server2/private
};

host "ftp-3.foobar.com" {
    ftproot = /var/ftp/server3
};
现在,我的问题是,我如何以可用的方式获得这些信息?比方说,我想把地址之类的东西放在主机令牌之后,放进一个结构中。我该怎么做?另外,我如何简单地将解析后的值打印到命令行?另外,要运行它,我是否只需在编译的c程序中对配置文件和管道进行cat?提前感谢您的帮助

这是我的密码:

%{
// tokens.l
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"

int yyparse();

%}

%option noyywrap

%x OPTION
%x OPTID

%%

<INITIAL>global             { return GLOBAL; }
<INITIAL>host               { return HOST; }
<INITIAL>"[a-zA-z1-9./-]+"  { return NAME; }
<INITIAL>\{                 { return CURLY_OPEN; BEGIN OPTION; }
<INITIAL>\n                 { return EOLN; }
<INITIAL><<EOF>>            { return EOFTOK; }


<OPTION>[a-zA-z1-9./-_]+    { return ID_NAME; BEGIN OPTID; }
<OPTION>[\t]                {}
<OPTION>[\};]               { return OPTION_CLOSE; BEGIN INITIAL;}

<OPTID>[a-zA-z1-9./-]+      { return ID_STRING; BEGIN OPTION; }
<OPTID>[0-9.]+              { return ID_NUM; BEGIN OPTION; }
<OPTID>[\n]                 { return EOLN; }

%%

int main(int argc, char **argv) {
    // Where I am confused..
}
%{
//代币
#包括
#包括
#包括“y.tab.h”
int-yyparse();
%}
%选项No yywrap
%x选项
%x选项
%%
全局{返回全局;}
主机{返回主机;}
“[a-zA-z1-9./-]+”{返回名称;}
\{{return CURLY_OPEN;BEGIN选项;}
\n{return EOLN;}
{返回EOFTOK;}
[a-zA-z1-9./-+{return ID_NAME;BEGIN OPTID;}
[\t]{}
[\};]{return OPTION\u CLOSE;BEGIN INITIAL;}
[a-zA-z1-9./-]+{返回ID_字符串;开始选项;}
[0-9.]+{return ID_NUM;BEGIN OPTION;}
[\n]{return EOLN;}
%%
int main(int argc,字符**argv){
//我感到困惑的地方。。
}
和我的yacc文件:

%{
// parse.y
#include <stdio.h>
#include <stdlib.h>

int yyerror(char *);
int yylex(void);

%}

%token ERROR EOLN EOFTOK
%token OPTION_CLOSE GLOBAL HOST NAME ID_NAME ID_STRING ID_NUM CURLY_OPEN

%%

input
    : lines EOFTOK  { YYACCEPT; }
    ;
lines
    :
    | lines line
    ;
line
    : option
    | opident
    | OPTION_CLOSE
    ;
option
    : GLOBAL CURLY_OPEN
    | HOST NAME CURLY_OPEN
    ;
opident
    : ID_NAME '=' ID_STRING
    | ID_NAME '=' ID_NUM
    ;
%%

int yyerror(char *msg) {}
%{
//parse.y
#包括
#包括
int yyerror(字符*);
int yylex(无效);
%}
%令牌错误EOLN EOFTOK
%令牌选项\u关闭全局主机名ID\u名称ID\u字符串ID\u NUM CURLY\u打开
%%
输入
:行EOFTOK{YYACCEPT;}
;
线
:
|线
;
线
:选项
|见解
|选项(u关闭)
;
选项
:全局卷曲打开
|主机名CURLY_OPEN
;
见解
:ID\u NAME'='ID\u字符串
|ID\u NAME'='ID\u NUM
;
%%
int yyerror(char*msg){}

通常,在调用解析器之前,可以访问并设置变量,如键/值对的链接列表:

typedef struct sNode {
    char *key;
    char *val;
    struct sNode *next;
} tNode;
tNode *lookupHead = NULL;
然后,在Yacc代码中,类似于:

opident
    : ID_NAME '=' ID_STRING { addLookupStr (lookupHead, $1, $3); }
    | ID_NAME '=' ID_NUM    { other function call here }
    ;
void addLookupStr (char *newkey, char *newval) {
    // Check for duplicate keys, then attempt to add. All premature returns
    // should also be logging errors and setting error flags as needed.

    tNode *curr = lookupHead;
    while (curr != NULL) {
        if (strcmp (curr->key, newkey) == 0)
            return;
        curr = curr->next;
    }

    if ((curr = malloc (sizeof (tNode))) == NULL)
        return;

    if ((curr->key = strdup (newkey)) == NULL) {
        free (curr);
        return;
    }

    if ((curr->val = strdup (newval)) == NULL) {
        free (curr->newkey);
        free (curr);
        return;
    }

    // All possibly-failing ops complete, insert at head of list.

    curr->next = lookupHead;
    lookupHead = curr;
}
这将基本上在找到规则时执行该代码(用规则中的项替换
$
变量,
$1
ID\u NAME
标记的值,
$2
=
等等)

该函数类似于:

opident
    : ID_NAME '=' ID_STRING { addLookupStr (lookupHead, $1, $3); }
    | ID_NAME '=' ID_NUM    { other function call here }
    ;
void addLookupStr (char *newkey, char *newval) {
    // Check for duplicate keys, then attempt to add. All premature returns
    // should also be logging errors and setting error flags as needed.

    tNode *curr = lookupHead;
    while (curr != NULL) {
        if (strcmp (curr->key, newkey) == 0)
            return;
        curr = curr->next;
    }

    if ((curr = malloc (sizeof (tNode))) == NULL)
        return;

    if ((curr->key = strdup (newkey)) == NULL) {
        free (curr);
        return;
    }

    if ((curr->val = strdup (newval)) == NULL) {
        free (curr->newkey);
        free (curr);
        return;
    }

    // All possibly-failing ops complete, insert at head of list.

    curr->next = lookupHead;
    lookupHead = curr;
}