Translation of Programming Languages

Klein is a small, mostly functional programming language that is designed specifically to be used as a manageable source language in a course on compiler design and implementation. Though small and simple, the language is Turing-complete. Klein was motivated by Doug Baldwin's old teaching language MinimL.

For more on the name **Klein** and its logo, see
the endnotes.

Here are a complete grammar for Klein and a list of syntax features not included in the grammar.

Following the grammar and list of syntax features are
*informal* and possibly *incomplete* textual
descriptions of many of the language's features. The purpose
of these sections is to clarify the syntax of the language.
They are not sufficient on their own; they complement the
formal definition. If you have any questions, please ask
sooner rather than later.

Here is the grammar for Klein. In this grammar,
** ε**, the lowercase Greek letter epsilon,
stands for the empty string. It indicates that nothing is a
legal alternative.

<PROGRAM> ::= <DEFINITIONS> <DEFINITIONS> ::=ε| <DEF> <DEFINITIONS> <DEF> ::=function<IDENTIFIER>(<FORMALS>) :<TYPE> <BODY> <FORMALS> ::=ε| <NONEMPTYFORMALS> <NONEMPTYFORMALS> ::= <FORMAL> | <FORMAL>,<NONEMPTYFORMALS> <FORMAL> ::= <IDENTIFIER>:<TYPE> <BODY> ::= <PRINT-STATEMENT> <BODY> | <EXPR> <TYPE> ::=integer|boolean<EXPR> ::= <EXPR><<SIMPLE-EXPR> | <EXPR>=<SIMPLE-EXPR> | <SIMPLE-EXPR> <SIMPLE-EXPR> ::= <SIMPLE-EXPR>or<TERM> | <SIMPLE-EXPR>+<TERM> | <SIMPLE-EXPR>-<TERM> | <TERM> <TERM> ::= <TERM>and<FACTOR> | <TERM>*<FACTOR> | <TERM>/<FACTOR> | <FACTOR> <FACTOR> ::=if<EXPR>then<EXPR>else<EXPR> |not<FACTOR> | <IDENTIFIER>(<ACTUALS>)| <IDENTIFIER> | <LITERAL> |-<FACTOR> |(<EXPR>)<ACTUALS> ::=ε| <NONEMPTYACTUALS> <NONEMPTYACTUALS> ::= <EXPR> | <EXPR>,<NONEMPTYACTUALS> <LITERAL> ::= <NUMBER> | <BOOLEAN> <PRINT-STATEMENT> ::=print (<EXPR>)

Note: The whitespace in the grammar is intended to aid readability. It is not significant.

These are the reserved words and symbols of Klein:

integer boolean true false + - * / < = ( ) if then else not and or , : (* *) function main print

Integers must be in the range -2^{32} to
2^{32}-1.

Identifiers must be no longer than 256 characters.

Klein keywords and identifiers are case-sensitive. Upper- and
lower-case letters are *not* considered equivalent.

** main** and

A comment in Klein begins with the characters ** (***
and continues up to the matching characters

Klein operators and punctuation are self-delimiting.

A function may have zero or more formal parameters. The scope of a formal parameter is the body of the function. Arguments are passed by value.

Binary operators and function calls evaluate their arguments from left to right.

Whitespace consists only of blanks, tabs, and end-of-line
characters. It serves to separate tokens. Whitespace characters
may *not* appear inside a literal, identifier, keyword, or
operator. Otherwise, whitespace is insignificant.

All data in Klein are integers or booleans, and nearly every element in a program is an expression that produces an integer result or a boolean result.

There are only two boolean values. The two primitive boolean
literals are ** true** and

Integer literals are strings of digits. There are no leading plus or minus signs to indicate positive or negative values; all integer literals are positive. Leading zeros are not permitted for non-zero integer literals.

User-defined identifiers are strings beginning with a letter
and consisting of letters, digits, and the underscore
( ** _** ).

The language provides the following kinds of expression.

*Arithmetic*

Adds, subtracts, multiplies, or divides two integers.

x + y x - y x * y x / y

*Comparison*

Compares two integers, yielding one of the boolean values
** true** or

x < y x = y

*Boolean Connective*

Negates a single boolean value, or computes the disjunction or
conjunction of two boolean values. The unary ** not**
yields

not x x or y x and y

** or** and

*Conditional Selection*

Evaluates a test expression, and uses its value to select one
of two other expressions to evaluate. Yields the value of the
first of these expressions if the test expression produces a
true value, and the value of the second if the test expression
yields a false value. The **else** clause is required.

For example:

if flag < 0 then x + y else x - y

produces the sum of x and y if flag is less than 0; otherwise, it produces their difference.

*Function Call*

Applies a function to zero or more arguments, and yields the result. All functions return either an integer value or a boolean value; Klein has no notion of a "void" function.

For example:

f( x+y, 1 )computes the sum of x and y, passes that value and a 1 to the function f, and produces the value returned by applying the function to its arguments.

*Miscellaneous*

Compound expressions can be nested to any depth.

Note that the only user-defined identifiers in Klein are the names of functions and the names of formal parameters to functions. There are no "variables".

Each function declaration consists of the function's name, its formal parameters and their types, the type of the function, and its body.

Function names are unique.

A function may refer only to its formal parameters and to other functions.

A Klein function may call itself.

For the purposes of user interaction, Klein provides the
primitive function ** print(expression)**.
For example:

print( x+y )

** print** writes its argument on standard output,
followed by a new line character.

Unlike all user-defined functions, the value of a call to
** print** is undefined. For this reason, if a
function contains a call to

A Klein program consists of a sequence of function definitions.
Every program must define a function named ** main**,
which is called first when the program runs.

Users can provide arguments to ** main** on the
command line. The result returned by

For example, here is a complete Klein program that computes the absolute value of its argument:

function main( n : integer ) : integer if n < 0 then -n else n

If this program were compiled into an executable file named
** abs**, then running it under Unix might look
something like this:

mac os x >abs -3 3

**The Language's Name**

I chose the name to indicate the size of the language.kleinis the German word for "small" or "little". It is one of the first German words I learned back in the eighth grade.

There are a number of projects in the software world named "Klein". In particular, this language is not affiliated in anyway with the now-defunct Klein project at Sun Microsystems, which was "a Self virtual machine written fully in Self". Self is a very cool prototype-based object-oriented programming language -- check it out.

**The Language's Logo**

The Klein logo is a picture of a bottle whose neck feeds in on itself. This is an example of a Klein bottle, "a non-orientable surface ... in which notions of left and right cannot be consistently defined". A Möbius strip is a non-orientable surface with boundary; a Klein bottle is a non-orientable surface without a boundary.

The bottle is not called "Klein" because it is small. It shares its name with German mathematician Felix Klein, who first described this mathematical object in 1882. I chose the logo because it happens to have an attractive visual representation.