The next step in developing the complete compiler is to define the language that it will compile. The language designed for this purpose is called SPL - Simple Programming Language. In some respects it is a subset of the popular languages Pascal and Algol, but with the restriction that numbers are limited to the range 0 to 255, and that the language includes only the essential types of statement.
Programs in SPL are written as lines of text; the line numbers have no significance, except when editing. Spaces must be used to separate words, and must not occur within words, but otherwise they are ignored and can be added to make the structure of programs clearer.
All variable names, array names, procedure names, and labqls, can consist of up to six letters, all of which are significant. None of the language words may be used as symbols. On the BBC Computer all symbols and language words are in lower case; however, on the Atom, and in the following examples, upper case is used.
Any text between brackets '{' and '}' is ignored by the compiler, and can be inserted, to comment SPL programs, anywhere spaces are permitted.
Programs normally consist of a procedure such as the following:
PROC MAIN(); BEGIN stmt; stmt; ... stmt END
where 'stmt' represents any of the statements described below. The statements in the body of the procedure between BEGIN and END are separated by semi-colons.
SPL contains the following statements:
Arrays are declared with the ARRAY statement. For example:
ARRAY MAX[3],B[2]
reserves space for arrays with elements:
MAX[0], MAX[1], MAX[2], MAX[3], and B[0], B[1], and B[2].
These array elements can then be used is tha same way as simple variables. Arrays can have up to 255 elements, and there is no checking that arrays are within bounds.
Any number of procedures, with one parameter, can be declared. For example:
PROC ADD(X); statement
and the procedure is called by:
ADD(expression)
The parameter is a local parameter; i.e. the use of X in the procedure ADD above does not affect the value of X outside the procedure. Thus, in the following example:
PROC INC(X); X=X+1 ENTER: WRHEX(X); INC(X); WRHEX(X)
the two calls to WRHEX, which print the value of X, both print the same value.
The single parameter is optional; thus a procedure can be defined:
PROC INC(); J=J+1
which alters the value of J outside the procedure. Note that a procedure cannot be declared inside another procedure which has a parameter.
A function is identical to a procedure, except that its last statement is a RETURN statement specifying the result to be returned. For example:
PROC ADDONE(N); RETURN N+1
defines a function ADDONE whose value is one greater than its argument. Thus:
WRHEX(2+ADDONE(3))
would print '06'.
The assignment statement is of the form:
variable = expression
where the variable is an identifier or an array element. For example:
TIME=TIME+1 SYMBOL[RDCH()]=A-3
Expressions can use any of the following operations, which work on 8 bit numbers:
+ : add - : subtract & : logical AND | : logical OR >> : right shift << : left shift
All these operators have the same priority, and brackets can be used to alter the order of evaluation. The shift operators shift the left-hand operand the number of places specified by the right-hand operand, which must be a constant as in:
A=B>>3 (equivalent to A=B/8) A=B<<4 (equivalent to A=B*16)
Any statement can be prefixed by a label:
LOOP: A=A+1
A jump can be made to the labelled statement by means of the GOTO statement, as in:
GOTO LOOP
The IF statement has the form:
IF condition THEN statement
in which the statement is only executed if the condition is true. There may also be an ELSE clause:
IF condition THEN statement ELSE statement
in which case the second statement will only be executed if
the condition is false.
Note that if one of the statements is itself an IF...THEN...ELSE
statement the ELSE statement associates with the nearest IF
condition.
For example:
IF A=1 THEN IF A>0 THEN WRHEX(1) ELSE WRHEX(2)
will, if A=2, write nothing.
The condition in an IF statement is of the form:
expression comparison expression
where the comparison is one of:
> : greater than <= : less than or equal < : less than >= : greater than or equal = : equal <> : not equal
Any number of statements can be grouped together within a BEGIN...END block, which has the format:
BEGIN statement; statement; ... statement END
The entire block then has the same status as a single statement. Note that the semi-colons are used as statement separators, not as statement terminators, and so there is no need for a semi-colon before the END statement.
The following symbols are defined in both versions of the compiler:
Symbol Operation Example RDCH Function to read a character A=RDCH()-48 WRCH Procedure to write a character WRCH(32) SCREEN Array of 256 screen locations SCREEN[0]=0
In addition, in the Atom version, the following symbols are defined:
Symbol Operation Example WRHEX Procedure to print in hex WRHEX(255) PORT Array of I/0 ports PORT[2)=4
A more formal definition of the syntax of a language like SPL can be given using 'bead' diagrams as shown below. The diagrams can be used to work out whether a given program is legal in terms of the language. Each construct, such as 'expr:', is defined by travelling along the line to its right, following the arrows. Constructs in square brackets, such as [stmt], are defined by referring to another diagram. Constructs in round brackets, such as (ARRAY) or (:), refer to keywords or symbols in the language. The language is defined recursively, so certain constructs, such as 'stmt:', contain references to themselves.