enum ops {
OP_INVALID,
+ OP_IMPLICIT,
/* Unary operations */
OP_HTON,
OP_NTOH,
struct {
/* EXPR_SYMBOL */
const struct datatype *sym_type;
+ const struct scope *scope;
const char *identifier;
};
struct {
static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr)
{
struct error_record *erec;
+ struct symbol *sym;
struct expr *new;
(*expr)->sym_type = ctx->ectx.dtype;
- erec = symbol_parse(*expr, &new);
- if (erec != NULL) {
- erec_queue(erec, ctx->msgs);
- return -1;
+
+ if ((*expr)->scope != NULL) {
+ sym = symbol_lookup((*expr)->scope, (*expr)->identifier);
+ if (sym == NULL)
+ return expr_error(ctx, *expr,
+ "undefined identifier '%s'",
+ (*expr)->identifier);
+ // FIXME: need to copy (on write)
+ new = expr_get(sym->expr);
+ } else {
+ erec = symbol_parse(*expr, &new);
+ if (erec != NULL) {
+ erec_queue(erec, ctx->msgs);
+ return -1;
+ }
}
expr_free(*expr);
"constant value",
expr_op_symbols[rel->op]);
+ if (rel->op == OP_IMPLICIT) {
+ switch (right->ops->type) {
+ case EXPR_RANGE:
+ rel->op = OP_RANGE;
+ break;
+ case EXPR_SET:
+ rel->op = OP_LOOKUP;
+ break;
+ case EXPR_LIST:
+ rel->op = OP_FLAGCMP;
+ break;
+ default:
+ rel->op = OP_EQ;
+ break;
+ }
+ }
+
switch (rel->op) {
case OP_LOOKUP:
/* Data for range lookups needs to be in big endian order */
static void symbol_expr_print(const struct expr *expr)
{
- printf("%s", expr->identifier);
+ printf("%s%s", expr->scope != NULL ? "$" : "", expr->identifier);
}
static void symbol_expr_destroy(struct expr *expr)
%token SET "set"
%token INCLUDE "include"
+%token DEFINE "define"
%token HOOK "hook"
%token <val> HOOKNUM "hooknum"
%type <expr> set_expr set_list_expr set_list_member_expr
%destructor { expr_free($$); } set_expr set_list_expr set_list_member_expr
-%type <expr> expr
-%destructor { expr_free($$); } expr
+%type <expr> expr initializer_expr
+%destructor { expr_free($$); } expr initializer_expr
%type <expr> match_expr
%destructor { expr_free($$); } match_expr
}
xfree($2);
}
+ | DEFINE identifier '=' initializer_expr stmt_seperator
+ {
+ symbol_bind(current_scope(state), $2, $4);
+ xfree($2);
+ }
;
line : common_block { $$ = NULL; }
$$ = symbol_expr_alloc(&@$, $1);
xfree($1);
}
+ | '$' identifier
+ {
+ $$ = symbol_expr_alloc(&@$, $2);
+ $$->scope = current_scope(state);
+ xfree($2);
+ }
;
integer_expr : NUM
| multiton_expr
;
+initializer_expr : expr
+ | set_expr
+ | list_expr
+ ;
+
match_expr : relational_expr
| membership_expr
;
relational_expr : expr /* implicit */ expr
{
- enum ops op;
-
- /* RHS determines operation */
- op = ($2->ops->type == EXPR_RANGE) ? OP_RANGE : OP_EQ;
- $$ = relational_expr_alloc(&@$, op, $1, $2);
+ $$ = relational_expr_alloc(&@$, OP_IMPLICIT, $1, $2);
}
| expr /* implicit */ list_expr
{
"-" { return DASH; }
"*" { return ASTERISK; }
"@" { return AT; }
+"$" { return '$'; }
+"=" { return '='; }
"=>" { return ARROW; }
"map" { return MAP; }
"vmap" { return VMAP; }
"NF_INET_POST_ROUTING" { yylval->val = NF_INET_POST_ROUTING; return HOOKNUM; }
"include" { return INCLUDE; }
+"define" { return DEFINE; }
"describe" { return DESCRIBE; }