From 719962c1f0f1ee1a6d5b5389417fb68adcde431b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Sun, 3 Jul 2011 18:13:23 +0200 Subject: milestone: added grammar for arithmetic expressions --- grammar/makefile | 7 ++++-- grammar/mini.samp | 2 +- grammar/rscript.l | 26 ++++++++++++-------- grammar/rscript.y | 28 +++++++++++++++++++-- grammar/utils.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- grammar/utils.h | 28 +++++++++++++++++++++ 6 files changed, 146 insertions(+), 18 deletions(-) (limited to 'grammar') diff --git a/grammar/makefile b/grammar/makefile index 29aab217..eb6c9522 100644 --- a/grammar/makefile +++ b/grammar/makefile @@ -1,5 +1,5 @@ rscript: lex.yy.c utils.o rscript.tab.h utils.h - gcc -o rscript lex.yy.c rscript.tab.c utils.o -lestr + gcc -g -o rscript lex.yy.c rscript.tab.c utils.o -lestr lex.yy.c: rscript.l rscript.tab.h flex rscript.l @@ -8,4 +8,7 @@ rscript.tab.h: rscript.y bison -d rscript.y utils.o: utils.c utils.h - gcc -c utils.c + gcc -g -Wall -c utils.c + +clean: + rm *.o diff --git a/grammar/mini.samp b/grammar/mini.samp index 54efacec..6aae758d 100644 --- a/grammar/mini.samp +++ b/grammar/mini.samp @@ -24,7 +24,7 @@ if 1 then { /var/log/log3 @@fwd rger } -if 1/*pri("*.*")*/ then { +if 2*4/5--(10-3)/*pri("*.*")*/ then { action(type="omfile" taget="/var/log/log5") action(type="omfile" taget="/var/log/log6") action(type="omfwd" taget="10.0.0.1" port="514") diff --git a/grammar/rscript.l b/grammar/rscript.l index d6dab45b..f7e51e25 100644 --- a/grammar/rscript.l +++ b/grammar/rscript.l @@ -45,11 +45,16 @@ static int preCommentState; /* keywords */ "if" { BEGIN EXPR; return IF; } "then" { BEGIN INITIAL; return THEN; } -"or" { printf("OR\n"); } -"and" { printf("AND\n"); } -"not" { printf("NOT\n"); } -"(" { printf("LPAREN\n"); } -")" { printf("RPAREN\n"); } +"or" { return OR; } +"and" { return AND; } +"not" { return NOT; } +"*" | +"/" | +"%" | +"+" | +"-" | +"(" | +")" { return yytext[0]; } "==" { printf("==\n"); } "<=" { printf("<=\n"); } ">=" { printf(">=\n"); } @@ -61,11 +66,12 @@ static int preCommentState; "contains_i" { printf("CONTAINS_I\n"); } "startswith" { printf("STARTSWITH\n"); } "startswith_i" { printf("STARTSWITH_I\n"); } --?0[0-7]+ { printf("NUMBER (oct) %s\n", yytext); } --?0x[0-7a-f] { printf("NUMBER (hex) %s\n", yytext); } --?([1-9][0-9]*|0) { printf("NUMBER (dec) %s\n", yytext); return NUMBER; } -\$[$!]{0,1}[a-z][a-z0-9\-_\.]* { printf("VARNAME: '%s'\n", yytext); } -\'([^'\\]|\\['])*\' { printf("EXPR string: -%s-\n", yytext); } +0[0-7]+ { printf("NUMBER (oct) %s\n", yytext); } +0x[0-7a-f] { printf("NUMBER (hex) %s\n", yytext); } +([1-9][0-9]*|0) { printf("NUMBER (dec) %s\n", yytext); + yylval.n = atoll(yytext); return NUMBER; } +\$[$!]{0,1}[a-z][a-z0-9\-_\.]* { printf("VARNAME: '%s'\n", yytext); return VAR; } +\'([^'\\]|\\['])*\' { printf("EXPR string: -%s-\n", yytext); return STRING; } [ \t\n] . { printf("invalid char in expr: %s\n", yytext); } "&" { return '&'; } diff --git a/grammar/rscript.y b/grammar/rscript.y index 7e9365c5..3b680990 100644 --- a/grammar/rscript.y +++ b/grammar/rscript.y @@ -8,11 +8,13 @@ %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 @@ -26,7 +28,12 @@ %token PROPFILT %token IF %token THEN -%token NUMBER +%token OR +%token AND +%token NOT +%token VAR +%token STRING +%token NUMBER %type nv nvlst %type obj @@ -34,6 +41,12 @@ %type act %type cfsysline %type block +%type expr + +%left AND OR +%left '+' '-' +%left '*' '/' '%' +%nonassoc UMINUS NOT %expect 3 /* two shift/reduce conflicts are created by the CFSYSLINE construct, which we @@ -72,7 +85,7 @@ rule: PRIFILT actlst { printf("PRIFILT: %s\n", $1); free($1); | PROPFILT actlst | scriptfilt -scriptfilt: IF NUMBER THEN actlst { printf("if filter detected\n"); } +scriptfilt: IF expr THEN actlst { printf("if filter detected, expr:\n"); cnfexprPrint($2,0); } /* 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 @@ -94,6 +107,17 @@ 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 '+' 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) { diff --git a/grammar/utils.c b/grammar/utils.c index 28e1a04a..c26a856c 100644 --- a/grammar/utils.c +++ b/grammar/utils.c @@ -8,11 +8,9 @@ void readConfFile(FILE *fp, es_str_t **str) { - int c; char ln[10240]; int len, i; int start; /* start index of to be submitted text */ - char *fgetsRet; int bContLine = 0; *str = es_newStr(4096); @@ -177,7 +175,7 @@ cnfcfsyslinelstReverse(struct cnfcfsyslinelst *lst) struct cnfcfsyslinelst *curr, *prev; if(lst == NULL) - return; + return NULL; prev = lst; lst = lst->next; prev->next = NULL; @@ -231,6 +229,75 @@ cnfactlstPrint(struct cnfactlst *actlst) printf("----------\n"); } +struct cnfexpr* +cnfexprNew(int nodetype, struct cnfexpr *l, struct cnfexpr *r) +{ + struct cnfexpr *expr; + if((expr = malloc(sizeof(struct cnfexpr))) != NULL) { + expr->nodetype = nodetype; + expr->l = l; + expr->r = r; + } + return expr; +} + + +inline static void +doIndent(indent) +{ + int i; + for(i = 0 ; i < indent ; ++i) + printf(" "); +} +void +cnfexprPrint(struct cnfexpr *expr, int indent) +{ + //printf("expr %p, indent %d, type '%c'\n", expr, indent, expr->nodetype); + switch(expr->nodetype) { + case 'N': + doIndent(indent); + printf("%lld\n", ((struct cnfnumval*)expr)->val); + break; + case '+': + case '-': + case '*': + case '/': + case '%': + case 'M': + if(expr->l != NULL) + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("%c\n", (char) expr->nodetype); + cnfexprPrint(expr->r, indent+1); + break; + default: + printf("error: unknown nodetype\n"); + break; + } +} + +struct cnfnumval* +cnfnumvalNew(long long val) +{ + struct cnfnumval *numval; + if((numval = malloc(sizeof(struct cnfnumval))) != NULL) { + numval->nodetype = 'N'; + numval->val = val; + } + return numval; +} + +struct cnfstringval* +cnfstringvalNew(es_str_t *estr) +{ + struct cnfstringval *strval; + if((strval = malloc(sizeof(struct cnfstringval))) != NULL) { + strval->nodetype = 'S'; + strval->estr = estr; + } + return strval; +} + /* debug helper */ void cstrPrint(char *text, es_str_t *estr) diff --git a/grammar/utils.h b/grammar/utils.h index 2a6ba10a..a402d4b2 100644 --- a/grammar/utils.h +++ b/grammar/utils.h @@ -58,6 +58,30 @@ struct cnfactlst { } data; }; +/* the following structures support expressions, and may (very much later + * be the sole foundation for the AST. + */ +struct cnfexpr { + int nodetype; + struct cnfexpr *l; + struct cnfexpr *r; +}; + +struct cnfnumval { + int nodetype; + long long val; +}; + +struct cnfstringval { + int nodetype; + es_str_t *estr; +}; + +/* future extensions +struct x { + int nodetype; +}; +*/ void readConfFile(FILE *fp, es_str_t **str); struct nvlst* nvlstNew(es_str_t *name, es_str_t *value); @@ -71,6 +95,10 @@ void cnfactlstDestruct(struct cnfactlst *actlst); void cnfactlstPrint(struct cnfactlst *actlst); struct cnfactlst* cnfactlstAddSysline(struct cnfactlst* actlst, char *line); struct cnfactlst* cnfactlstReverse(struct cnfactlst *actlst); +struct cnfexpr* cnfexprNew(int nodetype, struct cnfexpr *l, struct cnfexpr *r); +void cnfexprPrint(struct cnfexpr *expr, int indent); +struct cnfnumval* cnfnumvalNew(long long val); +struct cnfstringval* cnfstringvalNew(es_str_t *estr); /* debug helper */ void cstrPrint(char *text, es_str_t *estr); -- cgit