summaryrefslogtreecommitdiff
path: root/src/fspec/ragel/validator.rl
blob: 90ead2103a6cf5dc7894813901152592b7d67cba (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
#include <fspec/bcode.h>
#include <fspec/validator.h>
#include "util/ragel/ragel.h"
#include "fspec/private/bcode-types.h"

#include <assert.h>

struct stack {
   union {
      fspec_num num;
      fspec_off off;
      fspec_var var;
      fspec_strsz strsz;
      unsigned char b[sizeof(fspec_num)];
   } u;
   uint8_t i; // writing index for u.b
};

struct state {
   struct ragel ragel;
   struct stack stack;
};

%%{
   machine fspec_validator;
   variable p state.ragel.p;
   variable pe state.ragel.pe;
   variable eof state.ragel.eof;
   write data noerror nofinal;

#   BLT_HEADER = 0;
#   BLT_ADD = 1;
#   BLT_SUB = 2;
#   BLT_MUL = 3;
#   BLT_DIV = 4;
#   BLT_MOD = 5;
#   BLT_BIT_AND = 6;
#   BLT_BIT_OR = 7;
#   BLT_BIT_XOR = 8;
#   BLT_BIT_LEFT = 9;
#   BLT_BIT_RIGHT = 10;
#   BLT_DECLARE = 11;
#   BLT_READ = 12;
#   BLT_GOTO = 13;
#   BLT_FILTER = 14;
#   BLT_VISUAL = 15;
#
#   builtins = BLT_HEADER |
#              BLT_ADD | BLT_SUB | BLT_MUL | BLT_DIV | BLT_MOD |
#              BLT_BIT_AND | BLT_BIT_OR | BLT_BIT_XOR | BLT_BIT_LEFT | BLT_BIT_RIGHT
#              BLT_DECLARE | BLT_READ | BLT_GOTO | BLT_FILTER | BLT_VISUAL;
#
#   OP_ARG = 0;
#   OP_REF = 1;
#   OP_BLT = 2 OP_ARG builtins;
#   OP_FUN = 3;
#
#   arg_ops = OP_REF | OP_FUN | OP_BUILTIN OP_FUN
#
#   BLT_DECLARE = OP_BUILTIN 10 OP_ARG 2 OP_REF OP_REF;
#   BLT_READ = OP_BUILTIN 11 OP_ARG 1..255 OP_REF (arg_ops)*;
#
#   pattern = ((BLT_READ | BLT_GOTO) BLT_FILTER* BLT_VISUAL?)* $!pattern_error;
#   main := (BLT_HEADER <: BLT_DECLARE* <: pattern) %check_decls $advance $!syntax_error;
   main := any*;
}%%

bool
fspec_validator_parse(struct fspec_validator *validator, const char *name)
{
   int cs;
   %% write init;

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

   struct state state = {
      .ragel.name = name,
      .ragel.lineno = 1,
   };

   static_assert(sizeof(state.stack.u) == sizeof(state.stack.u.b), "bytes doesn't represent the largest member in union");

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

   return !state.ragel.error;
}