summaryrefslogtreecommitdiff
path: root/src/util/ragel/ragel.rl
blob: c52f27b44380a8ef587eaceb69e8c6c52e640360 (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
#include "ragel.h"

#include <inttypes.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

%%{
   machine ragel;
   write data noerror nofinal;

   action red { fputs("\x1b[31m", stderr); }
   action reset { fputs("\x1b[0m", stderr); }
   action end { fputs("\x1b[0m\n", stderr); }
   action mark { fputc((fpc == *error ? '^' : '~'), stderr); }
   action lead { fputc(' ', stderr); }
   action char { fputc(fc, stderr); }

   valid = ^cntrl - space - punct;
   mark_token = (space valid | punct${ *error = fpc; };
   search_err := ((any | mark_token) when { fpc != ragel->pe && fpc <= ragel->p })*;

   word = print | valid*;
   until_err = (any when { fpc != *error })*;
   print_err := (until_err <: (word - '\n'>red %reset <: (print - '\n')*) $char >*lead %!end %/end;
   print_mark := (until_err $lead <: (any | word) >red $mark) >*lead %!end %/end;
}%%

static void
ragel_exec_error(const struct ragel *ragel, const int start_cs, const char **error)
{
   (void)ragel_start;
   assert(ragel && ragel->cl && error);
   int cs = start_cs;
   const char *p = ragel->cl, *pe = ragel->pe, *eof = ragel->eof;
   assert(p <= pe);
   %% write exec;
}

void
ragel_throw_error(struct ragel *ragel, const char *fmt, ...)
{
   assert(ragel && fmt);
   ragel->error = true;

   const char *error = ragel->p;

   if (!ragel->input.binary)
      ragel_exec_error(ragel, ragel_en_search_err, &error);

   const char *name = (ragel->name ? ragel->name : "");
   assert(error >= ragel->cl);
   uint64_t column = (error - ragel->cl);
   fprintf(stderr, "\x1b[37m%s:%" PRIu64 ":%" PRIu64 " \x1b[31merror: \x1b[0m", name, ragel->lineno, column);

   va_list args;
   va_start(args, fmt);
   vfprintf(stderr, fmt, args);
   va_end(args);
   fputc('\n', stderr);

   if (!ragel->input.binary) {
      ragel_exec_error(ragel, ragel_en_print_err, &error);
      ragel_exec_error(ragel, ragel_en_print_mark, &error);
   }
}

void
ragel_set_name(struct ragel *ragel, const char *name)
{
   assert(ragel);
   ragel->name = name;
}

void
ragel_advance_line(struct ragel *ragel)
{
   assert(ragel);
   ++ragel->lineno;
   ragel->cl = ragel->p;
}

void
ragel_feed_input(struct ragel *ragel, const bool eof, const struct ragel_mem *input)
{
   assert(ragel);
   ragel->input = *input;
   ragel->cl = ragel->p = ragel->input.data;
   ragel->pe = ragel->input.end;
   ragel->eof = (eof ? ragel->pe : NULL);
   assert(ragel->p <= ragel->pe);
}