Nearby is CSTR #8, which is a report by Steve Johnson and Brian Kernighan describing the B implementation on Honeywell equipment.
The language being described was really the same, but it's interesting to look at the differences in description and environment. To describe the BNF syntax, Ken used a variant that depends on super- and subscripts to say "how many", which in the original were stacked above each other when they occurred simultaneously. This doesn't look too awful in the HTML rendering, but was probably better in the original.
The other thing that is observable is the degree to which the GCOS version had to struggle to work in that environment. Its library description is full of odd concepts like "the AFT" the *SRC file, and other peculiarities.
--DMR, July 1997 ]
	{..}m	m,m+1,...
	{..}mn	m,m+1,...,n
program ::=
	{definition}0
definition ::=
	name {[ {constant}01 ]}01 {ival {, ival}0}01 ;
	name ( {name {, name}0}01 ) statement
ival ::=
	constant
	name
statement ::=
	auto name {constant}01 {, name {constant}01}0 ;  statement
	extrn name {, name}0 ; statement
	name : statement
	case constant : statement
	{ {statement}0 }
	if ( rvalue ) statement {else statement}01
	while ( rvalue ) statement
	switch rvalue statement
	goto rvalue ;
	return {( rvalue )}01 ;
	{rvalue}01 ;
rvalue ::=
	( rvalue )
	lvalue
	constant
	lvalue assign rvalue
	inc-dec lvalue
	lvalue inc-dec
	unary rvalue
	& lvalue
	rvalue binary rvalue
	rvalue ? rvalue : rvalue
	rvalue ( {rvalue {, rvalue}0 }01 )
assign ::=
	= {binary}01
inc-dec ::=
	++
	--
	
unary ::=
	-
	!
binary ::=
	|
	&
	==
	!=
	<
	<=
	>
	>=
	<<
	>>
	-
	+
	%
	*
	/
lvalue ::=
	name
	* rvalue
	rvalue [ rvalue ]
constant ::=
	{digit}1
	' {char}12 '
	" {char}0 "
name ::=
	alpha {alpha-digit}07
alpha-digit ::=
	alpha
	digit
	*0	null
	*e	end-of-file
	*(	{
	*)	}
	*t	tab
	**	*
	*'	'
	*"	"
	*n	new line
(b? f:g[i] )(1, x>1)
*X
&x
lvalue op rvalue
if(rvalue) statement1
if(rvalue) statement1 else statement2
if(x=(rvalue)) statement1 if(!x) statement2
while(rvalue) statement
	x: if(rvalue) { statement goto x; ]
switch rvalue statement1
case constant:
goto rvalue ;
return ;
return ( rvalue ) ;
extrn name1 , name2 ... ;
	auto name1 {constant}01 , name2 {constant]01 ... ;
name :
main(); exit();
	name {ival , ival ...}0 ;
	name [ {constant}01 ] {ival , ival ...}0 ;
name ( arguments ) statement
/* The following function will print a non-negative number, n, to
  the base b, where 2<=b<=10,  This routine uses the fact that
  in the ANSCII character set, the digits O to 9 have sequential
  code values.  */
printn(n,b) {
	extrn putchar;
	auto a;
	if(a=n/b) /* assignment, not test for equality */
		printn(a, b); /* recursive */
	putchar(n%b + '0');
}
/* The following program will calculate the constant e-2 to about
   4000 decimal digits, and print it 50 characters to the line in
   groups of 5 characters.  The method is simple output conversion
   of the expansion
     1/2! + 1/3! + ... = .111....
   where the bases of the digits are 2, 3, 4, . . . */
main() {
	extrn putchar, n, v;
	auto i, c, col, a;
	i = col = 0;
	while(i<n)
		v[i++] = 1;
	while(col<2*n) {
		a = n+1 ;
		c = i = 0;
		while (i<n) {
			c =+ v[i] *10;
			v[i++]  = c%a;
			c =/ a--;
		}
		putchar(c+'0');
		if(!(++col%5))
			putchar(col%50?' ': '*n');
	}
	putchar('*n*n');
}
v[2000];
n 2000;
/* The following function is a general formatting, printing, and
   conversion subroutine.  The first argument is a format string.
   Character sequences of the form `%x' are interpreted and cause
   conversion of type 'x' of the next argument, other character
   sequences are printed verbatim.   Thus
    printf("delta is %d*n", delta);
    will convert the variable delta to decimal (%d) and print the
    string with the converted form of delta in place of %d.   The
    conversions %d-decimal, %o-octal, *s-string and %c-character
    are allowed.
    This program calls upon the function `printn'. (see section
    9.1) */
printf(fmt, x1,x2,x3,x4,x5,x6,x7,x8,x9) {
	extrn printn, char, putchar;
	auto adx, x, c, i, j;
	i= 0;	/* fmt index */
	adx = &x1;	/* argument pointer */
loop :
	while((c=char(fmt,i++) ) != `%') {
		if(c == `*e')
			return;
		putchar(c);
	}
	x = *adx++;
	switch c = char(fmt,i++) {
	case `d': /* decimal */
	case `o': /* octal */
		if(x < O) {
			x = -x ;
			putchar('-');
		}
		printn(x, c=='o'?8:1O);
		goto loop;
	case 'c' : /* char */
		putchar(x);
		goto loop;
	case 's': /* string */
		while(c=char(x, j++)) != '*e')
			putchar(c);
		goto loop;
	}
	putchar('%') ;
	i--;
	adx--;
	goto loop;
}
/etc/bc source interm
/etc/ba interm asource rm interm
as asource mv a.out object rm asource
ld object /etc/brt1 -lb /etc/bilib /etc/brt2
a.out
sh /usr/b/rc x
automatic = external + 100.; va; 4 / lvalue of first automatic on stack x; .external / rvalue of external on stack c; 100. / rvalue of constant on stack b12 / binary operator #12 (+) b1 / binary operator #1 (=) ... va: mov (r3)+,r0 add r4,rO / dp+offset of automatic asr rO / lvalues are word addresses mov r0,(r5)+ jmp *(r3)+ / linkage between subroutines x: mov *(r3)+,(r5)+ jmp *(r3)+ c: mov (r3)+,(r5)+ jmp *(r3)+ b12: add -(r5),-2(r5) jmp *(r3)+ b1: mov -(r5),r0 / rvalue mov -(r5),r1 / lvalue asl r1 / now byte address mov r0,(r1) / actual assignment mov r0,(r5)+ / = returns an lvalue jmp *(r3)+
b103 =& b104 === b105 =!= b106 =<= b107 =< b110 =>= b111 => b120 =/
error	name	meaninq
$)	--	{} imbalance
()	--	() imbalance
*/	--	/* */ imbalance
[]	--	[] imbalance
>c	--	case table overflow (fatal)
>e	--	expression stack overflow (fatal)
>i	--	label table overflow (fatal)
>s	--	symbol table overflow (fatal)
ex	--	expression syntax
lv	--	rvalue where lvalue expected
rd	name	name redeclaration
sx	keyword	statement syntax
un	name	undefined name
xx	--	external syntax