示例#1
0
static void predicate( TokType sense, NodeFactory & ifunless, Node pred ) {
	if ( sense == tokty_if ) {
		ifunless.add( pred );
	} else {
		//	TODO: This is a bug?
		ifunless.start( "sysval" );
		ifunless.put( "name", "not" );
		ifunless.add( pred );
		ifunless.end();
	}
}
示例#2
0
Node ReadStateClass::readVarVal( TokType fnc ) {
	NodeFactory bind;
	bind.start( BIND );
	
	Node lhs = this->readExprPrec( prec_assign );
	updateAsPattern( lhs, fnc == tokty_val );

	bind.add( lhs );
	this->checkToken( this->cstyle_mode ? tokty_equal : tokty_bind );
	Node x = this->readExpr();
	bind.add( x );
	bind.end();
	return bind.build();
}
示例#3
0
	Node canonise( const int level, Node fn ) {
		const bool is_var = fn->hasName( VAR );
		if ( is_var ) {
			if ( level == 0 ) {
				if ( this->name_needed ) this->badHeader();
				return this->anon( fn );
			} else if ( this->assume_no_name ) {
				return this->anon( fn );
			} else {
				return fn;
			}
		} else if ( fn->hasName( SEQ ) && not this->name_needed ) {
			return this->anon( fn );
		} else if ( fn->hasName( APP ) && fn->size() == 2 ) {
			NodeFactory b;
			b.start( APP );
			Node n = this->canonise( level + 1, fn->getChild( 0 ) );
			b.add( n );
			b.start( SEQ );
			squash( b, fn->getChild( 1 ) );
			b.end();
			b.end();
			return b.build();					
		} else {
			throw this->badHeader();
		}
	}
示例#4
0
Node ReadStateClass::readQueryPrec( const int prec ) {
	Node e = this->readExprPrec( prec );
	const std::string name = e->name();
	if ( 
		name == BIND 	||
		name == IN 		||
		name == FROM 	||
		name == WHERE 	||
		name == WHILE   ||
		name == ZIP 	||
		name == CROSS 	||
		name == OK 		||
		name == FINALLY ||
		name == DO
	) {
		return e;
	} else {
		NodeFactory where;
		where.start( WHERE );
		where.start( OK );
		where.end();
		where.add( e );
		where.end();
		return where.build();
	}
}
示例#5
0
static Node makeApp( Node lhs, Node rhs ) {
	if ( lhs->name() == GNX_SYSFN ) {
		NodeFactory sysapp;
		sysapp.start( SYSAPP );
		std::string name = lhs->attribute( GNX_SYSFN_VALUE );
		sysapp.put( SYSAPP_NAME, name );
		sysapp.add( rhs );
		sysapp.end();
		return sysapp.build();
	} else {
		NodeFactory app;
		app.start( APP );
		app.add( lhs );
		app.add( rhs );
		app.end();
		return app.build();
	}
}
示例#6
0
Node ReadStateClass::readReturn() {
	NodeFactory ret;
	ret.start( ASSERT );
	ret.put( ASSERT_TAILCALL, "true" );
	Node n = this->readExpr();
	ret.add( n );
	ret.end();
	return ret.build();
}
示例#7
0
static Node makeIndex( Node lhs, Node rhs ) {
	NodeFactory index;
	index.start( SYSAPP );
	index.put( SYSAPP_NAME, "index" );
	index.add( rhs );
	index.add( lhs );
	index.end();
	return index.build();
}
示例#8
0
Node ReadStateClass::readMap( TokType closer ) {
	NodeFactory list;
	list.start( SYSAPP );
	list.put( SYSAPP_NAME, "newMap" );
	Node x = this->readStmntsCheck( closer );
	list.add( x );
	list.end();
	return list.build();
}
示例#9
0
	Node getArgs() const {
		Node args = this->lhs->getChild( 1 );
		if ( args->hasName( SEQ ) ) return args;
		NodeFactory b;
		b.start( SEQ );
		b.add( args );
		b.end();
		return b.build();
	}
示例#10
0
Node ReadStateClass::readPackage() {
	NodeFactory pkg;
	pkg.start( "package" );
	string url = this->readPkgName();
	pkg.put( "url", url );
	this->checkToken( tokty_semi );
	Node body = this->readStmntsCheck( tokty_endpackage );
	pkg.add( body );
	pkg.end();
	return pkg.build();
}
示例#11
0
	void squash( NodeFactory acc, Node rhs ) {
		const std::string 
		name = rhs->name();
		if ( name == SEQ ) {
			int n = rhs->size();
			for ( int i = 0; i < n; i++ ) {
				squash( acc, rhs->getChild( i ) );
			}
		} else {
			acc.add( rhs );
		}
	}
示例#12
0
Node ReadStateClass::readIf( TokType sense, TokType closer ) {
	if ( this->cstyle_mode ) this->checkToken( tokty_oparen );
	Node pred = this->readExpr();
	this->checkToken( this->cstyle_mode ? tokty_cparen : tokty_then );
	Node then_part = this->readStmnts();
	if ( this->tryToken( tokty_else ) ) {	
		NodeFactory ifunless;
		ifunless.start( IF );
		predicate( sense, ifunless, pred );
		ifunless.add( then_part );
		Node x = this->readStmnts();
		if ( not this->cstyle_mode ) this->checkToken( closer );
		ifunless.add( x );
		ifunless.end();
		return ifunless.build();
	} else if ( this->cstyle_mode || this->tryToken( closer ) ) {
		NodeFactory ifunless;
		ifunless.start( IF );
		predicate( sense, ifunless, pred );
		ifunless.add( then_part );
		ifunless.end();
		return ifunless.build();
	} else {
		TokType new_sense;
		if ( this->tryToken( tokty_elseif ) ) {
			new_sense = tokty_if;
		} else {
			this->checkToken( tokty_elseunless );
			new_sense = tokty_unless;
		}
		NodeFactory ifunless;
		ifunless.start( IF );
		predicate( sense, ifunless, pred );
		ifunless.add( then_part );
		Node x = this->readIf( new_sense, closer );
		ifunless.add( x );
		ifunless.end();
		return ifunless.build();
	}
}
示例#13
0
Node ReadStateClass::readListOrVector( bool vector_vs_list, TokType closer ) {
	NodeFactory list;
	list.start( vector_vs_list ? VECTOR : LIST );
	Node stmnts = this->readCompoundCore();
	if ( not vector_vs_list && this->tryToken( tokty_bar ) ) {
		list.add( stmnts );
		list.end();
		Node L = list.build();
		NodeFactory append;
		append.start( LIST_APPEND );
		append.add( L );
		Node x = this->readCompoundCoreCheck( closer );
		append.add( x );
		append.end();
		return append.build();
	} else {
		this->checkToken( closer );
		list.add( stmnts );
		list.end();
		return list.build();
	}
}
示例#14
0
Node ReadStateClass::readTry( const bool try_vs_transaction ) {
	NodeFactory ftry;
	ftry.start( try_vs_transaction ? "try" : "transaction" );
	Node app = this->readExpr();
	ftry.add( app );

	while ( this->tryToken( tokty_catch ) ) {

		if ( this->tryPeekToken( tokty_oparen ) ) {
			ftry.start( "catch.return" );
		} else {
			ftry.start( "catch.then" );
			ftry.put( "event", this->readIdName() );			
		}		
		
		ReadStateClass pattern( *this );
		pattern.setPatternMode();
		Node catch_patt = pattern.readExpr();
		ftry.add( catch_patt );
		
		this->checkToken( tokty_then );
		Node e = this->readExpr();
		ftry.add( e );

		ftry.end();
	}

	if ( this->tryToken( tokty_else ) ) {
		ftry.start( "catch.else" );
		Node else_stmnts = this->readStmnts();
		ftry.add( else_stmnts );
		ftry.end();
	}

	this->checkToken( try_vs_transaction? tokty_endtry : tokty_endtransaction );
	ftry.end();
	return ftry.build();
}
示例#15
0
Node ReadStateClass::readLambda() {
	#ifdef DBG_COMMON2GNX
		cerr << "LAMBDA" << endl;
	#endif

	Node ap = this->readCanonicalLambdaLHS( false );
	#ifdef DBG_COMMON2GNX
		cerr << "Now check =>> is next token" << endl;
	#endif
	if ( not this->cstyle_mode ) this->checkToken( tokty_fnarrow );
	Node body = this->readCompoundStmnts();
	if ( not this->cstyle_mode ) this->checkToken( tokty_endfn );	

	Uncurry components( ap, body );
	components.uncurry();

	Node fun = components.getFun();
	
	NodeFactory fn;
	fn.start( FN );
	if ( fun && fun->hasAttribute( "name" ) ) {
		fn.put( FN_NAME, fun->attribute( "name" ) );
	}
	{
		Node a = components.getArgs();
		fn.add( a );
		Node b = components.getBody();
		fn.add( b );
	}
	fn.end();
	Node lambda = fn.build();			
	#ifdef DBG_COMMON2GNX
		cerr << "Built lambda: ";
		lambda->render( cerr );
		cerr << endl;
	#endif
	return lambda;
}
示例#16
0
Node ReadStateClass::readCompoundCore() {
	if ( this->cstyle_mode ) {
		NodeFactory stmnts;
		stmnts.start( SEQ );
		while ( this->tryPeekToken( tokty_semi ) || not this->tryPeekCloser() ) {
			Node n = this->readSingleStmnt();
			stmnts.add( n );
		}
		stmnts.end();
		return stmnts.build();
	} else {
		return this->readStmnts();
	}
}
示例#17
0
	void uncurry() {
		#ifdef DBG_COMMON2GNX
			cerr << "At start of uncurrying" << endl;
			cerr << "  LHS: ";
			this->lhs->render( cerr );
			cerr << endl;
			cerr << "  RHS: ";
			this->rhs->render( cerr );
			cerr << endl;
		#endif

		while ( this->isCurryd() ) {
			NodeFactory b;
			b.start( FN );
			Node arg = this->lhs->getChild( 1 );
			if ( arg->hasName( SEQ ) ) {
				b.add( arg );
			} else {
				b.start( SEQ );
				b.add( arg );
				b.end();
			}
			b.add( this->rhs );
			b.end();
			this->rhs = b.build();
			this->lhs = this->lhs->getChild( 0 );
			#ifdef DBG_COMMON2GNX
				cerr << "Uncurried" << endl;
				cerr << "  LHS: ";
				this->lhs->render( cerr );
				cerr << endl;
				cerr << "  RHS: ";
				this->rhs->render( cerr );
				cerr << endl;
			#endif
		}
	}
示例#18
0
Node ReadStateClass::readSingleStmnt( const bool top_level ) {
	if ( this->cstyle_mode ) {
		Item it = this->item_factory->read();
		//cerr << "SINGLE " << tok_type_name( it->tok_type ) << endl;
		switch ( it->tok_type ) {
			case tokty_obrace: 
				return this->readCompoundCoreCheck( tokty_cbrace );
			case tokty_function: 
				if ( this->cstyle_mode && this->item_factory->peek()->tok_type == tokty_oparen ) {
					return this->readLambda();
				} else {
					return this->readDefinition();
				}
			case tokty_if: 
				return this->readIf( tokty_if, tokty_endif );
			case tokty_for: 
				return this->readFor();
			case tokty_switch: 
				return this->readSwitch();
			case tokty_recordclass:
				return this->readRecordClass();
			case tokty_dsemi:
			case tokty_semi: 
				return makeEmpty();
			default: 
				this->item_factory->unread();
				// --- Fall-through --- //
		}
	}
	
	//	Fall thru!
	Node n = this->readOptEmptyExpr();
	if ( this->tryToken( tokty_dsemi ) ) {
		NodeFactory f;
		f.start( ERASE );
		f.add( n );
		f.end();
		return f.build();
	} else if ( this->tryToken( tokty_semi ) ) {
		return n;
	} else {
		if ( this->item_factory->peek()->role.IsCloser() && not top_level ) {
			return n;	
		} else {
			throw CompileTimeError( "Missing semi-colon?" ).culprit( "Token", this->item_factory->peek()->nameString() );
		}
	}
}
示例#19
0
Node ReadStateClass::readSwitchStmnts() {
	NodeFactory st;
	st.start( SEQ );
	while (
		not ( 
			this->tryPeekToken( tokty_cbrace ) ||
			this->tryPeekToken( tokty_case ) ||
			this->tryPeekToken( tokty_default )
		) 
	) {
		Node x = this->readSingleStmnt();
		st.add( x );
	}
	st.end();
	return st.build();
}
示例#20
0
Node ReadStateClass::readThrow() {
	NodeFactory panic;
	panic.start( "throw" );

	panic.put( "event", this->readIdName() );
	panic.put(
		"level",
		this->tryToken( tokty_bang ) ? "rollback" :
		this->tryToken( tokty_dbang ) ? "failover" :
		this->tryToken( tokty_panic ) ? "panic" :
		"escape"
	);
	if ( this->tryPeekToken( tokty_oparen ) ) {
		Node e = this->readExpr();
		panic.add( e );
	} else {
		panic.start( SEQ );
		panic.end();
	}

	panic.end();
	return panic.build();
}
示例#21
0
Node ReadStateClass::readOptExprPrec( int prec ) {
	ItemFactory ifact = this->item_factory;
	Node e = this->prefixProcessing();
	if ( not e ) return Node();
	//cerr << "starting postfix checking ... " << this->isPostfixAllowed() << endl;
	while ( this->isPostfixAllowed() ) {
	    int q;
	    //cerr << "peeking" << endl;
		Item it = ifact->peek();
		if ( it->item_is_signed_num() ) {
			NodeFactory t;
			t.start( SYSAPP );
			t.put( "name", "+" );
			t.add( e );			
			if ( it->tok_type == tokty_int ) {
				t.start( "constant" );
				t.put( "type", "int" );
				t.put( "value", it->nameString() );
				t.end();
			} else {
				throw CompileTimeError( "Only integers supported so far" ).culprit( "Item", it->nameString() );
			}
			t.end();
			e = t.build();
			ifact->drop();
		} else if ( it->item_is_postfix() ) {
	        q = it->precedence;
            if ( q >= prec ) break;
	        ifact->drop();
	        e = this->postfixProcessing( e, it, q );
		} else {
			break;
		}
    }
    return e;
}
示例#22
0
Node ReadStateClass::readDefinition() {
	//cerr << "DEFINITION" << endl;
	Node ap = this->readCanonicalLambdaLHS( true );

	if ( not this->cstyle_mode ) this->checkToken( tokty_fnarrow );
	Node body0 = this->readCompoundStmnts();
	if ( not this->cstyle_mode ) this->checkToken( tokty_enddefine );
	if ( this->cstyle_mode ) {
		this->is_postfix_allowed = false;
	}

	Uncurry components( ap, body0 );
	components.uncurry();

	Node fn = components.getFun();
	if ( not fn->hasAttribute( "name" ) ) {
		throw Ginger::Mishap( "Cannot determine function name" );
	}
	Node args = components.getArgs();
	Node body = components.getBody();

	const std::string name( fn->attribute( GNX_VID_NAME ) );
	NodeFactory def;
	def.start( BIND );
	def.start( VAR );
	def.put( GNX_VID_NAME, name );
	def.put( GNX_VID_PROTECTED, "true" );
	def.end();
	def.start( FN );
	def.put( FN_NAME, name );
	def.add( args );
	def.add( body );
	def.end();
	def.end();
	return def.build();
}
示例#23
0
Node ReadStateClass::readElement() {
	NodeFactory element;
	element.start( SEQ );
	for (;;) {
		element.start( SYSAPP );
		element.put( SYSAPP_NAME, "newElement" );
		element.start( SYSAPP );
		element.put( SYSAPP_NAME, "newAttrMap" );

		// Cache the element name for the close tag. Anything other than
		// a literal name will need the close-anything tag.
		std::string element_name;
		Item item = this->item_factory->peek();
		if ( item->tok_type == tokty_id ) {
			element_name = item->nameString();
		}

		Node name = this->readAtomicExpr();
		element.add( name );	

		bool closed = false;
		for (;;) {
			if ( this->tryToken( tokty_gt ) ) break;
			if ( this->tryToken( tokty_slashgt ) ) { closed = true; break; }

			Node key_or_keyvalue = this->readAtomicExpr( false );

			if ( this->tryToken( tokty_equal ) ) {
				Node a1 = makeAssert1( key_or_keyvalue );
				element.add( a1 );
				Node value = this->readAtomicExpr();
				element.add( value );
			} else {
				element.start( SYSAPP );
				element.put( SYSAPP_NAME, "explodeMapsAndMaplets" );
				element.add( key_or_keyvalue );
				element.end();
			}
		}
		element.end(); 	// newAttrMap.
		if ( not closed ) {
			//	Read the children.
			bool ended = false;
			for (;;) {
				if ( this->tryToken( tokty_ltslash ) ) break;
				if ( this->tryToken( tokty_endelement ) ) { ended = true; break; }
				Node child = this->readExpr();
				element.add( child );
			}
			if ( not ended ) {
				const string ename( this->readIdName() );
				if ( ename != element_name ) {
					throw CompileTimeError( "Element close tag does not match open tag" ).culprit( "Open tag", element_name ).culprit( "Close tag", ename );
				}
				this->checkToken( tokty_gt );
			}
		}
		element.end();	//	newElement.

		//	Uniquely, at this point in the language, no semi-colon is
		//	needed if the next item is ANOTHER element.
		if ( not this->tryToken( tokty_lt ) ) break;
	}			
	element.end();
	Node answer = element.build();
	return answer->size() == 1 ? answer->getChild( 0 ) : answer;
}
示例#24
0
Node ReadStateClass::readSwitch() {
	NodeFactory sw;
	sw.start( SWITCH );

	bool else_seen = false;
	Node swelse;

	if ( this->cstyle_mode ) {
		
		this->checkToken( tokty_oparen );
		Node swvalue = this->readExprCheck( tokty_cparen );
		sw.add( swvalue );
	
		this->checkToken( tokty_obrace );
	
		for (;;) {
			if ( this->tryToken( tokty_case ) ) {
				Node e = this->readExpr();
				sw.add( e );
				this->checkToken( tokty_colon );
				Node b = this->readSwitchStmnts();
				sw.add( b );
			} else if ( this->tryToken( tokty_default ) ) {
				if ( else_seen ) {
					throw CompileTimeError( "Switch with two default parts" );
				}
				else_seen = true;
				this->checkToken( tokty_colon );
				swelse = this->readSwitchStmnts();
			} else {
				break;
			}
		}
		this->checkToken( tokty_cbrace );

	} else {
		Node swvalue = this->readExpr();
		sw.add( swvalue );

		for (;;) {
			if ( this->tryToken( tokty_case ) ) {
				Node e = this->readExprCheck( tokty_then );
				sw.add( e );
				Node b = this->readStmnts();
				sw.add( b );
			} else if ( this->tryToken( tokty_else ) ) {
				if ( else_seen ) {
					throw CompileTimeError( "Switch with two else parts" );
				}
				else_seen = true;
				swelse = this->readOptExpr();
			} else {
				break;
			}
		}
		this->checkToken( tokty_endswitch );
	}

	if ( else_seen ) {
		sw.add( swelse );
	}

	sw.end();
	return sw.build();
}
示例#25
0
Node ReadStateClass::prefixProcessingCore() {
	ItemFactory ifact = this->item_factory;
	Item item = ifact->read();
	
	#ifdef DBG_COMMON2GNX
		cerr << "First item was " << tok_type_name( item->tok_type ) << endl;
	#endif
	
	TokType fnc = item->tok_type;
	Role role = item->role;

	//cout << "PREFIX PROCESSING: " << item->nameString() << endl;
	//cout << "  tokty = " << tok_type_name( fnc ) << endl;

	if ( role.IsLiteral() ) {
		NodeFactory simple;
		simple.start( "constant" );
		simple.put( "type", tok_type_as_type( fnc ) );
		simple.put( "value", item->nameString() );
		simple.end();
	 	return simple.build();
	} else if ( role.IsUnary() ) {
		if ( role.IsForm() ) {
			NodeFactory unary;
			unary.start( tok_type_as_tag( fnc ) );
			Node x = this->readExprPrec( item->precedence );
			unary.add( x );
			unary.end();
			return unary.build();
		} else if ( role.IsSys() ) {
			NodeFactory sf;
			sf.start( SYSAPP );
			sf.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) );
			Node x = this->readExprPrec( item->precedence );
			sf.add( x );
			sf.end();
			return sf.build();
		} else {
			throw CompileTimeError( "Internal error - unreachable code reached" );
		}
	}

	switch ( fnc ) {
		case tokty_sub: {
			Node e = this->readExprPrec( prec_negate );
			NodeFactory neg;
			neg.start( SYSAPP );
			neg.put( SYSAPP_NAME, "negate" );
			neg.add( e );
			neg.end();
			return neg.build();
		}
		case tokty_add: {
			Node e = this->readExprPrec( prec_negate );
			NodeFactory pos;
			pos.start( SYSAPP );
			pos.put( SYSAPP_NAME, "positivate" );
			pos.add( e );
			pos.end();
			return pos.build();			
		}
		case tokty_id: 
			return this->readId( item->nameString() );
		case tokty_anon:
			return this->readAnon( item->nameString() );
		// changed for ${VAR} case study
		case tokty_envvar: 
			return this->readEnvVar();
		case tokty_return: 
			return this->readReturn();
		case tokty_throw: 
			return this->readThrow();
		case tokty_try: 
		case tokty_transaction: 
			return this->readTry( fnc == tokty_try );
		case tokty_charseq: 
			return makeCharSequence( item );
		case tokty_val:
        case tokty_var : 
	        return this->readVarVal( fnc );
		case tokty_oparen: {
			if ( this->cstyle_mode ) {
				return this->readOptEmptyExprCheck( tokty_cparen );
			} else {
				return this->readStmntsCheck( tokty_cparen );
			}
		}
		case tokty_obracket:
			return this->readListOrVector( true, tokty_cbracket );
		case tokty_obrace: 
			return this->readMap( tokty_cbrace );
		case tokty_fat_obracket:
			return this->readListOrVector( false, tokty_fat_cbracket );
		case tokty_fat_ocbracket: {
			Node list( new Ginger::Mnx( LIST ) );
			return list;
		}
		case tokty_unless:
			return this->readIf( tokty_unless, tokty_endunless );
		case tokty_if: {
			if ( this->cstyle_mode ) break;
			return this->readIf( tokty_if, tokty_endif );
		}
		case tokty_syscall:
			return this->readSyscall();
		case tokty_for: {
			if ( this->cstyle_mode ) break;
		  	return this->readFor();
		}
		case tokty_function: {
			#ifdef DBG_COMMON2GNX
				cerr << "FUNCTION" << endl;
			#endif
			if ( this->item_factory->peek()->tok_type == tokty_oparen ) {
				return this->readLambda();
			} else {
				break;
			}
		}
		case tokty_define:
			//cerr << "DEFINE" << endl;
			return this->readDefinition();
		case tokty_fn: 
			return this->readLambda();
		case tokty_lt:
			return this->readElement();
		case tokty_package: 
			return this->readPackage();
		case tokty_import: 
			return this->readImport();
		case tokty_dhat:
			return this->readDHat();
		case tokty_switch: {
			if ( this->cstyle_mode ) break;
			return this->readSwitch();
		}
		case tokty_recordclass:
			return this->readRecordClass();
		default: 
			{}
	}
	ifact->unread();
    return Node();
}
示例#26
0
Node ReadStateClass::postfixProcessing( Node lhs, Item item, int prec ) {
	Role role = item->role;
	TokType fnc = item->tok_type;
	if ( role.IsBinary() ) {
		const bool direction = tok_type_as_direction( fnc );
		if ( role.IsSys() ) {
			NodeFactory a;
			a.start( SYSAPP );
			a.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) );
			Node rhs = this->readExprPrec( prec );
			a.add( direction ? lhs : rhs );
			a.add( !direction ? lhs : rhs );
			a.end();
			return a.build();
		} else if ( role.IsForm() ) {
			NodeFactory a;
			a.start( tok_type_as_tag( fnc ) );
			Node rhs = this->readExprPrec( prec );
			a.add( direction ? lhs : rhs );
			a.add( !direction ? lhs : rhs );
			a.end();
			return a.build();			
		} else {
			throw CompileTimeError( "Internal error - postfixProcessing" );
		}
	} else if ( role.IsUnary() ) {
		if ( role.IsSys() ) {
			NodeFactory a;
			a.start( SYSAPP );
			a.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) );
			a.add( lhs );
			a.end();
			return a.build();
		} else if ( role.IsForm() ) {
			NodeFactory a;
			a.start( tok_type_as_tag( fnc ) );
			Node rhs = this->readExprPrec( prec );
			a.add( lhs );
			a.end();
			return a.build();			
		} else {
			throw CompileTimeError( "Internal error (postfixProcessing): None of these cases defined yet" );			
		}
	} else {
		switch ( fnc ) {
			case tokty_bindrev:
			case tokty_bind: {
				Node rhs = this->readExprPrec( prec );
				updateAsPattern( fnc == tokty_bind ? lhs : rhs, true );
				NodeFactory bind;
				bind.start( BIND );
				bind.add( fnc == tokty_bind ? lhs : rhs );
				bind.add( fnc != tokty_bind ? lhs : rhs );
				bind.end();
				return bind.build();
			}
			case tokty_cross:
			case tokty_zip: {
				NodeFactory factory;
				factory.start( fnc == tokty_cross ? CROSS : ZIP );
				factory.add( lhs );
				Node rhs = this->readQueryPrec( prec );
				factory.add( rhs );
				factory.end();
				return factory.build();				
			}
			case tokty_finally: {
				NodeFactory finally;
				finally.start( FINALLY );
				finally.add( lhs );
				Node rhs = this->readExprPrec( prec );
				finally.add( rhs );
				finally.end();
				return finally.build();
			}
			case tokty_until:
			case tokty_while: {
				NodeFactory whileuntil;
				whileuntil.start( WHILE );
				whileuntil.add( lhs );
				Node rhs = this->readExprPrec( prec );
				if ( fnc == tokty_until ) {
					whileuntil.start( SYSAPP );
					whileuntil.put( SYSAPP_NAME, "not" );
				}
				whileuntil.add( rhs );
				if ( fnc == tokty_until ) {
					whileuntil.end();
				}
				if ( this->tryToken( tokty_then ) ) {
					Node then = this->readExprPrec( prec_then );
					whileuntil.add( then );
				} else {
					whileuntil.start( SEQ );
					whileuntil.end();
				}
				whileuntil.end();
				return whileuntil.build();				
			}
			case tokty_where: {
				NodeFactory where;
				where.start( WHERE );
				where.add( lhs );
				Node rhs = this->readExprPrec( prec );
				where.add( rhs );
				where.end();
				return where.build();
			}
			case tokty_do: {
				NodeFactory node;
				node.start( DO );
				node.add( lhs );
				Node do_stmnts = this->readCompoundStmnts();
				if ( not this->tryToken( tokty_enddo ) ) {
					this->checkPeekCloser();
				}
				node.add( do_stmnts );
				node.end();
				return node.build();
			}
			case tokty_from: {				
				updateAsPattern( lhs, true );
				NodeFactory node;
				node.start( FROM );
				Node from_expr = this->readExprPrec( prec );
				node.add( lhs );
				node.add( from_expr );

				const bool has_by_part = this->tryToken( tokty_by );
				
				if ( has_by_part ) {
					Node by_expr = this->readExprPrec( prec );
					node.add( by_expr );
				}

				const bool has_to_part = this->tryToken( tokty_to );

				if ( has_to_part && not has_by_part ) {
					//	We should insert a default.
					//	TODO: refactor (extract) adding a constant int.
					pushConstant( node, "int", "1" );
				}
				
				if ( has_to_part ) {
					Node to_expr = this->readExprPrec( prec );
					node.add( to_expr );
				}
				
				node.end();
				return node.build();
			}
			case tokty_in: {				
				updateAsPattern( lhs, true );
				Node in_expr = this->readExprPrec( prec );
				NodeFactory node;
				node.start( IN );
				node.add( lhs );
				node.add( in_expr );
				node.end();
				return node.build();
			}
			case tokty_dsemi:
			case tokty_semi: {
				Node rhs = this->readOptExprPrec( prec );
				bool hasnt_rhs = not( rhs );
				if ( fnc == tokty_semi && hasnt_rhs ) {
					return lhs;
				} else {
					NodeFactory s;
					s.start( fnc == tokty_semi ? SEQ : ERASE );
					s.add( lhs );
					if ( not hasnt_rhs ) s.add( rhs );
					s.end();
					return s.build();
				}
			}
			case tokty_obracket: {
				//	Indexing operator.
				Node rhs = this->readStmntsCheck( tokty_cbracket );
				return makeIndex( lhs, rhs );
			}
			case tokty_oparen: {	
				Node rhs = this->readOptEmptyExprCheck( tokty_cparen );
				return makeApp( lhs, rhs );
			}
			case tokty_at:
			case tokty_dot: {
				Node func = this->readExprPrec( prec_tight );
				Node rhs = this->readOptExprPrec( prec );			
				NodeFactory seq;
				seq.start( SEQ );
				seq.add( lhs );
				if ( not not rhs ) { seq.add( rhs ); }
				seq.end();
				return makeApp( func, seq.build() );
			}
			case tokty_double: {
				NodeFactory add;
				//	TODO: Bug??
				add.start( "add" );
				add.add( lhs );
				pushConstant( add, "double", item->nameString() );
				add.end();
				Node t = add.build();
				//cerr << "DEBUG arity " << term_arity( t ) << endl;
				return t;
			}
			case tokty_int: {
				NodeFactory add;
				//	TODO: Bug??
				add.start( "add" );
				add.add( lhs );
				pushConstant( add, "int", item->nameString() );
				add.end();
				Node t = add.build();
				//cerr << "DEBUG arity " << term_arity( t ) << endl;
				return t;
			}
			/*
				case tokty_explode: {
				NodeFactory expl;
				expl.start( SYSAPP );
				expl.put( SYSAPP_NAME, "explode" );
				expl.add( lhs );
				expl.end();
				Node t = expl.build();
				return t;
			}
			*/
			default: {
				throw CompileTimeError( "This keyword not handled" ).culprit( "Keyword", item->nameString() );
			}
		}
	}
    throw;	//	Unreachable.
}