AST_EXP_UNKNOWN = 0,
AST_EXP_STRING,
AST_EXP_CONSTANT,
+ AST_EXP_FLOAT_CONSTANT,
AST_EXP_IDENTIFIER,
AST_EXP_NESTED,
} type;
union {
char *string;
uint64_t constant;
+ double float_constant;
char *identifier;
/*
* child can be nested.
FIELD_REF_STRING,
FIELD_REF_SEQUENCE,
FIELD_REF_S64,
+ FIELD_REF_DOUBLE,
};
struct field_ref {
int64_t v;
} __attribute__((packed));
+struct literal_double {
+ double v;
+} __attribute__((packed));
+
struct literal_string {
char string[0];
} __attribute__((packed));
FILTER_OP_LOAD_FIELD_REF,
FILTER_OP_LOAD_STRING,
FILTER_OP_LOAD_S64,
+ FILTER_OP_LOAD_DOUBLE,
NR_FILTER_OPS,
};
IR_DATA_UNKNOWN = 0,
IR_DATA_STRING,
IR_DATA_NUMERIC, /* numeric and boolean */
+ IR_DATA_FLOAT,
IR_DATA_FIELD_REF,
};
union {
char *string;
int64_t num;
+ double flt;
char *ref;
} u;
};
%option reentrant yylineno noyywrap bison-bridge
%option extra-type="struct filter_parser_ctx *"
/* bison-locations */
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E ([Ee][+-]?{D}+)
+P ([Pp][+-]?{D}+)
+FS (f|F|l|L)
+IS ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U))
+
INTEGER_SUFFIX [ \n\t]*(U|UL|ULL|LU|LLU|Ul|Ull|lU|llU|u|uL|uLL|Lu|LLu|ul|ull|lu|llu)
DIGIT [0-9]
NONDIGIT [a-zA-Z_]
<char_const,string_lit>\n ; /* ignore */
<char_const,string_lit>. setstring(yyextra, yylval, yytext); return CHAR_STRING_TOKEN;
+
+0[xX]{H}+{IS}? setstring(yyextra, yylval, yytext); return HEXADECIMAL_CONSTANT;
+0[0-7]*{IS}? setstring(yyextra, yylval, yytext); return OCTAL_CONSTANT;
+[1-9]{D}*{IS}? setstring(yyextra, yylval, yytext); return DECIMAL_CONSTANT;
+
+{D}+{E}{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+{D}*"."{D}+{E}?{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+{D}+"."{D}*{E}?{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}+{P}{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}*"."{H}+{P}?{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}+"."{H}*{P}?{FS}? setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+
"[" return LSBRAC;
"]" return RSBRAC;
"(" return LPAREN;
"&" return AND_BIN;
"|" return OR_BIN;
"~" return NOT_BIN;
-[1-9]{DIGIT}*{INTEGER_SUFFIX}? setstring(yyextra, yylval, yytext); return DECIMAL_CONSTANT;
-0{OCTALDIGIT}*{INTEGER_SUFFIX}? setstring(yyextra, yylval, yytext); return OCTAL_CONSTANT;
-0[xX]{HEXDIGIT}+{INTEGER_SUFFIX}? setstring(yyextra, yylval, yytext); return HEXADECIMAL_CONSTANT;
{IDENTIFIER} printf_debug("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER;
[ \t\n]+ ; /* ignore */
. return ERROR;
%start translation_unit
%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE
%token ESCSEQ CHAR_STRING_TOKEN
-%token DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT
+%token DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT FLOAT_CONSTANT
%token LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW
%token STAR PLUS MINUS
%token MOD_OP DIV_OP RIGHT_OP LEFT_OP
sscanf(yylval.gs->s, "0x%" PRIx64,
&$$->u.expression.u.constant);
}
+ | FLOAT_CONSTANT
+ {
+ $$ = make_node(parser_ctx, NODE_EXPRESSION);
+ $$->u.expression.type = AST_EXP_FLOAT_CONSTANT;
+ sscanf(yylval.gs->s, "%lg",
+ &$$->u.expression.u.float_constant);
+ }
| STRING_LITERAL_START DQUOTE
{
$$ = make_node(parser_ctx, NODE_EXPRESSION);
free(insn);
return ret;
}
+ case IR_DATA_FLOAT:
+ {
+ struct load_op *insn;
+ uint32_t insn_len = sizeof(struct load_op)
+ + sizeof(struct literal_double);
+
+ insn = calloc(insn_len, 1);
+ if (!insn)
+ return -ENOMEM;
+ insn->op = FILTER_OP_LOAD_DOUBLE;
+ insn->reg = reg_sel(node);
+ if (insn->reg == REG_ERROR)
+ return -EINVAL;
+ *(double *) insn->data = node->u.load.u.flt;
+ ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+ free(insn);
+ return ret;
+ }
case IR_DATA_FIELD_REF:
{
struct load_op *insn;
return op;
}
+static
+struct ir_op *make_op_load_float(double v, enum ir_side side)
+{
+ struct ir_op *op;
+
+ op = calloc(sizeof(struct ir_op), 1);
+ if (!op)
+ return NULL;
+ op->op = IR_OP_LOAD;
+ op->data_type = IR_DATA_FLOAT;
+ op->signedness = IR_SIGN_UNKNOWN;
+ op->side = side;
+ op->u.load.u.flt = v;
+ return op;
+}
+
static
struct ir_op *make_op_load_field_ref(char *string, enum ir_side side)
{
}
if ((left->data_type == IR_DATA_STRING
- && right->data_type == IR_DATA_NUMERIC)
- || (left->data_type == IR_DATA_NUMERIC &&
+ && (right->data_type == IR_DATA_NUMERIC || right->data_type == IR_DATA_FLOAT))
+ || ((left->data_type == IR_DATA_NUMERIC || left->data_type == IR_DATA_FLOAT) &&
right->data_type == IR_DATA_STRING)) {
fprintf(stderr, "[error] binary operation '%s' operand type mismatch\n", op_str);
goto error;
case AST_EXP_CONSTANT:
return make_op_load_numeric(node->u.expression.u.constant,
side);
+ case AST_EXP_FLOAT_CONSTANT:
+ return make_op_load_float(node->u.expression.u.float_constant,
+ side);
case AST_EXP_IDENTIFIER:
if (node->u.expression.pre_op != AST_LINK_UNKNOWN) {
fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
return ret;
}
case AST_EXP_CONSTANT:
+ case AST_EXP_FLOAT_CONSTANT:
case AST_EXP_STRING:
break;
}
fprintf(stream, "<constant value=\"%" PRIu64 "\"/>\n",
node->u.expression.u.constant);
break;
+ case AST_EXP_FLOAT_CONSTANT:
+ print_tabs(stream, indent);
+ fprintf(stream, "<float_constant value=\"%lg\"/>\n",
+ node->u.expression.u.float_constant);
+ break;
case AST_EXP_IDENTIFIER:
print_tabs(stream, indent);
fprintf(stream, "<identifier value=\"%s\"/>\n",