From 2ad4f85286636070e97563a31c0e2950da3ed309 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Fri, 13 Nov 2015 19:33:22 -0500 Subject: [PATCH] bitwise operators --- c/dsls/filter_dsl_lexer.l | 13 +++++++++ c/dsls/filter_dsl_parse.y | 37 ++++++++++++++++++----- c/dsls/put_dsl_lexer.l | 23 ++++++++++++--- c/dsls/put_dsl_parse.y | 58 ++++++++++++++++++++++++++++--------- c/mapping/lrec_evaluators.c | 6 ++++ c/mapping/mlr_val.h | 10 +++++++ c/todo.txt | 16 ++++++++++ 7 files changed, 138 insertions(+), 25 deletions(-) diff --git a/c/dsls/filter_dsl_lexer.l b/c/dsls/filter_dsl_lexer.l index b0f5546d3..2fc8ff9b5 100644 --- a/c/dsls/filter_dsl_lexer.l +++ b/c/dsls/filter_dsl_lexer.l @@ -20,6 +20,19 @@ return FILTER_DSL_AND; } +"|" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return FILTER_DSL_BIT_OR; +} +"^" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return FILTER_DSL_BIT_XOR; +} +"&" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return FILTER_DSL_BIT_AND; +} + "=~" { *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); return FILTER_DSL_MATCHES; diff --git a/c/dsls/filter_dsl_parse.y b/c/dsls/filter_dsl_parse.y index 6023c5543..9c97205fc 100644 --- a/c/dsls/filter_dsl_parse.y +++ b/c/dsls/filter_dsl_parse.y @@ -43,6 +43,7 @@ filter_dsl_body(A) ::= filter_dsl_bool_expr(B). { past->proot = A; } +// ---------------------------------------------------------------- filter_dsl_bool_expr(A) ::= filter_dsl_or_term(B). { A = B; } @@ -50,7 +51,6 @@ filter_dsl_bool_expr(A) ::= filter_dsl_bool_expr(B) FILTER_DSL_OR(O) filter_dsl_ A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } -// ---------------------------------------------------------------- filter_dsl_or_term(A) ::= filter_dsl_and_term(B). { A = B; } @@ -58,20 +58,43 @@ filter_dsl_or_term(A) ::= filter_dsl_or_term(B) FILTER_DSL_AND(O) filter_dsl_and A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } -// ---------------------------------------------------------------- -filter_dsl_and_term(A) ::= filter_dsl_eqne_term(B). { + +filter_dsl_and_term(A) ::= filter_dsl_bit_or_term(B). { A = B; } -filter_dsl_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_MATCHES(O) filter_dsl_eqne_term(C). { +filter_dsl_and_term(A) ::= filter_dsl_and_term(B) FILTER_DSL_BIT_OR(O) filter_dsl_bit_or_term(C). { A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } -filter_dsl_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_DOES_NOT_MATCH(O) filter_dsl_eqne_term(C). { + + +filter_dsl_bit_or_term(A) ::= filter_dsl_bit_xor_term(B). { + A = B; +} +filter_dsl_bit_or_term(A) ::= filter_dsl_bit_or_term(B) FILTER_DSL_BIT_XOR(O) filter_dsl_bit_xor_term(C). { A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } -filter_dsl_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_EQ(O) filter_dsl_eqne_term(C). { + +filter_dsl_bit_xor_term(A) ::= filter_dsl_bit_and_term(B). { + A = B; +} +filter_dsl_bit_xor_term(A) ::= filter_dsl_bit_xor_term(B) FILTER_DSL_BIT_AND(O) filter_dsl_bit_and_term(C). { A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } -filter_dsl_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_NE(O) filter_dsl_eqne_term(C). { + +// ---------------------------------------------------------------- +filter_dsl_bit_and_term(A) ::= filter_dsl_eqne_term(B). { + A = B; +} +filter_dsl_bit_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_MATCHES(O) filter_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +filter_dsl_bit_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_DOES_NOT_MATCH(O) filter_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +filter_dsl_bit_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_EQ(O) filter_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +filter_dsl_bit_and_term(A) ::= filter_dsl_eqne_term(B) FILTER_DSL_NE(O) filter_dsl_eqne_term(C). { A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } diff --git a/c/dsls/put_dsl_lexer.l b/c/dsls/put_dsl_lexer.l index 4827ffbc0..2afbed38b 100644 --- a/c/dsls/put_dsl_lexer.l +++ b/c/dsls/put_dsl_lexer.l @@ -124,14 +124,29 @@ *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); return PUT_DSL_MOD; } -"&&" { - *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); - return PUT_DSL_MOD; -} + "||" { *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); return PUT_DSL_MOD; } +"&&" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return PUT_DSL_MOD; +} + +"|" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return PUT_DSL_BIT_OR; +} +"^" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return PUT_DSL_BIT_XOR; +} +"&" { + *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); + return PUT_DSL_BIT_AND; +} + "==" { *yyextra = mlr_dsl_ast_node_alloc(yytext, MLR_DSL_AST_NODE_TYPE_OPERATOR); return PUT_DSL_MOD; diff --git a/c/dsls/put_dsl_parse.y b/c/dsls/put_dsl_parse.y index 1241211a6..9aab96c11 100644 --- a/c/dsls/put_dsl_parse.y +++ b/c/dsls/put_dsl_parse.y @@ -57,32 +57,62 @@ put_dsl_assignment(A) ::= PUT_DSL_FIELD_NAME(B) PUT_DSL_ASSIGN(O) put_dsl_bool_ sllv_add(pasts, A); } + // ---------------------------------------------------------------- -put_dsl_bool_expr(A) ::= put_dsl_bool_expr(B) FILTER_DSL_OR(O) put_dsl_or_term(C). { - A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); -} put_dsl_bool_expr(A) ::= put_dsl_or_term(B). { A = B; } - -// ---------------------------------------------------------------- -put_dsl_or_term(A) ::= put_dsl_or_term(B) FILTER_DSL_AND(O) put_dsl_and_term(C). { +put_dsl_bool_expr(A) ::= put_dsl_bool_expr(B) PUT_DSL_OR(O) put_dsl_or_term(C). { A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); } + put_dsl_or_term(A) ::= put_dsl_and_term(B). { A = B; } +put_dsl_or_term(A) ::= put_dsl_or_term(B) PUT_DSL_AND(O) put_dsl_and_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} -// ---------------------------------------------------------------- -put_dsl_and_term(A) ::= put_dsl_eqne_term(B) FILTER_DSL_EQ(O) put_dsl_eqne_term(C). { - A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); -} -put_dsl_and_term(A) ::= put_dsl_eqne_term(B) FILTER_DSL_NE(O) put_dsl_eqne_term(C). { - A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); -} -put_dsl_and_term(A) ::= put_dsl_eqne_term(B). { + +put_dsl_and_term(A) ::= put_dsl_bit_or_term(B). { A = B; } +put_dsl_and_term(A) ::= put_dsl_and_term(B) PUT_DSL_BIT_OR(O) put_dsl_bit_or_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} + + +put_dsl_bit_or_term(A) ::= put_dsl_bit_xor_term(B). { + A = B; +} +put_dsl_bit_or_term(A) ::= put_dsl_bit_or_term(B) PUT_DSL_BIT_XOR(O) put_dsl_bit_xor_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} + +put_dsl_bit_xor_term(A) ::= put_dsl_bit_and_term(B). { + A = B; +} +put_dsl_bit_xor_term(A) ::= put_dsl_bit_xor_term(B) PUT_DSL_BIT_AND(O) put_dsl_bit_and_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} + +// ---------------------------------------------------------------- +put_dsl_bit_and_term(A) ::= put_dsl_eqne_term(B). { + A = B; +} +put_dsl_bit_and_term(A) ::= put_dsl_eqne_term(B) PUT_DSL_MATCHES(O) put_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +put_dsl_bit_and_term(A) ::= put_dsl_eqne_term(B) PUT_DSL_DOES_NOT_MATCH(O) put_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +put_dsl_bit_and_term(A) ::= put_dsl_eqne_term(B) PUT_DSL_EQ(O) put_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} +put_dsl_bit_and_term(A) ::= put_dsl_eqne_term(B) PUT_DSL_NE(O) put_dsl_eqne_term(C). { + A = mlr_dsl_ast_node_alloc_binary(O->text, MLR_DSL_AST_NODE_TYPE_OPERATOR, B, C); +} + // ---------------------------------------------------------------- put_dsl_eqne_term(A) ::= put_dsl_expr(B). { diff --git a/c/mapping/lrec_evaluators.c b/c/mapping/lrec_evaluators.c index 09a2c3929..6a1857b05 100644 --- a/c/mapping/lrec_evaluators.c +++ b/c/mapping/lrec_evaluators.c @@ -1078,6 +1078,9 @@ static function_lookup_t FUNCTION_LOOKUP_TABLE[] = { { FUNC_CLASS_MATH, "//", 2 , "Interger division."}, { FUNC_CLASS_MATH, "%", 2 , "Remainder; never negative-valued."}, { FUNC_CLASS_MATH, "**", 2 , "Exponentiation; same as pow."}, + { FUNC_CLASS_MATH, "|", 2 , "Bitwise OR."}, + { FUNC_CLASS_MATH, "^", 2 , "Bitwise XOR."}, + { FUNC_CLASS_MATH, "&", 2 , "Bitwise AND."}, { FUNC_CLASS_BOOLEAN, "=~", 2 , "String (left-hand side) matches regex (right-hand side), e.g. '$name =~ \"^a.*b$\"'."}, { FUNC_CLASS_BOOLEAN, "!=~", 2 , "String (left-hand side) does not match regex (right-hand side), e.g. '$name !=~ \"^a.*b$\"'."}, @@ -1322,6 +1325,9 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_binary_func_name(char* fnnm, } else if (streq(fnnm, "roundm")) { return lrec_evaluator_alloc_from_n_nn_func(n_nn_roundm_func, parg1, parg2); } else if (streq(fnnm, "fmtnum")) { return lrec_evaluator_alloc_from_s_xs_func(s_xs_fmtnum_func, parg1, parg2); } else if (streq(fnnm, "urandint")) { return lrec_evaluator_alloc_from_i_ii_func(i_ii_urandint_func, parg1, parg2); + } else if (streq(fnnm, "|")) { return lrec_evaluator_alloc_from_i_ii_func(i_ii_bitwise_or_func, parg1, parg2); + } else if (streq(fnnm, "^")) { return lrec_evaluator_alloc_from_i_ii_func(i_ii_bitwise_xor_func, parg1, parg2); + } else if (streq(fnnm, "&")) { return lrec_evaluator_alloc_from_i_ii_func(i_ii_bitwise_and_func, parg1, parg2); } else { return NULL; } } diff --git a/c/mapping/mlr_val.h b/c/mapping/mlr_val.h index e0e92d4d6..837a5ab3b 100644 --- a/c/mapping/mlr_val.h +++ b/c/mapping/mlr_val.h @@ -186,6 +186,16 @@ static inline mv_t i_ii_urandint_func(mv_t* pval1, mv_t* pval2) { return (mv_t) {.type = MT_INT, .u.intv = u}; } +static inline mv_t i_ii_bitwise_or_func(mv_t* pval1, mv_t* pval2) { + return (mv_t) {.type = MT_INT, .u.intv = pval1->u.intv | pval2->u.intv}; +} +static inline mv_t i_ii_bitwise_xor_func(mv_t* pval1, mv_t* pval2) { + return (mv_t) {.type = MT_INT, .u.intv = pval1->u.intv ^ pval2->u.intv}; +} +static inline mv_t i_ii_bitwise_and_func(mv_t* pval1, mv_t* pval2) { + return (mv_t) {.type = MT_INT, .u.intv = pval1->u.intv & pval2->u.intv}; +} + mv_t i_iii_modadd_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t i_iii_modsub_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t i_iii_modmul_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); diff --git a/c/todo.txt b/c/todo.txt index 042e71632..d37961927 100644 --- a/c/todo.txt +++ b/c/todo.txt @@ -28,6 +28,22 @@ TOP OF LIST o now is a good time to look at bitops. first get the precedence right. +* mlr doc precedence: + Operators Associativity + --------- ------------- + || left to right + && left to right + | left to right + ^ left to right + & left to right + == != left to right + < <= > >= left to right + << >> left to right + binary+ binary- left to right + binary* / % left to right + ! ~ ++ -- unary+ unary- & right to left + () left to right + * packaging: - brew version bump?!? - cut a release w/ manpage