bug-recutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH][RFC]: Extra operators


From: Ekaitz Zarraga
Subject: [PATCH][RFC]: Extra operators
Date: Wed, 20 Jan 2021 12:35:20 +0000

Hi,

I've been playing around with recutils these days I think it would be fine to 
have some extra operators for rounding reals to an specific precision to be 
able to compare them better, or to convert them to integers.

In this patch I just propose the inclusion of a very simple round() operator 
that converts from real to integer but I'd like to add more of these, using a 
more generic syntax parser for them.

I'd like to have:

- ceil, floor and round
- also some round(X, precision) to be able to compare real numbers in a safer 
way.


If this is fine, I can follow the same idea of the patch I attach below to 
implement the changes myself.


I'd also like to add some extra functionality to `recfmt` to be able to iterate 
on multiple fieldnames and so on, but I'm not sure if this functionality is 
welcome.
I also realized that `recfmt` is using printf's %f format for reals and that 
gives us 6 decimal positions in every number, some rounding or even the 
inclusion of a precision field in real numbers could be a nice to have for 
those cases that handle currency or similar values.

If recutils is open to accept those kind of changes, I could send the patches 
for them.


Thank you.


The promised (very-simple) patch of the `round` operation:

>From ffc28f564aba979ed0593ef82f7d22de34be1fd7 Mon Sep 17 00:00:00 2001
From: Ekaitz Zarraga <ekaitz@elenq.tech>
Date: Wed, 20 Jan 2021 13:15:09 +0100
Subject: [PATCH] rec-sex: Add round operator

    * src/rec-sex-ast.h: add operation ROUND
    * src/rec-sex-lex.l: add scanning rules for "round\s*("
    * src/rec-sex-tab.y: add parsing rules for TOK_ROUND
    * src/rec-sex.c: add round operation and include math
---
 src/rec-sex-ast.h |  1 +
 src/rec-sex-lex.l |  4 ++++
 src/rec-sex-tab.y |  2 ++
 src/rec-sex.c     | 24 ++++++++++++++++++++++++
 4 files changed, 31 insertions(+)

diff --git a/src/rec-sex-ast.h b/src/rec-sex-ast.h
index e2ad509..74fbf6c 100644
--- a/src/rec-sex-ast.h
+++ b/src/rec-sex-ast.h
@@ -51,6 +51,7 @@ enum rec_sex_ast_node_type_e
   REC_SEX_OP_AFTER,
   REC_SEX_OP_COND,
   REC_SEX_OP_CONCAT,
+  REC_SEX_OP_ROUND,

   /* Values.  */
   REC_SEX_INT,
diff --git a/src/rec-sex-lex.l b/src/rec-sex-lex.l
index 4f20b98..78f6095 100644
--- a/src/rec-sex-lex.l
+++ b/src/rec-sex-lex.l
@@ -124,6 +124,10 @@ STRING             '([^']|\\(.|\n))*'|\"([^"]|\\(.|\n))*\"
 ":"      { return REC_SEX_TOK_COLON; }
 "&"      { return REC_SEX_TOK_AMP; }

+"round"{BLANK}*\( {
+  return REC_SEX_TOK_ROUND;
+}
+
 {FIELD_NAME}(\.{FIELD_NAME})?(\[[0-9]+\])? {
   int res;
   char *match;
diff --git a/src/rec-sex-tab.y b/src/rec-sex-tab.y
index 2a06d9a..f34733f 100644
--- a/src/rec-sex-tab.y
+++ b/src/rec-sex-tab.y
@@ -107,6 +107,7 @@
 %token <node> REC_SEX_TOK_BP REC_SEX_TOK_EP
 %token <node> REC_SEX_TOK_ERR
 %token <node> REC_SEX_TOK_SHARP
+%right <node> REC_SEX_TOK_ROUND

 %type <ast> input
 %type <node> exp
@@ -163,5 +164,6 @@ exp : REC_SEX_TOK_INT          { $$ = $1; }
     | exp REC_SEX_TOK_AMP exp  { CREATE_NODE_OP2 (REC_SEX_OP_CONCAT, $$, $1, 
$3); }
     | REC_SEX_TOK_SHARP REC_SEX_TOK_NAM    { CREATE_NODE_OP1 (REC_SEX_OP_SHA, 
$$, $2); }
     | REC_SEX_TOK_BP exp REC_SEX_TOK_EP { $$ = $2; }
+    | REC_SEX_TOK_ROUND exp REC_SEX_TOK_EP { CREATE_NODE_OP1 
(REC_SEX_OP_ROUND, $$, $2);}

 %%
diff --git a/src/rec-sex.c b/src/rec-sex.c
index 1c78e42..e39cb7f 100644
--- a/src/rec-sex.c
+++ b/src/rec-sex.c
@@ -29,6 +29,8 @@
 #include <rec-sex-parser.h>
 #include <rec-sex-tab.h>

+#include <math.h>
+
 struct rec_sex_s
 {
   rec_sex_ast_t ast;
@@ -241,6 +243,28 @@ Please report this!\n");
         break;
         /* Operations.  */
       }
+    case REC_SEX_OP_ROUND:
+      {
+          int op_int;
+          double op_real;
+
+          GET_CHILD_VAL (child_val1, 0);
+
+          if(child_val1.type == REC_SEX_VAL_INT){
+            /* Integer operation.  */
+            res=child_val1;
+            break;
+          }
+
+          if(child_val1.type == REC_SEX_VAL_REAL){
+            /* Real operation.  */
+            ATOD_VAL (op_real, child_val1);
+            res.type = REC_SEX_VAL_INT;
+            res.int_val = (int) round(op_real);
+            break;
+          }
+          break;
+      }
     case REC_SEX_OP_NEG:
     case REC_SEX_OP_ADD:
       {
--
2.29.2







reply via email to

[Prev in Thread] Current Thread [Next in Thread]