ANN: The ML/I Macro processor

Parzival Herzog <>
6 Apr 2002 23:37:53 -0500

          From comp.compilers

Related articles
ANN: The ML/I Macro processor (Parzival Herzog) (2002-04-06)
Re: ANN: The ML/I Macro processor (2002-04-07)
| List of all articles for this month |

From: Parzival Herzog <>
Newsgroups: comp.compilers
Date: 6 Apr 2002 23:37:53 -0500
Organization: Shaw Residential Internet
Keywords: macros, available
Posted-Date: 06 Apr 2002 23:37:53 EST

This is to announce that I am making available a new implementation of
an ancient classic.

Please refer to for more details.

A binary release for Win32 is available, and the source release should
work on any modern machine with an ANSI C compiler. It has been
verified to compile and run under Win2K, with Microsoft C, gcc, and
lcc, and under SuSE Linux (I386) with gcc.

I believe comp.compilers readers would likely be interested in this,
and if anyone can suggest another suitable venue for announcing
ML/I, I would appreciate the suggestion.

Send mail to: ml1 @ shaw . ca

                                                    The ML1 macro processor

      ML/I is an ancient (and very good) general purpose macro processor.
      Originally written in DEC PDP7 assembly language by Peter J. Brown of
      the University Mathematical Laboratory, Cambridge, England. Its
      "machine-independent logic" was then re-written in "L", a special
      purpose language. ML/I was thus made easily portable by writing ML/I
      macros to translate L to some target language, and by writing by hand
      a very simple run-time supporting L: the "machine-dependent logic".

      ML/I was widely ported in the 1970's, but is now all but forgotten. It
      deserves to be more widely known, because:
        1. It is a historically significant advance in macro-processing, and
              in code portability.
        2. It is still one of the most advanced macro-processors in
              existence. It is much superior to M4; it can be a useful
              alternative to other text processing tools such as awk or perl,
              especially when constructions that span more than one line or
              nested constructions need to be recognized, or comments and
              strings need to be processed. It is an ideal pre-processor for
              text formats such as HTML or XML.
        3. It is an example of how much can be done with very little computer
              resources. The original implementation had a code size of 3000
              18-bit words. It could do quite significant work on a 4096 word
        4. Its documentation is outstanding in its clarity, precision and
              usefulness. Instead of making something which is actually simple
              appear to be incredibly complex (like much that passes for
              advanced technology today,) it makes something quite complex,
              appear to be incredibly simple.

                                                          Main features of ML/I

How ML/I processes text, simplified

      ML/I processes input text by scanning for macro constructions stored
      in its environment. Constructions are recognized by their opening
      delimiter, which can consist of one or more indivisible sequences of
      characters or atoms. Text that does not occur within a macro construct
      is copied to the output.

      Once a construction is recognized, ML/I scans succeeding text for
      further delimiters, until it reaches a closing delimiter. At this
      point, a macro call has been recognized, and its delimiters and
      arguments have been enumerated. Each parsed argument may of course
      contain further macro constructions, and such parsing of nested
      constructs will consume delimiters that would otherwise be recognized
      as delimiters of an outer construction.

      The recognized macro is now evaluated, and the result of this
      evaluation is sent to the output, replacing the text of the call.
      Unlike some other macro-processors, ML/I does not re-scan the result
      of a macro evaluation. To evaluate the macro, ML/I adds the
      unevaluated macro arguments and delimiters to its environment, and the
      commences scanning the replacement text which is associated with the
      recognized macro. The scanning process of the replacement text is
      identical to the scanning process of the original source text, but it
      takes place in the context of a changed environment, so that the
      replacement text has access to the arguments and delimiters of the
      invoked macro.

      At any point in a scan, the environment can be augmented with further
      macro definitions, and these immediately affect the evaluation of
      subsequent text. Macro arguments are not evaluated until they are
      inserted into the replacement text; therefore a macro can control the
      environment under which its arguments are evaluated, and can even
      avoid evaluating one or more of its arguments altogether.

Types of macro constructs

      ML/I offers the following macro facilities:


                    + have opening and closing delimiters, and arbitrary interior
                        delimiter syntax, following a regular grammar.
                    + Arguments are referred to by number, and
                    + are unevaluated at the time of the call, and most often
                        evaluated at the point of insertion into replacement text.
                    + Delimiters are referred to by number, and can be examined and
                        inserted in the replacement text.
                    + Built in operation macros define new constructs, perform
                        assignments of integer expressions, and perform conditional
                        go tos within a text.


                    + have only opening and closing delimiters;
                    + have a predefined replacement text consisting of nothing,
                        delimiters only, or delimiters and text;
                    + can be defined as matched (like parentheses,) or not.
                    + Macros are not recognized within skips.
                    + Skips are useful for processing comments and other inactive
                        source text.


                    + have only opening and closing delimiters,
                    + are used to insert macro arguments, delimiters, (invisible)
                        jump labels and evaluated arithmetic expressions into
                        replacement text, and
                    + can determine whether inserted arguments
                              - are evaluated or not, and
                              - if evaluated, whether in the context of the dynamic
                                  naming scope, (environment as it exists at the point of
                                  insertion,) or the lexical naming scope (environment as
                                  it exists at the point where an argument was scanned;)
                              - have (unevaluated) leading and trailing spaces removed.

      Warning markers:

                    + consist of one delimiter (possibly with multiple atoms) only.
                    + In warning mode, macro calls are recognized only if preceded
                        by a warning marker.
                    + Multiple warning markers can be defined, and
                    + Warning markers and warning mode are a part of the evaluation
                        environment, so that local warnings can be defined, and
                        warning mode can be invoked or revoked in local contexts.
                    + Skips are recognized regardless of warning mode.


                    + consist of one delimiter only;
                    + can occur legally only outside of a construction, thus
                    + are used exclusively to stop runaway unclosed macro

      Exclusive namespace:
                    ML/I uses no reserved words in a context where such words must
                    conflict with names occurring in the subject text.

                    + There are just 20 built-in operation macro names. These names
                        are all in upper case, and begin with "MC". All these names
                        can be hidden from subject text by defining a global warning
                        marker that does not occur in the subject text.
                    + Builtin delimiters of operation macros can have their
                        spelling changed. This would be for convenience only, because
                        the contexts where builtin delimiters are recognized are
                        strictly distinguishable from subject text.
                    + There are no built-in quoting conventions. Instead, each
                        macro process must define one or more skips that function as
                        quotes appropriate to the context of the process.
                    + There is no built-in syntax for inserts. Each macro process
                        must define inserts suited to the process.
[ML/I is pretty cool. Maybe it's time to dust off my Trac processor again.

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.