Package de.dante.extex.interpreter.primitives

This package contains classes for the primitives which are mapped to Java code.

See:
          Description

Class Summary
Ignorespaces This class provides an implementation for the primitive \ignorespaces.
Relax This class provides an implementation for the primitive \relax.
 

Package de.dante.extex.interpreter.primitives Description

This package contains classes for the primitives which are mapped to Java code. Those primitives are implemented directly opposed to the implementation as macros.

The binding to the appropriate names is performed during initialization of the interpreter. The information may come from a configuration file or a format file.

Writing New Primitives

The core primitives of ExTeX are written in Java and bound to control sequences or active characters. In this section we will explain how to write new primitives in Java.

Executable Code

Executable primitives are those primitives which can be invoked in a left-hand-side context of the expansion. This is the case whenever the next top-level macro is treated. You can consider for example the treatment of the macro \def as such a case:

     \def\abc{123}
In this example \def is an executable primitive.

Executable code has to implement the interface Code. Doing this directly is not hard. Nevertheless the abstract base class AbstractCode is provided which contains default implementations for all methods already. Thus only the interesting methods have to be overwritten.

In the simplest case only a constructor with one String argument and the method execute() has to be defined. Such an empty frame can be seen in the following example:

    package my.package;

    import de.dante.extex.interpreter.context.Context;
    import de.dante.extex.interpreter.Flags;
    import de.dante.extex.interpreter.TokenSource;
    import de.dante.extex.interpreter.exception.InterpreterException;
    import de.dante.extex.interpreter.type.AbstractCode;
    import de.dante.extex.typesetter.Typesetter;
 
    class MyPrimitive extends AbstractCode {

      public MyPrimitive(final String name) {
        super(name);
        // initialization code -- if required
      }

      public boolean execute(final Flags prefix,
                             final Context context,
                             final TokenSource source,
                             final Typesetter typesetter
                            ) throws InterpreterException {
        // implement the execution behaviour here
        return true;
      }
    }

In the method execute() you have access to other components. This can be utilized to implement the desired functionality. The following parameters are provided:

Flags prefix
This parameter gives access to prefix arguments like \immediate or \global. For this purpose the class Flags provides appropriate getters.

You can even modify the flags passed to the method. Usually you should invoke prefix.clear() somewhere in your implementation when the prefix is not needed any more. If this method is omitted then the prefix is passed on to the next execution. This can be desirable if you want to implement a prefix primitive yourself.

Context context
The context provides reading and writing access to the data stored in the processor. This information is the memory. It is written to file when dumping a format. Refer to the documentation of the interface Context for details.
TokenSource source
The source provides access to the token stream. It can be used to get the next tokens if required. For example when implementing a primitive like \def it is necessary to read the next tokens as arguments: the macro name, the parameter pattern, and the expansion text.

The token source can also be used to push tokens to the input stream to be read back in later. This feature is used when implementing expandable primitives.

Typesetter typesetter
The typesetter is the component which collects nodes and finally sends them to the document writer. With access to this component it is possible to produce some output to the paper.

The return value indicates how to deal with prefix flags. The usual behaviour is to return true. This indicates that the flags should be cleared afterwards. For those primitives which modify the prefix flags the return value false must be used.

Registering New Macros

The primary way to register new macros is in the configuration file used by ExTeX. For example the default file is located in the package config and named extex.xml. There you can find lines like the following one:

     <define name="def"
              class="de.dante.extex.interpreter.primitives.macro.Def"/>

To add another primitive to ExTeX you should make a copy of this configuration file under a different name and add a line like the one shown above:

     <define name="myPrim"
              class="my.package.MyPrimitive"/>
Now you can invoke ExTeX on the command line with the parameter -configuration or add a line extex.config to your .extex file pointing ExTeX to your new configuration file:
     extex -configuration config/myExTeX.xml
This is enough. In the instance of ExTeX with these settings the new macro \myPrim is defined and points to your code for execution.

Registering New Macros Dynamically

One extension provided with ExTeX contains a dynamic definition of new macros. Those macros are defined at runtime. The assignment of the Java code to the macro name can be controlled with the help of a primitive. Check out whether the macro \javadef is defined in one of the configuration files provided and consult the documentation.

Exceptions

The implementing Java code for new primitives can signal abnormal situations with the help of exceptions. The exceptions used should be derived from InterpreterException. RuntimeExceptions and Errors or derived classes should not be used.

ExTeX provides means for externalzing strings. Thus it should be made easy to translate the messages to other languages. For this purpose the class Localizer is provided. See the documentation of this class for details.

Assignments

Assignments are a special kind of executable code. TeX defines that the parameter \globaldef is evaluated and the macro \afterassignment has some effect. To ease the development of assignments the abstract base class AbstractAssignment is provided. This class defines the method execute() appropriately. The only task left is to overwrite the method assign() to perform the assignment.

    package my.package;

    import de.dante.extex.interpreter.contect.Context;
    import de.dante.extex.interpreter.Flags;
    import de.dante.extex.interpreter.TokenSource;
    import de.dante.extex.interpreter.exception.InterpreterException;
    import de.dante.extex.interpreter.type.AbstractAssignment;
    import de.dante.extex.typesetter.Typesetter;
 
    class MyAssign extends AbstractAssignment {

      public MyAssign(final String name) {
        super(name);
        // initialization code -- if required
      }

      public void assign(final Flags prefix,
                         final Context context,
                         final TokenSource source,
                         final Typesetter typesetter
                        ) throws InterpreterException {
        // implement the assignment here
      }
    }

The arguments of the method assign() are the same as the arguments of execute() described above. In contrast to the remarks made there it is not necessary to return something. The clearing of the flags is done in the abstract class automatically.

Expandable Code

Some macros are expandable. This means that they can be used on the right-hand-side of an invocation as well. This feature is expressed by the interface ExpandableCode. Since Java does not allow multiple inheritance no abstract base class is provided.

To implement an expandable primitive it is sufficient to declare the interface for the class and implement the method expand(). This is sketched in the following example:

    package my.package;

    import de.dante.extex.interpreter.contect.Context;
    import de.dante.extex.interpreter.Flags;
    import de.dante.extex.interpreter.TokenSource;
    import de.dante.extex.interpreter.exception.InterpreterException;
    import de.dante.extex.interpreter.type.AbstractCode;
    import de.dante.extex.interpreter.type.ExpandableCode;
    import de.dante.extex.typesetter.Typesetter;
 
    class MyExpandable extends AbstractCode implements ExpandableCode {

      public MyExpandable(final String name) {
        super(name);
        // initialization code -- if required
      }

      public boolean execute(final Flags prefix,
                             final Context context,
                             final TokenSource source,
                             final Typesetter typesetter
                            ) throws InterpreterException {
        // implement the execution behaviour here
        return true;
      }

      public void evaluate(final Flags prefix,
                           final Context context,
                           final TokenSource source,
                           final Typesetter typesetter
                          ) throws InterpreterException {
        // implement the evaluation behaviour here
      }
    }
The parameters of evaluate() are ikdentical to those of execute(). But note, that the expected behaviour of evaluate() is that it does not modify the context or the typesetter but exclusively modifies the token source. Usually it reads some tokens and piuts back its result to the token stream.

Conditionals – Also Called Ifs

Conditionals are special because they modify the flow of control. In the macro programming language of TeX this may lead to a mode where tokens are absorbed at high speed. In this mode is necessary to identify conitionals to honor matching pairs of start and end tokens.

All neccesary actions are performed by the abstract base class AbstractIf. The only thing to do is to implement the method conditional() which computes whether the then or the else branch should be considered relevant. This is shown in the following example:

    package my.package;

    import de.dante.extex.interpreter.primitives.conditional.AbstractIf;
    import de.dante.extex.interpreter.contect.Context;
    import de.dante.extex.interpreter.Flags;
    import de.dante.extex.interpreter.TokenSource;
    import de.dante.extex.interpreter.exception.InterpreterException;
    import de.dante.extex.typesetter.Typesetter;
 
    class MyIf extends AbstractIf {

      public MyIf(final String name) {
        super(name);
        // initialization code -- if required
      }

      public boolean conditional(final Flags prefix,
                                 final Context context,
                                 final TokenSource source,
                                 final Typesetter typesetter
                                ) throws InterpreterException {
        // implement the evaluation of the conditional here
	return result;
      }
    }
The parameters are the same as the parameters for execute() described above.

Note that any conditional is expandable automatically. Thus it should not modify the context or the typesetter.

Interaction With Other Macros

Several primitives of ExTeX are implemented generically. Let us consider for example the macro \the. This primitive simply gathers the next token and delegates the task of providing an appropriate definition for \the to the definition of this token.

The ability to be usable after \the is expressed with the help of the interface Theable. Thus it is enough for a primitive to implement this interface if it needs to be usable after \the.

The following list contains some macros of TeX and the related interfaces:

\advance Advanceable
\box Boxable
\count CountConvertible
\dimen DimenConvertible
\divide Dividable
\font FontConvertible
\multiply Multiplyable
\show Showable
\showthe Theable
\the Theable