rendered paste body%include {
#include <string.h>
#include <math.h>
#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); }