Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_compile_parse_expression_tuple.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 Parser
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 static const afw_value_t *
18 afw_compile_parse_ExpressionTupleObject(afw_compile_parser_t *parser);
19 
20 
21 static const afw_value_t *
22 afw_compile_parse_ExpressionTupleValue(afw_compile_parser_t *parser);
23 
24 
25 static void impl_parse_ExpressionTupleValues(
26  afw_compile_parser_t *parser, const afw_value_t *function_value,
27  afw_size_t *count, const afw_value_t * * *values);
28 
29 
30 static const afw_value_t *
31 impl_parse_tuple_operation_expression_tuple_with_variables(
32  afw_compile_parser_t *parser);
33 
34 
35 static const afw_value_t *
36 impl_parse_tuple_operation_lambda_function(
37  afw_compile_parser_t *parser);
38 
39 
41 impl_parse_tuple_lambda_type(afw_compile_parser_t *parser);
42 
43 
44 static void
45 impl_parse_tuple_lambda_parameters(afw_compile_parser_t *parser,
46  afw_size_t *count,
47  const afw_value_script_function_parameter_t ** *parameters);
48 
49 
50 static const afw_value_t *
51 impl_parse_tuple_operation_list(
52  afw_compile_parser_t *parser);
53 
54 
55 static const afw_value_t *
56 impl_parse_tuple_operation_object(
57  afw_compile_parser_t *parser);
58 
59 
60 static const afw_value_t *
61 impl_parse_tuple_operation_property_reference(
62  afw_compile_parser_t *parser);
63 
64 
65 static const afw_value_t *
66 impl_parse_tuple_operation_template(
67  afw_compile_parser_t *parser);
68 
69 
70 static const afw_value_t *
71 impl_parse_tuple_operation_variable_reference(
72  afw_compile_parser_t *parser);
73 
74 
75 static const afw_value_t *
76 impl_parse_tuple_operation_expression(
77  afw_compile_parser_t *parser);
78 
79 
80 
81 /*ebnf>>>*/
82 
83 //* QuotedExpression ::= '"' Expression '"' /* ws: explicit */
84 
85 //* QuotedFunctionName ::= '"' FunctionName '"' /* ws: explicit */
86 
87 //* QuotedMethodName ::= '"' MethodName '"' /* ws: explicit */
88 
89 //* QuotedPropertyName ::= '"' PropertyName '"' /* ws: explicit */
90 
91 //* QuotedScript ::= '"' Script '"' /* ws: explicit */
92 
93 //* QuotedTemplate ::= '"' Template '"' /* ws: explicit */
94 
95 //* QuotedVariableReference ::= '"' VariableReference '"' /* ws: explicit */
96 
97 /*<<<ebnf*/
98 
99 
100 
101 /*ebnf>>>
102  *
103  * ExpressionTuple ::= '[' ExpressionTupleAnnotation ',' ExpressionTupleOperation ']'
104  *
105  *<<<ebnf*/
107 afw_compile_parse_ExpressionTuple(afw_compile_parser_t *parser)
108 {
109  const afw_value_t *annotation;
110  const afw_value_t *result;
111  afw_size_t save_hybrid_start_offset;
112  afw_size_t start_offset;
113 
114  afw_compile_save_cursor(start_offset);
115 
116  afw_compile_get_token();
117 
118  if (!afw_compile_token_is(open_bracket)) {
119  AFW_COMPILE_THROW_ERROR_Z( "Expecting '['");
120  }
121 
122  save_hybrid_start_offset = parser->hybrid_start_offset;
123  parser->hybrid_start_offset = parser->cursor - 1;
124 
125  /* Annotation is parsed, but ignored. */
126  annotation = afw_compile_parse_ExpressionTupleAnnotation(parser);
127 
128  /* Parse based on tuple operation to get result. */
129  result = afw_compile_parse_ExpressionTupleOperation(parser);
130 
131  /* If there is an annotation, make annotated value. */
132  if (annotation) {
134  afw_compile_create_contextual_to_cursor(start_offset),
135  result,
136  ((afw_value_object_t *)annotation)->internal,
137  parser->p, parser->xctx);
138  }
139 
140  /* Make sure tuple ends with a ']'. */
141  afw_compile_get_token();
142  if (!afw_compile_token_is(close_bracket)) {
143  AFW_COMPILE_THROW_ERROR_Z( "Expecting ']'");
144  }
145 
146  /* Restore hybrid start offset. */
147  parser->hybrid_start_offset = save_hybrid_start_offset;
148 
149  /* Return result. */
150  return result;
151 }
152 
153 
154 /*ebnf>>>
155  *
156  * ExpressionTupleAnnotation ::= 'null' | Object
157  *
158  *<<<ebnf*/
160 afw_compile_parse_ExpressionTupleAnnotation(afw_compile_parser_t *parser)
161 {
162  afw_compile_get_token();
163 
164  if (afw_compile_token_is(null)) {
165  return NULL;
166  }
167 
168  if (afw_compile_token_is(open_brace)) {
169  afw_compile_reuse_token();
170  return afw_compile_parse_Object(parser, true, true);
171  }
172 
173  AFW_COMPILE_THROW_ERROR_Z( "Expecting null or Object");
174 }
175 
176 
177 
178 /*ebnf>>>
179  *
180  *# Expression tuple version of an expression with variable assignments
181  *
182  * ExpressionTupleOperation_expressionTuple ::= '"exprT"' ','
183  * '['
184  * ( ( QuotedVariableReference "," ExpressionTupleValue )
185  * ( "," QuotedVariableReference "," ExpressionTupleValue )* )?
186  * ']' ',' ExpressionTupleValue
187  *
188  *<<<ebnf*/
189 static const afw_value_t *
190 impl_parse_tuple_operation_expression_tuple_with_variables(
191  afw_compile_parser_t *parser)
192 {
193  const afw_value_t *expression_tuple;
194  afw_value_assignment_t *assignment;
195  int start_nelts;
196  const afw_value_assignment_t * *assignments;
197  afw_size_t start_offset;
198 
199  start_offset = parser->hybrid_start_offset;
200  start_nelts = parser->values->nelts;
201 
202  afw_compile_get_token();
203  if (!afw_compile_token_is(comma)) {
204  goto error;
205  }
206 
207  afw_compile_get_token();
208  if (!afw_compile_token_is(open_bracket)) {
209  goto error;
210  }
211 
212  afw_compile_get_token();
213  if (!afw_compile_token_is(close_bracket)) {
214  for (;;) {
215 
216  if (!afw_compile_token_is(utf8_string)) {
217  goto error;
218  }
219 
220  assignment = afw_pool_calloc_type(parser->p,
221  afw_value_assignment_t, parser->xctx);
222  APR_ARRAY_PUSH(parser->values, afw_value_assignment_t *) =
223  assignment;
224 
225  assignment->name = afw_utf8_clone(parser->token->string,
226  parser->p, parser->xctx);
227 
228  afw_compile_get_token();
229  if (!afw_compile_token_is(comma)) {
230  goto error;
231  }
232 
233  assignment->value =
234  afw_compile_parse_ExpressionTupleValue(parser);
235 
236  afw_compile_get_token();
237  if (afw_compile_token_is(close_bracket)) {
238  break;
239  }
240  if (!afw_compile_token_is(comma)) {
241  goto error;
242  }
243  afw_compile_get_token();
244  }
245  }
246 
247  APR_ARRAY_PUSH(parser->values, afw_value_assignment_t *) = NULL;
248  assignments = afw_pool_malloc(parser->p,
249  (parser->values->nelts - start_nelts) *
250  sizeof(afw_value_assignment_t *),
251  parser->xctx);
252  memcpy((void *)assignments,
253  ((afw_value_assignment_t **)parser->values->elts) + start_nelts,
254  (parser->values->nelts - start_nelts) *
255  sizeof(afw_value_assignment_t *));
256  parser->values->nelts = start_nelts;
257 
258  afw_compile_get_token();
259  if (!afw_compile_token_is(comma)) {
260  goto error;
261  }
262 
263  expression_tuple = afw_compile_parse_ExpressionTupleValue(parser);
264 
266  afw_compile_create_contextual_to_cursor(start_offset),
267  assignments, expression_tuple,
268  parser->p, parser->xctx);
269 
270 error:
271  AFW_COMPILE_THROW_ERROR_Z("Invalid expression with variables tuple");
272 }
273 
274 
276 impl_parse_tuple_lambda_type(afw_compile_parser_t *parser)
277 {
278  afw_utf8_t s1;
279  afw_utf8_t s2;
280  const afw_utf8_octet_t *s;
281  const afw_utf8_t *data_type_id;
282  afw_size_t len;
284  afw_value_type_t *type;
285 
286  afw_compile_get_token();
287  if (!afw_compile_token_is(utf8_string)) {
288  goto error;
289  }
290 
291  parameter = afw_pool_calloc_type(parser->p,
293 
294  s = parser->token->string->s;
295  len = parser->token->string->len;
296  memset(&s2, 0, sizeof(s2));
297  for (s1.s = s; len > 0 && *s != ' '; s++, len--);
298  s1.len = s - s1.s;
299  if (len > 0) {
300  s++; len--;
301  for (s2.s = s; len > 0 && *s != ' '; s++, len--);
302  if (len > 0) {
303  goto error;
304  }
305  s2.len = s - s2.s;
306  }
307 
308  data_type_id = &s1;
309  if (s2.len > 0) {
310  data_type_id = &s2;
311  if (s1.len > 0) {
312  type = afw_pool_calloc_type(parser->p,
313  afw_value_type_t, parser->xctx);
314  parameter->type = type;
316  data_type_id, parser->xctx);
317  if (!type->data_type) {
318  goto error;
319  }
321  }
322  }
323 
324  return parameter;
325 
326 error:
327  AFW_COMPILE_THROW_ERROR_Z("Invalid lambda type");
328 }
329 
330 
331 static void
332 impl_parse_tuple_lambda_parameters(afw_compile_parser_t *parser,
333  afw_size_t *count,
334  const afw_value_script_function_parameter_t ** *parameters)
335 {
337  afw_size_t start_offset;
338  int start_nelts;
339  void *mem;
340 
341  start_nelts = parser->values->nelts;
342  afw_compile_save_offset(start_offset);
343 
344  afw_compile_get_token();
345  if (!afw_compile_token_is(open_bracket)) {
346  goto error;
347  }
348 
349  afw_compile_get_token();
350  if (!afw_compile_token_is(close_bracket)) {
351  afw_compile_parse_link_new_value_block(parser, start_offset);
352  afw_compile_reuse_token();
353  for (;;) {
354  parameter = impl_parse_tuple_lambda_type(parser);
355 
356  afw_compile_get_token();
357  if (!afw_compile_token_is(comma)) {
358  goto error;
359  }
360 
361  afw_compile_get_token();
362  if (!afw_compile_token_is(utf8_string)) {
363  goto error;
364  }
365 
366  parameter->name = afw_utf8_clone(parser->token->string,
367  parser->p, parser->xctx);
368 
369  afw_compile_parse_add_symbol_entry(parser,
370  parser->token->string);
371 
372  APR_ARRAY_PUSH(parser->values, afw_value_script_function_parameter_t *) =
373  parameter;
374 
375  afw_compile_get_token();
376  if (afw_compile_token_is(close_bracket)) {
377  break;
378  }
379 
380  if (!afw_compile_token_is(comma)) {
381  goto error;
382  }
383  }
384  }
385 
386  *count = parser->values->nelts - start_nelts;
387  *parameters = NULL;
388  if (*count > 0) {
389  *parameters = mem = afw_pool_malloc(parser->p,
390  (*count) * sizeof(afw_value_script_function_parameter_t *),
391  parser->xctx);
392  memcpy(mem,
393  ((afw_value_script_function_parameter_t **)parser->values->elts) + start_nelts,
394  (*count) * sizeof(afw_value_script_function_parameter_t *));
395  }
396 
397  parser->values->nelts = start_nelts;
398  return;
399 
400 error:
401  AFW_COMPILE_THROW_ERROR_Z("Invalid lambda parameter");
402 
403 }
404 
405 
406 /*ebnf>>>
407  *
408  *# Lambda function (return type, parameter names, expression tuple)
409  *
410  * ExpressionTupleOperation_lambda ::= '"lambda"' ','
411  * ( FunctionDeclarationObject | FunctionDeclarationURI ) ','
412  * ExpressionTupleValue
413  *
414  *<<<ebnf*/
415 static const afw_value_t *
416 impl_parse_tuple_operation_lambda_function(
417  afw_compile_parser_t *parser)
418 {
420  afw_size_t count;
421  const afw_value_script_function_parameter_t **parameters;
422  const afw_value_t *body;
423  afw_size_t start_offset;
424 
425  start_offset = parser->hybrid_start_offset;
426 
427  afw_compile_get_token();
428  if (!afw_compile_token_is(comma)) {
429  goto error;
430  }
431 
432  returns = impl_parse_tuple_lambda_type(parser);
433 
434  afw_compile_get_token();
435  if (!afw_compile_token_is(comma)) {
436  goto error;
437  }
438 
439  impl_parse_tuple_lambda_parameters(parser, &count, &parameters);
440 
441  afw_compile_get_token();
442  if (!afw_compile_token_is(comma)) {
443  goto error;
444  }
445 
446  body = afw_compile_parse_ExpressionTupleValue(parser);
447 
448  if (count > 0) {
449  afw_compile_parse_pop_value_block(parser);
450  }
451 
453  afw_compile_create_contextual_to_cursor(start_offset),
454  returns->type, count, parameters, body, parser->p, parser->xctx);
455 
456 error:
457  AFW_COMPILE_THROW_ERROR_Z("Invalid lambda function tuple");
458 }
459 
460 
461 /*ebnf>>>
462  *
463  *# An list with ExpressionTupleValue property values.
464  *
465  * ExpressionTupleOperation_list ::='"list"' ( "," ExpressionTupleValue )*
466  *
467  *<<<ebnf*/
468 static const afw_value_t *
469 impl_parse_tuple_operation_list(
470  afw_compile_parser_t *parser)
471 {
472  const afw_value_t *result;
473  const afw_list_t *list;
474  const afw_value_t *value;
475 
476  /* Create object to hold result. */
477  list = afw_list_create_generic(parser->p, parser->xctx);
478 
479  /* List properties - ( "," ExpressionTupleValue )* */
480  for (;;) {
481 
482  /* "]" is end of tuple or "," is another property,value. */
483  afw_compile_get_token();
484  if (afw_compile_token_is(close_bracket)) {
485  afw_compile_reuse_token();
486  break;
487  }
488 
489  /* "," */
490  if (!afw_compile_token_is(comma)) {
491  goto error;
492  }
493 
494  /* ExpressionTupleValue */
495  value = afw_compile_parse_ExpressionTupleValue(parser);
496 
497  /* Set property in object. */
498  afw_list_add_value(list, value, parser->xctx);
499  }
500 
501  /* Return object value. */
502  result = afw_value_create_list(list, parser->p, parser->xctx);
503  return result;
504 
505 error:
506  AFW_COMPILE_THROW_ERROR_Z("Invalid list tuple");
507 }
508 
509 
510 /*ebnf>>>
511  *
512  *# An object with ExpressionTupleValue property values.
513  *
514  * ExpressionTupleOperation_object ::='"obj"'
515  * ( "," QuotedPropertyName "," ExpressionTupleValue )*
516  *
517  *<<<ebnf*/
518 static const afw_value_t *
519 impl_parse_tuple_operation_object(
520  afw_compile_parser_t *parser)
521 {
522  const afw_value_t *result;
523  const afw_object_t *object;
524  const afw_utf8_t *property_name;
525  const afw_value_t *value;
526 
527  /* Create object to hold result. */
528  object = afw_object_create_managed(parser->p, parser->xctx);
529 
530  /* Object properties - ( "," QuotedPropertyName "," ExpressionTupleValue )* */
531  for (;;) {
532 
533  /* "]" is end of tuple or "," is another property,value. */
534  afw_compile_get_token();
535  if (afw_compile_token_is(close_bracket)) {
536  afw_compile_reuse_token();
537  break;
538  }
539  if (!afw_compile_token_is(comma)) {
540  goto error;
541  }
542 
543  /* QuotedPropertyName */
544  afw_compile_get_token();
545  if (!afw_compile_token_is(utf8_string)) {
546  goto error;
547  }
548  property_name = afw_utf8_clone(parser->token->string,
549  parser->p, parser->xctx);
550 
551  /* "," */
552  afw_compile_get_token();
553  if (!afw_compile_token_is(comma)) {
554  goto error;
555  }
556 
557  /* ExpressionTupleValue */
558  value = afw_compile_parse_ExpressionTupleValue(parser);
559 
560  /* Set property in object. */
561  afw_object_set_property(object, property_name, value, parser->xctx);
562  }
563 
564  /* Return object value. */
565  result = afw_value_create_object(object, parser->p, parser->xctx);
566  return result;
567 
568 error:
569  AFW_COMPILE_THROW_ERROR_Z("Invalid object tuple");
570 }
571 
572 
573 /*ebnf>>>
574  *
575  *# Property reference (property name)
576  *#
577  *# This is either QuotedPropertyName or an ExpressionTuple that evaluates to a
578  *# property name.
579  *
580  * ExpressionTupleOperation_propertyReference ::='"prop"' ','
581  * ( QuotedPropertyName | ExpressionTupleValue ) ',' ExpressionTupleObject
582  *
583  *<<<ebnf*/
584 static const afw_value_t *
585 impl_parse_tuple_operation_property_reference(
586  afw_compile_parser_t *parser)
587 {
588  const afw_value_t *object_value;
589  const afw_value_t *key;
590  const afw_value_t *result;
591  afw_size_t start_offset;
592 
593  start_offset = parser->hybrid_start_offset;
594 
595  /* , */
596  afw_compile_get_token();
597  if (!afw_compile_token_is(comma)) {
598  goto error;
599  }
600 
601  /* QuotedPropertyName | ExpressionTuple */
602  key = NULL;
603  afw_compile_get_token();
604  if (afw_compile_token_is(utf8_string)) {
605  key = afw_value_create_string(parser->token->string,
606  parser->p, parser->xctx);
607  }
608  else {
609  afw_compile_reuse_token();
610  key = afw_compile_parse_ExpressionTupleValue(parser);
611  }
612 
613  /* , */
614  afw_compile_get_token();
615  if (!afw_compile_token_is(comma)) {
616  goto error;
617  }
618 
619  /* ExpressionTupleObject */
620  object_value = afw_compile_parse_ExpressionTupleObject(parser);
621 
622  /* Create and return result. */
624  afw_compile_create_contextual_to_cursor(start_offset),
625  object_value, key, parser->p, parser->xctx);
626  return result;
627 
628 error:
629  AFW_COMPILE_THROW_ERROR_Z("Invalid property reference tuple");
630 }
631 
632 
633 /*ebnf>>>
634  *
635  *# A script in a string (See Script production)
636  *
637  * ExpressionTupleOperation_script ::='"script"' ',' QuotedScript
638  *
639  *<<<ebnf*/
640 static const afw_value_t *
641 impl_parse_tuple_operation_script(
642  afw_compile_parser_t *parser)
643 {
644  afw_compile_get_token();
645  if (!afw_compile_token_is(comma)) {
646  goto error;
647  }
648 
649  afw_compile_get_token();
650  if (!afw_compile_token_is(utf8_string)) {
651  goto error;
652  }
653 
655  return afw_compile_to_value(parser->token->string,
656  parser->contextual.source_location,
657  afw_compile_type_script,
658  parser->compiled_value, parser->shared, NULL, parser->xctx);
659 
660 error:
661  AFW_COMPILE_THROW_ERROR_Z("Invalid script tuple");
662 }
663 
664 
665 /*ebnf>>>
666  *
667  *# A template in a string (See Template production)
668  *
669  * ExpressionTupleOperation_template ::='"tmpl"' ',' QuotedTemplate
670  *
671  *<<<ebnf*/
672 static const afw_value_t *
673 impl_parse_tuple_operation_template(
674  afw_compile_parser_t *parser)
675 {
676  afw_compile_get_token();
677  if (!afw_compile_token_is(comma)) {
678  goto error;
679  }
680 
681  afw_compile_get_token();
682  if (!afw_compile_token_is(utf8_string)) {
683  goto error;
684  }
685 
687  return afw_compile_to_value(parser->token->string,
688  parser->contextual.source_location,
689  afw_compile_type_template,
690  parser->compiled_value, parser->shared, NULL, parser->xctx);
691 
692 error:
693  AFW_COMPILE_THROW_ERROR_Z("Invalid template tuple");
694 }
695 
696 
697 /*ebnf>>>
698  *
699  *# A reference to a variable (variable name)
700  *
701  * ExpressionTupleOperation_variableReference ::='"var"' ','
702  * QuotedVariableReference
703  *
704  *<<<ebnf*/
705 static const afw_value_t *
706 impl_parse_tuple_operation_variable_reference(
707  afw_compile_parser_t *parser)
708 {
709  afw_utf8_t qualifier;
710  afw_utf8_t name;
711  afw_size_t len;
712  const afw_utf8_octet_t *s;
713  afw_size_t start_offset;
714 
715  start_offset = parser->hybrid_start_offset;
716 
717  afw_compile_get_token();
718  if (!afw_compile_token_is(comma)) {
719  goto error;
720  }
721 
722  afw_compile_get_token();
723  if (!afw_compile_token_is(utf8_string)) {
724  goto error;
725  }
726  afw_memory_copy(&name, parser->token->string);
727  memset(&qualifier, 0, sizeof(qualifier));
728  for (s = name.s, len = name.len; len > 0; len--, s++) {
729  if (*s == ':') {
730  if (len < 2 || *(s + 1) != ':') {
731  goto error;
732  }
733  qualifier.len = s - name.s;
734  qualifier.s = name.s;
735  name.s = s + 2;
736  name.len -= qualifier.len + 2;
737  break;
738  }
739  }
740 
742  afw_compile_create_contextual_to_cursor(start_offset),
743  &qualifier, &name, parser->p, parser->xctx);
744 
745 error:
746  AFW_COMPILE_THROW_ERROR_Z("Invalid variable reference tuple");
747 }
748 
749 
750 
751 /*ebnf>>>
752  *
753  *# An expression in a string (See Expression production)
754  *
755  * ExpressionTupleOperation_expression ::= '"expr"' ',' QuotedExpression
756  *
757  *<<<ebnf*/
758 static const afw_value_t *
759 impl_parse_tuple_operation_expression(
760  afw_compile_parser_t *parser)
761 {
762  afw_compile_get_token();
763  if (!afw_compile_token_is(comma)) {
764  goto error;
765  }
766 
767  afw_compile_get_token();
768  if (!afw_compile_token_is(utf8_string)) {
769  goto error;
770  }
771 
773  return afw_compile_to_value(parser->token->string,
774  parser->contextual.source_location,
775  afw_compile_type_expression,
776  parser->compiled_value, parser->shared, NULL, parser->xctx);
777 
778 error:
779  AFW_COMPILE_THROW_ERROR_Z("Invalid expression tuple");
780 }
781 
782 
783 /*ebnf>>>
784  *
785  *# ExpressionTuple must evaluate to a single object.
786  *
787  * ExpressionTupleObject ::= Object | ExpressionTuple
788  *
789  *<<<ebnf*/
791 afw_compile_parse_ExpressionTupleObject(afw_compile_parser_t *parser)
792 {
793  const afw_value_t *result;
794 
795  afw_compile_get_token();
796  if (afw_compile_token_is(open_brace)) {
797  afw_compile_reuse_token();
798  result = afw_compile_parse_Object(parser, true, true);
799  }
800  else {
801  afw_compile_reuse_token();
802  result = afw_compile_parse_ExpressionTuple(parser);
803  }
804 
805  return result;
806 }
807 
808 
809 /*ebnf>>>
810  *
811  *# Expression operation
812  *
813  * ExpressionTupleOperation ::=
814  * ExpressionTupleOperation_call |
815  * ExpressionTupleOperation_callAdaptiveFunction |
816  * ExpressionTupleOperation_callLambdaFunction |
817  * ExpressionTupleOperation_callMethod |
818  * ExpressionTupleOperation_expressionTuple |
819  * ExpressionTupleOperation_lambda |
820  * ExpressionTupleOperation_list |
821  * ExpressionTupleOperation_object |
822  * ExpressionTupleOperation_propertyReference |
823  * ExpressionTupleOperation_script |
824  * ExpressionTupleOperation_template |
825  * ExpressionTupleOperation_variableReference |
826  * ExpressionTupleOperation_expression
827  *
828  *<<<ebnf*/
830 afw_compile_parse_ExpressionTupleOperation(afw_compile_parser_t *parser)
831 {
832  const afw_value_t *result;
833  const afw_value_t *function_value;
834  const afw_compile_value_contextual_t *contextual;
835  afw_utf8_t qualifier;
836  afw_utf8_t name;
837  const afw_value_t * *argv;
838  afw_size_t argc;
839 
840  afw_compile_get_token();
841  if (!afw_compile_token_is(comma)) {
842  goto error;
843  }
844 
845  afw_compile_get_token();
846  if (!afw_compile_token_is(utf8_string)) {
847  goto error;
848  }
849 
850  if (parser->token->string->len < 1) {
851  goto error;
852  }
853 
854 /*ebnf>>>
855  *
856  *# Call an built-in adaptive function (function, parameters ...)
857  *
858  * ExpressionTupleOperation_callAdaptiveFunction ::= ( '"callA"' ',' )?
859  * ( QuotedFunctionName | ExpressionTuple )
860  * (',' ExpressionTupleValue)*
861  *
862  *<<<ebnf*/
863  if (afw_utf8_equal(parser->token->string,
864  &afw_s_a_tuple_operation_call_adaptive_function))
865  {
866  contextual = afw_compile_create_contextual_to_cursor(parser->hybrid_start_offset);
867  afw_compile_get_token();
868  if (!afw_compile_token_is(comma)) {
869  goto error;
870  }
871 
872  /* Get function definition for built-in function. */
873  afw_compile_get_token();
874  if (!afw_compile_token_is(utf8_string)) {
875  goto error;
876  }
877  afw_compile_split_qualified_name(parser->token->string,
878  &qualifier, &name, parser->xctx);
879  function_value = (const afw_value_t *)
881  &qualifier, &name, parser->xctx);
882  if (!function_value) {
883  AFW_COMPILE_THROW_ERROR_FZ(
884  "Unknown built-in function %" AFW_UTF8_FMT,
885  AFW_UTF8_FMT_ARG(parser->token->string));
886  }
887 
888  /* Parser args and create call value result. */
889  impl_parse_ExpressionTupleValues(parser, function_value, &argc, &argv);
890  result = afw_value_call_create(contextual, argc, argv,
891  parser->p, parser->xctx);
892  }
893 
894 /*ebnf>>>
895  *
896  *# Call either a lambda or adaptive function (function, parameters ...)
897  *#
898  *# This is either QuotedVariableReference of a variable containing a lambda value,
899  *# a QuotedFunctionName identifies an adaptive function, or an ExpressionTuple
900  *# that evaluates to a lambda value.
901  *
902  * ExpressionTupleOperation_call ::= '"call"' ','
903  * ( QuotedVariableReference | QuotedFunctionName | ExpressionTuple )
904  * (',' ExpressionTupleValue)*
905  *
906  *<<<ebnf*/
907  else if (afw_utf8_equal(parser->token->string,
908  &afw_s_a_tuple_operation_call))
909  {
910  contextual = afw_compile_create_contextual_to_cursor(parser->hybrid_start_offset);
911  afw_compile_get_token();
912  if (!afw_compile_token_is(comma)) {
913  goto error;
914  }
915 
916  /*
917  * If quoted string, a function value is a reference or built-in
918  * function.
919  */
920  afw_compile_get_token();
921  if (afw_compile_token_is(utf8_string)) {
922  function_value = afw_compile_parse_reference_create(parser,
923  contextual, parser->token->string);
924  }
925 
926  /* If not quoted string, function value is an ExpressionTuple. */
927  else {
928  function_value = afw_compile_parse_ExpressionTuple(parser);
929  }
930 
931  /* Parser args and create call value result. */
932  impl_parse_ExpressionTupleValues(parser, function_value, &argc, &argv);
933  result = afw_value_call_create(contextual, argc, argv,
934  parser->p, parser->xctx);
935  }
936 
937 /*ebnf>>>
938  *
939  *# Call a lambda function (function, parameters ...)
940  *
941  * ExpressionTupleOperation_callLambdaFunction ::= '"callL"' ','
942  * ( QuotedVariableReference | ExpressionTuple )
943  * (',' ExpressionTupleValue)*
944  *
945  *<<<ebnf*/
946  else if (afw_utf8_equal(parser->token->string,
947  &afw_s_a_tuple_operation_call_lambda_function))
948  {
949  contextual = afw_compile_create_contextual_to_cursor(parser->hybrid_start_offset);
950  afw_compile_get_token();
951  if (!afw_compile_token_is(comma)) {
952  goto error;
953  }
954 
955  /* If quoted string, function value is a reference. */
956  afw_compile_get_token();
957  if (afw_compile_token_is(utf8_string)) {
958  function_value = afw_compile_parse_reference_create(parser,
959  contextual, parser->token->string);
960  if (afw_value_is_function_definition(function_value)) {
961  AFW_COMPILE_THROW_ERROR_FZ(
962  "Use call or callA to call built-in function %"
963  AFW_UTF8_FMT,
964  AFW_UTF8_FMT_ARG(parser->token->string));
965  }
966  }
967 
968  /* If not quoted string, function value is an ExpressionTuple. */
969  else {
970  function_value = afw_compile_parse_ExpressionTuple(parser);
971  }
972 
973  /* Parser args and create call value result. */
974  impl_parse_ExpressionTupleValues(parser, function_value, &argc, &argv);
975  result = afw_value_call_create(contextual, argc, argv,
976  parser->p, parser->xctx);
977  }
978 
979  /* Expression tuple with variables. */
980  else if (afw_utf8_equal(parser->token->string,
981  &afw_s_a_tuple_operation_expression_tuple_with_variables))
982  {
983  result =
984  impl_parse_tuple_operation_expression_tuple_with_variables(parser);
985  }
986 
987  /* Lambda function. */
988  else if (afw_utf8_equal(parser->token->string,
989  &afw_s_a_tuple_operation_lambda_function))
990  {
991  result = impl_parse_tuple_operation_lambda_function(parser);
992  }
993 
994  /* List. */
995  else if (afw_utf8_equal(parser->token->string,
996  &afw_s_a_tuple_operation_list))
997  {
998  result = impl_parse_tuple_operation_list(parser);
999  }
1000 
1001  /* Object. */
1002  else if (afw_utf8_equal(parser->token->string,
1003  &afw_s_a_tuple_operation_object))
1004  {
1005  result = impl_parse_tuple_operation_object(parser);
1006  }
1007 
1008  /* Property reference. */
1009  else if (afw_utf8_equal(parser->token->string,
1010  &afw_s_a_tuple_operation_property_reference))
1011  {
1012  result = impl_parse_tuple_operation_property_reference(parser);
1013  }
1014 
1015  /* Script. */
1016  else if (afw_utf8_equal(parser->token->string,
1017  &afw_s_a_tuple_operation_script))
1018  {
1019  result = impl_parse_tuple_operation_script(parser);
1020  }
1021 
1022  /* Template. */
1023  else if (afw_utf8_equal(parser->token->string,
1024  &afw_s_a_tuple_operation_template))
1025  {
1026  result = impl_parse_tuple_operation_template(parser);
1027  }
1028 
1029  /* Variable reference. */
1030  else if (afw_utf8_equal(parser->token->string,
1031  &afw_s_a_tuple_operation_variable_reference))
1032  {
1033  result = impl_parse_tuple_operation_variable_reference(parser);
1034  }
1035 
1036  /* Expression. */
1037  else if (afw_utf8_equal(parser->token->string,
1038  &afw_s_a_tuple_operation_expression))
1039  {
1040  result = impl_parse_tuple_operation_expression(parser);
1041  }
1042 
1043  /* Error. */
1044  else {
1045  goto error;
1046  }
1047 
1048  /* Return result. */
1049  return result;
1050 
1051 error:
1052  AFW_COMPILE_THROW_ERROR_Z("Invalid operation");
1053 }
1054 
1055 
1056 
1057 /*ebnf>>>
1058  *
1059  * ExpressionTupleValue ::= ExpressionTuple | Double | Integer | Object |
1060  * String | 'true' | 'false' | 'null'
1061  *
1062  *<<<ebnf*/
1063 static void impl_parse_ExpressionTupleValues(afw_compile_parser_t *parser,
1064  const afw_value_t *function_value, afw_size_t *argc, const afw_value_t * * *argv)
1065 {
1066  int start_nelts;
1067  void *args;
1068 
1069  start_nelts = parser->values->nelts;
1070  if (function_value) {
1071  APR_ARRAY_PUSH(parser->values, const afw_value_t *) = function_value;
1072  }
1073  for (;;) {
1074  afw_compile_get_token();
1075  if (afw_compile_token_is(close_bracket)) {
1076  afw_compile_reuse_token();
1077  break;
1078  }
1079  if (!afw_compile_token_is(comma)) {
1080  AFW_COMPILE_THROW_ERROR_Z("Expecting ','");
1081  }
1082  APR_ARRAY_PUSH(parser->values, const afw_value_t *) =
1083  afw_compile_parse_ExpressionTupleValue(parser);
1084  }
1085  *argc = parser->values->nelts - start_nelts;
1086  *argv = NULL;
1087  if (*argc > 0) {
1088  args = afw_pool_malloc(parser->p,
1089  sizeof(afw_value_t *) * (*argc), parser->xctx);
1090  memcpy(args,
1091  ((afw_value_t **)parser->values->elts) + start_nelts,
1092  sizeof(afw_value_t *) * (*argc));
1093  *argv = args;
1094  }
1095  parser->values->nelts = start_nelts;
1096 
1097  /* Function value argv[0] does not count for argc. */
1098  if (function_value) {
1099  (*argc)--;
1100  }
1101 }
1102 
1103 
1104 /* Parse ExpressionTupleValue. */
1106 afw_compile_parse_ExpressionTupleValue(afw_compile_parser_t *parser)
1107 {
1108  const afw_value_t *result;
1109 
1110  afw_compile_get_token();
1111 
1112  if (afw_compile_token_is(open_bracket)) {
1113  afw_compile_reuse_token();
1114  result = afw_compile_parse_ExpressionTuple(parser);
1115  }
1116 
1117  else if (afw_compile_token_is(open_brace)) {
1118  afw_compile_reuse_token();
1119  result = afw_compile_parse_Object(parser, true, true);
1120  }
1121 
1122  else if (afw_compile_token_is(utf8_string)) {
1123  result = afw_value_create_string(
1124  parser->token->string, parser->p, parser->xctx);
1125  }
1126 
1127  else if (afw_compile_token_is(integer)) {
1128  result = afw_value_create_integer(
1129  parser->token->integer, parser->p, parser->xctx);
1130  }
1131 
1132  else if (afw_compile_token_is(number)) {
1133  result = afw_value_create_double(
1134  parser->token->number, parser->p, parser->xctx);
1135  }
1136 
1137  else if (afw_compile_token_is(boolean)) {
1138  result = afw_value_create_boolean(
1139  parser->token->boolean, parser->p, parser->xctx);
1140  }
1141 
1142  else if (afw_compile_token_is(null)) {
1143  result = afw_value_create_null(
1144  parser->token->null, parser->p, parser->xctx);
1145  }
1146 
1147  else {
1148  AFW_COMPILE_THROW_ERROR_Z( "Invalid parameter");
1149  }
1150 
1151  return result;
1152 }
#define AFW_DEFINE_INTERNAL(type)
Define an internal function for /src/afw/ source*.c files.
Adaptive Framework Core Internal.
afw_value_create_boolean(afw_boolean_t internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type boolean value.
afw_value_create_double(double internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type double value.
afw_value_create_integer(afw_integer_t internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type integer value.
afw_value_create_list(const afw_list_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type list value.
afw_value_create_null(void *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type null value.
afw_value_create_object(const afw_object_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type object value.
afw_value_create_string(const afw_utf8_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type string value.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_COMPILE_THROW_ERROR_Z(message_z)
#define afw_compile_to_value(string, source_location, compile_type, parent, shared, p, xctx)
Compile string to adaptive value.
Definition: afw_compile.h:189
afw_compile_split_qualified_name(const afw_utf8_t *qualified_name, afw_utf8_t *qualifier, afw_utf8_t *name, afw_xctx_t *xctx)
Split name with optional qualifier.
Definition: afw_compile.c:548
afw_environment_get_qualified_function(const afw_utf8_t *qualifier, const afw_utf8_t *name, afw_xctx_t *xctx)
Get the qualified function instance.
const afw_data_type_t * afw_environment_get_data_type(const afw_utf8_t *type, afw_xctx_t *xctx)
Get the data_type associated with configuration entry type.
#define afw_list_create_generic(p, xctx)
Create an value list in memory.
Definition: afw_list.h:81
afw_list_add_value(const afw_list_t *instance, const afw_value_t *value, afw_xctx_t *xctx)
Call method add_value of interface afw_list_setter.
Definition: afw_list.c:104
#define afw_memory_copy(to, from)
Copy to preallocated memory of same type.
Definition: afw_memory.h:39
#define afw_object_create_managed(p, xctx)
Create an empty entity object in its own pool.
Definition: afw_object.h:913
afw_object_set_property(const afw_object_t *instance, const afw_utf8_t *property_name, const afw_value_t *value, afw_xctx_t *xctx)
Set the value of an object's property.
Definition: afw_object.c:46
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
const afw_utf8_t * afw_utf8_clone(const afw_utf8_t *string, const afw_pool_t *p, afw_xctx_t *xctx)
Clone a utf-8 string into a specific pool.
Definition: afw_utf8.h:347
const afw_value_t * afw_value_expression_definition_create(const afw_compile_value_contextual_t *contextual, const afw_value_assignment_t *const *assignments, const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for expression definition value.
const afw_value_t * afw_value_annotated_create(const afw_compile_value_contextual_t *contextual, const afw_value_t *value, const afw_object_t *annotation, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for annotated value.
const afw_value_t * afw_value_script_function_definition_create(const afw_compile_value_contextual_t *contextual, const afw_value_type_t *returns, afw_size_t count, const afw_value_script_function_parameter_t **parameters, const afw_value_t *body, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for lambda definition value.
#define afw_value_is_function_definition(A_VALUE)
Macro to determine if value is a function definition.
Definition: afw_value.h:614
const afw_value_t * afw_value_call_create(const afw_compile_value_contextual_t *contextual, afw_size_t argc, const afw_value_t *const *argv, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for call value.
const afw_value_t * afw_value_reference_by_key_create(const afw_compile_value_contextual_t *contextual, const afw_value_t *aggregate_value, const afw_value_t *key, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for reference_by_key value.
const afw_value_t * afw_value_qualified_variable_reference_create(const afw_compile_value_contextual_t *contextual, const afw_utf8_t *qualifier, const afw_utf8_t *name, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for variable reference value.
Contextual information provided in some values.
const afw_utf8_t * source_location
Source location.
Interface afw_list public struct.
Interface afw_object public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Struct for value assignment.
struct for data type object values.
Interface afw_value public struct.
Struct for script function parameter.
Type meta (data type, data type parameters, and value meta object.
const afw_data_type_t * data_type
data type or NULL.