/* Bison file for rsyslog config format v2 (RainerScript). * Please note: this file introduces the new config format, but maintains * backward compatibility. In order to do so, the grammar is not 100% clean, * but IMHO still sufficiently easy both to understand for programmers * maitaining the code as well as users writing the config file. Users are, * of course, encouraged to use new constructs only. But it needs to be noted * that some of the legacy constructs (specifically the in-front-of-action * PRI filter) are very hard to beat in ease of use, at least for simpler * cases. * * Copyright 2011-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ %{ #include "config.h" #include #include #include "rainerscript.h" #include "parserif.h" #define YYDEBUG 1 extern int yylineno; /* keep compile rule clean of errors */ extern int yylex(void); extern int yyerror(char*); %} %union { char *s; long long n; es_str_t *estr; enum cnfobjType objType; struct cnfobj *obj; struct cnfstmt *stmt; struct nvlst *nvlst; struct objlst *objlst; struct cnfexpr *expr; struct cnfarray *arr; struct cnffunc *func; struct cnffparamlst *fparams; } %token NAME %token FUNC %token BEGINOBJ %token ENDOBJ %token BEGIN_ACTION %token BEGIN_PROPERTY %token BEGIN_CONSTANT %token BEGIN_TPL %token BEGIN_RULESET %token STOP %token SET %token UNSET %token CONTINUE %token CALL %token LEGACY_ACTION %token LEGACY_RULESET %token PRIFILT %token PROPFILT %token BSD_TAG_SELECTOR %token BSD_HOST_SELECTOR %token IF %token THEN %token ELSE %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 %token CMP_CONTAINS %token CMP_CONTAINSI %token CMP_STARTSWITH %token CMP_STARTSWITHI %type nv nvlst value %type obj property constant %type propconst %type expr %type stmt s_act actlst block script %type fparams %type array arrayelt %left AND OR %left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT CMP_CONTAINS CMP_CONTAINSI CMP_STARTSWITH CMP_STARTSWITHI %left '+' '-' '&' %left '*' '/' '%' %nonassoc UMINUS NOT %expect 1 /* dangling else */ /* If more erors show up, Use "bison -v grammar.y" if more conflicts arise and * check grammar.output for were exactly these conflicts exits. */ %% /* note: we use left recursion below, because that saves stack space AND * offers the right sequence so that we can submit the top-layer objects * one by one. */ conf: /* empty (to end recursion) */ | conf obj { cnfDoObj($2); } | conf stmt { cnfDoScript($2); } | conf LEGACY_RULESET { cnfDoCfsysline($2); } | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); } | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); } obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); } | BEGIN_TPL nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_TPL, $2); } | BEGIN_TPL nvlst ENDOBJ '{' propconst '}' { $$ = cnfobjNew(CNFOBJ_TPL, $2); $$->subobjs = $5; } | BEGIN_RULESET nvlst ENDOBJ '{' script '}' { $$ = cnfobjNew(CNFOBJ_RULESET, $2); $$->script = $5; } propconst: { $$ = NULL; } | propconst property { $$ = objlstAdd($1, $2); } | propconst constant { $$ = objlstAdd($1, $2); } property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); } constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); } nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } nv: NAME '=' value { $$ = nvlstSetName($3, $1); } value: STRING { $$ = nvlstNewStr($1); } | array { $$ = nvlstNewArray($1); } script: stmt { $$ = $1; } | script stmt { $$ = scriptAddStmt($1, $2); } stmt: actlst { $$ = $1; } | IF expr THEN block { $$ = cnfstmtNew(S_IF); $$->d.s_if.expr = $2; $$->d.s_if.t_then = $4; $$->d.s_if.t_else = NULL; } | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF); $$->d.s_if.expr = $2; $$->d.s_if.t_then = $4; $$->d.s_if.t_else = $6; } | SET VAR '=' expr ';' { $$ = cnfstmtNewSet($2, $4); } | UNSET VAR ';' { $$ = cnfstmtNewUnset($2); } | PRIFILT block { $$ = cnfstmtNewPRIFILT($1, $2); } | PROPFILT block { $$ = cnfstmtNewPROPFILT($1, $2); } block: stmt { $$ = $1; } | '{' script '}' { $$ = $2; } actlst: s_act { $$ = $1; } | actlst '&' s_act { $$ = scriptAddStmt($1, $3); } /* s_act are actions and action-like statements */ s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); } | LEGACY_ACTION { $$ = cnfstmtNewLegaAct($1); } | STOP { $$ = cnfstmtNew(S_STOP); } | CALL NAME { $$ = cnfstmtNewCall($2); } | CONTINUE { $$ = cnfstmtNewContinue(); } 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 CMP_CONTAINS expr { $$ = cnfexprNew(CMP_CONTAINS, $1, $3); } | expr CMP_CONTAINSI expr { $$ = cnfexprNew(CMP_CONTAINSI, $1, $3); } | expr CMP_STARTSWITH expr { $$ = cnfexprNew(CMP_STARTSWITH, $1, $3); } | expr CMP_STARTSWITHI expr { $$ = cnfexprNew(CMP_STARTSWITHI, $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 '%' expr { $$ = cnfexprNew('%', $1, $3); } | '(' expr ')' { $$ = $2; } | '-' expr %prec UMINUS { $$ = cnfexprNew('M', NULL, $2); } | FUNC '(' ')' { $$ = (struct cnfexpr*) cnffuncNew($1, NULL); } | FUNC '(' fparams ')' { $$ = (struct cnfexpr*) cnffuncNew($1, $3); } | NUMBER { $$ = (struct cnfexpr*) cnfnumvalNew($1); } | STRING { $$ = (struct cnfexpr*) cnfstringvalNew($1); } | VAR { $$ = (struct cnfexpr*) cnfvarNew($1); } | array { $$ = (struct cnfexpr*) $1; } fparams: expr { $$ = cnffparamlstNew($1, NULL); } | expr ',' fparams { $$ = cnffparamlstNew($1, $3); } array: '[' arrayelt ']' { $$ = $2; } arrayelt: STRING { $$ = cnfarrayNew($1); } | arrayelt ',' STRING { $$ = cnfarrayAdd($1, $3); } %% /* int yyerror(char *s) { printf("parse failure on or before line %d: %s\n", yylineno, s); return 0; } */