%{ #include #include #include "utils.h" #define YYDEBUG 1 %} %union { char *s; long long n; es_str_t *estr; enum cnfobjType objType; struct cnfobj *obj; struct nvlst *nvlst; struct cnfactlst *actlst; struct cnfexpr *expr; } %token NAME %token VALUE %token BEGINOBJ %token ENDOBJ %token CFSYSLINE %token BEGIN_ACTION %token LEGACY_ACTION %token PRIFILT %token PROPFILT %token IF %token THEN %token OR %token AND %token NOT %token VAR %token STRING %token NUMBER %token CMP_EQ %token CMP_NE %token CMP_LE %token CMP_GE %token CMP_LT %token CMP_GT %type nv nvlst %type obj %type actlst %type act %type cfsysline %type block %type expr %left AND OR %left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT %left '+' '-' %left '*' '/' '%' %nonassoc UMINUS NOT %expect 3 /* these shift/reduce conflicts are created by the CFSYSLINE construct, which we * unfortunately can not avoid. The problem is that CFSYSLINE can occur both in * global context as well as within an action. It's not permitted somewhere else, * but this is suficient for conflicts. The "dangling else" built-in resolution * works well to solve this issue, so we accept it (it's a wonder that our * old style grammar doesn't work at all, so we better do not complain...). * Use "bison -v rscript.y" if more conflicts arise and check rscript.out for * were exactly these conflicts exits. */ %% conf: /* empty (to end recursion) */ | obj conf | cfsysline conf | rule conf obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); cnfobjPrint($$); cnfobjDestruct($$); } | BEGIN_ACTION nvlst ENDOBJ { struct cnfobj *t = cnfobjNew(CNFOBJ_ACTION, $2); cnfobjPrint(t); cnfobjDestruct(t); printf("XXXX: this is an new-style action!\n"); } cfsysline: CFSYSLINE { printf("XXXX: processing CFSYSLINE: %s\n", $1); } nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); } rule: PRIFILT actlst { printf("PRIFILT: %s\n", $1); free($1); $2 = cnfactlstReverse($2); cnfactlstPrint($2); } | PROPFILT actlst | scriptfilt scriptfilt: IF expr THEN actlst { printf("if filter detected, expr:\n"); cnfexprPrint($2,0); struct exprret r; cnfexprEval($2, &r); printf("eval result: %lld\n", r.d.n); } /* note: we can do some limited block-structuring with the v6 engine. In that case, * we must not support additonal filters inside the blocks, so they must consist of * "act", only. We can implement that via the "&" actlist logic. */ block: actlst | block actlst /* v7: | actlst v7: | block rule */ actlst: act { printf("action (end actlst)\n");$$=$1; } | actlst '&' act { printf("in actionlist \n"); $3->next = $1; $$ = $3; } | actlst cfsysline { printf("in actionlist/CFSYSLINE: %s\n", $2); $$ = cnfactlstAddSysline($1, $2); } | '{' block '}' { $$ = $2; } act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfactlstNew(CNFACT_V2, $2, NULL); } | LEGACY_ACTION { printf("legacy action: '%s'\n", $1); $$ = cnfactlstNew(CNFACT_LEGACY, NULL, $1); } expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); } | expr OR expr { $$ = cnfexprNew(OR, $1, $3); } | NOT expr { $$ = cnfexprNew(NOT, NULL, $2); } | expr CMP_EQ expr { $$ = cnfexprNew(CMP_EQ, $1, $3); } | expr CMP_NE expr { $$ = cnfexprNew(CMP_NE, $1, $3); } | expr CMP_LE expr { $$ = cnfexprNew(CMP_LE, $1, $3); } | expr CMP_GE expr { $$ = cnfexprNew(CMP_GE, $1, $3); } | expr CMP_LT expr { $$ = cnfexprNew(CMP_LT, $1, $3); } | expr CMP_GT expr { $$ = cnfexprNew(CMP_GT, $1, $3); } | expr '+' expr { $$ = cnfexprNew('+', $1, $3); } | expr '-' expr { $$ = cnfexprNew('-', $1, $3); } | expr '*' expr { $$ = cnfexprNew('*', $1, $3); } | expr '/' expr { $$ = cnfexprNew('/', $1, $3); } | expr '%' expr { $$ = cnfexprNew('%', $1, $3); } | '(' expr ')' { $$ = $2; printf("( expr)\n"); } | '-' expr %prec UMINUS { printf("uminus\n"); $$ = cnfexprNew('M', NULL, $2); } | NUMBER { $$ = cnfnumvalNew($1); } | STRING { $$ = cnfstringvalNew($1); } | VAR { printf("variables not yet implemented!\n"); } %% int yyerror(char *s) { printf("yyerror called: %s\n", s); } int main() { yydebug = 0; return yyparse(); }