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';
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 };
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;
}
|