%include { #include #include #include "cparse_flex_lemon.h" #include "cparse.h" static struct configValue value; yystype lemon_lval; } %token_prefix TOKEN_ %token_type {yystype} %type expr {yystype} %type NUMBER {yystype} %type STRING {yystype} %type SYMBOL {yystype} %left PLUS MINUS. %left DIVIDE MULTIPLY. %left EXCL. %left YES NO. %nonassoc INCLUDE EQUALS EOL. %fallback SYMBOL INTEGER. %syntax_error { printf("Syntax error.\n"); } %destructor STRING { printf("should destruct string: %s\n", %%.str_val); } /* The entire input should consist of one parameter list */ input ::= param_list. /* Parameter list can include assignments and includes */ param_list ::= param_list assignment. param_list ::= param_list include. param_list ::= error EOL. param_list ::= . assignment ::= SYMBOL(SYM) EQUALS value EOL. { value.param = SYM.str_val; setConfig(&value); } assignment ::= boolean SYMBOL(SYM) EOL. { value.param = SYM.str_val; value.type = CONFIG_BOOLEAN; setConfig(&value); } assignment ::= SYMBOL(SYM) EOL. { setConfigBoolean(SYM.str_val, 1); free(SYM.str_val); } assignment ::= EOL. value ::= string_op(A). { value.value.str_val = A.str_val; value.type = CONFIG_STRING; } value ::= LPAREN INTEGER RPAREN float_op(A). { value.value.int_val = lrint(A.dbl_val); value.type = CONFIG_INTEGER; } value ::= float_op(A). { value.value.dbl_val = A.dbl_val; value.type = CONFIG_FLOAT; } value ::= SYMBOL(A). { value.value.str_val = A.str_val; value.type = CONFIG_SYMBOL; } value ::= EXCL SYMBOL(A). { struct configValue *cfg = getConfig(A.str_val); if(cfg) { switch(cfg->type) { case CONFIG_STRING: case CONFIG_SYMBOL: lemon_error("! doesn't make sense with symbol"); break; case CONFIG_FLOAT: value.value.dbl_val = !cfg->value.dbl_val; break; case CONFIG_INTEGER: value.value.int_val = !cfg->value.int_val; break; case CONFIG_BOOLEAN: value.value.int_val = (cfg->value.int_val ? 0 : 1); break; } value.type = cfg->type; } else { lemon_error("undefined symbol in negation"); } } value ::= boolean. string_op(A) ::= STRING(B). { A.str_val = B.str_val; } string_op(A) ::= SYMBOL(B). { A.str_val = strdup(getConfigString(B.str_val, "")); } string_op(A) ::= string_op(B) PLUS string_op(C). { char *tmp = malloc(strlen(B.str_val) + strlen(C.str_val)); sprintf(tmp, "%s%s", B.str_val, C.str_val); A.str_val = tmp; free(B.str_val); free(C.str_val); } float_op(A) ::= SYMBOL(B). { A.dbl_val = getConfigDouble(B.str_val, 0.0); } float_op(A) ::= float_op(B) PLUS float_op(C). { A.dbl_val = B.dbl_val + C.dbl_val; } float_op(A) ::= float_op(B) MINUS float_op(C). { A.dbl_val = B.dbl_val - C.dbl_val; } float_op(A) ::= float_op(B) MULTIPLY float_op(C). { A.dbl_val = B.dbl_val * C.dbl_val; } float_op(A) ::= float_op(B) DIVIDE float_op(C). { if(C.dbl_val != 0.0) { A.dbl_val = B.dbl_val / C.dbl_val; } else { A.dbl_val = 0.0; lemon_error("divide by zero"); } } float_op(A) ::= MINUS float_op(B). [EXCL] { A.dbl_val = -B.dbl_val; } float_op(A) ::= LPAREN float_op(B) RPAREN. { A.dbl_val = B.dbl_val; } float_op(A) ::= NUMBER(B). { A.dbl_val = B.dbl_val; } boolean(A) ::= YES. { A.int_val = 1; value.type = CONFIG_BOOLEAN; } boolean(A) ::= NO. { A.int_val = 0; value.type = CONFIG_BOOLEAN; } boolean(A) ::= EXCL boolean(B). { A.int_val = !B.int_val; } include ::= INCLUDE string_op(INC) EOL. { printf("should include %s\n", INC.str_val); }