Go to the first, previous, next, last section, table of contents.


Language Reference

Files processed with chpp are passed through two stages, which are, however, not sequential in nature but can rather be viewed as coroutines. The first stage processes commands (see section Commands). Command processing is a sequential process, i.e. no loops or recursions occur. The second stage is macro processing (see section The Meta-Char) and allows for loops as well as for recursion.

Commands

Command processing is line-oriented. It affects only lines which have, as their first non-whitespace character, the command-char (#). All other lines are passed through literally. Another function of command processing is the concatenation of lines: If the last character of a line is the backslash (\), then the backslash, the following newline and all leading whitespace of the next line are ignored.

A line invoking a command consists of optional whitespace at the beginning, the command-char #, optional whitespace, the command name, whitespace and the command arguments (if any). Thus, the following lines are all commands (given that the command names exist):

#abc
    #def arg
 #  ghi too many arguments

while the following lines are not:

this is a line without commands.
although this line contains a # it is not a command.

Command Reference

Command: include filename

Command: define name[(argname[,argname...])] value

Command: edefine name

Command: if condition

Command: ifdefined symbol
Command: ifdef symbol

Command: ifnotdefined symbol
Command: ifndef symbol

Command: error message

Command: discard
Command: disc

The Meta-Char

The second stage processes everything that is passed through by the first stage. It is called macro processing because its main use is the expansion of macros. There is just one special character for this stage, namely the meta-char (%). Only character sequences beginning with the meta-char are modified by the macro processing stage. All other characters are simply passed through. Since chpp was designed to be non-intrusive, even uses of the meta-char which do not correspond to the uses described in this chapter are copied verbatim. For example:

Temerature today is 10% above normal.
=> Temperature today is 10% above normal.

In cases where it is absolutely necessary that the meta-char not be interpreted as special, it can be quoted with itself (i.e. %%), yielding one meta-char. Example:

%<heinz=deinz>\
%%heinz evals to %heinz.
=> %heinz evals to deinz.

Data Types

The only primitive type in chpp is the string. Values of that type are referred to as scalars (see section Scalars). Values of any type can be combined arbitrarily to lists (see section Lists) and hashes (see section Hashes). Macros (see section Macros) also form a data type as they can be stored and used, even though they cannot be directly manipulated.

Scalars

Scalars are strings of arbitrary length (including the length 0).

Lists

Lists are ordered collections of arbitrary values indexed by consecutive numbers starting at 0. It follows that lists cannot have holes.

Hashes

Hashes are ordered collections of arbitrary values indexed by arbitrary scalars, i.e. they establish a so-called key/value mapping.

Macros

Macros are what most programming languages call functions. A macro in chpp is a body of text which can be parameterized by formal arguments which are implicitly assigned the values of the actual arguments in a local scope upon invocation. Thus, having defined a macro

%define(hello,name,Gruess Dich Gott %name!)

calling the macro with the argument Heinz

%hello(Heinz)

is semantically equivalent to

%locals(name,%<name=Heinz>Gruess Dich Gott %name!)

Variables

In order to be able to retain values for subsequent use it is necessary to store them in variables.

Accessing Variables

There are two different syntactic forms of variable access, called the short and the long form.

The short form consists of the meta-char followed by the variable name, e.g. %name. The variable name is taken as-is, i.e. is not evaluated. The variable name ends with the first char that is not a letter, a digit or the underscore (_). If a variable with the given name does not exist, the whole string is not interpreted as a variable access and is copied verbatim, i.e. %name evaluates to %name if there is no variable with the name name.

The long form consists of the meta-char followed by the variable name within angle brackets, e.g. %<name>. The variable name is evaluated before the variable is looked up, making it possible, for example, to use variable names containing right angle brackets: The term %<%">>>"> accesses the variable >>>. If a variable with the name does not exists, an error message is issued.

List and Hash Subscription

If the variable is a list or a hash, it can be subscribed by appending the index in brackets or curly braces to the name, in both the short and the long form. In order to access nested data structures, any number of such indexes can be used in one access, for example %name[3]{foo}.

Macro Invocation

A macro can be invoked by appending, in the short or long form of variable access, to the variable name or subscript a left parenthesis followed by the actual arguments separated by commas followed by a right parenthesis, e.g. %list(a,b). The value that is yielded by the macro invocation cannot be subscribed further, i.e. %list(a,b)[1] is not allowed. However, see section Subscribing Non-Variables.

Arguments of a macro-call are processed as follows: First, all leading and trailing whitespace from all arguments is removed. Then, the remaining strings are evaluated and the results are passed by-value as arguments to the macro. In order to pass an argument with leading or trailing whitespace to a macro, it must be quoted. For example:

%define(foobar,arg,"%arg")

%foobar(  xyz  )
=> "xyz"
%foobar(    )
=> ""
%foobar(  %"  "  )
=> "  "
%foobar(%"  xyz  ")
=> "  xyz  "

Subscribing Non-Variables

It is possible to subscribe values that are not variables, for example ones that are returned from macros, by using a modified long form of variable access. Instead of the variable name the expression yielding the value enclosed in parentheses is used. Upon evaluation, the expression is evaluated and all following subscriptions are applied to it. Example:

%<(%list(a,b))[1]>
=> b

Assignment

Assignment syntax is an enhancement of the long form of variable access. The last subscription (or the variable name, if no subscription is used) is followed by an equal sign (=) which is followed by an expression yielding the value to be assigned.

When assigning is attempted to an element of a list which is out of bounds, the list is enlarged. Elements between the formerly last element and the newly added element default to the empty string. Indexes less then 0 are not allowed.

Assigning to a key in a hash which is not part of it, adds the key/value pair to the hash.

It is not possible to assign to a subscript of a value which is not subscribable, i.e. it is not possible to do %<bar[3]=foo> if bar is not a list. To make bar an empty list, simply do %<bar=%list()>.

Assignment always copies the assigned value. In other words, there are no references or pointers. However, see section Planned but not yet Implemented Features.

Scoping Rules

chpp uses dynamic scoping (see, however, section Planned but not yet Implemented Features). This means that a variable is visible from the time its declaration is executed until the time its scope level ceases to exist. This also means that the scope of a variable is not immediately evident from the source of the program.

A new scope level is created when a macro is called and when the macro locals is executed. A macro call introduces a new scope level which contains all arguments to the macro, while local creates a new scope level with arbitrary variable names, which are initialized to be the empty string. The scope which is the one last created is called the innermost scope, while the outermost scope, which is always available, is referred to as the global scope.

Upon variable access all scopes starting with the innermost scope are tested for containing a variable with that name and, if one is found, that variable is used. If no scope containing a variable with that name is found, an error message is produced.

When a value is assigned to a variable, each scope, string with the innermost scope is searched for a variable bearing that name and, if one is found, the value is assigned to the variable in that scope. If the variable is not contained in any scope, a new variable is created in the global scope.

Arithmetic Expansion

chpp permits the evaluation of arithmetic expressions by enclosing the expression in square brackets ([]) preceded by the meta-char. The expression is first evaluated according to chpp rules and the resulting value is treated as an arithmetic expression which, in turn, yields a number. Whitespace between operators and operands is ignored. The following table is a summary of all available operators together with their arity. They are sorted by precedence, the first line being of the highest precedence. All binary operators evaluate from left to right. All operators have the same meaning as the corresponding operators in the C language.

@multitable @columnfractions .2 .8

  • Operators @tab Arity
  • !, ~, - @tab unary
  • *, /, % @tab binary
  • +, - @tab binary
  • <, >, <=, >= @tab binary
  • ==, != @tab binary
  • & @tab binary
  • ^ @tab binary
  • | @tab binary
  • && @tab binary
  • || @tab binary Precedence of operators can be overridden by using parentheses (()). In order to make arithmetic expressions more readable, it is allowed to refer to the values of variables within an arithmetic expression by writing its name--without a preceding meta-char. Note that subscription and macro invocation using this syntax is not allowed. Some examples:
    %[1+2]
    => 3
    %[1.5+3.3]
    => 4.800000
    %[3==3]
    => 1
    %[3!=3]
    => 0
    %[(1+2)*(3+4)]
    => 21
    %<x=4>%[%x+1]
    => 5
    %<x=4>%[x+1]
    => 5
    

    Quotation

    To prevent some string from evaluation, it can be quoted by enclosing it in a pair of double-quotes (""), preceded by the meta-char. The only special characters after the first double-quote are the quote-char (the backslash, \) and the closing double-quote. The quote-char gives special meanings to some characters following it: an n becomes a newline character and a t is interpreted as a tabulator. All other character preceded by the quote-char stand for themselves. This includes the quote-char and the double-quote, i.e. %"\\\"" evaluates to \".

    Explicit Evaluation

    In order to evaluate a string twice, for example to evaluate the contents of a variable, the string must be enclosed in curly braces ({}), preceded by the meta-char. Example:

    %<a=abc>%<b=%%a>%{%b}
    => abc
    


    Go to the first, previous, next, last section, table of contents.