# Producing Specifications

## Output Files

```outputfile ::= (`@N' | `@O') filename [`=='] `@{' expression `@}' .
```

When processing to obtain the specification, these directives create an output file named filename that contains an expression consisting of text and calls to macros (defined later). Filenames must be unique within a FunnelWeb-file.

The `=='-part is optional an can be left out. It is included to pair the same option for macros.

When processing to obtain the documentation, the expression is printed using the `tt font`. Above, the filename is set and below a note is included that this code is attached to an output file.

The difference between `@N' and `@O' lies in the way in which the files are treated by Eli. A file extracted by `@O' becomes part of the specification described by the FunnelWeb file, while a file extracted by `@N' does not. Most files should be extracted by `@O'; non-product files, extracted by `@N', are those that are used in the derivation of product components, but are not themselves components of the product.

As an example of the use of a non-product file, consider the problem of making keywords case-insensitive but retaining case sensitivity in identifiers (see Making Literal Symbols Case Insensitive of Lexical Analysis). Here is a portion of a FunnelWeb file implementing such a processor:

```@O@<nolit.gla@>==@{
identifier: C_IDENTIFIER
@}

@N@<keyword.gla@>==@{
\$[a-z]+
@}

@O@<keyword.specs@>==@{
keyword.gla :kwd
@}
```

Note that the file `keyword.gla' can not form part of the final product specification. If it did, the specified processor would treat all completely lower case identifiers as comments! Nevertheless, file `keyword.gla' is necessary to specify the representation of the keywords in the grammar so that they can be extracted and processed separately (see Making Literal Symbols Case Insensitive of Lexical Analysis). Thus file `keyword.gla' is extracted by `@N', while the other files are extracted by `@O'.

## Extracting Output Files with Eli

Within Eli, the derivation `:fwGen` can be used to obtain a directory that contains all the output files contained in a FunnelWeb specification. With the sample specification from the Introduction, you can run following Eli-derivations:

`first.fw :fwGen !ls`
This generates a directory containing all the output files (only `helloworld.lido' in this case) and runs the command `ls` with its name.

`first.fw :fwGen/helloworld.lido>`
This generates a directory containing all the output files from `first.fw'. It then selects the file `helloworld.lido' and copies its contents to the standard output.

## Macros

A macro definition binds a unique macro name to a macro body containing an expression consisting of text, calls to other macros, and formal parameters. The syntax for a macro definition is as follows:

```macro ::= `@\$' name [formal_parameter_list]
[`@Z'] [`@M'] [`==' / `+='] `@{' expression `@}' .
```

The complexity of the macro definition syntax is mostly to enable the user to attach various attributes to the macro.

By default, a macro must be invoked exactly once by one other macro or by an output file command. However, if the user uses the `@Z` sequence in the macro definition, the macro is then permitted to be invoked zero times, as well as once. Similarly, if the user uses the `@M` sequence in the macro definition, the macro is permitted to be called many times as well as once. If both `@Z` and `@M` are present then the macro is permitted to be invoked zero, one, or many times.

The purpose of enforcing the default "exactly one call" rule is to flag pieces of code that the user may have defined in a macro but not hooked into the rest of the program. Experience shows that this is a common error. Similarly, it can be dangerous to multiply invoke a macro intended to be invoked only once. For example, it may be dangerous to invoke a scrap of non-idempotent initialization code in two different parts of the main function of a program!

If the text string `==` (or nothing) follows the macro name, the expression that follows is the entire text of the macro body. If the text string `+=` follows the macro name, then more than one such definition is allowed (but not required) in the document and the body of the macro consists of the concatenation of all such expressions in the order in which they occur in the input file. Such a macro is said to be additive and is additively defined. Thus a macro body can either be defined in one place using one definition (using `==`) or it can be distributed throughout the input file in a sequence of one or more macro definitions (using `+=`). If neither `==` and `+=` are present, FunnelWeb assumes a default of `==`.

Additively defined macros can have parameter lists and `@Z` and `@M` attributes, but these must be specified only in the first definition of the macro. However, `+=` must appear in each definition.

### Names

Names are used to identify macros and sections. A name consists of a sequence of from zero to 80 printable characters, including the blank character. End of line characters are not permitted in names. Names are case sensitive; two different macros are permitted to have names that differ in case only. Like free text, names are typeset by FunnelWeb and are safe from misinterpretation by the target typesetter. For example, it is quite acceptable to use the macro name `@<\medskip@>` even if the target typesetter is TeX.

```name ::= `@<' name_text `@>' .

name_text ::= {ordinary_char / text_special} .

```

### Formal Parameter Lists

FunnelWeb allows macros to have up to nine macro parameters, named `@1`, `@2`,..., `@9`. If a macro does not have a formal parameter list, it is defined to have no parameters, and an actual parameter list must not appear at the point of call. If a macro has a formal parameter list, it is defined to have one or more parameters, and a corresponding actual parameter must be supplied for each formal parameter, at the point of call.

Because FunnelWeb parameters have predictable names, the only information that a formal parameter list need convey is how many parameters a macro has. For this reason a formal parameter list takes the form of the highest numbered formal parameter desired, enclosed in parentheses sequences.

```formal_parameter_list ::= `@(' formal_parameter `@)' .

formal_parameter ::= `@1' / `@2' / `@3' / `@4' / `@5' /
`@6' / `@7' / `@8' / `@9' .
```

## Macro Calls

A macro call consists of a name optionally followed by an actual parameter list. The number of parameters in the actual parameter list must be the same as the number of formal parameters specified in the definition of the macro. If the macro has no formal parameter list, its call must have no actual parameter list.

```macro_call ::= name [actual_parameter_list] .

actual_parameter_list ::= `@(' actpar { `@,' actpar } `@)' .

actpar ::= expression /
( whitespace `@"' expression `@"' whitespace ) .

whitespace ::= {` ' / eol} .
```

FunnelWeb allows parameters to be passed directly, or delimited by special double quotes. Each form is useful under different circumstances. Direct specification is useful where the parameters are short and can be all placed on one line. Double quoted parameters allow whitespace on either side (that is not considered part of the parameter) and are useful for laying out rather messy parameters. Here are examples of the two forms.

```@<Generic Loop@>@(
@"x:=1;@"  @,
@"x<=10;@" @,
@"print "x=%u, x^2=%u",x,x*x;
x:=x+1;@+@"
@)

@<Colours@>@(red@,green@,blue@,yellow@)
```

As shown, the two forms may be mixed within the same parameter list.

Formal parameters can appear in the expressions forming macro bodies in accordance with the syntax rules defined above. A formal parameter expands to the text of the expansion of its corresponding actual parameter. There is nothing preventing a formal parameter being provided as part of an expression that forms an actual parameter. If that happens, the formal parameter is bound to the actual parameter of the calling macro, not the called macro. After the following definitions,

```@\$@<One@>@(@1@)=@{A walrus in @1 is a walrus in vain.@}
@\$@<Two@>@(@1@)=@{@<One@>@(S@1n@)@}
```
the call

```@<Two@>@(pai@)
```
will result in the expansion

```A walrus in Spain is a walrus in vain.
```

## Controlling Macro Expansion

### Indentation

When FunnelWeb expands a macro, it can do so in two ways. First it can treat the text it is processing as a one-dimensional stream of text, and merely insert the body of the macro in place of the macro call. Second, it can treat the text of the macro as a two dimensional object and indent each line of the macro body by the amount that the macro call itself was indented. Consider the following macros.

```@\$@<Loop Structure@>@{@-
i=1;
while (i<=N)
@<Loop body@>
endwhile
@}

@\$@<Loop body@>@{@-
a[i]:=0;
i:=i+1;@}
```

Under the regime of no indentation the loop structure macro expands to:

```i=1;
while (i<=N)
a[i]:=0;
i:=i+1;
endwhile
```

Under the regime of blank indentation the loop structure macro expands to:

```i=1;
while (i<=N)
a[i]:=0;
i:=i+1;
endwhile
```

The `indentation` pragma determines which of these two regimes will be used to expand the macros when constructing the product files. The syntax of the pragma is:

```pragma_indent ::= ps `indentation' s `=' s (`blank' / `none') .

s ::= {` '}+ .

ps ::= (`@p' / `@P') ` ' .
```

Its two forms look like this:

```@p indentation = blank
@p indentation = none
```

In the current version of FunnelWeb, the indentation regime is an attribute that is attached to an entire run of Tangle; it is not possible to bind it to particular product files or to particular macros. As a result, it doesn't matter where indentation pragmas occur in the input file or how many there are so long as they are all the same. By default FunnelWeb uses blank indentation.

### Output Length

FunnelWeb also keeps an eye on the line lengths of product files and flags all lines longer than a certain limit with error messages. Unlike the maximum input line length, which can vary dynamically throughout the input file, the maximum product file line length remains fixed throughout the generation of all the product files. The maximum product file line length pragma allows this value to be set. If there is more than one such pragma in an input file, the pragmas must all specify the same value.

```pragma_moll ::= ps `maximum_output_line_length' s `=' s numorinf .

s ::= {` '}+ .

ps ::= (`@p' / `@P') ` ' .

number ::= { decimal_digit }+ .

numorinf ::= number / `infinity' .
```

The default value is 80 characters.