2012-02-23 102 views
0

因此,對於我正在開發的項目,我使用Lex和Yacc來解析FTP配置文件。配置文件看起來像這樣:Lex&Yacc解析器如何輸出值?

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程序中捕獲配置文件和管道?預先感謝任何幫助!

這裏是我的代碼:

%{ 
// 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.. 
} 

和我的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) {} 

回答

1

你一般會有哪些人可以訪問並調用解析器,像鑰匙的鏈接列表之前設置變量/值對:

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

的規則發現這基本上是執行該代碼(在規則中的項目替換$變量,$1對於ID_NAME令牌值,$2=,依此類推)。

功能會是這樣的:

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