diff options
-rw-r--r-- | filter/config.Y | 99 |
1 files changed, 63 insertions, 36 deletions
diff --git a/filter/config.Y b/filter/config.Y index 379494ba..910ac100 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -19,8 +19,27 @@ static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } -#define f_generate_complex(fi_code, da, arg) \ - f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da) +static struct f_method_scope { + struct f_inst *object; +} f_method_scope_stack[32]; +static int f_method_scope_pos = -1; + +#define FM (f_method_scope_stack[f_method_scope_pos]) + +static inline void f_push_method_scope(struct f_inst *object) +{ + if (++f_method_scope_pos >= (int) ARRAY_SIZE(f_method_scope_stack)) + cf_error("Too many nested method calls"); + FM = (struct f_method_scope) { + .object = object, + }; +} + +static inline void f_pop_method_scope(void) +{ + ASSERT_DIE(f_method_scope_pos >= 0); + f_method_scope_pos--; +} static int f_new_var(struct sym_scope *s) @@ -469,7 +488,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %nonassoc ELSE %type <xp> cmds_int cmd_prep -%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail +%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail method_cmd method_term %type <fda> dynamic_attr %type <fsa> static_attr %type <f> filter where_filter @@ -956,6 +975,35 @@ static_attr: | ONLINK { $$ = f_new_static_attr(T_BOOL, SA_ONLINK, 0); } ; +method_term: + IS_V4 { $$ = f_new_inst(FI_IS_V4, FM.object); } + | TYPE { $$ = f_new_inst(FI_TYPE, FM.object); } + | IP { $$ = f_new_inst(FI_IP, FM.object); } + | RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, FM.object); } + | LEN { $$ = f_new_inst(FI_LENGTH, FM.object); } + | MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, FM.object); } + | ASN { $$ = f_new_inst(FI_ASN, FM.object); } + | SRC { $$ = f_new_inst(FI_NET_SRC, FM.object); } + | DST { $$ = f_new_inst(FI_NET_DST, FM.object); } + | MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, FM.object, $3); } + | FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, FM.object); } + | LAST { $$ = f_new_inst(FI_AS_PATH_LAST, FM.object); } + | LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, FM.object); } + | DATA { $$ = f_new_inst(FI_PAIR_DATA, FM.object); } + | DATA1 { $$ = f_new_inst(FI_LC_DATA1, FM.object); } + | DATA2 { $$ = f_new_inst(FI_LC_DATA2, FM.object); } + | MIN { $$ = f_new_inst(FI_MIN, FM.object); } + | MAX { $$ = f_new_inst(FI_MAX, FM.object); } + ; + +method_cmd: + EMPTY { $$ = f_const_empty(FM.object->i_FI_EA_GET.da); } + | PREPEND '(' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, FM.object, $3 ); } + | ADD '(' term ')' { $$ = f_new_inst(FI_CLIST_ADD, FM.object, $3 ); } + | DELETE '(' term ')' { $$ = f_new_inst(FI_CLIST_DEL, FM.object, $3 ); } + | FILTER '(' term ')' { $$ = f_new_inst(FI_CLIST_FILTER, FM.object, $3 ); } + ; + term: '(' term ')' { $$ = $2; } | term '+' term { $$ = f_new_inst(FI_ADD, $1, $3); } @@ -983,32 +1031,12 @@ term: | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); } - | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); } - | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); } - | term '.' IP { $$ = f_new_inst(FI_IP, $1); } - | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); } - | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); } - | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); } - | term '.' ASN { $$ = f_new_inst(FI_ASN, $1); } - | term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); } - | term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); } - | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); } - | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); } - | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); } - | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); } - | term '.' DATA { $$ = f_new_inst(FI_PAIR_DATA, $1); } - | term '.' DATA1 { $$ = f_new_inst(FI_LC_DATA1, $1); } - | term '.' DATA2 { $$ = f_new_inst(FI_LC_DATA2, $1); } - | term '.' MIN { $$ = f_new_inst(FI_MIN, $1); } - | term '.' MAX { $$ = f_new_inst(FI_MAX, $1); } - -/* Communities */ -/* This causes one shift/reduce conflict - | dynamic_attr '.' ADD '(' term ')' { } - | dynamic_attr '.' DELETE '(' term ')' { } - | dynamic_attr '.' CONTAINS '(' term ')' { } - | dynamic_attr '.' RESET{ } -*/ + | term '.' { + f_push_method_scope($1); + } method_term { + f_pop_method_scope(); + $$ = $4; + } | EMPTY { $$ = f_const_empty_list; } | '+' EMPTY '+' { $$ = f_const_empty_path; } @@ -1026,8 +1054,6 @@ term: | FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT, $3); } -/* | term '.' LEN { $$->code = P('P','l'); } */ - | term_bs | function_call ; @@ -1140,11 +1166,12 @@ cmd: $$ = f_new_inst(FI_SWITCH, $2, $4); } - | dynamic_attr '.' EMPTY ';' { $$ = f_new_inst(FI_EA_SET, f_const_empty($1), $1); } - | dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, $1, $5 ); } - | dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD, $1, $5 ); } - | dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_DEL, $1, $5 ); } - | dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_FILTER, $1, $5 ); } + | dynamic_attr '.' { + f_push_method_scope(f_new_inst(FI_EA_GET, $1)); + } method_cmd ';' { + f_pop_method_scope(); + $$ = f_new_inst(FI_EA_SET, $4, $1); + } | BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); } | BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); } ; |