Motr  M0
parser.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
29 #include <errno.h>
30 #include <err.h>
31 #include <sysexits.h>
32 #include <stdlib.h> /* malloc, NULL */
33 #include <string.h> /* memset */
34 
35 #include "xcode/ff2c/parser.h"
36 
37 static struct ff2c_term *alloc(void)
38 {
39  struct ff2c_term *term;
40 
41  term = malloc(sizeof *term);
42  if (term == NULL)
43  err(EX_TEMPFAIL, "Cannot allocate term (%zu bytes)", sizeof *term);
44  memset(term, 0, sizeof *term);
45  return term;
46 }
47 
48 static void error(struct ff2c_context *ctx, const char *msg)
49 {
50  char buf[100];
51 
52  ff2c_context_loc(ctx, sizeof buf, buf);
53  errx(2, "%s: %s", buf, msg);
54 }
55 
56 static struct ff2c_term *add(struct ff2c_term *term)
57 {
58  struct ff2c_term *new;
59 
60  new = alloc();
61  new->fn_parent = term;
62  return term->fn_tail = *(term->fn_head == NULL ?
63  &term->fn_head : &term->fn_tail->fn_next) = new;
64 }
65 
66 static void token(struct ff2c_context *ctx, struct ff2c_term *term,
67  struct ff2c_token *tok)
68 {
69  switch (tok->ft_type) {
70  case FTT_TAG:
71  term->fn_type = FNT_TAG;
72  break;
73  case FTT_ESCAPE:
74  term->fn_type = FNT_ESCAPE;
75  break;
76  default:
77  err(EX_SOFTWARE, "impossible token");
78  }
79  term->fn_tok = *tok;
80 }
81 
82 static int declaration(struct ff2c_context *ctx, struct ff2c_term *term);
83 
84 static int field(struct ff2c_context *ctx, struct ff2c_term *term)
85 {
86  int result;
87 
88  result = declaration(ctx, term);
89  if (result == 0) {
90  struct ff2c_token tok;
91 
92  while (1) {
93  result = ff2c_token_get(ctx, &tok);
94  if (result > 0) {
95  result = 0;
96  if (tok.ft_type == FTT_TAG ||
97  tok.ft_type == FTT_ESCAPE)
98  token(ctx, add(term), &tok);
99  else {
100  ff2c_token_put(ctx, &tok);
101  break;
102  }
103  } else
104  error(ctx, "unterminated field");
105  }
106  }
107  return result;
108 }
109 
110 static int field_list(struct ff2c_context *ctx, struct ff2c_term *term)
111 {
112  int result;
113  struct ff2c_token tok;
114 
115  result = ff2c_token_get(ctx, &tok);
116  if (result > 0 && tok.ft_type == FTT_OPEN) {
117  do
118  result = field(ctx, add(term));
119  while (result == 0 && (result = ff2c_token_get(ctx, &tok) > 0) &&
120  tok.ft_type == FTT_SEMICOLON);
121  if (result > 0) {
122  if (tok.ft_type == FTT_CLOSE)
123  return 0;
124  else
125  error(ctx, "\"}\" or \";\"expected");
126  } else if (result == 0)
127  error(ctx, "unterminated field list");
128  } else
129  error(ctx, "\"{\" expected");
130  return -EINVAL;
131 }
132 
133 static int type(struct ff2c_context *ctx, struct ff2c_term *term)
134 {
135  int result;
136 
137  result = ff2c_token_get(ctx, &term->fn_tok);
138  if (result > 0) {
139  switch (term->fn_tok.ft_type) {
140  case FTT_VOID:
141  case FTT_U8:
142  case FTT_U32:
143  case FTT_U64:
144  case FTT_OPAQUE:
145  term->fn_type = FNT_ATOMIC;
146  return 0;
147  case FTT_RECORD:
148  case FTT_UNION:
149  case FTT_SEQUENCE:
150  case FTT_ARRAY:
151  term->fn_type = FNT_COMPOUND;
152  return field_list(ctx, term);
153  case FTT_IDENTIFIER:
154  term->fn_type = FNT_TYPENAME;
155  return 0;
156  default:
157  break;
158  }
159  }
160  error(ctx, "type expected");
161  return -EINVAL;
162 }
163 
164 static int declaration(struct ff2c_context *ctx, struct ff2c_term *term)
165 {
166  int result;
167 
168  term->fn_type = FNT_DECLARATION;
169  result = type(ctx, add(term));
170  if (result == 0) {
171  result = ff2c_token_get(ctx, &term->fn_tok);
172  if (result > 0 && term->fn_tok.ft_type == FTT_IDENTIFIER)
173  return 0;
174  else
175  error(ctx, "declaration must be terminated "
176  "with an identifier");
177  }
178  return -EINVAL;
179 }
180 
181 static int require(struct ff2c_context *ctx, struct ff2c_term *term)
182 {
183  int result;
184 
185  term->fn_type = FNT_REQUIRE;
186  result = ff2c_token_get(ctx, &term->fn_tok);
187  if (result > 0 && term->fn_tok.ft_type == FTT_STRING)
188  return 0;
189  else {
190  error(ctx, "\"require\" must be followed by a pathname");
191  return -EINVAL;
192  }
193 }
194 
195 static int statement(struct ff2c_context *ctx, struct ff2c_term *term)
196 {
197  int result;
198  struct ff2c_token tok;
199 
200  result = ff2c_token_get(ctx, &tok);
201  if (result > 0) {
202  if (tok.ft_type == FTT_REQUIRE)
203  result = require(ctx, term);
204  else {
205  ff2c_token_put(ctx, &tok);
206  result = declaration(ctx, term);
207  }
208  }
209  return result;
210 }
211 
212 static int ff(struct ff2c_context *ctx, struct ff2c_term *term)
213 {
214  int result;
215  struct ff2c_token tok;
216 
217  term->fn_type = FNT_FF;
218  do
219  result = statement(ctx, add(term));
220  while (result == 0 && (result = ff2c_token_get(ctx, &tok) > 0) &&
221  tok.ft_type == FTT_SEMICOLON);
222  return result;
223 }
224 
225 int ff2c_parse(struct ff2c_context *ctx, struct ff2c_term **out)
226 {
227  *out = alloc();
228  return ff(ctx, *out);
229 }
230 
232 {
233  free(term);
234 }
235 
236 const char *ff2c_term_type_name[] = {
237  [FNT_FF] = "FF",
238  [FNT_REQUIRE] = "REQUIRE",
239  [FNT_DECLARATION] = "DECLARATION",
240  [FNT_ATOMIC] = "ATOMIC",
241  [FNT_COMPOUND] = "COMPOUND",
242  [FNT_TYPENAME] = "TYPENAME",
243  [FNT_TAG] = "TAG",
244  [FNT_ESCAPE] = "ESCAPE",
245 };
246 
249 /*
250  * Local variables:
251  * c-indentation-style: "K&R"
252  * c-basic-offset: 8
253  * tab-width: 8
254  * fill-column: 80
255  * scroll-step: 1
256  * End:
257  */
Definition: parser.h:49
Definition: lex.h:63
#define NULL
Definition: misc.h:38
const char * ff2c_term_type_name[]
Definition: parser.c:236
Definition: lex.h:81
Definition: lex.h:65
static struct ff2c_term * add(struct ff2c_term *term)
Definition: parser.c:56
static int type(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:133
void ff2c_token_put(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:217
int ff2c_token_get(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:134
Definition: parser.h:43
Definition: sock.c:887
static int field_list(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:110
static int ff(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:212
static int declaration(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:164
Definition: lex.h:87
enum ff2c_token_type ft_type
Definition: lex.h:95
Definition: lex.h:73
static int field(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:84
static struct ff2c_term * alloc(void)
Definition: parser.c:37
static int statement(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:195
static void token(struct ff2c_context *ctx, struct ff2c_term *term, struct ff2c_token *tok)
Definition: parser.c:66
Definition: lex.h:59
static void error(struct ff2c_context *ctx, const char *msg)
Definition: parser.c:48
int ff2c_context_loc(struct ff2c_context *ctx, int nr, char *buf)
Definition: lex.c:234
Definition: lex.h:67
static int require(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:181
Definition: lex.h:94
Definition: lex.h:85
Definition: lex.h:61
Definition: lex.h:79
Definition: lex.h:77
struct m0_rpc_fop_session_terminate term
Definition: session.c:53
Definition: nucleus.c:42
#define out(...)
Definition: gen.c:41
Definition: lex.h:71
void ff2c_term_fini(struct ff2c_term *term)
Definition: parser.c:231
int ff2c_parse(struct ff2c_context *ctx, struct ff2c_term **out)
Definition: parser.c:225
Definition: lex.h:69