aboutsummaryrefslogtreecommitdiff
path: root/flatcc/src/compiler/parser.h
blob: ef2ecc15a64e1cdd9621c032d7e7f4b27e57e505 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#ifndef PARSER_H
#define PARSER_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "../../config/config.h"
#include "flatcc/flatcc.h"
#include "symbols.h"

#define ELEM_BUFSIZ (64 * 1024)
#define ERROR_BUFSIZ 200

#define REVERT_LIST(TYPE, FIELD, HEAD)                                      \
    do {                                                                    \
        TYPE *tmp__next, *tmp__prev = 0, *tmp__link = *(HEAD);              \
        while (tmp__link) {                                                 \
            tmp__next = tmp__link->FIELD;                                   \
            tmp__link->FIELD = tmp__prev;                                   \
            tmp__prev = tmp__link;                                          \
            tmp__link = tmp__next;                                          \
        }                                                                   \
        *(HEAD) = tmp__prev;                                                \
    } while (0)

typedef struct fb_parser fb_parser_t;
typedef flatcc_options_t fb_options_t;

typedef void (*fb_error_fun)(void *err_ctx, const char *buf, size_t len);

void __flatcc_fb_default_error_out(void *err_ctx, const char *buf, size_t len);
#define  fb_default_error_out __flatcc_fb_default_error_out

int __flatcc_fb_print_error(fb_parser_t *P, const char * format, ...);
#define fb_print_error __flatcc_fb_print_error

struct fb_parser {
    fb_parser_t *dependencies;
    fb_parser_t *inverse_dependencies;
    fb_error_fun error_out;
    void *error_ctx;

    const char *managed_input;

    fb_token_t *ts, *te;
    int tcapacity;
    int doc_mode;
    fb_doc_t *doc;
    fb_token_t *token;

    size_t elem_end;
    void *elem_buffers;
    size_t elem;
    size_t offset_size;

    const char *line;
    long linenum;

    /* Internal id (not a pointer into token stream). */
    fb_token_t t_none;
    fb_token_t t_ubyte;

    int failed;

    unsigned char *tmp_field_marker;
    fb_symbol_t **tmp_field_index;
    int nesting_level;

    int has_schema;
    fb_options_t opts;
    fb_schema_t schema;
    fb_scope_t *current_scope;
    char *path;
    char *referer_path;
};

static inline void checkmem(const void *p)
{
    if (!p) {
        fprintf(stderr, "error: out of memory, aborting...\n");
        exit(1);
    }
}

static inline void *new_elem(fb_parser_t *P, size_t size)
{
    size_t elem;
    void *buf;

    size = (size + 15) & ~(size_t)15;
    elem = P->elem;
    if (elem + size > P->elem_end) {
        buf = calloc(ELEM_BUFSIZ, 1);
        checkmem(buf);
        *(void**)buf = P->elem_buffers;
        P->elem_buffers = buf;
        elem = P->elem = (size_t)buf + 16;
        P->elem_end = (size_t)buf + ELEM_BUFSIZ;
    }
    P->elem += size;
    return (void*)elem;
}

int __flatcc_fb_print_error(fb_parser_t *P, const char * format, ...);
#define fb_print_error __flatcc_fb_print_error

const char *__flatcc_error_find_file_of_token(fb_parser_t *P, fb_token_t *t);
#define error_find_file_of_token __flatcc_error_find_file_of_token

/*
 * This is the primary error reporting function.
 * The parser is flagged as failed and error count incremented.
 *
 * If s is not null, then s, len replaces the token text of `t` but
 * still reports the location of t. `peer` is optional and prints the
 * token location and text and the end of the message.
 * `msg` may be the only non-zero argument besides `P`.
 *
 * Various helper functions are available for the various cases.
 *
 * `fb_print_error` may be called instead to generate text to the error
 * output that is not counted as an error.
 */
void __flatcc_error_report(fb_parser_t *P, fb_token_t *t, const char *msg, fb_token_t *peer, const char *s, size_t len);
#define error_report __flatcc_error_report

static void error_tok_2(fb_parser_t *P, fb_token_t *t, const char *msg, fb_token_t *peer)
{
    error_report(P, t, msg, peer, 0, 0);
}

static inline void error_tok(fb_parser_t *P, fb_token_t *t, const char *msg)
{
    error_tok_2(P, t, msg, 0);
}

/* Only use the token location. */
static inline void error_tok_as_string(fb_parser_t *P, fb_token_t *t, const char *msg, char *s, size_t len)
{
    error_report(P, t, msg, 0, s, len);
}

static inline void error(fb_parser_t *P, const char *msg)
{
    error_tok(P, 0, msg);
}

static inline void error_name(fb_parser_t *P, fb_name_t *name, const char *msg)
{
    if (!name) {
        error(P, msg);
    } else {
        error_report(P, 0, msg, 0, name->name.s.s, (size_t)name->name.s.len);
    }
}

static inline void error_sym(fb_parser_t *P, fb_symbol_t *s, const char *msg)
{
    error_tok(P, s->ident, msg);
}

static inline void error_sym_2(fb_parser_t *P, fb_symbol_t *s, const char *msg, fb_symbol_t *s2)
{
    error_tok_2(P, s->ident, msg, s2->ident);
}

static inline void error_sym_tok(fb_parser_t *P, fb_symbol_t *s, const char *msg, fb_token_t *t2)
{
    error_tok_2(P, s->ident, msg, t2);
}

void error_ref_sym(fb_parser_t *P, fb_ref_t *ref, const char *msg, fb_symbol_t *s2);

static inline void error_ref(fb_parser_t *P, fb_ref_t *ref, const char *msg)
{
    error_ref_sym(P, ref, msg, 0);
}

/*
 * If `opts` is null, defaults options are being used, otherwise opts is
 * copied into the parsers options. The name may be path, the basename
 * without default extension will be extracted. The `error_out` funciton is
 * optional, otherwise output is printed to stderr, truncated to a
 * reasoanble size per error. `error_ctx` is provided as argument to
 * `error_out` if non-zero, and otherwise ignored.
 *
 * This api only deals with a single schema file so a parent level
 * driver must handle file inclusion and update P->dependencies but
 * order is not significant (parse order is, but this is handled by
 * updating the `include_index` in the root schema).
 *
 * P->dependencies must be cleared by callee in any order but once one
 * is cleared the entire structure should be taken down because symbols
 * trees point everywhere. For parses without file inclusion
 * dependencies will be null. Dependencies are not handled at this
 * level. P->inverse_dependencies is just the reverse list.
 *
 * The file at the head of the dependencies list is the root and the
 * one that provides the root schema. Other root schemas are not used.
 */
int __flatcc_fb_init_parser(fb_parser_t *P, fb_options_t *opts, const char *name,
        fb_error_fun error_out, void *error_ctx, fb_root_schema_t *rs);
#define fb_init_parser __flatcc_fb_init_parser

int __flatcc_fb_parse(fb_parser_t *P, const char *input, size_t len, int own_buffer);
#define fb_parse __flatcc_fb_parse

void __flatcc_fb_clear_parser(fb_parser_t *P);
#define fb_clear_parser __flatcc_fb_clear_parser

#endif /* PARSER_H */