parser.h
Go to the documentation of this file.
1 #ifndef NVIM_VIML_PARSER_PARSER_H
2 #define NVIM_VIML_PARSER_PARSER_H
3 
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <assert.h>
7 
8 #include "nvim/lib/kvec.h"
9 #include "nvim/func_attr.h"
10 #include "nvim/mbyte.h"
11 #include "nvim/memory.h"
12 
14 typedef struct {
15  const char *data;
16  size_t size;
17  bool allocated;
18 } ParserLine;
19 
23 typedef void (*ParserLineGetter)(void *cookie, ParserLine *ret_pline);
24 
26 typedef struct {
27  size_t line;
28  size_t col;
30 
32 typedef struct {
33  enum {
34  kPTopStateParsingCommand = 0,
36  } type;
37  union {
38  struct {
39  enum {
40  kExprUnknown = 0,
41  } type;
42  } expr;
43  } data;
45 
47 typedef struct {
51  void *cookie;
53  kvec_withinit_t(ParserLine, 4) lines;
55  vimconv_T conv;
57 
61 typedef struct {
63  size_t end_col;
64  const char *group;
66 
68 typedef kvec_withinit_t(ParserHighlightChunk, 16) ParserHighlight;
69 
71 typedef struct {
79  ParserHighlight *colors;
81  bool can_continuate;
82 } ParserState;
83 
84 static inline void viml_parser_init(
85  ParserState *const ret_pstate,
86  const ParserLineGetter get_line, void *const cookie,
87  ParserHighlight *const colors)
89 
97 static inline void viml_parser_init(
98  ParserState *const ret_pstate,
99  const ParserLineGetter get_line, void *const cookie,
100  ParserHighlight *const colors)
101 {
102  *ret_pstate = (ParserState) {
103  .reader = {
104  .get_line = get_line,
105  .cookie = cookie,
106  .conv = MBYTE_NONE_CONV,
107  },
108  .pos = { 0, 0 },
109  .colors = colors,
110  .can_continuate = false,
111  };
112  kvi_init(ret_pstate->reader.lines);
113  kvi_init(ret_pstate->stack);
114 }
115 
116 static inline void viml_parser_destroy(ParserState *const pstate)
118 
122 static inline void viml_parser_destroy(ParserState *const pstate)
123 {
124  for (size_t i = 0; i < kv_size(pstate->reader.lines); i++) {
125  ParserLine pline = kv_A(pstate->reader.lines, i);
126  if (pline.allocated) {
127  xfree((void *)pline.data);
128  }
129  }
130  kvi_destroy(pstate->reader.lines);
131  kvi_destroy(pstate->stack);
132 }
133 
134 static inline void viml_preader_get_line(ParserInputReader *const preader,
135  ParserLine *const ret_pline)
137 
139 static inline void viml_preader_get_line(ParserInputReader *const preader,
140  ParserLine *const ret_pline)
141 {
142  ParserLine pline;
143  preader->get_line(preader->cookie, &pline);
144  if (preader->conv.vc_type != CONV_NONE && pline.size) {
145  ParserLine cpline = {
146  .allocated = true,
147  .size = pline.size,
148  };
149  cpline.data = (char *)string_convert(&preader->conv,
150  (char_u *)pline.data,
151  &cpline.size);
152  if (pline.allocated) {
153  xfree((void *)pline.data);
154  }
155  pline = cpline;
156  }
157  kvi_push(preader->lines, pline);
158  *ret_pline = pline;
159 }
160 
161 static inline bool viml_parser_get_remaining_line(ParserState *const pstate,
162  ParserLine *const ret_pline)
163  REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
164 
170 static inline bool viml_parser_get_remaining_line(ParserState *const pstate,
171  ParserLine *const ret_pline)
172 {
173  const size_t num_lines = kv_size(pstate->reader.lines);
174  if (pstate->pos.line == num_lines) {
175  viml_preader_get_line(&pstate->reader, ret_pline);
176  } else {
177  *ret_pline = kv_last(pstate->reader.lines);
178  }
179  assert(pstate->pos.line == kv_size(pstate->reader.lines) - 1);
180  if (ret_pline->data != NULL) {
181  ret_pline->data += pstate->pos.col;
182  ret_pline->size -= pstate->pos.col;
183  }
184  return ret_pline->data != NULL;
185 }
186 
187 static inline void viml_parser_advance(ParserState *const pstate,
188  const size_t len)
189  REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
190 
197 static inline void viml_parser_advance(ParserState *const pstate,
198  const size_t len)
199 {
200  assert(pstate->pos.line == kv_size(pstate->reader.lines) - 1);
201  const ParserLine pline = kv_last(pstate->reader.lines);
202  if (pstate->pos.col + len >= pline.size) {
203  pstate->pos.line++;
204  pstate->pos.col = 0;
205  } else {
206  pstate->pos.col += len;
207  }
208 }
209 
210 static inline void viml_parser_highlight(ParserState *const pstate,
211  const ParserPosition start,
212  const size_t end_col,
213  const char *const group)
214  REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
215 
222 static inline void viml_parser_highlight(ParserState *const pstate,
223  const ParserPosition start,
224  const size_t len,
225  const char *const group)
226 {
227  if (pstate->colors == NULL || len == 0) {
228  return;
229  }
230  assert(kv_size(*pstate->colors) == 0
231  || kv_Z(*pstate->colors, 0).start.line < start.line
232  || kv_Z(*pstate->colors, 0).end_col <= start.col);
233  kvi_push(*pstate->colors, ((ParserHighlightChunk) {
234  .start = start,
235  .end_col = start.col + len,
236  .group = group,
237  }));
238 }
239 
240 #ifdef INCLUDE_GENERATED_DECLARATIONS
241 # include "viml/parser/parser.h.generated.h"
242 #endif
243 
244 #endif // NVIM_VIML_PARSER_PARSER_H
xfree(tofree)
char_u * string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp)
Definition: mbyte.c:2290
const char * group
Highlight group.
Definition: parser.h:64
Parser state item.
Definition: parser.h:32
#define kvi_destroy(v)
Definition: kvec.h:205
size_t col
Byte index in the line.
Definition: parser.h:28
int vc_type
Zero or more ConvFlags.
Definition: mbyte.h:64
size_t line
Line index in ParserInputReader.lines.
Definition: parser.h:27
#define kvi_init(v)
Definition: kvec.h:133
Structure defining input reader.
Definition: parser.h:47
return NULL
Definition: eval.c:23643
#define kv_size(v)
Definition: kvec.h:68
int len
Definition: helpers.c:1459
ParserPosition pos
Position up to which input was parsed.
Definition: parser.h:75
ParserHighlight * colors
Highlighting support.
Definition: parser.h:79
Definition: parser.h:61
static int REAL_FATTR_WARN_UNUSED_RESULT
Definition: typval_encode.c.h:295
ParserPosition start
Start of the highlight: line and column.
Definition: parser.h:62
#define MBYTE_NONE_CONV
Definition: mbyte.h:56
#define REAL_FATTR_NONNULL_ALL
Definition: func_attr.h:183
#define kvi_push(v, x)
Definition: kvec.h:199
ParserInputReader reader
Line reader.
Definition: parser.h:73
size_t size
Parsed line size.
Definition: parser.h:16
Parser position in the input.
Definition: parser.h:26
assert(len >=0)
#define kv_A(v, i)
Definition: kvec.h:66
bool allocated
True if line may be freed.
Definition: parser.h:17
One parsed line.
Definition: parser.h:14
ParserLineGetter get_line
Function used to get next line.
Definition: parser.h:49
#define kv_Z(v, i)
Definition: kvec.h:70
size_t end_col
End column, points to the start of the next character.
Definition: parser.h:63
const char * data
Parsed line pointer.
Definition: parser.h:15
vimconv_T conv
Conversion, for :scriptencoding.
Definition: parser.h:55
#define REAL_FATTR_NONNULL_ARG(...)
Definition: func_attr.h:187
Definition: mbyte.h:48
typedef kvec_withinit_t(ParserHighlightChunk, 16) ParserHighlight
Highlighting defined by a parser.
static int REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE
Definition: typval_encode.c.h:258
unsigned char char_u
Definition: types.h:11
int i
Definition: typval.c:868
err type
Definition: helpers.c:1468
#define kv_last(v)
Definition: kvec.h:71
void * cookie
Data for get_line function.
Definition: parser.h:51
Structure defining parser state.
Definition: parser.h:71
void(* ParserLineGetter)(void *cookie, ParserLine *ret_pline)
Definition: parser.h:23
Structure used for string conversions.
Definition: mbyte.h:63