summaryrefslogtreecommitdiff
path: root/src/ragel/ragel.rl
blob: 655bb9c6763c32f555b49df40276230a8a3cea05 (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
#include "ragel.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

%%{
   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('^', stderr); }
   action tail { fputc('~', stderr); }
   action lead { fputc(' ', stderr); }

   word = alnum*;
   token = ' ' | punct;
   until_err = (any when { fpc != *error })*;
   search_err := ((any | token %{ *error = fpc; }) when { fpc != ragel->pe && fpc <= ragel->p })*;
   print_err := (until_err %red <: word %reset <: (any - '\n')*) ${ fputc(fc, stderr); } >lead %!end %/end;
   print_mark := (until_err ${ fputc(' ', stderr); } %red %mark <: any word $tail) >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;
   %% 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 : "");
   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);
}