Avoid being exponential, do not allow ! =
This commit is contained in:
parent
c8518ae136
commit
d4d7562806
3 changed files with 31 additions and 26 deletions
|
@ -8,10 +8,7 @@
|
||||||
FIXME (nonurgent): define keyword
|
FIXME (nonurgent): define keyword
|
||||||
FIXME (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate
|
FIXME (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate
|
||||||
FIXME: create community lists
|
FIXME: create community lists
|
||||||
FIXME: '! =' should not be permitted. Ze `!=' by nemelo byt totez jako `! =' Nadefinujes si pres %token novy token a do cf-lex.l pridas nove pravidlo, ktere jej rozpoznava. Napriklad != return NEQ;
|
|
||||||
FIXME: IP addresses in ipv6
|
FIXME: IP addresses in ipv6
|
||||||
|
|
||||||
FIXME: how can functions return value?
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
@ -42,6 +39,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, UNSET, RETURN,
|
||||||
%nonassoc THEN
|
%nonassoc THEN
|
||||||
%nonassoc ELSE
|
%nonassoc ELSE
|
||||||
|
|
||||||
|
%token GEQ LEQ NEQ
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr function_call
|
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr function_call
|
||||||
%type <f> filter filter_body where_filter
|
%type <f> filter filter_body where_filter
|
||||||
%type <i> type break_command pair
|
%type <i> type break_command pair
|
||||||
|
@ -56,7 +55,7 @@ filter_def:
|
||||||
FILTER SYM { cf_push_scope( $2 ); } filter_body {
|
FILTER SYM { cf_push_scope( $2 ); } filter_body {
|
||||||
cf_define_symbol($2, SYM_FILTER, $4);
|
cf_define_symbol($2, SYM_FILTER, $4);
|
||||||
$4->name = $2->name;
|
$4->name = $2->name;
|
||||||
printf( "We have new filter defined (%s)\n", $2->name );
|
DBG( "We have new filter defined (%s)\n", $2->name );
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -81,7 +80,7 @@ type:
|
||||||
one_decl:
|
one_decl:
|
||||||
type SYM {
|
type SYM {
|
||||||
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
||||||
printf( "New variable %s type %x\n", $2->name, $1 );
|
DBG( "New variable %s type %x\n", $2->name, $1 );
|
||||||
$2->aux = 0;
|
$2->aux = 0;
|
||||||
{
|
{
|
||||||
struct f_val * val;
|
struct f_val * val;
|
||||||
|
@ -109,7 +108,6 @@ declsn: one_decl { $$ = $1; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
filter_body:
|
filter_body:
|
||||||
function_body {
|
function_body {
|
||||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
|
@ -152,7 +150,7 @@ where_filter:
|
||||||
;
|
;
|
||||||
|
|
||||||
function_params:
|
function_params:
|
||||||
'(' declsn ')' { printf( "Have function parameters\n" ); $$=$2; }
|
'(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
|
||||||
| '(' ')' { $$=NULL; }
|
| '(' ')' { $$=NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -164,14 +162,14 @@ function_body:
|
||||||
|
|
||||||
CF_ADDTO(conf, function_def)
|
CF_ADDTO(conf, function_def)
|
||||||
function_def:
|
function_def:
|
||||||
FUNCTION SYM { printf( "Begining of function %s\n", $2->name ); cf_push_scope($2); } function_params function_body {
|
FUNCTION SYM { DBG( "Begining of function %s\n", $2->name ); cf_push_scope($2); } function_params function_body {
|
||||||
extern struct f_inst *startup_func;
|
extern struct f_inst *startup_func;
|
||||||
cf_define_symbol($2, SYM_FUNCTION, $5);
|
cf_define_symbol($2, SYM_FUNCTION, $5);
|
||||||
if (!strcasecmp($2->name, "startup"))
|
if (!strcasecmp($2->name, "startup"))
|
||||||
startup_func = $5;
|
startup_func = $5;
|
||||||
$2->aux = (int) $4;
|
$2->aux = (int) $4;
|
||||||
$2->aux2 = $5;
|
$2->aux2 = $5;
|
||||||
printf("Hmm, we've got one function here - %s\n", $2->name);
|
DBG("Hmm, we've got one function here - %s\n", $2->name);
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -263,7 +261,7 @@ constant:
|
||||||
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = $1; }
|
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = $1; }
|
||||||
| ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
| ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
| prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); }
|
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
|
||||||
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
|
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -283,7 +281,7 @@ function_call:
|
||||||
struct f_inst *inst = $3;
|
struct f_inst *inst = $3;
|
||||||
if ($1->class != SYM_FUNCTION)
|
if ($1->class != SYM_FUNCTION)
|
||||||
cf_error("You can not call something which is not function. Really.");
|
cf_error("You can not call something which is not function. Really.");
|
||||||
printf("You are calling function %s\n", $1->name);
|
DBG("You are calling function %s\n", $1->name);
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = P('c','a');
|
$$->code = P('c','a');
|
||||||
$$->a1.p = inst;
|
$$->a1.p = inst;
|
||||||
|
@ -292,7 +290,7 @@ function_call:
|
||||||
while (sym || inst) {
|
while (sym || inst) {
|
||||||
if (!sym || !inst)
|
if (!sym || !inst)
|
||||||
cf_error("wrong number of arguments for function %s.", $1->name);
|
cf_error("wrong number of arguments for function %s.", $1->name);
|
||||||
printf( "You should pass parameter called %s\n", sym->name);
|
DBG( "You should pass parameter called %s\n", sym->name);
|
||||||
inst->a1.p = sym;
|
inst->a1.p = sym;
|
||||||
sym = (void *) sym->aux;
|
sym = (void *) sym->aux;
|
||||||
inst = inst->next;
|
inst = inst->next;
|
||||||
|
@ -300,17 +298,18 @@ function_call:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* NEQ, LEQ and GEQ are responsible for 42 shift/reduce conflicts */
|
||||||
|
|
||||||
term:
|
term:
|
||||||
'(' term ')' { $$ = $2; }
|
'(' term ')' { $$ = $2; }
|
||||||
| term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
|
| term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '!' '=' term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $4; }
|
| term NEQ term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '<' '=' term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $4; }
|
| term LEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
|
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
|
||||||
| term '>' '=' term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $4; $$->a2.p = $1; }
|
| term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; }
|
||||||
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
|
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
|
||||||
|
|
||||||
| constant { $$ = $1; }
|
| constant { $$ = $1; }
|
||||||
|
@ -404,7 +403,7 @@ cmd:
|
||||||
}
|
}
|
||||||
| SYM '=' term ';' {
|
| SYM '=' term ';' {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
printf( "Ook, we'll set value\n" );
|
DBG( "Ook, we'll set value\n" );
|
||||||
if (($1->class & ~T_MASK) != SYM_VARIABLE)
|
if (($1->class & ~T_MASK) != SYM_VARIABLE)
|
||||||
cf_error( "You may only set variables, and this is %x.\n", $1->class );
|
cf_error( "You may only set variables, and this is %x.\n", $1->class );
|
||||||
$$->code = 's';
|
$$->code = 's';
|
||||||
|
@ -413,7 +412,7 @@ cmd:
|
||||||
}
|
}
|
||||||
| RETURN term ';' {
|
| RETURN term ';' {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
printf( "Ook, we'll return the value\n" );
|
DBG( "Ook, we'll return the value\n" );
|
||||||
$$->code = 'r';
|
$$->code = 'r';
|
||||||
$$->a1.p = $2;
|
$$->a1.p = $2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,14 +446,16 @@ interpret(struct f_inst *what)
|
||||||
int
|
int
|
||||||
i_same(struct f_inst *f1, struct f_inst *f2)
|
i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
{
|
{
|
||||||
if (!f1)
|
|
||||||
return 1;
|
|
||||||
if ((!!f1) != (!!f2))
|
if ((!!f1) != (!!f2))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!f1)
|
||||||
|
return 1;
|
||||||
if (f1->aux != f2->aux)
|
if (f1->aux != f2->aux)
|
||||||
return 0;
|
return 0;
|
||||||
if (f1->code != f2->code)
|
if (f1->code != f2->code)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (f1 == f2) /* It looks strange, but it is possible with call rewriting trickery */
|
||||||
|
return 1;
|
||||||
|
|
||||||
switch(f1->code) {
|
switch(f1->code) {
|
||||||
case ',': /* fall through */
|
case ',': /* fall through */
|
||||||
|
@ -495,8 +497,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
|
|
||||||
case 'r': ONEARG; break;
|
case 'r': ONEARG; break;
|
||||||
case P('c','p'): ONEARG; break;
|
case P('c','p'): ONEARG; break;
|
||||||
case P('c','a'): /* CALL, FIXME: exponential in some cases */
|
case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
|
||||||
ONEARG; if (!i_same(f1->a2.p, f2->a2.p)) return 0; break;
|
ONEARG;
|
||||||
|
if (!i_same(f1->a2.p, f2->a2.p))
|
||||||
|
return 0;
|
||||||
|
f2->a2.p = f1->a2.p;
|
||||||
|
break;
|
||||||
case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
|
case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
|
||||||
case P('i','M'): TWOARGS; break;
|
case P('i','M'): TWOARGS; break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -44,7 +44,7 @@ ip p;
|
||||||
if 1234 = i then printn "."; else { print "*** FAIL: if 1 else"; }
|
if 1234 = i then printn "."; else { print "*** FAIL: if 1 else"; }
|
||||||
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
||||||
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
||||||
print " data types; must be true: " 1.2.3.4 = 1.2.3.4 "," 1 ~ [1,2,3] "," 5 ~ [1..20] "," 2 ~ [ 1, 2, 3 ] "," 5 ~ [ 4 .. 7 ] "," 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ] "," 1.2.3.4 ~ 1.0.0.0/8 "," 1.0.0.0/8 ~ 1.0.0.0/8 "," 1.0.0.0/8 ~ [ 1.0.0.0/8+ ] "," 1.2.0.0/16 ~ [ 1.0.0.0/8{ 15 , 16 } ] "," defined(1) "," defined(1.2.3.4);
|
print " data types; must be true: " 1.2.3.4 = 1.2.3.4 "," 1 ~ [1,2,3] "," 5 ~ [1..20] "," 2 ~ [ 1, 2, 3 ] "," 5 ~ [ 4 .. 7 ] "," 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ] "," 1.2.3.4 ~ 1.0.0.0/8 "," 1.0.0.0/8 ~ 1.0.0.0/8 "," 1.0.0.0/8 ~ [ 1.0.0.0/8+ ] "," 1.2.0.0/16 ~ [ 1.0.0.0/8{ 15 , 16 } ] "," defined(1) "," defined(1.2.3.4) "," 1 != 2 "," 1 <= 2;
|
||||||
print " data types: must be false: " 1 ~ [ 2, 3, 4 ] "," 5 ~ [ 2, 3, 4, 7..11 ] "," 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ] "," (1,2) > (2,2) "," (1,1) > (1,1) "," 1.0.0.0/8 ~ [ 1.0.0.0/8- ] "," 1.2.0.0/17 ~ [ 1.0.0.0/8{ 15 , 16 } ];
|
print " data types: must be false: " 1 ~ [ 2, 3, 4 ] "," 5 ~ [ 2, 3, 4, 7..11 ] "," 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ] "," (1,2) > (2,2) "," (1,1) > (1,1) "," 1.0.0.0/8 ~ [ 1.0.0.0/8- ] "," 1.2.0.0/17 ~ [ 1.0.0.0/8{ 15 , 16 } ];
|
||||||
|
|
||||||
px = 1.2.0.0/18;
|
px = 1.2.0.0/18;
|
||||||
|
|
Loading…
Reference in a new issue