The input syntax is defined by the following rules:
.EX \f2input ::= \f2item* '$' \f2item ::= \f2integer | \f2atom | \f2string | \f2binary | \f2tuple | \f2list | \f2store | \f2push | \f2comment | \f2tag \f2integer ::= \f5'-'?\f5[0-9]+ \f2atom ::= "'" (\f5[^\e'] | '\e\e' | "\e'")* "'" \f2string ::= '"' (\f5[^\e"] | '\e\e' | '\e"')* '"' \f2binary ::= '~' \f2byte* '~' # preceded by \f2integer byte count \f2tuple ::= '{' \f2item* '}' \f2list ::= '#' (\f2item '&')* \f2store ::= '>' \f2reg \f2push ::= \f2reg \f2reg ::= \f5[^-%"~'`{}#& \en\er\et,0-9] \f2comment ::= '%' (\f5[^\e%] | '\e\e' | '\e%')* '%' \f2tag ::= '`' (\f5[^\e`] | '\e\e' | '\e`')* '`'
White space is any sequence of blank, tab, newline or carriage-return characters, and can appear before or after any instance of item in the grammar.
The input data is interpreted by a simple virtual machine. The machine contains a stack of values of primitive and compound types, and a set of registers also containing values of those types. White space and comments are ignored. Primitive integer , atom and string values are pushed onto the stack as they are recognised. Certain input bytes outside any value act as operators:
{ Note the current stack depth.
} Pop stack values to restore the most recently noted stack depth. Push a single value representing a tuple of those items; the left-most value in the tuple is the last one popped (the first in the original input stream).
~ Pop an integer value n from the stack. Read n bytes from the input stream and push a value onto the stack that represents them. The next byte must be the character ~ , which is discarded.
# Push a value representing an empty list onto the stack.
& Pop a value v . Pop another value l , which must represent a list. Push a value that represents the list v :: l . (Note that the items in a list therefore appear in reverse order in the input stream.)
> reg Pop the top value from the stack and store it in a register labelled by the byte reg .
reg Push the value of register reg (which must be non-null) onto the stack.
tag Associate the tag string with the value on top of the stack. The ubfa (2) implementation does so by replacing it by a special Tag tuple.
$ End-of-input: there must be exactly one value on the stack, which is the result.
Applications using UBF(A) typically take turns to exchange input values on a communication channel.
J L Armstrong, ``Getting Erlang to talk to the outside world'', "ACM SIGPLAN Erlang workshop 2002" , Pittsburg, PA USA
UBF web page, "http://www.sics.se/~joe/ubf/"