Standard macros just interpolate expressions literally. But phrep also allows for "complex macros", which utilize PHP callbacks for more clever code generation.

They can be defined by attaching an @ to macro names. The declaration body becomes a PHP code generation callback then.

The callback obviously took care of returning the literal abc string enclosed in double quotes for PHP code context.

You may ignore the following paragraphs. It's actually rather simple and obvious to utilize.

Function body

The substitution code should be enclosed in {} curly braces. This is mostly for legibility / decorative purposes. Technically it's not required:

#macro  XY@(i,str)  return $i                 \
                         . " . 'and' . "      \
                         . $str;

Multi-line #defines however strictly need backslash-escaped \ linebreaks.

Macro parameters

The macro arguments, $i and $str here, are stringified expression literals. The above example macro reference used 3 as integer parameter. Would the macro have been called as MSTR@(2+1, abc), then $i would contain 2+1 however.

Which is exactly how standard macros receive their parameters. This approach can incur extra work for code generation callbacks. With some extra work, it however permits to act on more involving expressions.

For example an EACH@($a && $b && $c) macro could explode its argument just on &&, then reshuffle the remaing expressions. See the NULLSAFE@ example.

Variadic functions

You can also declare a variadic parameter.

#define  LIT@(x,y,args...)  { return var_export($args,1); }

There $args could hold an array of stringified extra arguments or expressions, such as ['arg3', '$expr+4', '"arg5"'].

Note the C-style `args...` instead of PHPs `...args`.

Token parameters

Apart from named parameters $i, $str and $args, there's always an implied $token parameter to complex macro callbacks as well.

It holds a list of parser tokens from all macro arguments.

Working on a token string is of course more involving. Therefore you often want to split out the processing to an externalized helper function even:

#define  CONFIGMACRO@(expr)  { return \my\macro\func($expr); }

Utilize the config file for declaring any handler funcs. They could later be converted back to inline #defines and .def includes for distribution.

Plain macros or using stringified parameters already suffice for most cases. Complex token transformations only start to make sense if you want to introduce new syntax variations/shortcuts.

Macro helpers

There are a few built-in helper functions for token lists:

It's also planned to prepare a hook to nikic/PHP-Parser in later versions. To simplify working with expression trees, instead of plain token lists.

Why @ for macro names?

The @ suffix is used for complex macro names in phrep. And that's both for visualization and because it's easier to uncover combos of T_STRING and @ tokens. They also can't overlap with existing code/syntax.

Other uses

Now complex macros can also be utilized to implement some more weird syntax constructs. For instance they can semi-parse raw expression sections.

See examples/config/.