m_exp:
	proc returns (ptr);
	%replace
		true  by '1'b,
		false by '0'b;

	dcl
		lower char(26) static initial
		('abcdefghijklmnopqrstuvwxyz'),
		upper char(26) static initial
		('ABCDEFGHIJKLMNOPQRSTUVWXYZ');

	dcl
		true_ptr   ptr external,
		define_ptr ptr external,
		nil_ptr    ptr external,
		label_ptr  ptr external,
		lambda_ptr ptr external,
		cond_ptr   ptr external,
		quote_ptr  ptr external;

	dcl
		accum char(128) var external,
		scan entry,
		compute_hash entry,
		lookup returns(ptr),
		enter returns(ptr),
		cons entry(ptr,ptr) returns(ptr),
		replacd entry(ptr,ptr) returns(ptr),
		list entry returns(ptr);

	dcl
		m ptr;

	syntax:
		proc(n);
		dcl
			n fixed;
		put edit(n,' Syntax Error at ',accum)
			(skip,f(3),2a);
			do while (accum ^= ';');
			call scan();
			end;
		go to error_exit;
		end syntax;

	var:
		proc returns(ptr);
		dcl
			p ptr;
		if accum = 'T' then
			return (true_ptr);
		if accum = 'F' | accum = 'NIL' then
			return (nil_ptr);
		if index(lower,substr(accum,1,1)) = 0 then
			call syntax(10);
		accum = translate(accum,upper,lower);
		call compute_hash();
		p = lookup();
		if p = null then
			p = enter();
		call scan();
		return (p);
		end var;

	v_tail:
		proc returns (ptr) recursive;
		if accum = ']' then
			do;
			call scan();
			return (nil_ptr);
			end;
		if accum = ';' then
			do;
			call scan();
			return (v_list());
			end;
		call syntax(20);
		end v_tail;

	v_list:
		proc returns (ptr) recursive;
		return (cons(var(),v_tail()));
		end v_list;

	func:
		proc returns(ptr) recursive;
		dcl
			(v, e, f) ptr;
		if accum = 'label' then
			do;
			call scan();
			if accum ^= '[' then
				call syntax(30);
			call scan();
			v = var();
			if accum ^= ';' then
				call syntax(40);
			call scan();
			f = func();
			if accum ^= ']' then
				call syntax(42);
			call scan();
			return (cons(label_ptr,
				cons(v,cons(f,nil_ptr))));
			end;
		if accum = 'lambda' then
			do;
			call scan();
			if accum ^= '[' then
				call syntax(50);
			call scan();
			if accum ^= '[' then
				call syntax(60);
			call scan();
			if accum = ']' then
				do;
				call scan();
				v = nil_ptr;
				end;
			else
				v = v_list();
			if accum ^= ';' then
				call syntax(70);
			call scan();
			e = exp();
			if accum ^= ']' then
				call syntax(80);
			call scan();
			return (cons(lambda_ptr,
				cons(v,cons(e,nil_ptr))));
			end;
		return(var());
		end func;

	c_tail:
		proc returns(ptr) recursive;
		if accum = ']' then
			do;
			call scan();
			return (nil_ptr);
			end;
		if accum = ';' then
			do;
			call scan();
			return (c_list());
			end;
		call syntax(90);
		end c_tail;

	c_list:
		proc returns(ptr) recursive;
		dcl
			p ptr;
		p = exp();
		if accum ^= '-' then
			call syntax(100);
		call scan();
		if accum ^= '>' then
			call syntax(110);
		call scan();
		return (cons(cons(p,cons(exp(),nil_ptr)),c_tail()));
		end c_list;

	e_tail:
		proc returns (ptr) recursive;
		if accum = ']' then
			do;
			call scan();
			return (nil_ptr);
			end;
		if accum = ';' then
			do;
			call scan();
			return (e_list());
			end;
		call syntax(120);
		end e_tail;

	e_list:
		proc returns (ptr) recursive;
		return (cons(exp(),e_tail()));
		end e_list;

	exp:
		proc returns(ptr) recursive;
		dcl
			(f, el, ef) ptr;
		if accum = '"' then
			do;
			call scan();
			el = list();
			if accum ^= '"' then
				call syntax(122);
			call scan();
			return (cons(quote_ptr,cons(el,nil_ptr)));
			end;
		if accum = '[' then
			do;
			call scan();
			return (cons(cond_ptr,c_list()));
			end;
		f = func();
		if accum ^= '[' then
			/* (lambda or label) */
			return(f);
		call scan();
		if accum = ']' then
			do;
			call scan();
			el = nil_ptr;
			end;
		else
			el = e_list();
		if accum ^= '=' then
			return (cons(f,el));
		call scan();
		ef = exp();
		/* (define (( (f (lambda el ef) )   )) ) */
		el = cons(lambda_ptr,cons(el,cons(ef,nil_ptr)));
		el = cons(el,nil_ptr);
		f = cons(cons(cons(f,el),nil_ptr),nil_ptr);
		return (cons(define_ptr,cons(f,nil_ptr)));
		end exp;

	m = exp();
		do while (true);
		if accum = ';' then
			return (m);
		if accum ^= ']' then
			call syntax(130);
		call scan();
		end;
	error_exit:
	return (nil_ptr);
	end m_exp;
