Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_compile_parse_assignment_target.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Compiler Assignment Target Parser
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 
18 /*ebnf>>>
19  *
20  * AssignmentListDestructureTarget ::=
21  * '['
22  * (
23  * ( '...' AssignmentBindingTarget ) |
24  * ( AssignmentElement (',' AssignmentElement )*
25  * ( ',' '...' AssignmentBindingTarget )? )
26  * )
27  * ']'
28  *
29  *<<<ebnf*/
30 /* Note: Token '[' is already consumed. */
32 afw_compile_parse_AssignmentListDestructureTarget(
33  afw_compile_parser_t *parser,
35 {
39 
40  ld = afw_pool_calloc_type(parser->p,
41  afw_compile_list_destructure_t, parser->xctx);
42  afw_compile_get_token();
43  if (!afw_compile_token_is(ellipsis)) {
44  afw_compile_reuse_token();
45  ld->assignment_element = e =
46  afw_compile_parse_AssignmentElement(parser, assignment_type);
47  for (;;) {
48  afw_compile_get_token();
49  if (afw_compile_token_is(comma)) {
50  afw_compile_get_token();
51  if (afw_compile_token_is(ellipsis)) {
52  break;
53  }
54  afw_compile_reuse_token();
55  new_e = afw_compile_parse_AssignmentElement(parser,
56  assignment_type);
57  e->next = new_e;
58  e = new_e;
59  }
60  else if (afw_compile_token_is(close_bracket)) {
61  break;
62  }
63  else {
64  AFW_COMPILE_THROW_ERROR_Z("Expecting ',' or ']'");
65  }
66  }
67  }
68 
69  if (afw_compile_token_is(ellipsis)) {
70  afw_compile_parse_AssignmentBindingTarget(parser,
71  assignment_type, &ld->rest_type, &ld->rest);
72  afw_compile_get_token();
73  }
74 
75  if (!afw_compile_token_is(close_bracket)) {
76  AFW_COMPILE_THROW_ERROR_Z("Expecting ']'");
77  }
78 
79  return ld;
80 }
81 
82 
83 /*ebnf>>>
84  *
85  * AssignmentElement ::=
86  * AssignmentBindingTarget ( '=' Expression )?
87  *
88  *<<<ebnf*/
90 afw_compile_parse_AssignmentElement(
91  afw_compile_parser_t *parser,
93 {
95 
96  e = afw_pool_calloc_type(parser->p,
97  afw_compile_assignment_element_t, parser->xctx);
98  if (afw_compile_peek_next_token_is(comma)) {
99  return e;
100  }
101  afw_compile_parse_AssignmentBindingTarget(parser,
102  assignment_type, &e->type, &e->assignment_target);
103  afw_compile_get_token();
104  if (afw_compile_token_is(equal)) {
105  e->default_value = afw_compile_parse_Expression(parser);
106  }
107  else {
108  afw_compile_reuse_token();
109  }
110 
111  return e;
112 }
113 
114 
115 
116 /*ebnf>>>
117  *
118  * AssignmentObjectDestructureTarget ::=
119  * '{'
120  * (
121  * ( '...' AssignmentBindingTarget ) |
122  * (
123  * AssignmentProperty ( ',' AssignmentProperty )*
124  * ( ',' '...' AssignmentBindingTarget )?
125  * )
126  * )?
127  * '}'
128  *
129  *<<<ebnf*/
130 /* Note: Token '{' is already consumed. */
132 afw_compile_parse_AssignmentObjectDestructureTarget(
133  afw_compile_parser_t *parser,
135 {
139 
140  od = afw_pool_calloc_type(parser->p,
141  afw_compile_object_destructure_t, parser->xctx);
142  afw_compile_get_token();
143  if (!afw_compile_token_is(ellipsis)) {
144  afw_compile_reuse_token();
145  od->assignment_property = ap =
146  afw_compile_parse_AssignmentProperty(parser, assignment_type);
147  for (;;) {
148  afw_compile_get_token();
149  if (afw_compile_token_is(comma)) {
150  afw_compile_get_token();
151  if (afw_compile_token_is(ellipsis)) {
152  break;
153  }
154  afw_compile_reuse_token();
155  new_ap = afw_compile_parse_AssignmentProperty(parser,
156  assignment_type);
157  ap->next = new_ap;
158  ap = new_ap;
159  }
160  else if (afw_compile_token_is(close_brace)) {
161  break;
162  }
163  else {
164  AFW_COMPILE_THROW_ERROR_Z("Expecting ',' or '}'");
165  }
166  }
167  }
168 
169  if (afw_compile_token_is(ellipsis)) {
170  afw_compile_parse_AssignmentBindingTarget(parser,
171  assignment_type, &od->rest_type, &od->rest);
172  afw_compile_get_token();
173  }
174 
175  if (!afw_compile_token_is(close_brace)) {
176  AFW_COMPILE_THROW_ERROR_Z("Expecting '}'");
177  }
178 
179  return od;
180 }
181 
182 
183 
184 /*ebnf>>>
185  *
186  * AssignmentProperty ::=
187  * ( PropertyName ('=' Expression )? ) |
188  * ( PropertyName ( ':' AssignmentElement )? )
189  *
190  *<<<ebnf*/
191 /* Note: Token identifier is already consumed and passed as parameter. */
193 afw_compile_parse_AssignmentProperty(
194  afw_compile_parser_t *parser,
196 {
198  const afw_compile_value_contextual_t *contextual;
199  const afw_utf8_t *identifier;
200 
201 /*
202  if (afw_compile_token_is(identifier)) {
203  name = parser->token->identifier_name;
204  }
205  else if (afw_compile_token_is(integer)) {
206  name = afw_number_integer_to_utf8(
207  parser->token->integer,
208  parser->p, parser->xctx);
209  }
210  else {
211  AFW_COMPILE_THROW_ERROR_Z("Expecting property name");
212  }
213  */
214  ap = afw_pool_calloc_type(parser->p,
215  afw_compile_assignment_property_t, parser->xctx);
216  afw_compile_get_token();
217 
218  /* Get property name */
219  if (!afw_compile_token_is_unqualified_identifier()) {
220  AFW_COMPILE_THROW_ERROR_Z("Expecting PropertyName");
221  }
222  identifier = parser->token->identifier_name;
223 
224  /* ( PropertyName ( ':' AssignmentElement )? ) */
225  afw_compile_get_token();
226  if (afw_compile_token_is(colon)) {
227  ap->is_rename = true;
228  ap->property_name = identifier;
229  ap->assignment_element = afw_compile_parse_AssignmentElement(
230  parser, assignment_type);
231  }
232 
233  /* ( PropertyName ( '=' Expression )? ) */
234  else {
235  contextual = afw_compile_create_contextual_to_cursor(
236  parser->token->token_source_offset);
237  ap->variable_reference = afw_compile_parse_variable_reference_create(
238  parser, contextual, assignment_type, identifier);
239  if (afw_compile_token_is(equal)) {
240  ap->default_value = afw_compile_parse_Expression(parser);
241  }
242  else {
243  afw_compile_reuse_token();
244  }
245  }
246 
247  return ap;
248 }
249 
250 
251 
252 /*ebnf>>>
253  *
254  *#
255  *# Reference is only valid if assignment_type is assign_only
256  *#
257  * AssignmentBindingTarget ::=
258  * AssignmentListDestructureTarget |
259  * AssignmentObjectDestructureTarget |
260  * ( VariableName - ReservedWords )
261  *
262  *<<<ebnf*/
264 afw_compile_parse_AssignmentBindingTarget(
265  afw_compile_parser_t *parser,
267  const afw_value_type_t **type,
268  const afw_value_t **value)
269 {
270  const afw_compile_value_contextual_t *contextual;
272  const afw_utf8_t *variable_name;
273 
274  contextual = afw_compile_create_contextual_to_cursor(
275  parser->token->token_source_offset);
276 
277  afw_compile_get_token();
278 
279  /* List Destructure */
280  if (afw_compile_token_is(open_bracket)) {
281  target = afw_pool_calloc_type(parser->p,
282  afw_compile_assignment_target_t, parser->xctx);
283  target->assignment_type = assignment_type;
284  target->target_type =
285  afw_compile_assignment_target_type_list_destructure;
286  target->list_destructure =
287  afw_compile_parse_AssignmentListDestructureTarget(
288  parser, target->assignment_type);
290  contextual, target, parser->p, parser->xctx);
291  }
292 
293  /* Object Destructure */
294  else if (afw_compile_token_is(open_brace)) {
295  target = afw_pool_calloc_type(parser->p,
296  afw_compile_assignment_target_t, parser->xctx);
297  target->assignment_type = assignment_type;
298  target->target_type =
299  afw_compile_assignment_target_type_object_destructure;
300  target->object_destructure =
301  afw_compile_parse_AssignmentObjectDestructureTarget(
302  parser, target->assignment_type);
304  contextual, target, parser->p, parser->xctx);
305  }
306 
307  /* Special case for handling call from afw_compile_parse_AssignmentTarget */
308  else if (assignment_type == afw_compile_assignment_type_assign_only)
309  {
310  afw_compile_reuse_token();
311  *value = afw_compile_parse_Reference(parser);
312  if (!*value) {
313  AFW_COMPILE_THROW_ERROR_Z("Invalid assignment target");
314  }
315  }
316 
317  /* VariableName */
318  else if (afw_compile_token_is_unqualified_identifier() ||
319  afw_compile_token_is(open_parenthesis))
320  {
321  if (!afw_compile_token_is_unqualified_identifier()) {
322  AFW_COMPILE_THROW_ERROR_Z("Expecting VariableName");
323  }
324 
325  variable_name = parser->token->identifier_name;
326  if (afw_compile_is_reserved_word(parser, variable_name)) {
328  "Variable name can not be a reserved word");
329  }
330 
331  if (assignment_type == afw_compile_assignment_type_loc ||
332  assignment_type == afw_compile_assignment_type_const)
333  {
334  *type = afw_compile_parse_OptionalType(parser, false);
335  }
336 
337  *value = (const afw_value_t *)
338  afw_compile_parse_variable_reference_create(
339  parser, contextual, assignment_type,
340  variable_name);
341  }
342 
343  else {
344  AFW_COMPILE_THROW_ERROR_Z("Invalid assignment target");
345  }
346 }
347 
348 
349 
350 /*ebnf>>>
351  *
352  *#
353  *# If AssignmentBindingTarget does not return an assignment_target but
354  *# it does return a variable_reference and this is an assignment_type of
355  *# assign_only, create an assignment_target value from the variable_reference.
356  *#
357  * AssignmentTarget ::= AssignmentBindingTarget | Reference
358  *
359  *<<<ebnf*/
361 afw_compile_parse_AssignmentTarget(
362  afw_compile_parser_t *parser,
364 {
365  const afw_value_t *result;
366  const afw_value_type_t *type;
368 
369  afw_compile_parse_AssignmentBindingTarget(parser,
370  assignment_type, &type, &result);
371  if (!afw_value_is_assignment_target(result) &&
372  assignment_type != afw_compile_assignment_type_assign_only &&
374  {
375  target = afw_pool_calloc_type(parser->p,
376  afw_compile_assignment_target_t, parser->xctx);
377  target->assignment_type = assignment_type;
378  target->target_type =
379  afw_compile_assignment_target_type_variable_reference;
380  target->variable_type = type;
381  target->variable_reference =
382  (const afw_value_variable_reference_t *)result;
384  target->variable_reference->contextual,
385  target, parser->p, parser->xctx);
386  }
387 
388  return result;
389 }
390 
#define AFW_DEFINE_INTERNAL(type)
Define an internal function for /src/afw/ source*.c files.
Adaptive Framework Core Internal.
afw_compile_parse_OptionalType(afw_compile_parser_t *parser, afw_boolean_t is_return)
afw_compile_internal_assignment_type_t
Enum for assignment types.
#define AFW_COMPILE_THROW_ERROR_Z(message_z)
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
#define afw_value_is_variable_reference(A_VALUE)
Macro to determine if value is a variable reference.
Definition: afw_value.h:718
#define afw_value_is_assignment_target(A_VALUE)
Macro to determine if value is an assignment target.
Definition: afw_value.h:520
const afw_value_t * afw_value_assignment_target_create(const afw_compile_value_contextual_t *contextual, const afw_compile_assignment_target_t *assignment_target, const afw_pool_t *p, afw_xctx_t *xctx)
Create assignment target value.
Contextual information provided in some values.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_value public struct.
Type meta (data type, data type parameters, and value meta object.