epp_dodger(3)

πŸ“¦
version 29.0.6 Β· 3 versions
, in ubuntu stonking

πŸ’… epp_dodger β€” the Erlang module that skips the preprocessor and we stan

okay so bestie, welcome to epp_dodger, a module in the Erlang docs. Buckle up, this one's a baddie πŸŽ€


✨ NAME ✨

epp_dodger β€” bypassing the Erlang preprocessor. yeah, you heard me. dodging. sneaky. iconic behavior honestly πŸ’…


🌸 DESCRIPTION 🌸

So like, this module tokenizes and parses most Erlang source code without expanding preprocessor directives and macro applications, as long as those things are syntactically "well-behaved". Which, lowkey, is a whole mood πŸ¦‹

Here's the tea though: the normal parse trees from the erl_parse module cannot represent these things. Normally they get expanded by the Erlang preprocessor /stdlib/epp before the parser even sees them. So instead, epp_dodger builds an extended syntax tree using the erl_syntax module. Periodt. ✨


πŸ‘‘ DATA TYPES πŸ‘‘

  • errorinfo() :: erl_scan:error_info(). β€” yeah it's just the scanner's error info, she's borrowing it, it's fine πŸ’–
  • option() :: atom() | {atom(), term()}. β€” an option is either a plain atom or an atom-and-term pair. simple, elegant, no notes πŸŽ€

πŸ”₯ FUNCTIONS πŸ”₯

🫢 parse/3

parse(file:io_device(), erl_anno:location(), [option()]) ->
               {ok, erl_syntax:forms()}.

Reads and parses program text straight from an I/O stream, bestie 🌈

Characters are read from IODevice until end-of-file. Other than that little detail, the behavior is exactly the same as parse_file/2. StartLocation is the initial location, mmkay? πŸ“

See also: parse/2, parse_file/2, parse_form/2, quick_parse/3.


πŸ’– parse_file/2

parse_file(file:filename(), [option()]) ->
                    {ok, erl_syntax:forms()} | {error, errorinfo()}.

Reads and parses a file. the classic. the main character moment ✨

If it slays, you get {ok, Forms} back, where Forms is a list of abstract syntax trees representing the "program forms" of the file (peep erl_syntax:is_form/1 to see what counts as a form πŸ‘€).

Otherwise you get {error, errorinfo()} β€” typically when the file just could not be opened 😭

⚠️ no cap, important: parse errors do not make this function fail and do not return {error, errorinfo()}. They show up as error markers inside the returned list of forms instead. so like, check your forms, babes πŸ’€

Options:

  • {no_fail, boolean()} β€” if true, epp_dodger replaces any program forms that couldn't be parsed with nodes of type text (see erl_syntax:text/1), representing the raw token sequence of the form, instead of reporting a parse error. The default value is false.
  • {clever, boolean()} β€” if set to true, epp_dodger tries to repair the source code as it seems fit, in certain cases where parsing would otherwise fail. Currently, it inserts ++ operators between string literals and macros where it looks like concatenation was intended. And the default value is false. she's clever but she's off by default, respect πŸ™ˆ

See also: parse/2, quick_parse_file/1, erl_syntax:is_form/1.


πŸ¦‹ parse_form/3

parse_form(file:io_device(), erl_anno:location(), [option()]) ->
                    {ok, erl_syntax:forms(), erl_anno:location()} |
                    {eof, erl_anno:location()} |
                    {error, errorinfo(), erl_anno:location()}.

Reads and parses a single program form from an I/O stream 🎯

Characters are read from IODevice until an end-of-form marker is found (that's a period character followed by whitespace, iykyk) or until end-of-file. Apart from that, the behavior is similar to parse/3, except:

  • the return values also contain the final location, given that StartLocation is the initial location πŸ“
  • and {eof, Location} may be returned

See also: parse/3, parse_form/2, quick_parse_form/3.


🧚 quick_parse/3

quick_parse(file:io_device(), erl_anno:location(), [option()]) ->
                     {ok, erl_syntax:forms()}.

Similar to parse/3, but does a more quick-and-dirty processing of the code. no thoughts, head empty, just vibes πŸ’…

Peep quick_parse_file/2 for the details.

See also: parse/3, quick_parse/2, quick_parse_file/2, quick_parse_form/2.


⭐ quick_parse_file/2

quick_parse_file(file:filename(), [option()]) ->
                          {ok, erl_syntax:forms()} |
                          {error, errorinfo()}.

Similar to parse_file/2, but does a more quick-and-dirty processing of the code 🌈

Here's what she does: macro definitions and other preprocessor directives are discarded, and all macro calls are replaced with atoms. this is useful when you only care about the main structure of the code and not the details (ngl, relatable 🫠). Plus, the quick-parse method can usually handle more strange cases than the normal, more exact parsing.

Options: see parse_file/2. But heads up β€” for quick_parse_file/2, the option no_fail is true by default. so it's already in her chill mode 😌

See also: parse_file/2, quick_parse/2.


πŸ“ quick_parse_form/3

quick_parse_form(file:io_device(),
                 erl_anno:location(),
                 [option()]) ->
                    {ok, erl_syntax:forms(), erl_anno:location()} |
                    {eof, erl_anno:location()} |
                    {error, errorinfo(), erl_anno:location()}.

Similar to parse_form/3, but does a more quick-and-dirty processing of the code. See quick_parse_file/2 for details πŸ’–

See also: parse/3, parse_form/3, quick_parse_form/2.


πŸŽ€ tokens_to_string/1

tokens_to_string([term()]) -> string().

Generates a string corresponding to the given token sequence ✨

And the slayest part? The string can be re-tokenized to yield the same token list again. round trip, no cap, we love a reversible queen πŸ‘‘


<div style="text-align:center">🌈 πŸ’– ✨ πŸŽ€ πŸ¦‹ 🌸 πŸ’… 🫢 πŸ‘‘ 🌈</div>

and that's the whole page bestie!! brought to you by Ericsson AB, this is the syntax_tools 4.1 era, epp_dodger(3) β€” go forth and dodge some preprocessors, you got this πŸ’œβœ¨

πŸ“¦ where this page comes from