|ANN: The ML/I Macro processor firstname.lastname@example.org (Parzival Herzog) (2002-04-06)|
|Re: ANN: The ML/I Macro processor Trevor.Jenkins@suneidesis.com (2002-04-07)|
|From:||Parzival Herzog <email@example.com>|
|Date:||6 Apr 2002 23:37:53 -0500|
|Organization:||Shaw Residential Internet|
|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 http://members.shaw.ca/parz 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
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
+ 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.
+ 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
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.
Return to the
Search the comp.compilers archives again.