yacc解析conf

my.conf

globals {
name XXX;
home XXX;

ok on;

health {
good;
}

}

other {
iqn iqn.2015-10-10.com.name;
}

Makefile

FLEX = flex
YACC = bison
YFLAGS = -d
CC = gcc

BUILT_SOURCES = confl.c confy.c confy.h
CONFIGURE_SOURCE = configure.c configure.h
TEST_SOURCE = test.c

TARGET = test

$(TARGET):lex
$(CC) -o $@ $(TEST_SOURCE) $(BUILT_SOURCES) $(CONFIGURE_SOURCE)

lex:yacc
$(FLEX) -o confl.c confl.l
yacc:
$(YACC) -o confy.c -d confy.y

.PHONY:clean
clean:
-rm -f confl.c confy.c confy.h $(TARGET)

test.c

#include <stdio.h>
#include "configure.h"


int main(int argc, char *argv[])
{
conf_init();
printf("name: %s ", glo_conf.name);
conf_destroy();
return 0;
}

configure.c

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "configure.h"
#include "confy.h"

extern FILE *yyin;

int line = 1;

healthconf_t health_conf;
struct otherconf_t other_conf;
struct gloconf_t glo_conf;

static char config_path[MAXSIZE];


int get_health(const char *health)
{
if (health != NULL) {
strncpy(health_conf.health, health, MAXSIZE);
health_conf.count++;
}
return 0;
}

void yyerror(const char *str)
{
fprintf(stderr, "config: parse %s error at line %d, %s ",
config_path, line, str);

exit(1);
}

int yywrap() {
return 1;
}

extern int yyparse();

int conf_init()
{
int ret;
char cwd[MAXSIZE];
getcwd(cwd, MAXSIZE);

snprintf(config_path, MAXSIZE, "%s/my.conf", cwd);


/* default */
memset(glo_conf.name, 0x0, MAXSIZE);
strcpy(glo_conf.name, "none");
strcpy(other_conf.iqn, "none");
glo_conf.ok = 1;

memset(health_conf.health, 0x0, MAXSIZE);
strcpy(health_conf.health, "none");
health_conf.count = 0;

yyin = fopen(config_path, "r");
if (yyin == NULL) {
ret = errno;
fprintf(stderr, "open %s fail, ret %u ", config_path, ret);
goto err_ret;
}


yyparse();

return 0;
err_ret:
return ret;
}


int conf_destroy(void)
{
fclose(yyin);

return 0;
}

LLU str2val(const char *str)
{
LLU val;
val = atoll(str);
return val;
}


int keyis(const char *src, const char *dst)
{
int dstlen;

dstlen = strlen(dst);

if (strncmp(src, dst, dstlen) == 0)
return 1;
else
return 0;
}

int set_value(const char* key, const char* value, int type)
{
int vallen;
LLU _value;

vallen = strlen(value);

if (type == V_NUMBER)
_value = str2val(value);
else if (type == V_STATE) {
if (strncasecmp("on", value, vallen) == 0)
_value = 1;
else
_value = 0;
}

/**
* other configure
*/
else if (keyis("iqn", key))
strncpy(other_conf.iqn, value, MAXSIZE);
else if (keyis("health", key)) {
strncpy(health_conf.health, value, MAXSIZE);
health_conf.count++;
}

/**
* global configure
*/
else if (keyis("name", key))
strncpy(glo_conf.name, value, MAXSIZE);
else if (keyis("home", key))
strncpy(glo_conf.home, value, MAXSIZE);
else if (keyis("ok", key))
glo_conf.ok = _value;

/**
* error.
*/
else {
fprintf(stderr, "%s:%s no such key_value ", key, value);
}

return 0;
}

configure.h

#ifndef __CONFIGURE_H__
#define __CONFIGURE_H__

#include <stdint.h>
#define MAXSIZE 256
typedef unsigned long long LLU;

enum value_type {
V_STATE,
V_NUMBER,
V_STRING,
};


typedef struct {
int count;
char health[MAXSIZE];
}healthconf_t;

/* other configure */
struct otherconf_t
{
char iqn[MAXSIZE];
};

/* global configure */
struct gloconf_t
{
char name[MAXSIZE];
char home[MAXSIZE];
int ok;
};

extern int conf_init(void);
extern int conf_destroy(void);

extern healthconf_t health_conf;
extern struct otherconf_t other_conf;
extern struct gloconf_t glo_conf;

#endif

confl.l

%{
#include <stdio.h>
#include "configure.h"
#include "confy.h"

extern int line;
%}

%%
"globals" { return GLOBALS; }
"other" { return OTHER; }

"health" {
yylval.string = strdup(yytext);
return HEALTH;
}

"on" {
yylval.string = strdup(yytext);
return STATE;
}

"of" {
yylval.string = strdup(yytext);
return STATE;
}

[0-9]+ {
yylval.string = strdup(yytext);
return NUMBER;
}

[a-zA-Z0-9_]{0,512} {
yylval.string = strdup(yytext);
return WORD;
}

iqn.[0-9]{4}-[0-9]{2}(-[0-9]{1,4})?.com.[a-zA-Z0-9_]+ {
yylval.string = strdup(yytext);
return IQN;
}

[()] { return *yytext; }
{ { return OBRACE; }
} { return EBRACE; }
{ line++; }
; { return SEMICOLON; }
[ ]+ /** ignore whitespace */
#[^ ]* /** ignore comment */
. {
fprintf(stderr, "unkonw char %c ", *yytext);
return 0;
}

%%

confy.y

%{
#include <stdio.h>
#include "configure.h"

extern int yylex(void);
extern void yyerror(char *s);
extern int get_health(const char *health);
extern int set_value(const char* key, const char* value, int type);
%}

%defines

%union {
double value;
char *string;
}

%token OTHER GLOBALS SEMICOLON OBRACE EBRACE
%token <string> HEALTH
%token <string> WORD
%token <string> STATE
%token <string> NUMBER
%token <string> IQN

%start conf

%%

conf: subapps
;
subapps: subapp
| subapps subapp
;

subapp: app app_subsets
;

app: OTHER
| GLOBALS
;

app_subsets: OBRACE local_values sub_values EBRACE
;

local_values:
| local_values local_value
;

local_value: key_value SEMICOLON
;

sub_values:
| sub_value sub_values
;

// sub
sub_value: healths_value
;

healths_value: HEALTH OBRACE healths_lines EBRACE
;

healths_lines: healths_line
| healths_lines healths_line
;

healths_line: WORD SEMICOLON {
get_health($1);
free($1);
}
;

key_value: WORD NUMBER {
set_value($1, $2, V_NUMBER);
free($1);
free($2);
}
;

key_value: WORD WORD {
set_value($1, $2, V_STRING);
free($1);
free($2);
}
;

key_value: WORD STATE {
set_value($1, $2, V_STATE);
free($1);
free($2);
}
;
key_value: WORD IQN {
set_value($1, $2, V_STRING);
free($1);
free($2);
}
;
%%

原文地址:https://www.cnblogs.com/banwhui/p/4867775.html