1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "language/lexer/macro.h"
23 #include "data/settings.h"
24 #include "language/lexer/segment.h"
25 #include "language/lexer/scan.h"
26 #include "libpspp/assertion.h"
27 #include "libpspp/i18n.h"
28 #include "libpspp/message.h"
29 #include "libpspp/str.h"
32 #define _(msgid) gettext (msgid)
35 macro_destroy (struct macro *m)
41 for (size_t i = 0; i < m->n_params; i++)
43 struct macro_param *p = &m->params[i];
46 tokens_uninit (&p->def);
54 token_destroy (&p->charend);
58 token_destroy (&p->enclose[0]);
59 token_destroy (&p->enclose[1]);
67 ss_dealloc (&m->body);
68 tokens_uninit (&m->body_tokens);
73 macro_set_create (void)
75 struct macro_set *set = xmalloc (sizeof *set);
76 *set = (struct macro_set) {
77 .macros = HMAP_INITIALIZER (set->macros),
83 macro_set_destroy (struct macro_set *set)
88 struct macro *macro, *next;
89 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
91 hmap_delete (&set->macros, ¯o->hmap_node);
92 macro_destroy (macro);
94 hmap_destroy (&set->macros);
99 hash_macro_name (const char *name)
101 return utf8_hash_case_string (name, 0);
104 static struct macro *
105 macro_set_find__ (struct macro_set *set, const char *name)
108 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
109 hash_macro_name (name), &set->macros)
110 if (!utf8_strcasecmp (macro->name, name))
117 macro_set_find (const struct macro_set *set, const char *name)
119 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
122 /* Adds M to SET. M replaces any existing macro with the same name. Takes
125 macro_set_add (struct macro_set *set, struct macro *m)
127 struct macro *victim = macro_set_find__ (set, m->name);
130 hmap_delete (&set->macros, &victim->hmap_node);
131 macro_destroy (victim);
134 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
142 /* Accumulating tokens in me->params toward the end of any type of
146 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
149 /* Expecting a keyword for a keyword argument. */
152 /* Expecting an equal sign for a keyword argument. */
157 struct macro_expander
159 const struct macro_set *macros;
164 const struct macro *macro;
165 struct tokens **args;
166 const struct macro_param *param;
170 me_finished (struct macro_expander *me)
172 for (size_t i = 0; i < me->macro->n_params; i++)
175 me->args[i] = xmalloc (sizeof *me->args[i]);
176 tokens_copy (me->args[i], &me->macro->params[i].def);
182 me_next_arg (struct macro_expander *me)
186 assert (!me->macro->n_params);
187 return me_finished (me);
189 else if (me->param->positional)
192 if (me->param >= &me->macro->params[me->macro->n_params])
193 return me_finished (me);
196 me->state = me->param->positional ? ME_ARG : ME_KEYWORD;
202 for (size_t i = 0; i < me->macro->n_params; i++)
205 me->state = ME_KEYWORD;
208 return me_finished (me);
213 me_error (struct macro_expander *me)
215 me->state = ME_ERROR;
220 me_add_arg (struct macro_expander *me, const struct token *token)
222 if (token->type == T_STOP)
224 msg (SE, _("Unexpected end of file reading argument %s "
225 "to macro %s."), me->param->name, me->macro->name);
227 return me_error (me);
232 const struct macro_param *p = me->param;
233 struct tokens **argp = &me->args[p - me->macro->params];
235 *argp = xzalloc (sizeof **argp);
236 struct tokens *arg = *argp;
237 if (p->arg_type == ARG_N_TOKENS)
239 tokens_add (arg, token);
240 if (arg->n >= p->n_tokens)
241 return me_next_arg (me);
244 else if (p->arg_type == ARG_CMDEND)
246 if (token->type == T_ENDCMD || token->type == T_STOP)
247 return me_next_arg (me);
248 tokens_add (arg, token);
253 const struct token *end
254 = p->arg_type == ARG_CMDEND ? &p->charend : &p->enclose[1];
255 if (token_equal (token, end))
256 return me_next_arg (me);
257 tokens_add (arg, token);
263 me_expected (struct macro_expander *me, const struct token *token,
264 const struct token *wanted)
266 char *actual = token_to_string (token);
268 actual = xstrdup ("<eof>");
269 char *expected = token_to_string (wanted);
270 msg (SE, _("Found `%s' while expecting `%s' reading argument %s "
272 actual, expected, me->param->name, me->macro->name);
276 return me_error (me);
280 me_enclose (struct macro_expander *me, const struct token *token)
284 if (token_equal (&me->param->enclose[0], token))
290 return me_expected (me, token, &me->param->enclose[0]);
293 static const struct macro_param *
294 macro_find_parameter_by_name (const struct macro *m, struct substring name)
296 for (size_t i = 0; i < m->n_params; i++)
298 const struct macro_param *p = &m->params[i];
299 struct substring p_name = ss_cstr (p->name);
300 if (!utf8_strncasecmp (p_name.string, p_name.length,
301 name.string, name.length))
308 me_keyword (struct macro_expander *me, const struct token *token)
310 if (token->type != T_ID)
311 return me_finished (me);
313 const struct macro_param *p = macro_find_parameter_by_name (me->macro,
317 size_t arg_index = p - me->macro->params;
319 if (me->args[arg_index])
322 _("Argument %s multiply specified in call to macro %s."),
323 p->name, me->macro->name);
324 return me_error (me);
328 me->state = ME_EQUALS;
332 return me_finished (me);
336 me_equals (struct macro_expander *me, const struct token *token)
340 if (token->type == T_EQUALS)
346 const struct token equals = { .type = T_EQUALS };
347 return me_expected (me, token, &equals);
351 macro_expander_create (const struct macro_set *macros,
352 const struct token *token,
353 struct macro_expander **mep)
356 if (macro_set_is_empty (macros))
358 if (token->type != T_ID && token->type != T_MACRO_ID)
361 const struct macro *macro = macro_set_find (macros, token->string.string);
365 struct macro_expander *me = xmalloc (sizeof *me);
366 *me = (struct macro_expander) {
373 if (!macro->n_params)
377 me->state = macro->params[0].positional ? ME_ARG : ME_KEYWORD;
378 me->args = xcalloc (macro->n_params, sizeof *me->args);
379 me->param = macro->params;
385 macro_expander_destroy (struct macro_expander *me)
390 for (size_t i = 0; i < me->macro->n_params; i++)
393 tokens_uninit (me->args[i]);
400 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
403 Returns -1 if the tokens added do not actually invoke a macro. The caller
404 should consume the first token without expanding it.
406 Returns 0 if the macro expander needs more tokens, for macro arguments or to
407 decide whether this is actually a macro invocation. The caller should call
408 macro_expander_add() again with the next token.
410 Returns a positive number to indicate that the returned number of tokens
411 invoke a macro. The number returned might be less than the number of tokens
412 added because it can take a few tokens of lookahead to determine whether the
413 macro invocation is finished. The caller should call
414 macro_expander_get_expansion() to obtain the expansion. */
416 macro_expander_add (struct macro_expander *me, const struct token *token)
424 return me_add_arg (me, token);
427 return me_enclose (me, token);
430 return me_keyword (me, token);
433 return me_equals (me, token);
440 struct parse_macro_function_ctx
442 const struct tokens *tokens;
445 int nesting_countdown;
446 const struct macro_set *macros;
447 const struct macro_expander *me;
452 macro_expand (const struct tokens *tokens, int nesting_countdown,
453 const struct macro_set *macros, const struct macro_expander *me,
454 bool *expand, struct tokens *exp);
457 parse_macro_function (struct parse_macro_function_ctx *ctx,
458 struct substring function,
459 int min_args, int max_args)
461 const struct token *tokens = ctx->tokens->tokens;
462 size_t n_tokens = ctx->tokens->n;
464 if (!ss_equals_case (tokens[0].string, function))
467 size_t lparen_idx = *ctx->idx + 1;
468 if (lparen_idx >= n_tokens || tokens[lparen_idx].type != T_LPAREN)
470 printf ("`(' expected following %s'\n", function.string);
474 *ctx->args = (struct tokens) { .n = 0 };
476 size_t i = lparen_idx + 1;
477 for (size_t j = i; ; j++)
481 printf ("Missing closing parenthesis in arguments to %s.\n",
486 int type = tokens[j].type;
487 if (type == T_LPAREN)
489 int paren_nesting_level = 1;
495 printf ("Missing closing parenthesis in argument %zu to %s.\n",
496 ctx->args->n + 1, function.string);
499 if (tokens[j].type == T_LPAREN)
500 paren_nesting_level++;
501 else if (tokens[j].type == T_RPAREN)
502 paren_nesting_level--;
504 while (paren_nesting_level != 0);
506 else if (type == T_RPAREN || type == T_COMMA)
508 const struct tokens unexpanded_arg = {
509 .tokens = CONST_CAST (struct token *, &tokens[i]),
512 struct tokens expanded_arg = { .n = 0 };
513 macro_expand (&unexpanded_arg, ctx->nesting_countdown, ctx->macros,
514 ctx->me, ctx->expand, &expanded_arg);
516 if (expanded_arg.n != 1)
518 printf ("argument %zu to %s must be a single token "
519 "(not %zu tokens)\n", ctx->args->n + 1, function.string,
521 tokens_uninit (&expanded_arg);
525 tokens_add (ctx->args, &expanded_arg.tokens[0]);
526 tokens_uninit (&expanded_arg);
529 if (type == T_RPAREN)
534 if (ctx->args->n < min_args || ctx->args->n > max_args)
536 printf ("Wrong number of argument to %s.\n", function.string);
543 tokens_uninit (ctx->args);
548 macro_expand (const struct tokens *tokens, int nesting_countdown,
549 const struct macro_set *macros, const struct macro_expander *me,
550 bool *expand, struct tokens *exp)
552 if (nesting_countdown <= 0)
554 printf ("maximum nesting level exceeded\n");
555 for (size_t i = 0; i < tokens->n; i++)
556 tokens_add (exp, &tokens->tokens[i]);
560 for (size_t i = 0; i < tokens->n; i++)
562 const struct token *token = &tokens->tokens[i];
563 if (token->type == T_MACRO_ID && me)
565 const struct macro_param *param = macro_find_parameter_by_name (
566 me->macro, token->string);
569 printf ("expand %s to:\n", param->name);
570 const struct tokens *arg = me->args[param - me->macro->params];
571 tokens_print (arg, stdout);
572 if (*expand && param->expand_arg)
573 macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
575 for (size_t i = 0; i < arg->n; i++)
576 tokens_add (exp, &arg->tokens[i]);
583 struct macro_expander *subme;
584 int retval = macro_expander_create (macros, token, &subme);
585 for (size_t j = 1; !retval; j++)
587 static const struct token stop = { .type = T_STOP };
588 retval = macro_expander_add (
589 subme, i + j < tokens->n ? &tokens->tokens[i + j] : &stop);
594 macro_expand (&subme->macro->body_tokens, nesting_countdown - 1,
595 macros, subme, expand, exp);
596 macro_expander_destroy (subme);
600 macro_expander_destroy (subme);
603 if (token->type != T_MACRO_ID)
605 tokens_add (exp, token);
610 struct macro_function
616 static const struct macro_function functions[] = {
618 { "!concat", 1, INT_MAX },
624 { "!unquote", 1, 1 },
631 struct parse_macro_function_ctx ctx = {
635 .nesting_countdown = nesting_countdown,
640 if (parse_macro_function (&ctx, ss_cstr ("!length"), 1, 1))
642 char *s = token_to_string (&args.tokens[0]);
643 struct token t = { .type = T_POS_NUM, .number = strlen (s) };
644 tokens_add (exp, &t);
647 tokens_uninit (&args);
649 else if (parse_macro_function (&ctx, ss_cstr ("!blanks"), 1, 1))
651 if (args.tokens[0].type != T_POS_NUM)
652 printf ("argument to !BLANKS must be positive integer\n");
655 struct string s = DS_EMPTY_INITIALIZER;
656 ds_put_byte_multiple (&s, ' ', args.tokens[0].number);
657 struct token t = { .type = T_ID, .string = s.ss };
658 tokens_add (exp, &t);
661 tokens_uninit (&args);
663 else if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
665 else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
668 tokens_add (exp, token);
674 macro_expander_get_expansion (struct macro_expander *me, struct tokens *exp)
676 for (size_t i = 0; i < me->macro->n_params; i++)
678 printf ("%s:\n", me->macro->params[i].name);
679 tokens_print (me->args[i], stdout);
683 macro_expand (&me->macro->body_tokens, settings_get_mnest (),
684 me->macros, me, &expand, exp);
686 printf ("expansion:\n");
687 tokens_print (exp, stdout);