Previous: *Parser, Up: Parser Language


14.11.3 Parser-language Macros

The parser and matcher languages provide a macro facility so that common patterns can be abstracted. The macro facility allows new expression types to be independently defined in the two languages. The macros are defined in hierarchically organized tables, so that different applications can have private macro bindings.

— special form: define-*matcher-macro formals expression
— special form: define-*parser-macro formals expression

These special forms are used to define macros in the matcher and parser language, respectively. Formals is like the formals list of a define special form, and expression is a Scheme expression.

If formals is a list (or improper list) of symbols, the first symbol in the list is the name of the macro, and the remaining symbols are interpreted as the formals of a lambda expression. A lambda expression is formed by combining the latter formals with the expression, and this lambda expression, when evaluated, becomes the expander. The defined macro accepts the same number of operands as the expander. A macro instance is expanded by applying the expander to the list of operands; the result of the application is interpreted as a replacement expression for the macro instance.

If formals is a symbol, it is the name of the macro. In this case, the expander is a procedure of no arguments whose body is expression. When the formals symbol appears by itself as an expression in the language, the expander is called with no arguments, and the result is interpreted as a replacement expression for the symbol.

— procedure: define-*matcher-expander identifier expander
— procedure: define-*parser-expander identifier expander

These procedures provide a procedural interface to the macro-definition mechanism. Identifier must be a symbol, and expander must be an expander procedure, as defined above. Instances of the define-*matcher-macro and define-*parser-macro special forms expand into calls to these procedures.

The remaining procedures define the interface to the parser-macros table abstraction. Each parser-macro table has a separate binding space for macros in the matcher and parser languages. However, the table inherits bindings from one specified table; it's not possible to inherit matcher-language bindings from one table and parser-language bindings from another.

— procedure: make-parser-macros parent-table

Create and return a new parser-macro table that inherits from parent-table. Parent-table must be either a parser-macro table, or #f; usually it is specified as the value of global-parser-macros.

— procedure: parser-macros? object

This is a predicate for parser-macro tables.

— procedure: global-parser-macros

Return the global parser-macro table. This table is predefined and contains all of the bindings documented here.

There is a “current” table at all times, and macro definitions are always placed in this table. By default, the current table is the global macro table, but the following procedures allow this to be changed.

— procedure: current-parser-macros

Return the current parser-macro table.

— procedure: set-current-parser-macros! table

Change the current parser-macro table to table, which must satisfy parser-macros?.

— procedure: with-current-parser-macros table thunk

Bind the current parser-macro table to table, call thunk with no arguments, then restore the original table binding. The value returned by thunk is the returned as the value of this procedure. Table must satisfy parser-macros?, and thunk must be a procedure of no arguments.