summaryrefslogtreecommitdiff
path: root/src/fspec/ragel/lexer-expr.rl
blob: 29750432593ad34ced9b97e7fb13719886ad9d80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "lexer-expr.h"
#include "lexer-stack.h"
#include "util/ragel/ragel.h"

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <err.h>

static uint8_t
precedence(char op)
{
   switch (op) {
      case '^'return 4;
      case '*'return 3;
      case '/'return 3;
      case '+'return 2;
      case '-'return 2;
   }
   errx(EXIT_FAILURE, "unknown operator %c for precedence", op);
   return 0;
}

static size_t
pop(char cur, char *mstack, size_t open)
{
   static char cvar = 'a';

   // 1 + 2 + 4 + 3 * 2 / 2 * 2 * 2 - 2 * 2 + 5;
   while (open >= 3) {
      const char last_op = mstack[open - 2];
      const uint8_t last_prio = precedence(last_op);
      const uint8_t new_prio = precedence(cur);

      if (last_prio <= new_prio)
         break;

      printf("%c = ", cvar);
      for (size_t i = open - 3; i < open; ++i)
         printf("%c ", mstack[i]);
      puts(";");
      open -= 3;

      mstack[open++] = cvar;
      ++cvar;
   }

   return open;
}

%%{
   machine fspec_expr;
   include fspec_stack "lexer-stack.rl";
   variable p ragel.p;
   variable pe ragel.pe;
   variable eof ragel.eof;
   write data noerror nofinal;

   action op {
      open = pop(fc, mstack, open);
      mstack[open++] = fc;
   }

   logical_operators = '&&' | '||' | '==' | '<' | '>' | '<=' | '>=';
   calc_operators = '-' | '+' | '/' | '*' | '%';
   bitwise_operators = '&' | '|' | '^' | '<<' | '>>';

   main := |*
      '+' => op;
      '/' => op;
      '*' => op;
      '-' => op;
      '^' => op;
      stack_num => { mstack[open++] = fc;};
      '(' => { };
      ')' => { };
      ' ';
      ';' => {
         printf("v = ");
         for (size_t i = 0; i < open; ++i)
            printf("%c ", mstack[i]);
         puts(";");
      };
      *|;
}%%


bool
fspec_expr_parse(struct fspec_expr *expr, const char *name)
{
   int cs, act;
   const char *ts, *te;
   (void)ts;

   size_t open = 0;
   char mstack[25];

   %% write init;

   (void)fspec_expr_en_main;
   assert(expr);
   assert(expr->ops.read);
   assert(expr->ops.write);
   assert(expr->mem.input.data && expr->mem.input.len);
   assert(expr->mem.input.len <= (size_t)~0 && "input storage size exceeds size_t range");

   char var[256];
   struct stack stack = { .var.buf.mem = { .data = var, .len = sizeof(var) } };
   struct ragel ragel = { .name = name, .lineno = 1 };

   // static const fspec_num version = 0;

   struct fspec_mem input = expr->mem.input;
   for (bool eof = false; !ragel.error && !eof;) {
      const size_t bytes = expr->ops.read(expr, input.data, 1, input.len);
      const struct ragel_mem rl = { .data = input.data, .end = (char*)input.data + bytes };
      ragel_feed_input(&ragel, (eof = (bytes < input.len)), &rl);
      %% write exec;
   }

   return !ragel.error;
}