Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/DeclarationNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,918 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// DeclarationNode.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 12:34:05 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu May 21 09:28:54 2015
+// Update Count     : 13
+//
+
+#include <string>
+#include <list>
+#include <iterator>
+#include <algorithm>
+#include <cassert>
+
+#include "TypeData.h"
+#include "SynTree/Expression.h"
+
+
+using namespace std;
+
+// These must remain in the same order as the corresponding DeclarationNode enumerations.
+const char *DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue", "_Atomic" };
+const char *DeclarationNode::basicTypeName[] = { "char", "int", "float", "double", "void", "_Bool", "_Complex", "_Imaginary" };
+const char *DeclarationNode::modifierName[] = { "signed", "unsigned", "short", "long" };
+const char *DeclarationNode::tyConName[] = { "struct", "union", "context" };
+const char *DeclarationNode::typeClassName[] = { "type", "dtype", "ftype" };
+
+UniqueName DeclarationNode::anonymous( "__anonymous" );
+
+extern LinkageSpec::Type linkage;		/* defined in cfa.y */
+
+DeclarationNode *DeclarationNode::clone() const {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = maybeClone( type );
+	newnode->name = name;
+	newnode->storageClasses = storageClasses;
+	newnode->bitfieldWidth = maybeClone( bitfieldWidth );
+	newnode->hasEllipsis = hasEllipsis;
+	newnode->initializer = initializer;
+	newnode->next = maybeClone( next );
+	newnode->linkage = linkage;
+	return newnode;
+}
+
+DeclarationNode::DeclarationNode() : type( 0 ), bitfieldWidth( 0 ), initializer( 0 ), hasEllipsis( false ), linkage( ::linkage ) {
+}
+
+DeclarationNode::~DeclarationNode() {
+	delete type;
+	delete bitfieldWidth;
+	delete initializer;
+}
+
+bool DeclarationNode::get_hasEllipsis() const {
+	return hasEllipsis;
+}
+
+const char *storageClassName[] = {
+	// order must correspond with DeclarationNode::StorageClass
+	"extern",
+	"static",
+	"auto",
+	"register",
+	"inline",
+	"fortran",
+};
+
+void DeclarationNode::print( std::ostream &os, int indent ) const {
+	os << string(indent, ' ' );
+	if ( name == "" ) {
+		os << "unnamed: ";
+	} else {
+		os << name << ": ";
+	}
+
+	if ( linkage != LinkageSpec::Cforall ) {
+		os << LinkageSpec::toString( linkage ) << " ";
+	}
+
+	printEnums( storageClasses.begin(), storageClasses.end(), storageClassName, os );
+	if ( type ) {
+		type->print( os, indent );
+	} else {
+		os << "untyped entity ";
+	}
+
+	if ( bitfieldWidth ) {
+		os << endl << string(indent+2,  ' ') << "with bitfield width ";
+		bitfieldWidth->printOneLine( os );
+	}
+
+	if ( initializer != 0 ) {
+		os << endl << string(indent+2,  ' ') << "with initializer ";
+		initializer->printOneLine( os );
+	}
+
+	os << endl;
+}
+
+void DeclarationNode::printList( std::ostream &os, int indent ) const {
+	ParseNode::printList( os, indent );
+	if ( hasEllipsis ) {
+		os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
+	}
+}
+
+DeclarationNode *DeclarationNode::newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+
+	newnode->type = new TypeData( TypeData::Function );
+	newnode->type->function->params = param;
+	newnode->type->function->newStyle = newStyle;
+	newnode->type->function->body = body;
+
+	if ( body ) {
+		newnode->type->function->hasBody = true;
+	}
+
+	if ( ret ) {
+		newnode->type->base = ret->type;
+		ret->type = 0;
+		delete ret;
+	}
+
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newQualifier( Qualifier q ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData();
+	newnode->type->qualifiers.push_back( q );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newStorageClass( StorageClass sc ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->storageClasses.push_back( sc );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newBasicType( BasicType bt ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->basic->typeSpec.push_back( bt );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newModifier( Modifier mod ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Basic );
+	newnode->type->basic->modifiers.push_back( mod );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newForall( DeclarationNode* forall ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Unknown );
+	newnode->type->forall = forall;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newFromTypedef( std::string* name ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::SymbolicInst );
+	newnode->type->symbolic->name = assign_strptr( name );
+	newnode->type->symbolic->isTypedef = true;
+	newnode->type->symbolic->params = 0;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newAggregate( TyCon kind, std::string* name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Aggregate );
+	newnode->type->aggregate->kind = kind;
+	newnode->type->aggregate->name = assign_strptr( name );
+	if ( newnode->type->aggregate->name == "" ) {
+		newnode->type->aggregate->name = DeclarationNode::anonymous.newName();
+	}
+	newnode->type->aggregate->params = formals;
+	newnode->type->aggregate->actuals = actuals;
+	newnode->type->aggregate->members = fields;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newEnum( std::string *name, DeclarationNode *constants ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+	newnode->type = new TypeData( TypeData::Enum );
+	newnode->type->enumeration->name = newnode->name;
+	if ( newnode->type->enumeration->name == "" ) {
+		newnode->type->enumeration->name = DeclarationNode::anonymous.newName();
+	}
+	newnode->type->enumeration->constants = constants;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newEnumConstant( std::string* name, ExpressionNode *constant ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+	// do something with the constant
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newName( std::string* name ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newFromTypeGen( std::string* name, ExpressionNode *params ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::SymbolicInst );
+	newnode->type->symbolic->name = assign_strptr( name );
+	newnode->type->symbolic->isTypedef = false;
+	newnode->type->symbolic->actuals = params;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newTypeParam( TypeClass tc, std::string* name ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+	newnode->type = new TypeData( TypeData::Variable );
+	newnode->type->variable->tyClass = tc;
+	newnode->type->variable->name = newnode->name;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Aggregate );
+	newnode->type->aggregate->kind = Context;
+	newnode->type->aggregate->params = params;
+	newnode->type->aggregate->members = asserts;
+	newnode->type->aggregate->name = assign_strptr( name );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newContextUse( std::string *name, ExpressionNode *params ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::AggregateInst );
+	newnode->type->aggInst->aggregate = new TypeData( TypeData::Aggregate );
+	newnode->type->aggInst->aggregate->aggregate->kind = Context;
+	newnode->type->aggInst->aggregate->aggregate->name = assign_strptr( name );
+	newnode->type->aggInst->params = params;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newTypeDecl( std::string *name, DeclarationNode *typeParams ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->name = assign_strptr( name );
+	newnode->type = new TypeData( TypeData::Symbolic );
+	newnode->type->symbolic->isTypedef = false;
+	newnode->type->symbolic->params = typeParams;
+	newnode->type->symbolic->name = newnode->name;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newPointer( DeclarationNode *qualifiers ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Pointer );
+	return newnode->addQualifiers( qualifiers );
+}
+
+DeclarationNode *DeclarationNode::newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Array );
+	newnode->type->array->dimension = size;
+	newnode->type->array->isStatic = isStatic;
+	newnode->type->array->isVarLen = false;
+	return newnode->addQualifiers( qualifiers );
+}
+
+DeclarationNode *DeclarationNode::newVarArray( DeclarationNode *qualifiers ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Array );
+	newnode->type->array->dimension = 0;
+	newnode->type->array->isStatic = false;
+	newnode->type->array->isVarLen = true;
+	return newnode->addQualifiers( qualifiers );
+}
+
+DeclarationNode *DeclarationNode::newBitfield( ExpressionNode *size ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->bitfieldWidth = size;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newTuple( DeclarationNode *members ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Tuple );
+	newnode->type->tuple->members = members;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newTypeof( ExpressionNode *expr ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Typeof );
+	newnode->type->typeexpr->expr = expr;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newAttr( std::string *name, ExpressionNode *expr ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Attr );
+	newnode->type->attr->name = assign_strptr( name );
+	newnode->type->attr->expr = expr;
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::newAttr( std::string *name, DeclarationNode *type ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Attr );
+	newnode->type->attr->name = assign_strptr( name );
+	newnode->type->attr->type = type;
+	return newnode;
+}
+
+static void addQualifiersToType( TypeData *&src, TypeData *dst ) {
+	if ( src && dst ) {
+		if ( src->forall && dst->kind == TypeData::Function ) {
+			if ( dst->forall ) {
+				dst->forall->appendList( src->forall );
+			} else {
+				dst->forall = src->forall;
+			}
+			src->forall = 0;
+		}
+		if ( dst->base ) {
+			addQualifiersToType( src, dst->base );
+		} else if ( dst->kind == TypeData::Function ) {
+			dst->base = src;
+			src = 0;
+		} else {
+			dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
+		}
+	}
+}
+	  
+DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) {
+	if ( q ) {
+		storageClasses.splice( storageClasses.end(), q->storageClasses );
+		if ( q->type ) {
+			if ( ! type ) {
+				type = new TypeData;
+			}
+			addQualifiersToType( q->type, type );
+			if ( q->type && q->type->forall ) {
+				if ( type->forall ) {
+					type->forall->appendList( q->type->forall );
+				} else {
+					type->forall = q->type->forall;
+				}
+				q->type->forall = 0;
+			}
+		}
+	}
+	delete q;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) {
+	storageClasses = q->storageClasses;
+	return this;
+}
+
+static void addTypeToType( TypeData *&src, TypeData *&dst ) {
+	if ( src && dst ) {
+		if ( src->forall && dst->kind == TypeData::Function ) {
+			if ( dst->forall ) {
+				dst->forall->appendList( src->forall );
+			} else {
+				dst->forall = src->forall;
+			}
+			src->forall = 0;
+		}
+		if ( dst->base ) {
+			addTypeToType( src, dst->base );
+		} else {
+			switch ( dst->kind ) {
+			  case TypeData::Unknown:
+				src->qualifiers.splice( src->qualifiers.end(), dst->qualifiers );
+				dst = src;
+				src = 0;
+				break;
+
+			  case TypeData::Basic:
+				dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
+				if ( src->kind != TypeData::Unknown ) {
+					assert( src->kind == TypeData::Basic );
+					dst->basic->modifiers.splice( dst->basic->modifiers.end(), src->basic->modifiers );
+					dst->basic->typeSpec.splice( dst->basic->typeSpec.end(), src->basic->typeSpec );
+				}
+				break;
+
+			  default:
+				switch ( src->kind ) {
+				  case TypeData::Aggregate:
+				  case TypeData::Enum:
+					dst->base = new TypeData( TypeData::AggregateInst );
+					dst->base->aggInst->aggregate = src;
+					if ( src->kind == TypeData::Aggregate ) {
+						dst->base->aggInst->params = maybeClone( src->aggregate->actuals );
+					}
+					dst->base->qualifiers.splice( dst->base->qualifiers.end(), src->qualifiers );
+					src = 0;
+					break;
+
+				  default:
+					if ( dst->forall ) {
+						dst->forall->appendList( src->forall );
+					} else {
+						dst->forall = src->forall;
+					}
+					src->forall = 0;
+					dst->base = src;
+					src = 0;
+				}
+			}
+		}
+	}
+}
+
+DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) {
+	if ( o ) {
+		storageClasses.splice( storageClasses.end(), o->storageClasses );
+		if ( o->type ) {
+			if ( ! type ) {
+				if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
+					type = new TypeData( TypeData::AggregateInst );
+					type->aggInst->aggregate = o->type;
+					if ( o->type->kind == TypeData::Aggregate ) {
+						type->aggInst->params = maybeClone( o->type->aggregate->actuals );
+					}
+					type->qualifiers.splice( type->qualifiers.end(), o->type->qualifiers );
+				} else {
+					type = o->type;
+				}
+				o->type = 0;
+			} else {
+				addTypeToType( o->type, type );
+			}
+		}
+		if ( o->bitfieldWidth ) {
+			bitfieldWidth = o->bitfieldWidth;
+		}
+	}
+	delete o;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addTypedef() {
+	TypeData *newtype = new TypeData( TypeData::Symbolic );
+	newtype->symbolic->params = 0;
+	newtype->symbolic->isTypedef = true;
+	newtype->symbolic->name = name;
+	newtype->base = type;
+	type = newtype;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addAssertions( DeclarationNode* assertions ) {
+	assert( type );
+	switch ( type->kind ) {
+	  case TypeData::Symbolic:
+		if ( type->symbolic->assertions ) {
+			type->symbolic->assertions->appendList( assertions );
+		} else {
+			type->symbolic->assertions = assertions;
+		}
+		break;
+	
+	  case TypeData::Variable:
+		if ( type->variable->assertions ) {
+			type->variable->assertions->appendList( assertions );
+		} else {
+			type->variable->assertions = assertions;
+		}
+		break;
+	
+	  default:
+		assert( false );
+	}
+	
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addName( std::string* newname ) {
+	name = assign_strptr( newname );
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addBitfield( ExpressionNode *size ) {
+	bitfieldWidth = size;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addVarArgs() {
+	assert( type );
+	hasEllipsis = true;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addFunctionBody( StatementNode *body ) {
+	assert( type );
+	assert( type->kind == TypeData::Function );
+	assert( type->function->body == 0 );
+	type->function->body = body;
+	type->function->hasBody = true;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addOldDeclList( DeclarationNode *list ) {
+	assert( type );
+	assert( type->kind == TypeData::Function );
+	assert( type->function->oldDeclList == 0 );
+	type->function->oldDeclList = list;
+	return this;
+}
+
+static void
+setBase( TypeData *&type, TypeData *newType ) {
+	if ( type ) {
+		TypeData *prevBase = type;
+		TypeData *curBase = type->base;
+		while ( curBase != 0 ) {
+			prevBase = curBase;
+			curBase = curBase->base;
+		}
+		prevBase->base = newType;
+	} else {
+		type = newType;
+	}
+}
+
+DeclarationNode *DeclarationNode::addPointer( DeclarationNode *p ) {
+	if ( p ) {
+		assert( p->type->kind == TypeData::Pointer );
+		setBase( type, p->type );
+		p->type = 0;
+		delete p;
+	}
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addArray( DeclarationNode *a ) {
+	if ( a ) {
+		assert( a->type->kind == TypeData::Array );
+		setBase( type, a->type );
+		a->type = 0;
+		delete a;
+	}
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addNewPointer( DeclarationNode *p ) {
+	if ( p ) {
+		assert( p->type->kind == TypeData::Pointer );
+		if ( type ) {
+			switch ( type->kind ) {
+			  case TypeData::Aggregate:
+			  case TypeData::Enum:
+				p->type->base = new TypeData( TypeData::AggregateInst );
+				p->type->base->aggInst->aggregate = type;
+				if ( type->kind == TypeData::Aggregate ) {
+					p->type->base->aggInst->params = maybeClone( type->aggregate->actuals );
+				}
+				p->type->base->qualifiers.splice( p->type->base->qualifiers.end(), type->qualifiers );
+				break;
+
+			  default:
+				p->type->base = type;
+			}
+			type = 0;
+		}
+		delete this;
+		return p;
+	} else {
+		return this;
+	}
+}
+
+static TypeData *findLast( TypeData *a ) {
+	assert( a );
+	TypeData *cur = a;
+	while ( cur->base ) {
+		cur = cur->base;
+	}
+	return cur;
+}
+
+DeclarationNode *DeclarationNode::addNewArray( DeclarationNode *a ) {
+	if ( a ) {
+		assert( a->type->kind == TypeData::Array );
+		TypeData *lastArray = findLast( a->type );
+		if ( type ) {  
+			switch ( type->kind ) {
+			  case TypeData::Aggregate:
+			  case TypeData::Enum:
+				lastArray->base = new TypeData( TypeData::AggregateInst );
+				lastArray->base->aggInst->aggregate = type;
+				if ( type->kind == TypeData::Aggregate ) {
+					lastArray->base->aggInst->params = maybeClone( type->aggregate->actuals );
+				}
+				lastArray->base->qualifiers.splice( lastArray->base->qualifiers.end(), type->qualifiers );
+				break;
+			  default:
+				lastArray->base = type;
+			}
+			type = 0;
+		}
+		delete this;
+		return a;
+	} else {
+		return this;
+	}
+}
+
+DeclarationNode *DeclarationNode::addParamList( DeclarationNode *params ) {
+	TypeData *ftype = new TypeData( TypeData::Function );
+	ftype->function->params = params;
+	setBase( type, ftype );
+	return this;
+}
+
+static TypeData *addIdListToType( TypeData *type, DeclarationNode *ids ) {
+	if ( type ) {
+		if ( type->kind != TypeData::Function ) {
+			type->base = addIdListToType( type->base, ids );
+		} else {
+			type->function->idList = ids;
+		}
+		return type;
+	} else {
+		TypeData *newtype = new TypeData( TypeData::Function );
+		newtype->function->idList = ids;
+		return newtype;
+	}
+}
+	
+DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) {
+	type = addIdListToType( type, ids );
+	return this;
+}
+
+DeclarationNode *DeclarationNode::addInitializer( InitializerNode *init ) {
+	//assert
+	initializer = init;
+	return this;
+}
+
+DeclarationNode *DeclarationNode::cloneBaseType( string *newName ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	TypeData *srcType = type;
+	while ( srcType->base ) {
+		srcType = srcType->base;
+	}
+	newnode->type = maybeClone( srcType );
+	if ( newnode->type->kind == TypeData::AggregateInst ) {
+		// don't duplicate members
+		if ( newnode->type->aggInst->aggregate->kind == TypeData::Enum ) {
+			delete newnode->type->aggInst->aggregate->enumeration->constants;
+			newnode->type->aggInst->aggregate->enumeration->constants = 0;
+		} else {
+			assert( newnode->type->aggInst->aggregate->kind == TypeData::Aggregate );
+			delete newnode->type->aggInst->aggregate->aggregate->members;
+			newnode->type->aggInst->aggregate->aggregate->members = 0;
+		}
+	}
+	newnode->type->forall = maybeClone( type->forall );
+	newnode->storageClasses = storageClasses;
+	newnode->name = assign_strptr( newName );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) {
+	if ( o ) {
+		o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
+		if ( type ) {
+			TypeData *srcType = type;
+			while ( srcType->base ) {
+				srcType = srcType->base;
+			}
+			TypeData *newType = srcType->clone();
+			if ( newType->kind == TypeData::AggregateInst ) {
+				// don't duplicate members
+				if ( newType->aggInst->aggregate->kind == TypeData::Enum ) {
+					delete newType->aggInst->aggregate->enumeration->constants;
+					newType->aggInst->aggregate->enumeration->constants = 0;
+				} else {
+					assert( newType->aggInst->aggregate->kind == TypeData::Aggregate );
+					delete newType->aggInst->aggregate->aggregate->members;
+					newType->aggInst->aggregate->aggregate->members = 0;
+				}
+			}
+			newType->forall = maybeClone( type->forall );
+			if ( ! o->type ) {
+				o->type = newType;
+			} else {
+				addTypeToType( newType, o->type );
+				delete newType;
+			}
+		}
+	}
+	return o;
+}
+
+DeclarationNode *DeclarationNode::cloneType( string *newName ) {
+	DeclarationNode *newnode = new DeclarationNode;
+	newnode->type = maybeClone( type );
+	newnode->storageClasses = storageClasses;
+	newnode->name = assign_strptr( newName );
+	return newnode;
+}
+
+DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) {
+	if ( o ) {
+		o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
+		if ( type ) {
+			TypeData *newType = type->clone();
+			if ( ! o->type ) {
+				o->type = newType;
+			} else {
+				addTypeToType( newType, o->type );
+				delete newType;
+			}
+		}
+	}
+	return o;
+}
+
+DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) {
+	if ( node != 0 ) {
+		set_link( node );
+	}
+	return this;
+}
+
+DeclarationNode *DeclarationNode::extractAggregate() const {
+	if ( type ) {
+		TypeData *ret = type->extractAggregate();
+		if ( ret ) {
+			DeclarationNode *newnode = new DeclarationNode;
+			newnode->type = ret;
+			return newnode;
+		} // if
+	} // if
+	return 0;
+}
+
+void buildList( const DeclarationNode *firstNode, std::list< Declaration* > &outputList ) {
+	SemanticError errors;
+	std::back_insert_iterator< std::list< Declaration* > > out( outputList );
+	const DeclarationNode *cur = firstNode;
+	while ( cur ) {
+		try {
+			if ( DeclarationNode *extr = cur->extractAggregate() ) {
+				// handle the case where a structure declaration is contained within an object or type declaration
+				Declaration *decl = extr->build();
+				if ( decl ) {
+					*out++ = decl;
+				} // if
+			} // if
+			Declaration *decl = cur->build();
+			if ( decl ) {
+				*out++ = decl;
+			} // if
+		} catch( SemanticError &e ) {
+			errors.append( e );
+		} // try
+		cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+	} // while
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+}
+
+void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType* > &outputList ) {
+	SemanticError errors;
+	std::back_insert_iterator< std::list< DeclarationWithType* > > out( outputList );
+	const DeclarationNode *cur = firstNode;
+	while ( cur ) {
+		try {
+///       if ( DeclarationNode *extr = cur->extractAggregate() ) {
+/// 	// handle the case where a structure declaration is contained within an object or type
+/// 	// declaration
+/// 	Declaration *decl = extr->build();
+/// 	if ( decl ) {
+///          *out++ = decl;
+/// 	}
+///       }
+			Declaration *decl = cur->build();
+			if ( decl ) {
+				if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
+					*out++ = dwt;
+				} else if ( StructDecl *agg = dynamic_cast< StructDecl* >( decl ) ) {
+					StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
+					*out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
+					delete agg;
+				} else if ( UnionDecl *agg = dynamic_cast< UnionDecl* >( decl ) ) {
+					UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
+					*out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
+				} // if
+			} // if
+		} catch( SemanticError &e ) {
+			errors.append( e );
+		} // try
+		cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+	} // while
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+}
+
+void buildTypeList( const DeclarationNode *firstNode, std::list< Type* > &outputList ) {
+	SemanticError errors;
+	std::back_insert_iterator< std::list< Type* > > out( outputList );
+	const DeclarationNode *cur = firstNode;
+	while ( cur ) {
+		try {
+			*out++ = cur->buildType();
+		} catch( SemanticError &e ) {
+			errors.append( e );
+		} // try
+		cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+	} // while
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+}
+
+Declaration *DeclarationNode::build() const {
+	if ( type ) {
+		Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildInline(), linkage, maybeBuild< Initializer >(initializer) );
+		return newDecl;
+	} // if
+	if ( ! buildInline() ) {
+		return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) );
+	} // if
+	throw SemanticError( "invalid inline specification in declaration of ", this );
+}
+
+Type *DeclarationNode::buildType() const {
+	assert( type );
+  
+	switch ( type->kind ) {
+	  case TypeData::Enum:
+		return new EnumInstType( type->buildQualifiers(), type->enumeration->name );
+	  case TypeData::Aggregate: {
+		  ReferenceToType *ret;
+		  switch ( type->aggregate->kind ) {
+			case DeclarationNode::Struct:
+			  ret = new StructInstType( type->buildQualifiers(), type->aggregate->name );
+			  break;
+			case DeclarationNode::Union:
+			  ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name );
+			  break;
+			case DeclarationNode::Context:
+			  ret = new ContextInstType( type->buildQualifiers(), type->aggregate->name );
+			  break;
+			default:
+			  assert( false );
+		  } // switch
+		  buildList( type->aggregate->actuals, ret->get_parameters() );
+		  return ret;
+	  }
+	  case TypeData::Symbolic: {
+		  TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false );
+		  buildList( type->symbolic->actuals, ret->get_parameters() );
+		  return ret;
+	  }
+	  default:
+		return type->build();
+	} // switch
+}
+
+Declaration::StorageClass DeclarationNode::buildStorageClass() const {
+	static const Declaration::StorageClass scMap[] = {  
+		Declaration::Extern,
+		Declaration::Static,
+		Declaration::Auto,
+		Declaration::Register,
+		Declaration::Inline,
+		Declaration::Fortran
+	};  
+  
+	Declaration::StorageClass ret = Declaration::NoStorageClass;
+	for ( std::list< StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) {
+		assert( unsigned( *i ) < sizeof( scMap ) / sizeof( scMap[0] ) );
+	  if ( *i == Inline ) continue;
+	  if ( ret != Declaration::NoStorageClass ) {
+			throw SemanticError( "invalid combination of storage classes in declaration of ", this );
+		}
+		ret = scMap[ *i ];
+	}
+	return ret;
+}
+
+bool DeclarationNode::buildInline() const {
+	std::list< StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), Inline );
+  if ( first == storageClasses.end() ) return false;
+	std::list< StorageClass >::const_iterator next = std::find( ++first, storageClasses.end(), Inline );
+  if ( next == storageClasses.end() ) return true;
+	throw SemanticError( "duplicate inline specification in declaration of ", this );
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/ExpressionNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,732 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ExpressionNode.cc -- 
+// 
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:17:07 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 13:19:35 2015
+// Update Count     : 2
+// 
+
+#include <cassert>
+#include <cctype>
+#include <algorithm>
+
+#include "ParseNode.h"
+#include "SynTree/Type.h"
+#include "SynTree/Constant.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "UnimplementedError.h"
+#include "parseutility.h"
+#include "utility.h"
+
+using namespace std;
+
+ExpressionNode::ExpressionNode() : ParseNode(), argName( 0 ) {}
+
+ExpressionNode::ExpressionNode( string *name_) : ParseNode( *name_ ), argName( 0 ) {
+	delete name_;
+}
+
+ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.name ) {
+	if ( other.argName ) {
+		argName = other.argName->clone();
+	} else {
+		argName = 0;
+	} // if
+}
+
+ExpressionNode * ExpressionNode::set_asArgName( std::string *aName ) {
+	argName = new VarRefNode( aName );
+	return this;
+}
+
+ExpressionNode * ExpressionNode::set_asArgName( ExpressionNode *aDesignator ) {
+	argName = aDesignator;
+	return this;
+}
+
+void ExpressionNode::printDesignation( std::ostream &os, int indent ) const {
+	if ( argName ) {
+		os << string(' ', indent ) << "(designated by:  ";
+		argName->printOneLine( os, indent );
+		os << ")" << std::endl;
+	} // if
+}
+
+NullExprNode::NullExprNode() {}
+
+NullExprNode *NullExprNode::clone() const {
+	return new NullExprNode();
+}
+
+void NullExprNode::print( std::ostream & os, int indent ) const {
+	printDesignation( os );
+	os << "null expression";
+}
+
+void NullExprNode::printOneLine( std::ostream & os, int indent ) const {
+	printDesignation( os );
+	os << "null";
+}
+
+Expression *NullExprNode::build() const {
+	return 0;
+}
+
+CommaExprNode *ExpressionNode::add_to_list( ExpressionNode *exp ) {
+	return new CommaExprNode( this, exp );
+}
+
+//  enum ConstantNode::Type =  { Integer, Float, Character, String, Range }
+
+ConstantNode::ConstantNode( void ) : ExpressionNode(), sign( true ), longs(0), size(0) {}
+
+ConstantNode::ConstantNode( string *name_) : ExpressionNode( name_), sign( true ), longs(0), size(0) {}
+
+ConstantNode::ConstantNode( Type t, string *inVal ) : type( t ), sign( true ), longs(0), size(0) {
+	if ( inVal ) {
+		value = *inVal;
+		delete inVal;
+	} else {
+		value = "";
+	} // if
+
+	classify( value );
+}
+
+ConstantNode::ConstantNode( const ConstantNode &other ) : ExpressionNode( other ), type( other.type ), value( other.value ), sign( other.sign ),
+														  base( other.base ), longs( other.longs ), size( other.size ) {
+}
+
+// for some reason, std::tolower doesn't work as an argument to std::transform in g++ 3.1
+inline char tolower_hack( char c ) {
+	return std::tolower( c );
+}
+
+void ConstantNode::classify( std::string &str ) {
+	switch ( type ) {
+	  case Integer:
+	  case Float:
+		{
+			std::string sfx("");
+			char c;
+			int i = str.length() - 1;
+
+			while ( i >= 0 && ! isxdigit( c = str.at( i--)) )
+				sfx += c;
+
+			value = str.substr( 0, i + 2 );
+
+			// get rid of underscores
+			value.erase( remove( value.begin(), value.end(), '_'), value.end());
+
+			std::transform( sfx.begin(), sfx.end(), sfx.begin(), tolower_hack );
+
+			if ( sfx.find("ll") != string::npos ) {
+				longs = 2;
+			} else if ( sfx.find("l") != string::npos ) {
+				longs = 1;
+			} // if
+
+			assert(( longs >= 0) && ( longs <= 2));
+
+			if ( sfx.find("u") != string::npos )
+				sign = false;
+
+			break;
+		}
+	  case Character:
+		{
+			// remove underscores from hex and oct escapes
+			if ( str.substr(1,2) == "\\x")
+				value.erase( remove( value.begin(), value.end(), '_'), value.end());
+
+			break;
+		}
+	  default:
+		// shouldn't be here
+		;
+	}
+}
+
+ConstantNode::Type ConstantNode::get_type( void ) const {
+	return type;
+}
+
+ConstantNode *ConstantNode::append( std::string *newValue ) {
+	if ( newValue ) {
+		if ( type == String ) {
+			std::string temp = *newValue;
+			value.resize( value.size() - 1 );
+			value += newValue->substr(1, newValue->size());
+		} else
+			value += *newValue;
+
+		delete newValue;
+	} // if
+	return this;
+}
+
+void ConstantNode::printOneLine( std::ostream &os, int indent ) const {
+	os << string( indent, ' ');
+	printDesignation( os );
+
+	switch ( type ) {
+		/* integers */
+	  case Integer:
+		os << value ;
+		break;
+	  case Float:
+		os << value ;
+		break;
+
+	  case Character:
+		os << "'" << value << "'";
+		break;
+
+	  case String:
+		os << '"' << value << '"';
+		break;
+	}
+
+	os << ' ';
+}
+
+void ConstantNode::print( std::ostream &os, int indent ) const {
+	printOneLine( os, indent );
+	os << endl;
+}
+
+Expression *ConstantNode::build() const {
+	::Type::Qualifiers q;
+	BasicType *bt;
+
+	switch ( get_type()) {
+	  case Integer:
+		/* Cfr. standard 6.4.4.1 */
+		//bt.set_kind( BasicType::SignedInt );
+		bt = new BasicType( q, BasicType::SignedInt );
+		break;
+	  case Float:
+		bt = new BasicType( q, BasicType::Float );
+		break;
+	  case Character:
+		bt = new BasicType( q, BasicType::Char );
+		break;
+	  case String:
+		// string should probably be a primitive type
+		ArrayType *at;
+		std::string value = get_value();
+		at = new ArrayType( q, new BasicType( q, BasicType::Char ),
+							new ConstantExpr( Constant( new BasicType( q, BasicType::SignedInt ),
+														toString( value.size() - 1 ) ) ),  // account for '\0'
+							false, false );
+		return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) );
+	}
+	return new ConstantExpr(  Constant( bt, get_value()),  maybeBuild< Expression >( get_argName() ) );
+}
+
+VarRefNode::VarRefNode() : isLabel( false ) {}
+
+VarRefNode::VarRefNode( string *name_, bool labelp ) : ExpressionNode( name_), isLabel( labelp ) {}
+
+VarRefNode::VarRefNode( const VarRefNode &other ) : ExpressionNode( other ), isLabel( other.isLabel ) {
+}
+
+Expression *VarRefNode::build() const {
+	return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) );
+}
+
+void VarRefNode::printOneLine( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << get_name() << ' ';
+}
+
+void VarRefNode::print( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << '\r' << string( indent, ' ') << "Referencing: ";
+	os << "Variable: " << get_name();
+	os << endl;
+}
+
+OperatorNode::OperatorNode( Type t ) : type( t ) {}
+
+OperatorNode::OperatorNode( const OperatorNode &other ) : ExpressionNode( other ), type( other.type ) {
+}
+
+OperatorNode::~OperatorNode() {}
+
+OperatorNode::Type OperatorNode::get_type( void ) const{
+	return type;
+}
+
+void OperatorNode::printOneLine( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << OpName[ type ] << ' ';
+}
+
+void OperatorNode::print( std::ostream &os, int indent ) const{
+	printDesignation( os );
+	os << '\r' << string( indent, ' ') << "Operator: " << OpName[type] << endl;
+	return;
+}
+
+std::string OperatorNode::get_typename( void ) const{
+	return string( OpName[ type ]);
+}
+
+const char *OperatorNode::OpName[] = {
+	"TupleC",  "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic
+	// triadic
+	"Cond",   "NCond",
+	// diadic
+	"SizeOf",      "AlignOf", "Attr", "CompLit", "Plus",    "Minus",   "Mul",     "Div",     "Mod",      "Or",
+	"And",       "BitOr",   "BitAnd",  "Xor",     "Cast",    "LShift",  "RShift",  "LThan",   "GThan",
+	"LEThan",    "GEThan", "Eq",      "Neq",     "Assign",  "MulAssn", "DivAssn", "ModAssn", "PlusAssn",
+	"MinusAssn", "LSAssn", "RSAssn",  "AndAssn", "ERAssn",  "OrAssn",  "Index",   "FieldSel","PFieldSel",
+	"Range",
+	// monadic
+	"UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress"
+};
+
+CompositeExprNode::CompositeExprNode( void ) : ExpressionNode(), function( 0 ), arguments( 0 ) {
+}
+
+CompositeExprNode::CompositeExprNode( string *name_) : ExpressionNode( name_), function( 0 ), arguments( 0 ) {
+}
+
+CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *args ):
+	function( f ), arguments( args ) {
+}
+
+CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2):
+	function( f ), arguments( arg1) {
+	arguments->set_link( arg2);
+}
+
+CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) {
+	ParseNode *cur = other.arguments;
+	while ( cur ) {
+		if ( arguments ) {
+			arguments->set_link( cur->clone() );
+		} else {
+			arguments = ( ExpressionNode*)cur->clone();
+		} // if
+		cur = cur->get_link();
+	}
+}
+
+CompositeExprNode::~CompositeExprNode() {
+	delete function;
+	delete arguments;
+}
+
+// the names that users use to define operator functions
+static const char *opFuncName[] = {
+	"",  "", "",
+	"",   "",
+	// diadic
+	"",   "", "", "", "?+?",    "?-?",   "?*?",     "?/?",     "?%?",     "",       "",
+	"?|?",  "?&?",  "?^?",     "",    "?<<?",  "?>>?",  "?<?",   "?>?",    "?<=?",
+	"?>=?", "?==?",      "?!=?",     "?=?",  "?*=?", "?/=?", "?%=?", "?+=?", "?-=?",
+	"?<<=?", "?>>=?",  "?&=?", "?^=?",  "?|=?",  "?[?]",   "","","Range",
+	// monadic
+	"+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress"
+};
+
+#include "utility.h"
+
+Expression *CompositeExprNode::build() const {
+	OperatorNode *op;
+	std::list<Expression *> args;
+
+	buildList( get_args(), args );
+
+	if ( ! ( op = dynamic_cast<OperatorNode *>( function )) ) {
+		// a function as opposed to an operator
+		return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() ));
+	} else {
+		switch ( op->get_type()) {
+		  case OperatorNode::Incr:
+		  case OperatorNode::Decr:
+		  case OperatorNode::IncrPost:
+		  case OperatorNode::DecrPost:
+		  case OperatorNode::Assign:
+		  case OperatorNode::MulAssn:
+		  case OperatorNode::DivAssn:
+		  case OperatorNode::ModAssn:
+		  case OperatorNode::PlusAssn:
+		  case OperatorNode::MinusAssn:
+		  case OperatorNode::LSAssn:
+		  case OperatorNode::RSAssn:
+		  case OperatorNode::AndAssn:
+		  case OperatorNode::ERAssn:
+		  case OperatorNode::OrAssn:
+			// the rewrite rules for these expressions specify that the first argument has its address taken
+			assert( ! args.empty() );
+			args.front() = new AddressExpr( args.front() );
+			break;
+		  default:
+			/* do nothing */
+			;
+		}
+
+		switch ( op->get_type() ) {
+		  case OperatorNode::Incr:
+		  case OperatorNode::Decr:
+		  case OperatorNode::IncrPost:
+		  case OperatorNode::DecrPost:
+		  case OperatorNode::Assign:
+		  case OperatorNode::MulAssn:
+		  case OperatorNode::DivAssn:
+		  case OperatorNode::ModAssn:
+		  case OperatorNode::PlusAssn:
+		  case OperatorNode::MinusAssn:
+		  case OperatorNode::LSAssn:
+		  case OperatorNode::RSAssn:
+		  case OperatorNode::AndAssn:
+		  case OperatorNode::ERAssn:
+		  case OperatorNode::OrAssn:
+		  case OperatorNode::Plus:
+		  case OperatorNode::Minus:
+		  case OperatorNode::Mul:
+		  case OperatorNode::Div:
+		  case OperatorNode::Mod:
+		  case OperatorNode::BitOr:
+		  case OperatorNode::BitAnd:
+		  case OperatorNode::Xor:
+		  case OperatorNode::LShift:
+		  case OperatorNode::RShift:
+		  case OperatorNode::LThan:
+		  case OperatorNode::GThan:
+		  case OperatorNode::LEThan:
+		  case OperatorNode::GEThan:
+		  case OperatorNode::Eq:
+		  case OperatorNode::Neq:
+		  case OperatorNode::Index:
+		  case OperatorNode::Range:
+		  case OperatorNode::UnPlus:
+		  case OperatorNode::UnMinus:
+		  case OperatorNode::PointTo:
+		  case OperatorNode::Neg:
+		  case OperatorNode::BitNeg:
+		  case OperatorNode::LabelAddress:
+			return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args );
+		  case OperatorNode::AddressOf:
+			assert( args.size() == 1 );
+			assert( args.front() );
+
+			return new AddressExpr( args.front() );
+		  case OperatorNode::Cast:
+			{
+				TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args());
+				assert( arg );
+
+				DeclarationNode *decl_node = arg->get_decl();
+				ExpressionNode *expr_node = dynamic_cast<ExpressionNode *>( arg->get_link());
+
+				Type *targetType = decl_node->buildType();
+				if ( dynamic_cast< VoidType* >( targetType ) ) {
+					delete targetType;
+					return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) );
+				} else {
+					return new CastExpr( expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) );
+				} // if
+			}
+		  case OperatorNode::FieldSel:
+			{
+				assert( args.size() == 2 );
+
+				NameExpr *member = dynamic_cast<NameExpr *>( args.back());
+				// TupleExpr *memberTup = dynamic_cast<TupleExpr *>( args.back());
+
+				if ( member != 0 ) {
+					UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), args.front());
+					delete member;
+					return ret;
+					/* else if ( memberTup != 0 )
+					   {
+					   UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front());
+					   delete member;
+					   return ret;
+					   } */
+				} else
+					assert( false );
+			}
+		  case OperatorNode::PFieldSel:
+			{
+				assert( args.size() == 2 );
+
+				NameExpr *member = dynamic_cast<NameExpr *>( args.back());  // modify for Tuples   xxx
+				assert( member != 0 );
+
+				UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
+				deref->get_args().push_back( args.front() );
+
+				UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref );
+				delete member;
+				return ret;
+			}
+		  case OperatorNode::AlignOf:
+		  case OperatorNode::SizeOf:
+			{
+/// 	bool isSizeOf = ( op->get_type() == OperatorNode::SizeOf );
+
+				if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()) ) {
+					return new SizeofExpr( arg->get_decl()->buildType());
+				} else {
+					return new SizeofExpr( args.front());
+				} // if
+			}
+		  case OperatorNode::Attr:
+			{
+				VarRefNode *var = dynamic_cast<VarRefNode *>( get_args());
+				assert( var );
+				if ( ! get_args()->get_link() ) {
+					return new AttrExpr( var->build(), ( Expression*)0);
+				} else if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()->get_link()) ) {
+					return new AttrExpr( var->build(), arg->get_decl()->buildType());
+				} else {
+					return new AttrExpr( var->build(), args.back());
+				} // if
+			}
+		  case OperatorNode::CompLit:
+			throw UnimplementedError( "C99 compound literals" );
+			// the short-circuited operators
+		  case OperatorNode::Or:
+		  case OperatorNode::And:
+			assert( args.size() == 2);
+			return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), ( op->get_type() == OperatorNode::And ) );
+		  case OperatorNode::Cond:
+			{
+				assert( args.size() == 3);
+				std::list< Expression* >::const_iterator i = args.begin();
+				Expression *arg1 = notZeroExpr( *i++ );
+				Expression *arg2 = *i++;
+				Expression *arg3 = *i++;
+				return new ConditionalExpr( arg1, arg2, arg3 );
+			}
+		  case OperatorNode::NCond:
+			throw UnimplementedError( "GNU 2-argument conditional expression" );
+		  case OperatorNode::Comma:
+			{
+				assert( args.size() == 2);
+				std::list< Expression* >::const_iterator i = args.begin();
+				Expression *ret = *i++;
+				while ( i != args.end() ) {
+					ret = new CommaExpr( ret, *i++ );
+				}
+				return ret;
+			}
+			// Tuples
+		  case OperatorNode::TupleC:
+			{
+				TupleExpr *ret = new TupleExpr();
+				std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
+				return ret;
+			}
+		  default:
+			// shouldn't happen
+			return 0;
+		}
+	}
+}
+
+void CompositeExprNode::printOneLine( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << "( ";
+	function->printOneLine( os, indent );
+	for ( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
+		cur->printOneLine( os, indent );
+	}
+	os << ") ";
+}
+
+void CompositeExprNode::print( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << '\r' << string( indent, ' ') << "Application of: " << endl;
+	function->print( os, indent + ParseNode::indent_by );
+
+	os << '\r' << string( indent, ' ') ;
+	if ( arguments ) {
+		os << "... on arguments: " << endl;
+		arguments->printList( os, indent + ParseNode::indent_by );
+	} else
+		os << "... on no arguments: " << endl;
+}
+
+void CompositeExprNode::set_function( ExpressionNode *f ) {
+	function = f;
+}
+
+void CompositeExprNode::set_args( ExpressionNode *args ) {
+	arguments = args;
+}
+
+ExpressionNode *CompositeExprNode::get_function( void ) const {
+	return function;
+}
+
+ExpressionNode *CompositeExprNode::get_args( void ) const {
+	return arguments;
+}
+
+void CompositeExprNode::add_arg( ExpressionNode *arg ) {
+	if ( arguments )
+		arguments->set_link( arg );
+	else
+		set_args( arg );
+}
+
+CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {}
+
+CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) {
+}
+
+CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) {
+}
+
+CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ) {
+	add_arg( exp );
+
+	return this;
+}
+
+CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) {
+}
+
+ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {}
+
+ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) {
+}
+
+ValofExprNode::~ValofExprNode() {
+	delete body;
+}
+
+void ValofExprNode::print( std::ostream &os, int indent ) const {
+	printDesignation( os );
+	os << string( indent, ' ') << "Valof Expression:" << std::endl;
+	get_body()->print( os, indent + 4);
+}
+
+void ValofExprNode::printOneLine( std::ostream &, int indent ) const {
+	assert( false );
+}
+
+Expression *ValofExprNode::build() const {
+	return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
+}
+
+ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) {
+	if ( init_ == 0 )
+		init = 0;
+	else {
+		DeclarationNode *decl;
+		ExpressionNode *exp;
+
+		if (( decl = dynamic_cast<DeclarationNode *>( init_)) != 0)
+			init = new StatementNode( decl );
+		else if (( exp = dynamic_cast<ExpressionNode *>( init_)) != 0)
+			init = new StatementNode( StatementNode::Exp, exp );
+		else
+			throw SemanticError("Error in for control expression");
+	}
+}
+
+ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
+	: ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) {
+}
+
+ForCtlExprNode::~ForCtlExprNode() {
+	delete init;
+	delete condition;
+	delete change;
+}
+
+Expression *ForCtlExprNode::build() const {
+	// this shouldn't be used!
+	assert( false );
+	return 0;
+}
+
+void ForCtlExprNode::print( std::ostream &os, int indent ) const{
+	os << string( indent,' ') << "For Control Expression -- : " << endl;
+
+	os << "\r" << string( indent + 2,' ') << "initialization: ";
+	if ( init != 0)
+		init->print( os, indent + 4);
+
+	os << "\n\r" << string( indent + 2,' ') << "condition: ";
+	if ( condition != 0)
+		condition->print( os, indent + 4);
+	os << "\n\r" << string( indent + 2,' ') << "increment: ";
+	if ( change != 0)
+		change->print( os, indent + 4);
+}
+
+void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const {
+	assert( false );
+}
+
+TypeValueNode::TypeValueNode( DeclarationNode *decl )
+	: decl( decl ) {
+}
+
+TypeValueNode::TypeValueNode( const TypeValueNode &other )
+	: ExpressionNode( other ), decl( maybeClone( other.decl ) ) {
+}
+
+Expression *TypeValueNode::build() const {
+	return new TypeExpr( decl->buildType() );
+}
+
+void TypeValueNode::print( std::ostream &os, int indent ) const {
+	os << std::string( indent, ' ' ) << "Type:";
+	get_decl()->print( os, indent + 2);
+}
+
+void TypeValueNode::printOneLine( std::ostream &os, int indent ) const {
+	os << "Type:";
+	get_decl()->print( os, indent + 2);
+}
+
+ExpressionNode *flattenCommas( ExpressionNode *list ) {
+	if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
+		{
+			OperatorNode *op;
+			if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::Comma ) )
+				{
+					if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
+						composite->add_arg( next );
+					return flattenCommas( composite->get_args() );
+				}
+		}
+
+	if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
+		list->set_next( flattenCommas( next ) );
+
+	return list;
+}
+
+ExpressionNode *tupleContents( ExpressionNode *tuple ) {
+	if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
+		OperatorNode *op = 0;
+		if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::TupleC ) )
+			return composite->get_args();
+	}
+	return tuple;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/InitializerNode.cc
===================================================================
--- src/Parser/InitializerNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/InitializerNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,111 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// InitializerNode.cc -- 
+// 
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:20:24 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 13:21:40 2015
+// Update Count     : 2
+// 
+
+#include <cassert>
+#include <iostream>
+using namespace std;
+
+#include "ParseNode.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+
+InitializerNode::InitializerNode( ExpressionNode *_expr, bool aggrp, ExpressionNode *des )
+	: expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) {
+	if ( aggrp )
+		kids = dynamic_cast< InitializerNode *>( get_link() );
+
+	if ( kids != 0 )
+		set_link( 0 );
+}
+
+InitializerNode::InitializerNode( InitializerNode *init, bool aggrp, ExpressionNode *des )
+	: expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) {
+	if ( init != 0 )
+		set_link(init);
+
+	if ( aggrp )
+		kids = dynamic_cast< InitializerNode *>( get_link() );
+
+	if ( kids != 0 )
+		set_next( 0 );
+}
+
+InitializerNode::~InitializerNode() {
+	delete expr;
+}
+
+void InitializerNode::print( std::ostream &os, int indent ) const {
+	os << std::string(indent, ' ') << "Initializer expression" << std::endl;
+}
+
+void InitializerNode::printOneLine( std::ostream &os ) const {
+	if ( ! aggregate ) {
+		if ( designator != 0 ) {
+			os << "designated by: (";
+			ExpressionNode *curdes = designator;
+			while ( curdes != 0) {
+				curdes->printOneLine(os);
+				curdes = (ExpressionNode *)(curdes->get_link());
+				if ( curdes ) os << ", ";
+			} // while
+			os << ")";
+		} // if
+		if ( expr ) expr->printOneLine(os);
+	} else {  // It's an aggregate
+		os << "[--";
+		if ( next_init() != 0 )
+			next_init()->printOneLine(os);
+		if (aggregate) os << "--]";
+	} // if
+
+	InitializerNode *moreInit;
+	if  ( get_link() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_link() ) ) != 0) )
+		moreInit->printOneLine( os );
+}
+
+Initializer *InitializerNode::build() const {
+	// if ( get_expression() == 0 ) return 0;  // XXX (?)
+
+	if ( aggregate ) {
+		assert( next_init() != 0 );
+
+		std::list< Initializer *> initlist;
+		buildList<Initializer, InitializerNode>( next_init(), initlist );
+
+		std::list< Expression *> designlist;
+
+		if ( designator != 0 ) {
+			buildList<Expression, ExpressionNode>( designator, designlist );
+		} // if
+
+		return new ListInit( initlist, designlist );
+	} else {
+		std::list< Expression *> designators;
+
+		if ( designator != 0 )
+			buildList<Expression, ExpressionNode>( designator, designators );
+
+		if ( get_expression() != 0)
+			return new SingleInit( get_expression()->build(), designators );
+	} // if
+
+	return 0;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/LinkageSpec.cc
===================================================================
--- src/Parser/LinkageSpec.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/LinkageSpec.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,99 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LinkageSpec.cc -- 
+// 
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:22:09 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 13:23:21 2015
+// Update Count     : 2
+// 
+
+#include <string>
+#include <cassert>
+
+#include "LinkageSpec.h"
+#include "SemanticError.h"
+
+LinkageSpec::Type LinkageSpec::fromString( const std::string &stringSpec ) {
+	if ( stringSpec == "\"Cforall\"" ) {
+		return Cforall;
+	} else if ( stringSpec == "\"C\"" ) {
+		return C;
+	} else {
+		throw SemanticError( "Invalid linkage specifier " + stringSpec );
+	}
+}
+
+std::string LinkageSpec::toString( LinkageSpec::Type linkage ) {
+	switch ( linkage ) {
+	  case Intrinsic:
+		return "intrinsic";
+	  case Cforall:
+		return "Cforall";
+	  case C:
+		return "C";
+	  case AutoGen:
+		return "automatically generated";
+	  case Compiler:
+		return "compiler built-in";
+	}
+	assert( false );
+	return "";
+}
+
+bool LinkageSpec::isDecoratable( Type t ) {
+	switch ( t ) {
+	  case Intrinsic:
+	  case Cforall:
+	  case AutoGen:
+		return true;
+	  case C:
+	  case Compiler:
+		return false;
+	}
+	assert( false );
+	return false;
+}
+
+bool LinkageSpec::isGeneratable( Type t ) {
+	switch ( t ) {
+	  case Intrinsic:
+	  case Cforall:
+	  case AutoGen:
+	  case C:
+		return true;
+	  case Compiler:
+		return false;
+	}
+	assert( false );
+	return false;
+}
+
+bool LinkageSpec::isOverloadable( Type t ) {
+	return isDecoratable( t );
+}
+
+bool LinkageSpec::isBuiltin( Type t ) {
+	switch ( t ) {
+	  case Cforall:
+	  case AutoGen:
+	  case C:
+		return false;
+	  case Intrinsic:
+	  case Compiler:
+		return true;
+	}
+	assert( false );
+	return false;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/LinkageSpec.h
===================================================================
--- src/Parser/LinkageSpec.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/LinkageSpec.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,45 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LinkageSpec.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:24:28 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 13:26:14 2015
+// Update Count     : 3
+//
+
+#ifndef LINKAGESPEC_H
+#define LINKAGESPEC_H
+
+#include <string>
+
+struct LinkageSpec {
+	enum Type {
+		Intrinsic,										// C built-in defined in prelude
+		Cforall,										// ordinary
+		C,												// not overloadable, not mangled
+		AutoGen,										// built by translator (struct assignment)
+		Compiler										// gcc internal
+	};
+  
+	static Type fromString( const std::string & );
+	static std::string toString( Type );
+  
+	static bool isDecoratable( Type );
+	static bool isGeneratable( Type );
+	static bool isOverloadable( Type );
+	static bool isBuiltin( Type );
+};
+
+#endif // LINKAGESPEC_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/ParseNode.cc
===================================================================
--- src/Parser/ParseNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/ParseNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,101 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ParseNode.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:26:29 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:48:30 2015
+// Update Count     : 3
+// 
+
+#include "ParseNode.h"
+using namespace std;
+
+// Builder
+int ParseNode::indent_by = 4;
+
+ParseNode::ParseNode( void ) : next( 0 ) {};
+ParseNode::ParseNode( string _name ) : name( _name ), next( 0 ) {}
+
+ParseNode *ParseNode::set_name( string _name ) {
+	name = _name;
+	return this;
+}
+
+ParseNode *ParseNode::set_name( string *_name ) {
+	name = *_name; // deep copy
+	delete _name;
+
+	return this;
+}
+
+ParseNode::~ParseNode( void ) {
+	delete next;
+};
+
+string ParseNode::get_name( void ) {
+	return name;
+}
+
+ParseNode *ParseNode::get_link( void ) const {
+	return next;
+}
+
+ParseNode *ParseNode::get_last(void) {
+	ParseNode *current = this;
+
+	while ( current->get_link() != 0 )
+	current = current->get_link();
+
+	return current;
+}
+
+ParseNode *ParseNode::set_link(ParseNode *_next) {
+	ParseNode *follow;
+
+	if ( _next == 0 ) return this;
+
+	for ( follow = this; follow->next != 0; follow = follow->next );
+	follow->next = _next;
+
+	return this;
+}
+
+const string ParseNode::get_name(void) const {
+	return name;
+}
+
+void ParseNode::print(std::ostream &os, int indent) const {}
+
+
+void ParseNode::printList( std::ostream &os, int indent ) const {
+	print( os, indent );
+
+	if ( next ) {
+	next->printList( os, indent );
+	}
+}
+
+ParseNode &ParseNode::operator,( ParseNode &p ) {
+	set_link( &p );
+
+	return *this;
+}
+
+ParseNode *mkList( ParseNode &pn ) {
+	// it just relies on `operator,' to take care of the "arguments" and provides a nice interface to an awful-looking
+	// address-of, rendering, for example (StatementNode *)(&(*$5 + *$7)) into (StatementNode *)mkList(($5, $7))
+	// (although "nice" is probably not the word)
+	return &pn;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/ParseNode.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,515 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ParseNode.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 13:28:16 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 13:30:24 2015
+// Update Count     : 3
+//
+
+#ifndef PARSENODE_H
+#define PARSENODE_H
+
+#include <string>
+#include <list>
+#include <iterator>
+
+#include "utility.h"
+#include "SynTree/Declaration.h"
+#include "UniqueName.h"
+
+class ExpressionNode;
+class CompositeExprNode;
+class CommaExprNode;
+class StatementNode;
+class CompoundStmtNode;
+class DeclarationNode;
+class InitializerNode;
+
+// Builder
+class ParseNode {
+  public:
+	ParseNode( void );
+	ParseNode ( std::string );
+	virtual ~ParseNode( void );
+
+	ParseNode *set_name ( std::string ) ;
+	ParseNode *set_name ( std::string * ) ;
+
+	std::string get_name( void );
+
+	ParseNode *get_link( void ) const;
+	ParseNode *get_last( void );
+	ParseNode *set_link( ParseNode * );
+	void set_next( ParseNode *newlink ) { next = newlink; }
+
+	virtual ParseNode *clone() const { return 0; };
+
+	const std::string get_name( void ) const;
+	virtual void print( std::ostream &, int indent = 0 ) const;
+	virtual void printList( std::ostream &, int indent = 0 ) const;
+
+	ParseNode &operator,( ParseNode &);
+  protected:
+	std::string name;
+	ParseNode *next;
+	static int indent_by;
+};
+
+ParseNode *mkList( ParseNode & );
+
+class ExpressionNode : public ParseNode {
+  public:
+	ExpressionNode();
+	ExpressionNode( std::string * );
+	ExpressionNode( const ExpressionNode &other );
+	virtual ~ExpressionNode() {} // cannot delete asArgName because it might be referenced elsewhere
+
+	virtual ExpressionNode *clone() const = 0;
+
+	virtual CommaExprNode *add_to_list( ExpressionNode * );
+
+	ExpressionNode *get_argName() const { return argName; }
+	ExpressionNode *set_asArgName( std::string *aName );
+	ExpressionNode *set_asArgName( ExpressionNode *aDesignator );
+
+	virtual void print( std::ostream &, int indent = 0) const = 0;
+	virtual void printOneLine( std::ostream &, int indent = 0) const = 0;
+
+	virtual Expression *build() const = 0;
+  protected:
+	void printDesignation ( std::ostream &, int indent = 0) const;
+  private:
+	ExpressionNode *argName;
+};
+
+// NullExprNode is used in tuples as a place-holder where a tuple component is omitted e.g., [ 2, , 3 ]
+class NullExprNode : public ExpressionNode {
+  public:
+	NullExprNode();
+
+	virtual NullExprNode *clone() const;
+
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+
+	virtual Expression *build() const;
+};
+
+class ConstantNode : public ExpressionNode {
+  public:
+	enum Type {
+		Integer, Float, Character, String /* , Range, EnumConstant  */
+	};
+
+	ConstantNode( void );
+	ConstantNode( std::string * );
+	ConstantNode( Type, std::string * );
+	ConstantNode( const ConstantNode &other );
+
+	virtual ConstantNode *clone() const { return new ConstantNode( *this ); }
+
+	Type get_type( void ) const ;
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+
+	std::string get_value() const { return value; }
+	ConstantNode *append( std::string *newValue );
+
+	Expression *build() const;
+  private:
+	void classify( std::string &);
+	Type type;
+	std::string value;
+	bool sign;
+	short base;
+	int longs, size;
+};
+
+class VarRefNode : public ExpressionNode {
+  public:
+	VarRefNode();
+	VarRefNode( std::string *, bool isLabel = false );
+	VarRefNode( const VarRefNode &other );
+
+	virtual Expression *build() const ;
+
+	virtual VarRefNode *clone() const { return new VarRefNode( *this ); }
+
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+  private:
+	bool isLabel;
+};
+
+class TypeValueNode : public ExpressionNode {
+  public:
+	TypeValueNode( DeclarationNode * );
+	TypeValueNode( const TypeValueNode &other );
+
+	DeclarationNode *get_decl() const { return decl; }
+
+	virtual Expression *build() const ;
+
+	virtual TypeValueNode *clone() const { return new TypeValueNode( *this ); }
+
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+  private:
+	DeclarationNode *decl;
+};
+
+class OperatorNode : public ExpressionNode {
+  public:
+	enum Type { TupleC, Comma, TupleFieldSel,
+				Cond, NCond, 
+				SizeOf, AlignOf, Attr, CompLit, Plus, Minus, Mul, Div, Mod, Or, And, 
+				BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq, 
+				Assign, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn, 
+				ERAssn, OrAssn, Index, FieldSel, PFieldSel, Range,
+				UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress
+	};
+
+	OperatorNode( Type t );
+	OperatorNode( const OperatorNode &other );
+	virtual ~OperatorNode();
+
+	virtual OperatorNode *clone() const { return new OperatorNode( *this ); }
+
+	Type get_type( void ) const;
+	std::string get_typename( void ) const;
+
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+
+	virtual Expression *build() const { return 0; }
+  private:
+	Type type;
+	static const char *OpName[];
+};
+
+
+class CompositeExprNode : public ExpressionNode {
+  public:
+	CompositeExprNode( void );
+	CompositeExprNode( std::string * );
+	CompositeExprNode( ExpressionNode *f, ExpressionNode *args = 0 );
+	CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2 );
+	CompositeExprNode( const CompositeExprNode &other );
+	virtual ~CompositeExprNode();
+
+	virtual CompositeExprNode *clone() const { return new CompositeExprNode( *this ); }
+	virtual Expression *build() const;
+
+	virtual void print( std::ostream &, int indent = 0) const;
+	virtual void printOneLine( std::ostream &, int indent = 0) const;
+
+	void set_function( ExpressionNode * );
+	void set_args( ExpressionNode * );
+
+	void add_arg( ExpressionNode * );
+
+	ExpressionNode *get_function() const;
+	ExpressionNode *get_args() const;
+  private:
+	ExpressionNode *function;
+	ExpressionNode *arguments;
+};
+
+class CommaExprNode : public CompositeExprNode {
+  public:
+	CommaExprNode();
+	CommaExprNode( ExpressionNode * );
+	CommaExprNode( ExpressionNode *, ExpressionNode * );
+	CommaExprNode( const CommaExprNode &other );
+
+	virtual CommaExprNode *add_to_list( ExpressionNode * );
+	virtual CommaExprNode *clone() const { return new CommaExprNode( *this ); }
+};
+
+class ForCtlExprNode : public ExpressionNode {
+  public:
+	ForCtlExprNode( ParseNode *, ExpressionNode *, ExpressionNode * ) throw ( SemanticError );
+	ForCtlExprNode( const ForCtlExprNode &other );
+	~ForCtlExprNode();
+
+	StatementNode *get_init() const { return init; }
+	ExpressionNode *get_condition() const { return condition; }
+	ExpressionNode *get_change() const { return change; }
+
+	virtual ForCtlExprNode *clone() const { return new ForCtlExprNode( *this ); }
+	virtual Expression *build() const;
+
+	virtual void print( std::ostream &, int indent = 0 ) const;
+	virtual void printOneLine( std::ostream &, int indent = 0 ) const;
+  private:
+	StatementNode *init;
+	ExpressionNode *condition;
+	ExpressionNode *change;
+};
+
+class ValofExprNode : public ExpressionNode {
+  public:
+	ValofExprNode();
+	ValofExprNode( StatementNode *s = 0 );
+	ValofExprNode( const ValofExprNode &other );
+	~ValofExprNode();
+  
+	virtual ValofExprNode *clone() const { return new ValofExprNode( *this ); }
+
+	StatementNode *get_body() const { return body; }
+	void print( std::ostream &, int indent = 0 ) const;
+	void printOneLine( std::ostream &, int indent = 0 ) const;
+	Expression *build() const;
+
+  private:
+	StatementNode *body;
+};
+
+class TypeData;
+
+class DeclarationNode : public ParseNode {
+  public:
+	enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, Attribute };
+	enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran };
+	enum BasicType { Char, Int, Float, Double, Void, Bool, Complex, Imaginary };
+	enum Modifier { Signed, Unsigned, Short, Long };
+	enum TyCon { Struct, Union, Context };
+	enum TypeClass { Type, Dtype, Ftype };
+
+	static const char *qualifierName[];
+	static const char *basicTypeName[];
+	static const char *modifierName[];
+	static const char *tyConName[];
+	static const char *typeClassName[];
+
+	static DeclarationNode *newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param,
+										 StatementNode *body, bool newStyle = false );
+	static DeclarationNode *newQualifier( Qualifier );
+	static DeclarationNode *newStorageClass( StorageClass );
+	static DeclarationNode *newBasicType( BasicType );
+	static DeclarationNode *newModifier( Modifier );
+	static DeclarationNode *newForall( DeclarationNode *);
+	static DeclarationNode *newFromTypedef( std::string *);
+	static DeclarationNode *newAggregate( TyCon kind, std::string *name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields );
+	static DeclarationNode *newEnum( std::string *name, DeclarationNode *constants );
+	static DeclarationNode *newEnumConstant( std::string *name, ExpressionNode *constant );
+	static DeclarationNode *newName( std::string *);
+	static DeclarationNode *newFromTypeGen( std::string*, ExpressionNode *params );
+	static DeclarationNode *newTypeParam( TypeClass, std::string *);
+	static DeclarationNode *newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts );
+	static DeclarationNode *newContextUse( std::string *name, ExpressionNode *params );
+	static DeclarationNode *newTypeDecl( std::string *name, DeclarationNode *typeParams );
+	static DeclarationNode *newPointer( DeclarationNode *qualifiers );
+	static DeclarationNode *newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic );
+	static DeclarationNode *newVarArray( DeclarationNode *qualifiers );
+	static DeclarationNode *newBitfield( ExpressionNode *size );
+	static DeclarationNode *newTuple( DeclarationNode *members );
+	static DeclarationNode *newTypeof( ExpressionNode *expr );
+	static DeclarationNode *newAttr( std::string*, ExpressionNode *expr );
+	static DeclarationNode *newAttr( std::string*, DeclarationNode *type );
+
+	DeclarationNode *addQualifiers( DeclarationNode *);
+	DeclarationNode *copyStorageClasses( DeclarationNode *);
+	DeclarationNode *addType( DeclarationNode *);
+	DeclarationNode *addTypedef();
+	DeclarationNode *addAssertions( DeclarationNode *);
+	DeclarationNode *addName( std::string *);
+	DeclarationNode *addBitfield( ExpressionNode *size );
+	DeclarationNode *addVarArgs();
+	DeclarationNode *addFunctionBody( StatementNode *body );
+	DeclarationNode *addOldDeclList( DeclarationNode *list );
+	DeclarationNode *addPointer( DeclarationNode *qualifiers );
+	DeclarationNode *addArray( DeclarationNode *array );
+	DeclarationNode *addNewPointer( DeclarationNode *pointer );
+	DeclarationNode *addNewArray( DeclarationNode *array );
+	DeclarationNode *addParamList( DeclarationNode *list );
+	DeclarationNode *addIdList( DeclarationNode *list );       // old-style functions
+	DeclarationNode *addInitializer( InitializerNode *init );
+
+	DeclarationNode *cloneType( std::string *newName );
+	DeclarationNode *cloneType( DeclarationNode *existing );
+	DeclarationNode *cloneType( int ) { return cloneType( ( std::string *)0 ); }
+	DeclarationNode *cloneBaseType( std::string *newName );
+	DeclarationNode *cloneBaseType( DeclarationNode *newdecl );
+
+	DeclarationNode *appendList( DeclarationNode  *);
+
+	DeclarationNode *clone() const;
+	void print( std::ostream &, int indent = 0 ) const;
+	void printList( std::ostream &, int indent = 0 ) const;
+
+	Declaration *build() const;
+	::Type *buildType() const;
+
+	bool get_hasEllipsis() const;
+	std::string get_name() const { return name; }
+	LinkageSpec::Type get_linkage() const { return linkage; }
+	DeclarationNode *extractAggregate() const;
+
+	DeclarationNode();
+	~DeclarationNode();
+  private:
+	Declaration::StorageClass buildStorageClass() const;
+	bool buildInline() const;
+
+	TypeData *type;
+	std::string name;
+	std::list< StorageClass > storageClasses;
+	ExpressionNode *bitfieldWidth;
+	InitializerNode *initializer;
+	bool hasEllipsis;
+	LinkageSpec::Type linkage;
+
+	static UniqueName anonymous;
+};
+
+class StatementNode : public ParseNode {
+  public:
+	enum Type { Exp,   If,        Switch,  Case,    Default,  Choose,   Fallthru, 
+				While, Do,        For,
+				Goto,  Continue,  Break,   Return,  Throw,
+				Try,   Catch,     Finally, Asm,
+				Decl
+	};
+
+	StatementNode( void );
+	StatementNode( std::string );
+	StatementNode( Type, ExpressionNode *e = 0, StatementNode *s = 0 );
+	StatementNode( Type, std::string *target );
+	StatementNode( DeclarationNode *decl );
+
+
+	~StatementNode( void );
+
+	static StatementNode  *newCatchStmt( DeclarationNode *d = 0, StatementNode *s = 0, bool catchRestP = false );
+
+	void set_control( ExpressionNode * );
+	StatementNode * set_block( StatementNode * );
+
+	ExpressionNode *get_control() const ;
+	StatementNode *get_block() const;
+	StatementNode::Type get_type( void ) const;
+
+	StatementNode *add_label( std::string * );
+	std::list<std::string> *get_labels() const;
+
+	void addDeclaration( DeclarationNode *newDecl ) { decl = newDecl; }
+	void setCatchRest( bool newVal ) { isCatchRest = newVal; }
+
+	std::string get_target() const;
+
+	StatementNode *add_controlexp( ExpressionNode * );
+	StatementNode *append_block( StatementNode * );
+	StatementNode *append_last_case( StatementNode * );
+
+	void print( std::ostream &, int indent = 0) const;
+
+	virtual StatementNode *clone() const;
+
+	virtual Statement *build() const;
+  private:
+	static const char *StType[];
+	Type type;
+	ExpressionNode *control;
+	StatementNode *block;
+	std::list<std::string> *labels;
+	std::string *target;				// target label for jump statements
+	DeclarationNode *decl;
+
+	bool isCatchRest;
+};
+
+class CompoundStmtNode : public StatementNode {
+  public:
+	CompoundStmtNode( void );
+	CompoundStmtNode( std::string * );
+	CompoundStmtNode( StatementNode * );
+	~CompoundStmtNode();
+
+	void add_statement( StatementNode * );
+
+	void print( std::ostream &, int indent = 0 ) const;
+
+	virtual Statement *build() const;
+  private:
+	StatementNode *first, *last;
+};
+
+class NullStmtNode : public CompoundStmtNode {
+  public:
+	Statement *build() const;
+	void print( std::ostream &, int indent = 0) const;
+};
+
+class InitializerNode : public ParseNode {
+  public:
+	InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode *des = 0 );
+	InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode *des = 0 );
+	~InitializerNode();
+
+	ExpressionNode *get_expression() const { return expr; }
+
+	InitializerNode *set_designators( ExpressionNode *des ) { designator = des; return this; }
+	ExpressionNode *get_designators() const { return designator; }
+
+	InitializerNode *next_init() const { return kids; }
+
+	void print( std::ostream &, int indent = 0 ) const;
+	void printOneLine( std::ostream & ) const;
+
+	virtual Initializer *build() const;
+  private:
+	ExpressionNode *expr;
+	bool aggregate;
+	ExpressionNode *designator; // may be list
+	InitializerNode *kids;
+};
+
+
+
+template< typename SynTreeType, typename NodeType >
+void buildList( const NodeType *firstNode, std::list< SynTreeType *> &outputList ) {
+	SemanticError errors;
+	std::back_insert_iterator< std::list< SynTreeType *> > out( outputList );
+	const NodeType *cur = firstNode;
+
+	while ( cur ) {
+		try {
+			SynTreeType *result = dynamic_cast< SynTreeType *>( cur->build() );
+			if ( result ) {
+				*out++ = result;
+			} else {
+			} // if
+		} catch( SemanticError &e ) {
+			errors.append( e );
+		} // try
+		cur = dynamic_cast< NodeType *>( cur->get_link() );
+	} // while
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+}
+
+// in DeclarationNode.cc
+void buildList( const DeclarationNode *firstNode, std::list< Declaration *> &outputList );
+void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType *> &outputList );
+void buildTypeList( const DeclarationNode *firstNode, std::list< Type *> &outputList );
+
+// in ExpressionNode.cc
+ExpressionNode *flattenCommas( ExpressionNode *list );
+ExpressionNode *tupleContents( ExpressionNode *tuple );
+
+#endif // PARSENODE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/Parser.cc
===================================================================
--- src/Parser/Parser.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/Parser.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,70 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Parser.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 14:54:28 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 14:55:59 2015
+// Update Count     : 2
+// 
+
+#include "Parser.h"
+#include "TypedefTable.h"
+#include "lex.h"
+#include "cfa.tab.h"
+
+// global variables in cfa.y
+extern int yyparse(void);
+extern int yydebug;
+extern LinkageSpec::Type linkage;
+extern TypedefTable typedefTable;
+extern DeclarationNode *theTree;
+
+Parser *Parser::theParser = 0;
+
+Parser::Parser(): parseTree( 0 ), parseStatus( 1 ) {}
+
+Parser::~Parser() {
+	delete parseTree;
+}
+
+Parser &Parser::get_parser() {
+	if ( theParser == 0 ) {
+		theParser = new Parser;
+	} // if
+	return *theParser;
+}
+
+void Parser::parse( FILE *input ) {
+	extern FILE *yyin;
+	yyin = input;
+	extern int yylineno;
+	yylineno = 1;
+	typedefTable.enterScope();
+	parseStatus = yyparse();
+	parseTree = theTree;
+}
+
+void Parser::set_debug( bool debug ) {
+	yydebug = debug;
+}
+
+void Parser::set_linkage( LinkageSpec::Type linkage ) {
+	::linkage = linkage;
+}
+
+void Parser::freeTree() {
+	delete parseTree;
+	parseTree = 0;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/Parser.h
===================================================================
--- src/Parser/Parser.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/Parser.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,56 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Parser.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 14:56:50 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 14:58:56 2015
+// Update Count     : 2
+//
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <cstdio>
+
+#include "Parser/ParseNode.h"
+#include "LinkageSpec.h"
+
+class Parser {
+  public:
+	static Parser &get_parser();
+
+	// do the actual parse
+	void parse( FILE *input );
+
+	// accessors to return the result of the parse
+	DeclarationNode *get_parseTree() const { return parseTree; }
+	int get_parseStatus() const { return parseStatus; }
+
+	// mutators to control parse options
+	void set_debug( bool debug );
+	void set_linkage( LinkageSpec::Type linkage );
+
+	// free the parse tree without actually destroying the parser
+	void freeTree();
+
+	~Parser();
+  private:
+	Parser();
+	static Parser *theParser;
+	DeclarationNode *parseTree;
+	int parseStatus;
+};
+
+#endif // PARSER_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/StatementNode.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,404 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// StatementNode.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 14:59:41 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:10:45 2015
+// Update Count     : 7
+//
+
+#include <list>
+#include <algorithm>
+#include <cassert>
+
+#include "ParseNode.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Expression.h"
+#include "parseutility.h"
+#include "utility.h"
+
+using namespace std;
+
+const char *StatementNode::StType[] = {
+	"Exp",   "If",       "Switch", "Case",    "Default",  "Choose",   "Fallthru", 
+	"While", "Do",       "For", 
+	"Goto",  "Continue", "Break",  "Return",  "Throw",
+	"Try",   "Catch",    "Finally", "Asm",
+	"Decl"
+};
+
+StatementNode::StatementNode() : ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
+
+StatementNode::StatementNode( string name_) : ParseNode( name_), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
+
+StatementNode::StatementNode( DeclarationNode *decl ) : type( Decl ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), isCatchRest ( false ) {
+	if ( decl ) {
+		if ( DeclarationNode *agg = decl->extractAggregate() ) {
+			this->decl = agg;
+			StatementNode *nextStmt = new StatementNode;
+			nextStmt->type = Decl;
+			nextStmt->decl = decl;
+			next = nextStmt;
+			if ( decl->get_link() ) {
+				next->set_next( new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) ) );
+				decl->set_next( 0 );
+			}
+		} else {
+			if ( decl->get_link() ) {
+				next = new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) );
+				decl->set_next( 0 );
+			}
+			this->decl = decl;
+		}
+	}
+}
+
+StatementNode::StatementNode( Type t, ExpressionNode *ctrl_label, StatementNode *block_ ) :
+		type( t ), control( ctrl_label ), block( block_), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {
+	if ( t == Default )
+		control = 0;
+} 
+
+StatementNode::StatementNode( Type t, string *_target ) :
+		type( t ), control( 0 ), block( 0 ),   labels( 0 ), target(_target ), decl( 0 ), isCatchRest ( false ) {}
+
+StatementNode::~StatementNode() {
+	delete control;
+	delete block;
+	delete labels;
+	delete target;
+	delete decl;
+}
+
+StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) {
+	StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s ); 
+	ret->addDeclaration( d );
+	ret->setCatchRest( catchRestP );
+
+	return ret;
+}
+
+std::string StatementNode::get_target() const{
+	if ( target )
+		return *target;
+
+	return string("");
+}
+
+StatementNode * StatementNode::clone() const {
+	StatementNode *newnode = new StatementNode( type, maybeClone( control ), maybeClone( block ) );
+	if ( target ) {
+		newnode->target = new string( *target );
+	} else {
+		newnode->target = 0;
+	}
+	newnode->decl = maybeClone( decl );
+	return newnode;
+}
+
+void StatementNode::set_control( ExpressionNode *c ) {
+	control = c;
+}
+
+StatementNode * StatementNode::set_block( StatementNode *b ) {
+	block = b;
+
+	return this;
+}
+
+ExpressionNode *StatementNode::get_control() const {
+	return control;
+}
+
+StatementNode *StatementNode::get_block() const {
+	return block;
+}
+
+StatementNode::Type StatementNode::get_type() const {
+	return type;
+}
+
+StatementNode *StatementNode::add_label( std::string *l ) {
+	if ( l != 0 ) {
+		if ( labels == 0 )
+			labels = new std::list<std::string>();
+
+		labels->push_front(*l ); 
+		delete l;
+	}
+	return this;
+}
+
+std::list<std::string> *StatementNode::get_labels() const { return labels; }
+
+StatementNode *StatementNode::add_controlexp( ExpressionNode *e ) {
+	if ( control && e )
+		control->add_to_list( e ); // xxx - check this
+
+	return this;
+}
+
+StatementNode *StatementNode::append_block( StatementNode *stmt ) {
+	if ( stmt != 0 ) {
+		if ( block == 0 )
+			block = stmt;
+		else
+			block->set_link( stmt );
+	}
+	return this;
+}
+
+StatementNode *StatementNode::append_last_case( StatementNode *stmt ) {
+	if ( stmt != 0 ) {
+		StatementNode *next = ( StatementNode *)get_link();
+		if ( next && ( next->get_type() == StatementNode::Case || next->get_type() == StatementNode::Default ) )
+			next->append_last_case ( stmt );
+		else
+			if ( block == 0 )
+				block = stmt;
+			else
+				block->set_link( stmt );
+	}
+	return this;
+}
+
+void StatementNode::print( std::ostream &os, int indent ) const {
+	if ( labels != 0 )
+		if ( ! labels->empty()) {
+			std::list<std::string>::const_iterator i;
+
+			os << '\r' << string( indent, ' ');
+			for ( i = labels->begin(); i != labels->end(); i++ )
+				os << *i << ":";
+			os << endl;
+		}
+
+	switch ( type ) {
+	  case Decl:
+		decl->print( os, indent );
+		break;
+	  case Exp:
+		if ( control ) {
+			os << string( indent, ' ' );
+			control->print( os, indent );
+			os << endl;
+		} else 
+			os << string( indent, ' ' ) << "Null Statement" << endl;
+		break;
+	  default:
+		os << '\r' << string( indent, ' ') << StatementNode::StType[type] << endl;
+		if ( type == Catch ) {
+			if ( decl ) {
+				os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Declaration: " << endl;
+				decl->print( os, indent + 2*ParseNode::indent_by );
+			} else if ( isCatchRest ) {
+				os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Catches the rest " << endl;
+			} else {
+				; // should never reach here
+			}
+		}
+		if ( control ) {
+			os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Expression: " << endl;
+			control->printList( os, indent + 2*ParseNode::indent_by );
+		}
+		if ( block ) {
+			os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Branches of execution: " << endl;
+			block->printList( os, indent + 2*ParseNode::indent_by );  
+		}
+		if ( target ) {
+			os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Target: " << get_target() << endl;
+		}
+		break;
+	}
+}
+
+Statement *StatementNode::build() const {
+	std::list<Statement *> branches;
+	std::list<Expression *> exps;
+	std::list<Label> labs;
+
+	if ( labels != 0 ) {
+		std::back_insert_iterator< std::list<Label> > lab_it( labs );
+		copy( labels->begin(), labels->end(), lab_it );
+	}
+
+	// try {
+	buildList<Statement, StatementNode>( get_block(), branches );
+
+	switch ( type ) {
+	  case Decl:
+		return new DeclStmt( labs, maybeBuild< Declaration >( decl ) );
+	  case Exp:
+		{
+			Expression *e = maybeBuild< Expression >( get_control() );
+
+			if ( e )
+				return new ExprStmt( labs, e );
+			else
+				return new NullStmt( labs );
+		}
+	  case If:
+		{
+			Statement *thenb = 0, *elseb = 0;
+			assert( branches.size() >= 1 );
+
+			thenb = branches.front();
+			branches.pop_front();
+			if ( ! branches.empty() ) {
+				elseb = branches.front();
+				branches.pop_front();
+			}
+			return new IfStmt( labs, notZeroExpr( get_control()->build() ), thenb, elseb );
+		}
+	  case While:
+		assert( branches.size() == 1 );
+		return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front() );
+	  case Do:
+		assert( branches.size() == 1 );
+		return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front(), true );
+	  case For:
+		{
+			assert( branches.size() == 1 );
+
+			ForCtlExprNode *ctl = dynamic_cast<ForCtlExprNode *>( get_control() );
+			assert( ctl != 0 );
+
+			Statement *stmt = 0;
+			if ( ctl->get_init() != 0 )
+				stmt = ctl->get_init()->build();
+
+			Expression *cond = 0;
+			if ( ctl->get_condition() != 0 )
+				cond = notZeroExpr( ctl->get_condition()->build() );
+
+			Expression *incr = 0;
+			if ( ctl->get_change() != 0 )
+				incr = ctl->get_change()->build();
+
+			return new ForStmt( labs, stmt, cond, incr, branches.front() );
+		}
+	  case Switch:
+		return new SwitchStmt( labs, get_control()->build(), branches );
+	  case Choose:
+		return new ChooseStmt( labs, get_control()->build(), branches );
+	  case Fallthru:
+		return new FallthruStmt( labs );
+	  case Case: 
+		return new CaseStmt( labs, get_control()->build(), branches );
+	  case Default:
+		return new CaseStmt( labs, 0, branches, true );
+	  case Goto:
+		{
+			if ( get_target() == "" ) {					// computed goto
+				assert( get_control() != 0 );
+				return new BranchStmt( labs, get_control()->build(), BranchStmt::Goto );
+			}
+
+			return new BranchStmt( labs, get_target(), BranchStmt::Goto );
+		}
+	  case Break:
+		return new BranchStmt( labs, get_target(), BranchStmt::Break );
+	  case Continue:
+		return new BranchStmt( labs, get_target(), BranchStmt::Continue );
+	  case Return:
+	  case Throw :
+		buildList( get_control(), exps );
+		if ( exps.size() ==0 )
+			return new ReturnStmt( labs, 0, type == Throw );
+		if ( exps.size() > 0 )
+			return new ReturnStmt( labs, exps.back(), type == Throw );
+	  case Try:
+		{
+			assert( branches.size() >= 0 );
+			CompoundStmt *tryBlock = dynamic_cast<CompoundStmt *>( branches.front());
+			branches.pop_front();
+			FinallyStmt *finallyBlock = 0;
+			if ( ( finallyBlock = dynamic_cast<FinallyStmt *>( branches.back())) ) {
+				branches.pop_back();
+			}
+			return new TryStmt( labs, tryBlock, branches, finallyBlock );
+		}
+	  case Catch:
+		{
+			assert( branches.size() == 1 );
+
+			return new CatchStmt( labs, maybeBuild< Declaration >( decl ), branches.front(), isCatchRest );
+		}
+	  case Finally:
+		{
+			assert( branches.size() == 1 );
+			CompoundStmt *block = dynamic_cast<CompoundStmt *>( branches.front() );
+			assert( block != 0 );
+
+			return new FinallyStmt( labs, block );
+		}
+	  default:
+		// shouldn't be here
+		return 0;
+	}
+}
+
+CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) {
+}
+
+CompoundStmtNode::CompoundStmtNode( string *name_) : StatementNode(*name_), first( 0 ), last( 0 ) {
+}
+
+CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ): first( stmt ) {
+	if ( first ) {
+		last = ( StatementNode *)( stmt->get_last());
+	} else {
+		last = 0;
+	}
+}
+
+CompoundStmtNode::~CompoundStmtNode() {
+	delete first;
+}
+
+void CompoundStmtNode::add_statement( StatementNode *stmt ) {
+	if ( stmt != 0 ) {
+		last->set_link( stmt );
+		last = ( StatementNode *)( stmt->get_link());
+	}
+}
+
+void CompoundStmtNode::print( ostream &os, int indent ) const {
+	if ( first ) {
+		first->printList( os, indent+2 );
+	}
+}
+
+Statement *CompoundStmtNode::build() const {
+	std::list<Label> labs;
+	std::list<std::string> *labels = get_labels();
+
+	if ( labels != 0 ) {
+		std::back_insert_iterator< std::list<Label> > lab_it( labs );
+		copy( labels->begin(), labels->end(), lab_it );
+	}
+
+	CompoundStmt *cs = new CompoundStmt( labs );
+	buildList( first, cs->get_kids() );
+	return cs;
+}
+
+void NullStmtNode::print( ostream &os, int indent ) const {
+	os << "\r" << string( indent, ' ') << "Null Statement:" << endl;
+}
+
+Statement *NullStmtNode::build() const { 
+	return new NullStmt;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/TypeData.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,942 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypeData.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:12:51 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:17:56 2015
+// Update Count     : 4
+//
+
+#include <cassert>
+#include <algorithm>
+#include <iterator>
+#include "utility.h"
+#include "TypeData.h"
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+
+TypeData::TypeData( Kind k ) : kind( k ), base( 0 ), forall( 0 ) {
+	switch ( kind ) {
+	  case Unknown:
+	  case Pointer:
+	  case EnumConstant:
+		// nothing else to initialize
+		break;
+	  case Basic:
+		basic = new Basic_t;
+		break;
+	  case Array:
+		array = new Array_t;
+		array->dimension = 0;
+		array->isVarLen = false;
+		array->isStatic = false;
+		break;
+	  case Function:
+		function = new Function_t;
+		function->params = 0;
+		function->idList = 0;
+		function->oldDeclList = 0;
+		function->body = 0;
+		function->hasBody = false;
+		function->newStyle = false;
+		break;
+	  case Aggregate:
+		aggregate = new Aggregate_t;
+		aggregate->params = 0;
+		aggregate->actuals = 0;
+		aggregate->members = 0;
+		break;
+	  case AggregateInst:
+		aggInst = new AggInst_t;
+		aggInst->aggregate = 0;
+		aggInst->params = 0;
+		break;
+	  case Enum:
+		enumeration = new Enumeration_t;
+		enumeration->constants = 0;
+		break;
+	  case Symbolic:
+	  case SymbolicInst:
+		symbolic = new Symbolic_t;
+		symbolic->params = 0;
+		symbolic->actuals = 0;
+		symbolic->assertions = 0;
+		break;
+	  case Variable:
+		variable = new Variable_t;
+		variable->tyClass = DeclarationNode::Type;
+		variable->assertions = 0;
+		break;
+	  case Tuple:
+		tuple = new Tuple_t;
+		tuple->members = 0;
+		break;
+	  case Typeof:
+		typeexpr = new Typeof_t;
+		typeexpr->expr = 0;
+		break;
+	  case Attr:
+		attr = new Attr_t;
+		attr->expr = 0;
+		attr->type = 0;
+		break;
+	}
+}
+
+TypeData::~TypeData() {
+	delete base;
+	delete forall;
+
+	switch ( kind ) {
+	  case Unknown:
+	  case Pointer:
+	  case EnumConstant:
+		// nothing to destroy
+		break;
+	  case Basic:
+		delete basic;
+		break;
+	  case Array:
+		delete array->dimension;
+		delete array;
+		break;
+	  case Function:
+		delete function->params;
+		delete function->idList;
+		delete function->oldDeclList;
+		delete function->body;
+		delete function;
+		break;
+	  case Aggregate:
+		delete aggregate->params;
+		delete aggregate->actuals;
+		delete aggregate->members;
+		delete aggregate;
+		break;
+	  case AggregateInst:
+		delete aggInst->aggregate;
+		delete aggInst->params;
+		delete aggInst;
+		break;
+	  case Enum:
+		delete enumeration->constants;
+		delete enumeration;
+		break;
+	  case Symbolic:
+	  case SymbolicInst:
+		delete symbolic->params;
+		delete symbolic->actuals;
+		delete symbolic->assertions;
+		delete symbolic;
+		break;
+	  case Variable:
+		delete variable->assertions;
+		delete variable;
+		break;
+	  case Tuple:
+		delete tuple->members;
+		delete tuple;
+		break;
+	  case Typeof:
+		delete typeexpr->expr;
+		delete typeexpr;
+		break;
+	  case Attr:
+		delete attr->expr;
+		delete attr->type;
+		delete attr;
+		break;
+	}
+}
+
+TypeData *TypeData::clone() const {
+	TypeData *newtype = new TypeData( kind );
+	newtype->qualifiers = qualifiers;
+	newtype->base = maybeClone( base );
+	newtype->forall = maybeClone( forall );
+
+	switch ( kind ) {
+	  case Unknown:
+	  case EnumConstant:
+	  case Pointer:
+		// nothing else to copy
+		break;
+	  case Basic:
+		newtype->basic->typeSpec = basic->typeSpec;
+		newtype->basic->modifiers = basic->modifiers;
+		break;
+	  case Array:
+		newtype->array->dimension = maybeClone( array->dimension );
+		newtype->array->isVarLen = array->isVarLen;
+		newtype->array->isStatic = array->isStatic;
+		break;
+	  case Function:
+		newtype->function->params = maybeClone( function->params );
+		newtype->function->idList = maybeClone( function->idList );
+		newtype->function->oldDeclList = maybeClone( function->oldDeclList );
+		newtype->function->body = maybeClone( function->body );
+		newtype->function->hasBody = function->hasBody;
+		newtype->function->newStyle = function->newStyle;
+		break;
+	  case Aggregate:
+		newtype->aggregate->params = maybeClone( aggregate->params );
+		newtype->aggregate->actuals = maybeClone( aggregate->actuals );
+		newtype->aggregate->members = maybeClone( aggregate->members );
+		newtype->aggregate->name = aggregate->name;
+		newtype->aggregate->kind = aggregate->kind;
+		break;
+	  case AggregateInst:
+		newtype->aggInst->aggregate = maybeClone( aggInst->aggregate );
+		newtype->aggInst->params = maybeClone( aggInst->params );
+		break;
+	  case Enum:
+		newtype->enumeration->name = enumeration->name;
+		newtype->enumeration->constants = maybeClone( enumeration->constants );
+		break;
+	  case Symbolic:
+	  case SymbolicInst:
+		newtype->symbolic->params = maybeClone( symbolic->params );
+		newtype->symbolic->actuals = maybeClone( symbolic->actuals );
+		newtype->symbolic->assertions = maybeClone( symbolic->assertions );
+		newtype->symbolic->isTypedef = symbolic->isTypedef;
+		newtype->symbolic->name = symbolic->name;
+		break;
+	  case Variable:
+		newtype->variable->assertions = maybeClone( variable->assertions );
+		newtype->variable->name = variable->name;
+		newtype->variable->tyClass = variable->tyClass;
+		break;
+	  case Tuple:
+		newtype->tuple->members = maybeClone( tuple->members );
+		break;
+	  case Typeof:
+		newtype->typeexpr->expr = maybeClone( typeexpr->expr );
+		break;
+	  case Attr:
+		newtype->attr->expr = maybeClone( attr->expr );
+		newtype->attr->type = maybeClone( attr->type );
+		break;
+	}
+	return newtype;
+}
+
+void TypeData::print( std::ostream &os, int indent ) const {
+	using std::endl;
+	using std::string;
+
+	printEnums( qualifiers.begin(), qualifiers.end(), DeclarationNode::qualifierName, os );
+
+	if ( forall ) {
+		os << "forall " << endl;
+		forall->printList( os, indent+4 );
+	}
+
+	switch ( kind ) {
+	  case Unknown:
+		os << "entity of unknown type ";
+		break;
+	  case Pointer:
+		os << "pointer ";
+		if ( base ) {
+			os << "to ";
+			base->print( os, indent );
+		}
+		break;
+	  case EnumConstant:
+		os << "enumeration constant ";
+		break;
+	  case Basic:
+		printEnums( basic->modifiers.begin(), basic->modifiers.end(), DeclarationNode::modifierName, os );
+		printEnums( basic->typeSpec.begin(), basic->typeSpec.end(), DeclarationNode::basicTypeName, os );
+		break;
+	  case Array:
+		if ( array->isStatic ) {
+			os << "static ";
+		}
+		if ( array->dimension ) {
+			os << "array of ";
+			array->dimension->printOneLine( os, indent );
+		} else if ( array->isVarLen ) {
+			os << "variable-length array of ";
+		} else {
+			os << "open array of ";
+		}
+		if ( base ) {
+			base->print( os, indent );
+		}
+		break;
+	  case Function:
+		os << "function" << endl;
+		if ( function->params ) {
+			os << string( indent+2, ' ' ) << "with parameters " << endl;
+			function->params->printList( os, indent+4 );
+		} else {
+			os << string( indent+2, ' ' ) << "with no parameters " << endl;
+		}
+		if ( function->idList ) {
+			os << string( indent+2, ' ' ) << "with old-style identifier list " << endl;
+			function->idList->printList( os, indent+4 );
+		}
+		if ( function->oldDeclList ) {
+			os << string( indent+2, ' ' ) << "with old-style declaration list " << endl;
+			function->oldDeclList->printList( os, indent+4 );
+		}
+		os << string( indent+2, ' ' ) << "returning ";
+		if ( base ) {
+			base->print( os, indent+4 );
+		} else {
+			os << "nothing ";
+		}
+		os << endl;
+		if ( function->hasBody ) {
+			os << string( indent+2, ' ' ) << "with body " << endl;
+		}
+		if ( function->body ) {
+			function->body->printList( os, indent+2 );
+		}
+		break;
+	  case Aggregate:
+		os << DeclarationNode::tyConName[ aggregate->kind ] << ' ' << aggregate->name << endl;
+		if ( aggregate->params ) {
+			os << string( indent+2, ' ' ) << "with type parameters " << endl;
+			aggregate->params->printList( os, indent+4 );
+		}
+		if ( aggregate->actuals ) {
+			os << string( indent+2, ' ' ) << "instantiated with actual parameters " << endl;
+			aggregate->actuals->printList( os, indent+4 );
+		}
+		if ( aggregate->members ) {
+			os << string( indent+2, ' ' ) << "with members " << endl;
+			aggregate->members->printList( os, indent+4 );
+///     } else {
+///       os << string( indent+2, ' ' ) << "with no members " << endl;
+		}
+		break;
+	  case AggregateInst:
+		if ( aggInst->aggregate ) {
+			os << "instance of " ;
+			aggInst->aggregate->print( os, indent );
+		} else {
+			os << "instance of an unspecified aggregate ";
+		}
+		if ( aggInst->params ) {
+			os << string( indent+2, ' ' ) << "with parameters " << endl;
+			aggInst->params->printList( os, indent+2 );
+		}
+		break;
+	  case Enum:
+		os << "enumeration ";
+		if ( enumeration->constants ) {
+			os << "with constants" << endl;
+			enumeration->constants->printList( os, indent+2 );
+		}
+		break;
+	  case SymbolicInst:
+		os << "instance of type " << symbolic->name;
+		if ( symbolic->actuals ) {
+			os << " with parameters" << endl;
+			symbolic->actuals->printList( os, indent + 2 );
+		}
+		break;
+	  case Symbolic:
+		if ( symbolic->isTypedef ) {
+			os << "typedef definition ";
+		} else {
+			os << "type definition ";
+		}
+		if ( symbolic->params ) {
+			os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
+			symbolic->params->printList( os, indent + 2 );
+		}
+		if ( symbolic->assertions ) {
+			os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
+			symbolic->assertions->printList( os, indent + 4 );
+			os << string( indent+2, ' ' );
+		}
+		if ( base ) {
+			os << "for ";
+			base->print( os, indent + 2 );
+		}
+		break;
+	  case Variable:
+		os << DeclarationNode::typeClassName[ variable->tyClass ] << " variable ";
+		if ( variable->assertions ) {
+			os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
+			variable->assertions->printList( os, indent + 4 );
+			os << string( indent+2, ' ' );
+		}
+		break;
+	  case Tuple:
+		os << "tuple ";
+		if ( tuple->members ) {
+			os << "with members " << endl;
+			tuple->members->printList( os, indent + 2 );
+		}
+		break;
+	  case Typeof:
+		os << "type-of expression ";
+		if ( typeexpr->expr ) {
+			typeexpr->expr->print( os, indent + 2 );
+		}
+		break;
+	  case Attr:
+		os << "attribute type decl " << attr->name << " applied to ";
+		if ( attr->expr ) {
+			attr->expr->print( os, indent + 2 );
+		}
+		if ( attr->type ) {
+			attr->type->print( os, indent + 2 );
+		}
+		break;
+	}
+}
+
+TypeData *TypeData::extractAggregate( bool toplevel ) const {
+	TypeData *ret = 0;
+
+	switch ( kind ) {
+	  case Aggregate:
+		if ( ! toplevel && aggregate->members ) {
+			ret = clone();
+			ret->qualifiers.clear();
+		}
+		break;
+	  case Enum:
+		if ( ! toplevel && enumeration->constants ) {
+			ret = clone();
+			ret->qualifiers.clear();
+		}
+		break;
+	  case AggregateInst:
+		if ( aggInst->aggregate ) {
+			ret = aggInst->aggregate->extractAggregate( false );
+		}
+		break;
+	  default:
+		if ( base ) {
+			ret = base->extractAggregate( false );
+		}
+	}
+	return ret;
+}
+
+void buildForall( const DeclarationNode *firstNode, std::list< TypeDecl* > &outputList ) {
+	buildList( firstNode, outputList );
+	for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
+		if ( (*i)->get_kind() == TypeDecl::Any ) {
+			FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
+			assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
+			assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
+			assignType->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
+			(*i)->get_assertions().push_front( new FunctionDecl( "?=?", Declaration::NoStorageClass, LinkageSpec::Cforall, assignType, 0, false ) );
+		}
+	}
+}
+
+Declaration *TypeData::buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init ) const {
+	if ( kind == TypeData::Function ) {
+		FunctionDecl *decl;
+		if ( function->hasBody ) {
+			if ( function->body ) {
+				Statement *stmt = function->body->build();
+				CompoundStmt *body = dynamic_cast< CompoundStmt* >( stmt );
+				assert( body );
+				decl = new FunctionDecl( name, sc, linkage, buildFunction(), body, isInline );
+			} else {
+				// std::list<Label> ls;
+				decl = new FunctionDecl( name, sc, linkage, buildFunction(), new CompoundStmt( std::list<Label>() ), isInline );
+			}
+		} else {
+			decl = new FunctionDecl( name, sc, linkage, buildFunction(), 0, isInline );
+		}
+		for ( DeclarationNode *cur = function->idList; cur != 0; cur = dynamic_cast< DeclarationNode* >( cur->get_link() ) ) {
+			if ( cur->get_name() != "" ) {
+				decl->get_oldIdents().insert( decl->get_oldIdents().end(), cur->get_name() );
+			}
+		}
+		buildList( function->oldDeclList, decl->get_oldDecls() );
+		return decl;
+	} else if ( kind == TypeData::Aggregate ) {
+		return buildAggregate();
+	} else if ( kind == TypeData::Enum ) {
+		return buildEnum();
+	} else if ( kind == TypeData::Symbolic ) {
+		return buildSymbolic( name, sc );
+	} else if ( kind == TypeData::Variable ) {
+		return buildVariable();
+	} else {
+		if ( isInline ) {
+			throw SemanticError( "invalid inline specification in declaration of ", this );
+		} else {
+			return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init );
+		}
+	}
+	return 0;
+}
+
+Type *TypeData::build() const {
+	switch ( kind ) {
+	  case Unknown:
+		// fill in implicit int
+		return new BasicType( buildQualifiers(), BasicType::SignedInt );
+	  case Basic:
+		return buildBasicType();
+	  case Pointer:
+		return buildPointer();
+	  case Array:
+		return buildArray();
+	  case Function:
+		return buildFunction();
+	  case AggregateInst:
+		return buildAggInst();
+	  case EnumConstant:
+		// the name gets filled in later -- by SymTab::Validate
+		return new EnumInstType( buildQualifiers(), "" );
+	  case SymbolicInst:
+		return buildSymbolicInst();;
+	  case Tuple:
+		return buildTuple();
+	  case Typeof:
+		return buildTypeof();
+	  case Attr:
+		return buildAttr();
+	  case Symbolic:
+	  case Enum:
+	  case Aggregate:
+	  case Variable:
+		assert( false );
+	}
+
+	return 0;
+}
+
+Type::Qualifiers TypeData::buildQualifiers() const {
+	Type::Qualifiers q;
+	for ( std::list< DeclarationNode::Qualifier >::const_iterator i = qualifiers.begin(); i != qualifiers.end(); ++i ) {
+		switch ( *i ) {
+		  case DeclarationNode::Const:
+			q.isConst = true;
+			break;
+		  case DeclarationNode::Volatile:
+			q.isVolatile = true;
+			break;
+		  case DeclarationNode::Restrict:
+			q.isRestrict = true;
+			break;
+		  case DeclarationNode::Lvalue:
+			q.isLvalue = true;
+			break;
+		  case DeclarationNode::Atomic:
+			q.isAtomic = true;
+			break;
+		  case DeclarationNode::Attribute:
+			q.isAttribute = true;
+			break;
+		}
+	}
+	return q;
+}
+
+Type *TypeData::buildBasicType() const {
+	static const BasicType::Kind kindMap[] = { BasicType::Char, BasicType::SignedInt, BasicType::Float, BasicType::Double,
+											   BasicType::Char /* void */, BasicType::Bool, BasicType::DoubleComplex,
+											   BasicType::DoubleImaginary };
+	bool init = false;
+	bool sawDouble = false;
+	bool sawSigned = false;
+	BasicType::Kind ret;
+
+	for ( std::list< DeclarationNode::BasicType >::const_iterator i = basic->typeSpec.begin(); i != basic->typeSpec.end(); ++i ) {
+		if ( ! init ) {
+			init = true;
+			if ( *i == DeclarationNode::Void ) {
+				if ( basic->typeSpec.size() != 1 || ! basic->modifiers.empty() ) {
+					throw SemanticError( "invalid type specifier \"void\" in type: ", this );
+				} else {
+					return new VoidType( buildQualifiers() );
+				}
+			} else {
+				ret = kindMap[ *i ];
+			}
+		} else {
+			switch ( *i ) {
+			  case DeclarationNode::Float:
+				if ( sawDouble ) {
+					throw SemanticError( "invalid type specifier \"float\" in type: ", this );
+				} else {
+					switch ( ret ) {
+					  case BasicType::DoubleComplex:
+						ret = BasicType::FloatComplex;
+						break;
+					  case BasicType::DoubleImaginary:
+						ret = BasicType::FloatImaginary;
+						break;
+					  default:
+						throw SemanticError( "invalid type specifier \"float\" in type: ", this );
+					}
+				}
+				break;
+			  case DeclarationNode::Double:
+				if ( sawDouble ) {
+					throw SemanticError( "duplicate type specifier \"double\" in type: ", this );
+				} else {
+					switch ( ret ) {
+					  case BasicType::DoubleComplex:
+					  case BasicType::DoubleImaginary:
+						break;
+					  default:
+						throw SemanticError( "invalid type specifier \"double\" in type: ", this );
+					}
+				}
+				break;
+	
+			  case DeclarationNode::Complex:
+				switch ( ret ) {
+				  case BasicType::Float:
+					ret = BasicType::FloatComplex;
+					break;
+				  case BasicType::Double:
+					ret = BasicType::DoubleComplex;
+					break;
+				  default:
+					throw SemanticError( "invalid type specifier \"_Complex\" in type: ", this );
+				}
+				break;
+			  case DeclarationNode::Imaginary:
+				switch ( ret ) {
+				  case BasicType::Float:
+					ret = BasicType::FloatImaginary;
+					break;
+				  case BasicType::Double:
+					ret = BasicType::DoubleImaginary;
+					break;
+				  default:
+					throw SemanticError( "invalid type specifier \"_Imaginary\" in type: ", this );
+				}
+				break;
+			  default:
+				throw SemanticError( std::string( "invalid type specifier \"" ) + DeclarationNode::basicTypeName[ *i ] + "\" in type: ", this );
+			}
+		}
+		if ( *i == DeclarationNode::Double ) {
+			sawDouble = true;
+		}
+	}
+
+	for ( std::list< DeclarationNode::Modifier >::const_iterator i = basic->modifiers.begin(); i != basic->modifiers.end(); ++i ) {
+		switch ( *i ) {
+		  case DeclarationNode::Long:
+			if ( ! init ) {
+				init = true;
+				ret = BasicType::LongSignedInt;
+			} else {
+				switch ( ret ) {
+				  case BasicType::SignedInt:
+					ret = BasicType::LongSignedInt;
+					break;
+				  case BasicType::UnsignedInt:
+					ret = BasicType::LongUnsignedInt;
+					break;
+				  case BasicType::LongSignedInt:
+					ret = BasicType::LongLongSignedInt;
+					break;
+				  case BasicType::LongUnsignedInt:
+					ret = BasicType::LongLongUnsignedInt;
+					break;
+				  case BasicType::Double:
+					ret = BasicType::LongDouble;
+					break;
+				  case BasicType::DoubleComplex:
+					ret = BasicType::LongDoubleComplex;
+					break;
+				  case BasicType::DoubleImaginary:
+					ret = BasicType::LongDoubleImaginary;
+					break;
+				  default:
+					throw SemanticError( "invalid type modifier \"long\" in type: ", this );
+				}
+			}
+			break;
+		  case DeclarationNode::Short:
+			if ( ! init ) {
+				init = true;
+				ret = BasicType::ShortSignedInt;
+			} else {
+				switch ( ret ) {
+				  case BasicType::SignedInt:
+					ret = BasicType::ShortSignedInt;
+					break;
+				  case BasicType::UnsignedInt:
+					ret = BasicType::ShortUnsignedInt;
+					break;
+				  default:
+					throw SemanticError( "invalid type modifier \"short\" in type: ", this );
+				}
+			}
+			break;
+		  case DeclarationNode::Signed:
+			if ( ! init ) {
+				init = true;
+				ret = BasicType::SignedInt;
+			} else if ( sawSigned ) {
+				throw SemanticError( "duplicate type modifer \"signed\" in type: ", this );
+			} else {
+				switch ( ret ) {
+				  case BasicType::LongLongSignedInt:	// PAB
+					ret = BasicType::LongLongUnsignedInt;
+					break;
+				  case BasicType::LongSignedInt:
+					ret = BasicType::LongUnsignedInt;
+					break;
+				  case BasicType::SignedInt:
+				  case BasicType::ShortSignedInt:
+					break;
+				  case BasicType::Char:
+					ret = BasicType::SignedChar;
+					break;
+				  default:
+					throw SemanticError( "invalid type modifer \"signed\" in type: ", this );
+				}
+			}
+			break;
+		  case DeclarationNode::Unsigned:
+			if ( ! init ) {
+				init = true;
+				ret = BasicType::UnsignedInt;
+			} else if ( sawSigned ) {
+				throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
+			} else {
+				switch ( ret ) {
+				  case BasicType::LongLongSignedInt:	// PAB
+					ret = BasicType::LongLongUnsignedInt;
+					break;
+				  case BasicType::LongSignedInt:
+					ret = BasicType::LongUnsignedInt;
+					break;
+				  case BasicType::SignedInt:
+					ret = BasicType::UnsignedInt;
+					break;
+				  case BasicType::ShortSignedInt:
+					ret = BasicType::ShortUnsignedInt;
+					break;
+				  case BasicType::Char:
+					ret = BasicType::UnsignedChar;
+					break;
+				  default:
+					throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
+				}
+			}
+			break;
+		}
+
+		if ( *i == DeclarationNode::Signed ) {
+			sawSigned = true;
+		}
+	}
+
+	BasicType *bt;
+	if ( ! init ) {
+		bt = new BasicType( buildQualifiers(), BasicType::SignedInt );
+	} else {
+		bt = new BasicType( buildQualifiers(), ret );
+	}
+	buildForall( forall, bt->get_forall() );
+	return bt;
+}
+
+
+PointerType *TypeData::buildPointer() const {
+	PointerType *pt;
+	if ( base ) {
+		pt = new PointerType( buildQualifiers(), base->build() );
+	} else {
+		pt = new PointerType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+	}
+	buildForall( forall, pt->get_forall() );
+	return pt;
+}
+
+ArrayType *TypeData::buildArray() const {
+	ArrayType *at;
+	if ( base ) {
+		at = new ArrayType( buildQualifiers(), base->build(), maybeBuild< Expression >( array->dimension ),
+							array->isVarLen, array->isStatic );
+	} else {
+		at = new ArrayType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
+							maybeBuild< Expression >( array->dimension ), array->isVarLen, array->isStatic );
+	}
+	buildForall( forall, at->get_forall() );
+	return at;
+}
+
+FunctionType *TypeData::buildFunction() const {
+	assert( kind == Function );
+	bool hasEllipsis = function->params ? function->params->get_hasEllipsis() : true;
+	if ( ! function->params ) hasEllipsis = ! function->newStyle;
+	FunctionType *ft = new FunctionType( buildQualifiers(), hasEllipsis );
+	buildList( function->params, ft->get_parameters() );
+	buildForall( forall, ft->get_forall() );
+	if ( base ) {
+		switch ( base->kind ) {
+		  case Tuple:
+			buildList( base->tuple->members, ft->get_returnVals() );
+			break;
+		  default:
+			ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType* >( base->buildDecl( "", Declaration::NoStorageClass, 0, false, LinkageSpec::Cforall ) ) );
+		}
+	} else {
+		ft->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 ) );
+	}
+	return ft;
+}
+
+AggregateDecl *TypeData::buildAggregate() const {
+	assert( kind == Aggregate );
+	AggregateDecl *at;
+	switch ( aggregate->kind ) {
+	  case DeclarationNode::Struct:
+		at = new StructDecl( aggregate->name );
+		break;
+	
+	  case DeclarationNode::Union:
+		at = new UnionDecl( aggregate->name );
+		break;
+	
+	  case DeclarationNode::Context:
+		at = new ContextDecl( aggregate->name );
+		break;
+	
+	  default:
+		assert( false );
+	}
+	buildList( aggregate->params, at->get_parameters() );
+	buildList( aggregate->members, at->get_members() );
+
+	return at;
+}
+
+/// namespace {
+/// Type*
+/// makeType( Declaration* decl )
+/// {
+///   if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
+///     return dwt->get_type()->clone();
+///   } else {
+///     return 0;
+///   }
+/// }
+/// }
+
+ReferenceToType *TypeData::buildAggInst() const {
+	assert( kind == AggregateInst );
+	std::string name;
+
+	ReferenceToType *ret;
+	if ( aggInst->aggregate->kind == Enum ) {
+		ret = new EnumInstType( buildQualifiers(), aggInst->aggregate->enumeration->name );
+	} else {
+		assert( aggInst->aggregate->kind == Aggregate );
+		switch ( aggInst->aggregate->aggregate->kind ) {
+		  case DeclarationNode::Struct:
+			ret = new StructInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
+			break;
+		  case DeclarationNode::Union:
+			ret = new UnionInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
+			break;
+		  case DeclarationNode::Context:
+			ret = new ContextInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
+			break;
+		  default:
+			assert( false );
+		}
+	}
+	buildList( aggInst->params, ret->get_parameters() );
+	buildForall( forall, ret->get_forall() );
+	return ret;
+}
+
+NamedTypeDecl *TypeData::buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const {
+	assert( kind == Symbolic );
+	NamedTypeDecl *ret;
+	if ( symbolic->isTypedef ) {
+		ret = new TypedefDecl( name, sc, maybeBuild< Type >( base ) );
+	} else {
+		ret = new TypeDecl( name, sc, maybeBuild< Type >( base ), TypeDecl::Any );
+	}
+	buildList( symbolic->params, ret->get_parameters() );
+	buildList( symbolic->assertions, ret->get_assertions() );
+	return ret;
+}
+
+TypeDecl *TypeData::buildVariable() const {
+	assert( kind == Variable );
+	static const TypeDecl::Kind kindMap[] = { TypeDecl::Any, TypeDecl::Ftype, TypeDecl::Dtype };
+
+	TypeDecl *ret = new TypeDecl( variable->name, Declaration::NoStorageClass, 0, kindMap[ variable->tyClass ] );
+	buildList( variable->assertions, ret->get_assertions() );
+	
+	return ret;
+}
+
+EnumDecl *TypeData::buildEnum() const {
+	assert( kind == Enum );
+	EnumDecl *ret = new EnumDecl( enumeration->name );
+	buildList( enumeration->constants, ret->get_members() );
+
+	return ret;
+}
+
+TypeInstType *TypeData::buildSymbolicInst() const {
+	assert( kind == SymbolicInst );
+	TypeInstType *ret = new TypeInstType( buildQualifiers(), symbolic->name, false );
+	buildList( symbolic->actuals, ret->get_parameters() );
+	buildForall( forall, ret->get_forall() );
+
+	return ret;
+}
+
+TupleType *TypeData::buildTuple() const {
+	assert( kind == Tuple );
+	TupleType *ret = new TupleType( buildQualifiers() );
+	buildTypeList( tuple->members, ret->get_types() );
+	buildForall( forall, ret->get_forall() );
+
+	return ret;
+}
+
+TypeofType *TypeData::buildTypeof() const {
+	assert( kind == Typeof );
+	assert( typeexpr );
+	assert( typeexpr->expr );
+	TypeofType *ret = new TypeofType( buildQualifiers(), typeexpr->expr->build() );
+
+	return ret;
+}
+
+AttrType *TypeData::buildAttr() const {
+	assert( kind == Attr );
+	assert( attr );
+	AttrType *ret;
+	if ( attr->expr ) {
+		ret = new AttrType( buildQualifiers(), attr->name, attr->expr->build() );
+	} else {
+		assert( attr->type );
+		ret = new AttrType( buildQualifiers(), attr->name, attr->type->buildType() );
+	}
+
+	return ret;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/TypeData.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,145 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypeData.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:18:36 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:20:00 2015
+// Update Count     : 2
+//
+
+#ifndef TYPEDATA_H
+#define TYPEDATA_H
+
+#include <list>
+
+#include "ParseNode.h"
+#include "SynTree/Type.h"
+
+struct TypeData {
+	enum Kind { Unknown, Basic, Pointer, Array, Function, Aggregate, AggregateInst,
+				Enum, EnumConstant, Symbolic, SymbolicInst, Variable, Tuple, Typeof, Attr } kind;
+
+	TypeData( Kind k = Unknown );
+	~TypeData();
+	void print( std::ostream &, int indent = 0 ) const;
+	TypeData *clone() const;
+
+	Type *build() const;
+	FunctionType *buildFunction() const;
+
+	TypeData *base;
+	std::list< DeclarationNode::Qualifier > qualifiers;
+	DeclarationNode *forall;
+
+	struct Basic_t {
+		std::list< DeclarationNode::BasicType > typeSpec;
+		std::list< DeclarationNode::Modifier > modifiers;
+	};
+
+	struct Aggregate_t {
+		DeclarationNode::TyCon kind;
+		std::string name;
+		DeclarationNode *params;
+		ExpressionNode *actuals;						// holds actual parameters later applied to AggInst
+		DeclarationNode *members;
+	};
+
+	struct AggInst_t {
+		TypeData *aggregate;
+		ExpressionNode *params;
+	};
+
+	struct Array_t {
+		ExpressionNode *dimension;
+		bool isVarLen;
+		bool isStatic;
+	};
+
+	struct Enumeration_t {
+		std::string name;
+		DeclarationNode *constants;
+	};
+
+	struct Function_t {
+		DeclarationNode *params;
+		DeclarationNode *idList;						// old-style
+		DeclarationNode *oldDeclList;
+		StatementNode *body;
+		bool hasBody;
+		bool newStyle;
+	};
+
+	struct Symbolic_t {
+		std::string name;
+		bool isTypedef;
+		DeclarationNode *params;
+		ExpressionNode *actuals;
+		DeclarationNode *assertions;
+	};
+
+	struct Variable_t {
+		DeclarationNode::TypeClass tyClass;
+		std::string name;
+		DeclarationNode *assertions;
+	};
+
+	struct Tuple_t {
+		DeclarationNode *members;
+	};
+  
+	struct Typeof_t {
+		ExpressionNode *expr;
+	};
+
+	struct Attr_t {
+		std::string name;
+		ExpressionNode *expr;
+		DeclarationNode *type;
+	};
+
+	union {
+		Basic_t *basic;
+		Aggregate_t *aggregate;
+		AggInst_t *aggInst;
+		Array_t *array;
+		Enumeration_t *enumeration;
+		Function_t *function;
+		Symbolic_t *symbolic;
+		Variable_t *variable;
+		Tuple_t *tuple;
+		Typeof_t *typeexpr;
+		Attr_t *attr;
+	};
+
+	TypeData *extractAggregate( bool toplevel = true ) const;
+	// helper function for DeclNodeImpl::build
+	Declaration * buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init = 0 ) const;
+	// helper functions for build()
+	Type::Qualifiers buildQualifiers() const;
+	Type *buildBasicType() const;
+	PointerType * buildPointer() const;
+	ArrayType * buildArray() const;
+	AggregateDecl * buildAggregate() const;
+	ReferenceToType * buildAggInst() const;
+	NamedTypeDecl * buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const;
+	TypeDecl* buildVariable() const;
+	EnumDecl* buildEnum() const;
+	TypeInstType * buildSymbolicInst() const;
+	TupleType * buildTuple() const;
+	TypeofType * buildTypeof() const;
+	AttrType * buildAttr() const;
+};
+
+#endif // TYPEDATA_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/TypedefTable.cc
===================================================================
--- src/Parser/TypedefTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/TypedefTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,165 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypedefTable.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:20:13 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:24:03 2015
+// Update Count     : 2
+//
+
+#include <map>
+#include <list>
+#include "TypedefTable.h"
+#include <cassert>
+using namespace std;
+
+#if 0
+#include <iostream>
+#define debugPrint(x ) cerr << x
+#else
+#define debugPrint( x )
+#endif
+
+TypedefTable::TypedefTable() : currentScope( 0 ) {}
+
+bool TypedefTable::isKind( string identifier, kind_t kind ) const {
+	tableType::const_iterator id_pos = table.find( identifier );
+	if ( id_pos == table.end()) {
+		return true;
+	} else {
+		return (*((*id_pos ).second.begin())).kind == kind;
+	}
+}
+
+bool TypedefTable::isIdentifier( string identifier ) const {
+	return isKind( identifier, ID );
+}
+
+bool TypedefTable::isTypedef( string identifier ) const {
+	return isKind( identifier, TD );
+}
+
+bool TypedefTable::isTypegen( string identifier ) const {
+	return isKind( identifier, TG );
+}
+
+void TypedefTable::addToScope( const std::string &identifier, kind_t kind, int scope ) {
+	if ( currentContext != "" && scope == contextScope ) {
+		DeferredEntry entry = { identifier, kind };
+		contexts[currentContext].push_back( entry );
+	} else {
+		debugPrint( "Adding " << identifier << " as type " << kind << " scope " << scope << " from scope " << currentScope << endl );
+		Entry newEntry = { scope, kind };
+		tableType::iterator curPos = table.find( identifier );
+		if ( curPos == table.end()) {
+			list<Entry> newList;
+			newList.push_front( newEntry );
+			table[identifier] = newList;
+		} else {
+			list<Entry>::iterator listPos = (*curPos ).second.begin();
+			while ( listPos != (*curPos ).second.end() && listPos->scope > scope ) {
+				listPos++;
+			}
+			(*curPos ).second.insert( listPos, newEntry );
+		}
+	}
+}
+
+void TypedefTable::addToCurrentScope( const std::string &identifier, kind_t kind ) {
+	addToScope( identifier, kind, currentScope );
+}
+
+void TypedefTable::addToCurrentScope( kind_t kind ) {
+	addToCurrentScope( nextIdentifiers.top(), kind );
+}
+
+void TypedefTable::addToEnclosingScope( const std::string &identifier, kind_t kind ) {
+	assert( currentScope >= 1 );
+	addToScope( identifier, kind, currentScope - 1 );
+}
+
+void TypedefTable::addToEnclosingScope( kind_t kind ) {
+	addToEnclosingScope( nextIdentifiers.top(), kind );
+}
+
+void TypedefTable::addToEnclosingScope2( const std::string &identifier, kind_t kind ) {
+	assert( currentScope >= 2 );
+	addToScope( identifier, kind, currentScope - 2 );
+}
+
+void TypedefTable::addToEnclosingScope2( kind_t kind ) {
+	addToEnclosingScope2( nextIdentifiers.top(), kind );
+}
+
+void TypedefTable::setNextIdentifier( const std::string &identifier ) {
+	nextIdentifiers.top() = identifier;
+}
+
+void TypedefTable::openContext( std::string contextName ) {
+	map< string, deferListType >::iterator i = contexts.find( contextName );
+	if ( i != contexts.end() ) {
+		deferListType &entries = i->second;
+		for ( deferListType::iterator i = entries.begin(); i != entries.end(); i++) {
+			addToEnclosingScope( i->identifier, i->kind );
+		}
+	}
+}
+
+void TypedefTable::enterScope( void ) {
+	currentScope += 1;
+	deferListStack.push( deferListType() );
+	nextIdentifiers.push( "" );
+	debugPrint( "Entering scope " << currentScope << ", nextIdentifiers size is " << nextIdentifiers.size() << endl );
+}
+
+void TypedefTable::leaveScope( void ) {
+	debugPrint( "Leaving scope " << currentScope << endl );
+	for ( tableType::iterator i = table.begin(); i != table.end(); ) {
+		list<Entry> &declList = (*i ).second;
+		while ( ! declList.empty() && declList.front().scope == currentScope ) {
+			declList.pop_front();
+		}
+		if ( declList.empty() ) {			// standard idom for erasing during traversal
+			table.erase( i++ );
+		} else ++i;
+	}
+	currentScope -= 1;
+	for ( deferListType::iterator i = deferListStack.top().begin(); i != deferListStack.top().end(); i++) {
+		addToCurrentScope( i->identifier, i->kind );
+	}
+	deferListStack.pop();
+	debugPrint( "nextIdentifiers size is " << nextIdentifiers.size() << " top is " << nextIdentifiers.top() << endl );
+	nextIdentifiers.pop();
+}
+
+void TypedefTable::enterContext( std::string contextName ) {
+	currentContext = contextName;
+	contextScope = currentScope;
+}
+
+void TypedefTable::leaveContext( void ) {
+	currentContext = "";
+}
+
+void TypedefTable::print( void ) const {
+	for ( tableType::const_iterator i = table.begin(); i != table.end(); i++) {
+		debugPrint( (*i ).first << ": " );
+		list<Entry> declList = (*i ).second;
+		for ( list<Entry>::const_iterator j = declList.begin(); j != declList.end(); j++ ) {
+			debugPrint( "(" << (*j ).scope << " " << (*j).kind << ") " );
+		}
+		debugPrint( endl );
+	}
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/TypedefTable.h
===================================================================
--- src/Parser/TypedefTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/TypedefTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,95 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypedefTable.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:24:36 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:25:59 2015
+// Update Count     : 3
+//
+
+#ifndef TYPEDEFTABLE_H
+#define TYPEDEFTABLE_H
+
+#include <map>
+#include <list>
+#include <string>
+#include <stack>
+
+class TypedefTable {
+  public:
+	enum kind_t { ID, TD, TG };
+  private:
+	struct Entry {
+		int scope;
+		kind_t kind;
+	};
+	
+	struct DeferredEntry {
+		std::string identifier;
+		kind_t kind;
+	};
+
+	typedef std::map<std::string, std::list<Entry> > tableType;
+	tableType table;
+
+	int currentScope;
+	std::string currentContext;
+	int contextScope;
+	
+	typedef std::list< DeferredEntry > deferListType;
+	std::stack< deferListType > deferListStack;
+	std::map< std::string, deferListType > contexts;
+	
+	std::stack< std::string > nextIdentifiers;
+
+	bool isKind( std::string identifier, kind_t kind ) const;
+	void addToScope( const std::string &identifier, kind_t kind, int scope );
+  public:
+	TypedefTable();
+
+	bool isIdentifier( std::string identifier ) const;
+	bool isTypedef( std::string identifier ) const;
+	bool isTypegen( std::string identifier ) const;
+	
+	// "addToCurrentScope" adds the identifier/type pair to the current scope This does less than you think it does,
+	// since each declaration is within its own scope.  Mostly useful for type parameters.
+	void addToCurrentScope( const std::string &identifier, kind_t kind );
+	void addToCurrentScope( kind_t kind );		// use nextIdentifiers.top()
+
+	// "addToEnclosingScope" adds the identifier/type pair to the scope that encloses the current one.  This is the
+	// right way to handle type and typedef names
+	void addToEnclosingScope( const std::string &identifier, kind_t kind );
+	void addToEnclosingScope( kind_t kind );		// use nextIdentifiers.top()
+	
+	// "addToEnclosingScope2" adds the identifier/type pair to the scope that encloses the scope enclosing the the
+	// current one.  This is the right way to handle assertion names
+	void addToEnclosingScope2( const std::string &identifier, kind_t kind );
+	void addToEnclosingScope2( kind_t kind );		// use nextIdentifiers.top()
+	
+	// set the next identifier to be used by an "add" operation without an identifier parameter within the current scope
+	void setNextIdentifier( const std::string &identifier );
+	
+	// dump the definitions from a pre-defined context into the current scope
+	void openContext( std::string contextName );
+	
+	void enterScope();
+	void leaveScope();
+	void enterContext( std::string contextName );
+	void leaveContext();
+
+	void print() const;
+};
+
+#endif // TYPEDEFTABLE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/cfa.y
===================================================================
--- src/Parser/cfa.y	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/cfa.y	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,2735 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// cfa.y -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Sat Sep  1 20:22:55 2001
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 11:55:39 2015
+// Update Count     : 975
+// 
+
+// This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on
+// the C grammar by James A. Roskind, specifically parts of DECLARATIONS and EXTERNAL DEFINITIONS.  While
+// parts have been copied, important changes have been made in all sections; these changes are sufficient to
+// constitute a new grammar.  In particular, this grammar attempts to be more syntactically precise, i.e., it
+// parses less incorrect language syntax that must be subsequently rejected by semantic checks.  Nevertheless,
+// there are still several semantic checks required and many are noted in the grammar. Finally, the grammar is
+// extended with GCC and CFA language extensions.
+
+// Acknowledgments to Richard Bilson, Glen Ditchfield, and Rodolfo Gabriel Esteves who all helped when I got
+// stuck with the grammar.
+
+// The root language for this grammar is ANSI99/11 C. All of ANSI99/11 is parsed, except for:
+//
+// 1. designation with '=' (use ':' instead)
+//
+// Most of the syntactic extensions from ANSI90 to ANSI11 C are marked with the comment "C99/C11". This
+// grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions, except for:
+//
+// 1. nested functions
+// 2. generalized lvalues
+// 3. designation with and without '=' (use ':' instead)
+// 4. attributes not allowed in parenthesis of declarator
+//
+// All of the syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for
+// Cforall (CFA), which fixes several of C's outstanding problems and extends C with many modern language
+// concepts. All of the syntactic extensions for CFA C are marked with the comment "CFA". As noted above,
+// there is one unreconcileable parsing problem between C99 and CFA with respect to designators; this is
+// discussed in detail before the "designation" grammar rule.
+
+%{
+#define YYDEBUG_LEXER_TEXT (yylval)						// lexer loads this up each time
+#define YYDEBUG 1										// get the pretty debugging code to compile
+
+#undef __GNUC_MINOR__
+
+#include <cstdio>
+#include <stack>
+#include "TypedefTable.h"
+#include "lex.h"
+#include "ParseNode.h"
+#include "LinkageSpec.h"
+
+DeclarationNode *theTree = 0;							// the resulting parse tree
+LinkageSpec::Type linkage = LinkageSpec::Cforall;
+std::stack< LinkageSpec::Type > linkageStack;
+TypedefTable typedefTable;
+%}
+
+//************************* TERMINAL TOKENS ********************************
+
+// keywords
+%token TYPEDEF
+%token AUTO EXTERN REGISTER STATIC
+%token INLINE											// C99
+%token FORTRAN											// C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
+%token CONST VOLATILE
+%token RESTRICT											// C99
+%token FORALL LVALUE									// CFA
+%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
+%token BOOL COMPLEX IMAGINARY							// C99
+%token TYPEOF LABEL										// GCC
+%token ENUM STRUCT UNION
+%token TYPE FTYPE DTYPE CONTEXT							// CFA
+%token SIZEOF
+%token ATTRIBUTE EXTENSION								// GCC
+%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
+%token CHOOSE FALLTHRU TRY CATCH FINALLY THROW			// CFA
+%token ASM												// C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
+%token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATICASSERT THREADLOCAL // C11
+
+// names and constants: lexer differentiates between identifier and typedef names
+%token<tok> IDENTIFIER			QUOTED_IDENTIFIER		TYPEDEFname				TYPEGENname
+%token<tok> ATTR_IDENTIFIER		ATTR_TYPEDEFname		ATTR_TYPEGENname
+%token<tok> INTEGERconstant		FLOATINGconstant		CHARACTERconstant		STRINGliteral
+%token<tok> ZERO				ONE						// CFA
+
+// multi-character operators
+%token ARROW											// ->
+%token ICR DECR											// ++	--
+%token LS RS											// <<	>>
+%token LE GE EQ NE										// <=	>=	==	!=
+%token ANDAND OROR										// &&	||
+%token ELLIPSIS											// ...
+
+%token MULTassign	DIVassign	MODassign				// *=	/=	%=/
+%token PLUSassign	MINUSassign							// +=	-=
+%token LSassign		RSassign							// <<=	>>=
+%token ANDassign	ERassign	ORassign				// &=	^=	|=
+
+// Types declaration
+%union
+{
+	Token tok;
+	ParseNode *pn;
+	ExpressionNode *en;
+	DeclarationNode *decl;
+	DeclarationNode::TyCon aggKey;
+	DeclarationNode::TypeClass tclass;
+	StatementNode *sn;
+	ConstantNode *constant;
+	InitializerNode *in;
+}
+
+%type<tok> zero_one  identifier  no_attr_identifier  no_01_identifier
+%type<tok> identifier_or_typedef_name  no_attr_identifier_or_typedef_name  no_01_identifier_or_typedef_name
+%type<constant> string_literal_list
+
+// expressions
+%type<constant> constant
+%type<en> tuple							tuple_expression_list
+%type<en> unary_operator				assignment_operator
+%type<en> primary_expression			postfix_expression			unary_expression
+%type<en> cast_expression				multiplicative_expression	additive_expression			shift_expression
+%type<en> relational_expression			equality_expression			AND_expression				exclusive_OR_expression
+%type<en> inclusive_OR_expression		logical_AND_expression		logical_OR_expression		conditional_expression
+%type<en> constant_expression			assignment_expression		assignment_expression_opt
+%type<en> comma_expression				comma_expression_opt
+%type<en> argument_expression_list		argument_expression			for_control_expression		assignment_opt
+%type<en> subrange
+
+// statements
+%type<sn> labeled_statement				compound_statement			expression_statement		selection_statement
+%type<sn> iteration_statement			jump_statement				exception_statement			asm_statement
+%type<sn> fall_through_opt				fall_through
+%type<sn> statement						statement_list
+%type<sn> block_item_list				block_item
+%type<sn> case_clause
+%type<en> case_value					case_value_list
+%type<sn> case_label					case_label_list
+%type<sn> switch_clause_list_opt		switch_clause_list			choose_clause_list_opt		choose_clause_list
+%type<pn> handler_list					handler_clause				finally_clause
+
+// declarations
+%type<decl> abstract_array abstract_declarator abstract_function abstract_parameter_array
+%type<decl> abstract_parameter_declaration abstract_parameter_declarator abstract_parameter_function
+%type<decl> abstract_parameter_ptr abstract_ptr
+
+%type<aggKey> aggregate_key
+%type<decl>  aggregate_name
+
+%type<decl> array_dimension array_parameter_1st_dimension array_parameter_dimension multi_array_dimension
+
+%type<decl> assertion assertion_list_opt
+
+%type<en>   bit_subrange_size_opt bit_subrange_size
+
+%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type_name indirect_type_name
+
+%type<decl> context_declaration context_declaration_list context_declaring_list context_specifier
+
+%type<decl> declaration declaration_list declaration_list_opt declaration_qualifier_list
+%type<decl> declaration_specifier declarator declaring_list
+
+%type<decl> elaborated_type_name
+
+%type<decl> enumerator_list enum_name
+%type<en> enumerator_value_opt
+
+%type<decl> exception_declaration external_definition external_definition_list external_definition_list_opt
+
+%type<decl> field_declaration field_declaration_list field_declarator field_declaring_list
+%type<en> field field_list
+
+%type<decl> function_array function_declarator function_definition function_no_ptr function_ptr
+
+%type<decl> identifier_parameter_array identifier_parameter_declarator identifier_parameter_function
+%type<decl> identifier_parameter_ptr identifier_list
+
+%type<decl> new_abstract_array new_abstract_declarator_no_tuple new_abstract_declarator_tuple
+%type<decl> new_abstract_function new_abstract_parameter_declaration new_abstract_parameter_list
+%type<decl> new_abstract_ptr new_abstract_tuple
+
+%type<decl> new_array_parameter_1st_dimension
+
+%type<decl> new_context_declaring_list new_declaration new_field_declaring_list
+%type<decl> new_function_declaration new_function_return new_function_specifier
+
+%type<decl> new_identifier_parameter_array new_identifier_parameter_declarator_no_tuple
+%type<decl> new_identifier_parameter_declarator_tuple new_identifier_parameter_ptr
+
+%type<decl> new_parameter_declaration new_parameter_list new_parameter_type_list new_parameter_type_list_opt
+
+%type<decl> new_typedef_declaration new_variable_declaration new_variable_specifier
+
+%type<decl> old_declaration old_declaration_list old_declaration_list_opt old_function_array
+%type<decl> old_function_declarator old_function_no_ptr old_function_ptr
+
+%type<decl> parameter_declaration parameter_list parameter_type_list
+%type<decl> parameter_type_list_opt
+
+%type<decl> paren_identifier paren_typedef
+
+%type<decl> storage_class storage_class_name storage_class_list
+
+%type<decl> sue_declaration_specifier sue_type_specifier
+
+%type<tclass> type_class
+%type<decl> type_declarator type_declarator_name type_declaring_list
+
+%type<decl> typedef typedef_array typedef_declaration typedef_declaration_specifier typedef_expression
+%type<decl> typedef_function typedef_parameter_array typedef_parameter_function typedef_parameter_ptr
+%type<decl> typedef_parameter_redeclarator typedef_ptr typedef_redeclarator typedef_type_specifier
+%type<decl> typegen_declaration_specifier typegen_type_specifier
+
+%type<decl> type_name type_name_no_function
+%type<decl> type_parameter type_parameter_list
+
+%type<en> type_name_list
+
+%type<decl> type_qualifier type_qualifier_name type_qualifier_list type_qualifier_list_opt type_specifier
+
+%type<decl> variable_abstract_array variable_abstract_declarator variable_abstract_function
+%type<decl> variable_abstract_ptr variable_array variable_declarator variable_function variable_ptr
+
+// initializers
+%type<in>  initializer initializer_list initializer_opt
+
+// designators
+%type<en>  designator designator_list designation
+
+
+// Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string
+// is ambiguous:
+// .---------.				matches IF '(' comma_expression ')' statement
+// if ( C ) S1 else S2
+// `-----------------'		matches IF '(' comma_expression ')' statement ELSE statement */
+
+%nonassoc THEN	// rule precedence for IF '(' comma_expression ')' statement
+%nonassoc ELSE	// token precedence for start of else clause in IF statement
+
+%start translation_unit									// parse-tree root
+
+%%
+//************************* Namespace Management ********************************
+
+// The grammar in the ANSI C standard is not strictly context-free, since it relies upon the distinct terminal
+// symbols "identifier" and "TYPEDEFname" that are lexically identical.  While it is possible to write a
+// purely context-free grammar, such a grammar would obscure the relationship between syntactic and semantic
+// constructs.  Hence, this grammar uses the ANSI style.
+//
+// Cforall compounds this problem by introducing type names local to the scope of a declaration (for instance,
+// those introduced through "forall" qualifiers), and by introducing "type generators" -- parametrized types.
+// This latter type name creates a third class of identifiers that must be distinguished by the scanner.
+//
+// Since the scanner cannot distinguish among the different classes of identifiers without some context
+// information, it accesses a data structure (the TypedefTable) to allow classification of an identifier that
+// it has just read.  Semantic actions during the parser update this data structure when the class of
+// identifiers change.
+//
+// Because the Cforall language is block-scoped, there is the possibility that an identifier can change its
+// class in a local scope; it must revert to its original class at the end of the block.  Since type names can
+// be local to a particular declaration, each declaration is itself a scope.  This requires distinguishing
+// between type names that are local to the current declaration scope and those that persist past the end of
+// the declaration (i.e., names defined in "typedef" or "type" declarations).
+//
+// The non-terminals "push" and "pop" derive the empty string; their only use is to denote the opening and
+// closing of scopes.  Every push must have a matching pop, although it is regrettable the matching pairs do
+// not always occur within the same rule.  These non-terminals may appear in more contexts than strictly
+// necessary from a semantic point of view.  Unfortunately, these extra rules are necessary to prevent parsing
+// conflicts -- the parser may not have enough context and look-ahead information to decide whether a new
+// scope is necessary, so the effect of these extra rules is to open a new scope unconditionally.  As the
+// grammar evolves, it may be neccesary to add or move around "push" and "pop" nonterminals to resolve
+// conflicts of this sort.
+
+push:
+				{
+					typedefTable.enterScope();
+				}
+		;
+
+pop:
+				{
+					typedefTable.leaveScope();
+				}
+		;
+
+//************************* CONSTANTS ********************************
+
+constant:
+				// ENUMERATIONconstant is not included here; it is treated as a variable with type
+				// "enumeration constant".
+		INTEGERconstant									{ $$ = new ConstantNode(ConstantNode::Integer, $1); }
+		| FLOATINGconstant								{ $$ = new ConstantNode(ConstantNode::Float, $1); }
+		| CHARACTERconstant								{ $$ = new ConstantNode(ConstantNode::Character, $1); }
+		;
+
+identifier:
+		IDENTIFIER
+		| ATTR_IDENTIFIER								// CFA
+		| zero_one										// CFA
+		;
+
+no_01_identifier:
+		IDENTIFIER
+		| ATTR_IDENTIFIER								// CFA
+		;
+
+no_attr_identifier:
+		IDENTIFIER
+		;
+
+zero_one:												// CFA
+		ZERO
+		| ONE
+		;
+
+string_literal_list:									// juxtaposed strings are concatenated
+		STRINGliteral									{ $$ = new ConstantNode(ConstantNode::String, $1); }
+		| string_literal_list STRINGliteral				{ $$ = $1->append( $2 ); }
+		;
+
+//************************* EXPRESSIONS ********************************
+
+primary_expression:
+		IDENTIFIER										// typedef name cannot be used as a variable name
+				{ $$ = new VarRefNode($1); }
+		| zero_one
+				{ $$ = new VarRefNode($1); }
+		| constant
+				{ $$ = $1; }
+		| string_literal_list
+				{ $$ = $1; }
+		| '(' comma_expression ')'
+				{ $$ = $2; }
+		| '(' compound_statement ')'					// GCC, lambda expression
+				{ $$ = new ValofExprNode($2); }
+		;
+
+postfix_expression:
+		primary_expression
+		| postfix_expression '[' push assignment_expression pop ']'
+				// CFA, comma_expression disallowed in the context because it results in a commom user error:
+				// subscripting a matrix with x[i,j] instead of x[i][j]. While this change is not backwards
+				// compatible, there seems to be little advantage to this feature and many disadvantages. It
+				// is possible to write x[(i,j)] in CFA, which is equivalent to the old x[i,j].
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Index), $1, $4); }
+		| postfix_expression '(' argument_expression_list ')'
+				{ $$ = new CompositeExprNode($1, $3); }
+		| postfix_expression '.' no_attr_identifier
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), $1, new VarRefNode($3)); }
+		| postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
+		| postfix_expression ARROW no_attr_identifier
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), $1, new VarRefNode($3)); }
+		| postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
+		| postfix_expression ICR
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::IncrPost), $1); }
+		| postfix_expression DECR
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::DecrPost), $1); }
+				// GCC has priority: cast_expression
+		| '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99
+				{ $$ = 0; }
+		;
+
+argument_expression_list:
+		argument_expression
+		| argument_expression_list ',' argument_expression
+				{ $$ = (ExpressionNode *)($1->set_link($3)); }
+		;
+
+argument_expression:
+		// empty
+				{ $$ = 0; }								// use default argument
+		| assignment_expression
+		| no_attr_identifier ':' assignment_expression
+				{ $$ = $3->set_asArgName($1); }
+				// Only a list of no_attr_identifier_or_typedef_name is allowed in this context. However,
+				// there is insufficient look ahead to distinguish between this list of parameter names and a
+				// tuple, so the tuple form must be used with an appropriate semantic check.
+		| '[' push assignment_expression pop ']' ':' assignment_expression
+				{ $$ = $7->set_asArgName($3); }
+		| '[' push assignment_expression ',' tuple_expression_list pop ']' ':' assignment_expression
+				{ $$ = $9->set_asArgName(new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 )))); }
+		;
+
+field_list:												// CFA, tuple field selector
+		field
+		| field_list ',' field							{ $$ = (ExpressionNode *)$1->set_link( $3 ); }
+		;
+
+field:													// CFA, tuple field selector
+		no_attr_identifier
+				{ $$ = new VarRefNode( $1 ); }
+		| no_attr_identifier '.' field
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $3); }
+		| no_attr_identifier '.' '[' push field_list pop ']'
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $5); }
+		| no_attr_identifier ARROW field
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $3); }
+		| no_attr_identifier ARROW '[' push field_list pop ']'
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $5); }
+		;
+
+unary_expression:
+		postfix_expression
+		| ICR unary_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Incr), $2); }
+		| DECR unary_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Decr), $2); }
+		| EXTENSION cast_expression						// GCC
+				{ $$ = $2; }
+		| unary_operator cast_expression
+				{ $$ = new CompositeExprNode($1, $2); }
+		| '!' cast_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neg), $2); }
+		| '*' cast_expression							// CFA
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PointTo), $2); }
+				// '*' is is separated from unary_operator because of shift/reduce conflict in:
+				//		{ * X; } // dereference X
+				//		{ * int X; } // CFA declaration of pointer to int
+				// '&' must be moved here if C++ reference variables are supported.
+		| SIZEOF unary_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), $2); }
+		| SIZEOF '(' type_name_no_function ')'
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), new TypeValueNode($3)); }
+		| ATTR_IDENTIFIER
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1)); }
+		| ATTR_IDENTIFIER '(' type_name ')'
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), new TypeValueNode($3)); }
+		| ATTR_IDENTIFIER '(' argument_expression ')'
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), $3); }
+		| ALIGNOF unary_expression						// GCC, variable alignment
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), $2); }
+		| ALIGNOF '(' type_name_no_function ')'			// GCC, type alignment
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), new TypeValueNode($3)); }
+		| ANDAND no_attr_identifier						// GCC, address of label
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LabelAddress), new VarRefNode($2, true)); }
+		;
+
+unary_operator:
+		'&'												{ $$ = new OperatorNode(OperatorNode::AddressOf); }
+		| '+'											{ $$ = new OperatorNode(OperatorNode::UnPlus); }
+		| '-'											{ $$ = new OperatorNode(OperatorNode::UnMinus); }
+		| '~'											{ $$ = new OperatorNode(OperatorNode::BitNeg); }
+		;
+
+cast_expression:
+		unary_expression
+		| '(' type_name_no_function ')' cast_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
+		| '(' type_name_no_function ')' tuple
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
+		;
+
+multiplicative_expression:
+		cast_expression
+		| multiplicative_expression '*' cast_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mul),$1,$3); }
+		| multiplicative_expression '/' cast_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Div),$1,$3); }
+		| multiplicative_expression '%' cast_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mod),$1,$3); }
+		;
+
+additive_expression:
+		multiplicative_expression
+		| additive_expression '+' multiplicative_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Plus),$1,$3); }
+		| additive_expression '-' multiplicative_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Minus),$1,$3); }
+		;
+
+shift_expression:
+		additive_expression
+		| shift_expression LS additive_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LShift),$1,$3); }
+		| shift_expression RS additive_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::RShift),$1,$3); }
+		;
+
+relational_expression:
+		shift_expression
+		| relational_expression '<' shift_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LThan),$1,$3); }
+		| relational_expression '>' shift_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GThan),$1,$3); }
+		| relational_expression LE shift_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LEThan),$1,$3); }
+		| relational_expression GE shift_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GEThan),$1,$3); }
+		;
+
+equality_expression:
+		relational_expression
+		| equality_expression EQ relational_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Eq), $1, $3); }
+		| equality_expression NE relational_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neq), $1, $3); }
+		;
+
+AND_expression:
+		equality_expression
+		| AND_expression '&' equality_expression
+				{ $$ =new CompositeExprNode(new OperatorNode(OperatorNode::BitAnd), $1, $3); }
+		;
+
+exclusive_OR_expression:
+		AND_expression
+		| exclusive_OR_expression '^' AND_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Xor), $1, $3); }
+		;
+
+inclusive_OR_expression:
+		exclusive_OR_expression
+		| inclusive_OR_expression '|' exclusive_OR_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::BitOr), $1, $3); }
+		;
+
+logical_AND_expression:
+		inclusive_OR_expression
+		| logical_AND_expression ANDAND inclusive_OR_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::And), $1, $3); }
+		;
+
+logical_OR_expression:
+		logical_AND_expression
+		| logical_OR_expression OROR logical_AND_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Or), $1, $3); }
+		;
+
+conditional_expression:
+		logical_OR_expression
+		| logical_OR_expression '?' comma_expression ':' conditional_expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond), (ExpressionNode *)mkList((*$1,*$3,*$5))); }
+		| logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
+				{ $$=new CompositeExprNode(new OperatorNode(OperatorNode::NCond),$1,$4); }
+		| logical_OR_expression '?' comma_expression ':' tuple // CFA, tuple expression
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond), (ExpressionNode *)mkList(( *$1, *$3, *$5 ))); }
+		;
+
+constant_expression:
+		conditional_expression
+		;
+
+assignment_expression:
+				// CFA, assignment is separated from assignment_operator to ensure no assignment operations
+				// for tuples
+		conditional_expression
+		| unary_expression '=' assignment_expression
+				{ $$ =new CompositeExprNode(new OperatorNode(OperatorNode::Assign), $1, $3); }
+		| unary_expression assignment_operator assignment_expression
+				{ $$ =new CompositeExprNode($2, $1, $3); }
+		| tuple assignment_opt							// CFA, tuple expression
+				{ $$ = ($2 == 0) ? $1 : new CompositeExprNode( new OperatorNode( OperatorNode::Assign ), $1, $2 ); }
+		;
+
+assignment_expression_opt:
+		// empty
+				{ $$ = new NullExprNode; }
+		| assignment_expression
+		;
+
+tuple:													// CFA, tuple
+				// CFA, one assignment_expression is factored out of comma_expression to eliminate a
+				// shift/reduce conflict with comma_expression in new_identifier_parameter_array and
+				// new_abstract_array
+		'[' push pop ']'
+				{ $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ) ); }
+		| '[' push assignment_expression pop ']'
+				{ $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), $3 ); }
+		| '[' push ',' tuple_expression_list pop ']'
+				{ $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(new NullExprNode)->set_link( $4 ) ); }
+		| '[' push assignment_expression ',' tuple_expression_list pop ']'
+				{ $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 ) ) ); }
+		;
+
+tuple_expression_list:
+		assignment_expression_opt
+		| tuple_expression_list ',' assignment_expression_opt
+				{ $$ = (ExpressionNode *)$1->set_link( $3 ); }
+		;
+
+assignment_operator:
+		MULTassign										{ $$ = new OperatorNode(OperatorNode::MulAssn); }
+		| DIVassign										{ $$ = new OperatorNode(OperatorNode::DivAssn); }
+		| MODassign										{ $$ = new OperatorNode(OperatorNode::ModAssn); }
+		| PLUSassign									{ $$ = new OperatorNode(OperatorNode::PlusAssn); }
+		| MINUSassign									{ $$ = new OperatorNode(OperatorNode::MinusAssn); }
+		| LSassign										{ $$ = new OperatorNode(OperatorNode::LSAssn); }
+		| RSassign										{ $$ = new OperatorNode(OperatorNode::RSAssn); }
+		| ANDassign										{ $$ = new OperatorNode(OperatorNode::AndAssn); }
+		| ERassign										{ $$ = new OperatorNode(OperatorNode::ERAssn); }
+		| ORassign										{ $$ = new OperatorNode(OperatorNode::OrAssn); }
+		;
+
+comma_expression:
+		assignment_expression
+		| comma_expression ',' assignment_expression	// { $$ = (ExpressionNode *)$1->add_to_list($3); }
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Comma),$1,$3); }
+		;
+
+comma_expression_opt:
+		// empty
+				{ $$ = 0; }
+		| comma_expression
+		;
+
+//*************************** STATEMENTS *******************************
+
+statement:
+		labeled_statement
+		| compound_statement
+		| expression_statement							{ $$ = $1; }
+		| selection_statement
+		| iteration_statement
+		| jump_statement
+		| exception_statement
+		| asm_statement
+		;
+
+labeled_statement:
+		no_attr_identifier ':' attribute_list_opt statement
+				{ $$ = $4->add_label($1);}
+		;
+
+compound_statement:
+		'{' '}'
+				{ $$ = new CompoundStmtNode( (StatementNode *)0 ); }
+		| '{'
+				// Two scopes are necessary because the block itself has a scope, but every declaration within
+				// the block also requires its own scope
+		  push push
+		  label_declaration_opt							// GCC, local labels
+		  block_item_list pop '}'						// C99, intermix declarations and statements
+				{ $$ = new CompoundStmtNode( $5 ); }
+		;
+
+block_item_list:										// C99
+		block_item
+		| block_item_list push block_item
+				{ if ($1 != 0) { $1->set_link($3); $$ = $1; } }
+		;
+
+block_item:
+		declaration										// CFA, new & old style declarations
+				{ $$ = new StatementNode( $1 ); }
+		| EXTENSION declaration							// GCC
+				{ $$ = new StatementNode( $2 ); }
+		| statement pop
+		;
+
+statement_list:
+		statement
+		| statement_list statement
+				{ if ($1 != 0) { $1->set_link($2); $$ = $1; } }
+		;
+
+expression_statement:
+		comma_expression_opt ';'
+				{ $$ = new StatementNode(StatementNode::Exp, $1, 0); }
+		;
+
+selection_statement:
+		IF '(' comma_expression ')' statement				%prec THEN
+				// explicitly deal with the shift/reduce conflict on if/else
+				{ $$ = new StatementNode(StatementNode::If, $3, $5); }
+		| IF '(' comma_expression ')' statement ELSE statement
+				{ $$ = new StatementNode(StatementNode::If, $3, (StatementNode *)mkList((*$5, *$7)) ); }
+		| SWITCH '(' comma_expression ')' case_clause	// CFA
+				{ $$ = new StatementNode(StatementNode::Switch, $3, $5); }
+		| SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
+				{ $$ = new StatementNode(StatementNode::Switch, $3, $8); /* xxx */ }
+				// The semantics of the declaration list is changed to include any associated initialization,
+				// which is performed *before* the transfer to the appropriate case clause.  Statements after
+				// the initial declaration list can never be executed, and therefore, are removed from the
+				// grammar even though C allows it.
+		| CHOOSE '(' comma_expression ')' case_clause	// CFA
+				{ $$ = new StatementNode(StatementNode::Choose, $3, $5); }
+		| CHOOSE '(' comma_expression ')' '{' push declaration_list_opt choose_clause_list_opt '}' // CFA
+				{ $$ = new StatementNode(StatementNode::Choose, $3, $8); }
+		;
+
+// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a
+// case clause allows a list of values and subranges.
+
+case_value:												// CFA
+		constant_expression								{ $$ = $1; }
+		| constant_expression ELLIPSIS constant_expression // GCC, subrange
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range),$1,$3); }
+		| subrange										// CFA, subrange
+		;
+
+case_value_list:										// CFA
+		case_value
+		| case_value_list ',' case_value
+				{ $$ = new CompositeExprNode(new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(tupleContents($1))->set_link($3) ); }
+		;
+
+case_label:												// CFA
+		CASE case_value_list ':'						{ $$ = new StatementNode(StatementNode::Case, $2, 0); }
+		| DEFAULT ':'								    { $$ = new StatementNode(StatementNode::Default); }
+				// A semantic check is required to ensure only one default clause per switch/choose statement.
+		;
+
+case_label_list:										// CFA
+		case_label
+		| case_label_list case_label					{ $$ = (StatementNode *)($1->set_link($2)); }
+		;
+
+case_clause:											// CFA
+		case_label_list statement						{ $$ = $1->append_last_case($2); }
+		;
+
+switch_clause_list_opt:									// CFA
+		// empty
+				{ $$ = 0; }
+		| switch_clause_list
+		;
+
+switch_clause_list:										// CFA
+		case_label_list statement_list
+				{ $$ = $1->append_last_case($2); }
+		| switch_clause_list case_label_list statement_list
+				{ $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
+		;
+
+choose_clause_list_opt:									// CFA
+		// empty
+				{ $$ = 0; }
+		| choose_clause_list
+		;
+
+choose_clause_list:										// CFA
+		case_label_list fall_through
+				{ $$ = $1->append_last_case($2); }
+		| case_label_list statement_list fall_through_opt
+				{ $$ = $1->append_last_case((StatementNode *)mkList((*$2,*$3))); }
+		| choose_clause_list case_label_list fall_through
+				{ $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
+		| choose_clause_list case_label_list statement_list fall_through_opt
+				{ $$ = (StatementNode *)($1->set_link($2->append_last_case((StatementNode *)mkList((*$3,*$4))))); }
+		;
+
+fall_through_opt:										// CFA
+		// empty
+				{ $$ = 0; }
+		| fall_through
+		;
+
+fall_through:											// CFA
+		FALLTHRU										{ $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
+		| FALLTHRU ';'									{ $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
+		;
+
+iteration_statement:
+		WHILE '(' comma_expression ')' statement
+				{ $$ = new StatementNode(StatementNode::While, $3, $5); }
+		| DO statement WHILE '(' comma_expression ')' ';'
+				{ $$ = new StatementNode(StatementNode::Do, $5, $2); }
+		| FOR '(' push for_control_expression ')' statement
+				{ $$ = new StatementNode(StatementNode::For, $4, $6); }
+		;
+
+for_control_expression:
+		comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
+				{ $$ = new ForCtlExprNode($1, $4, $6); }
+		| declaration comma_expression_opt ';' comma_expression_opt // C99
+				// Like C++, the loop index can be declared local to the loop.
+				{ $$ = new ForCtlExprNode($1, $2, $4); }
+		;
+
+jump_statement:
+		GOTO no_attr_identifier ';'
+				{ $$ = new StatementNode(StatementNode::Goto, $2); }
+		| GOTO '*' comma_expression ';'				// GCC, computed goto
+				// The syntax for the GCC computed goto violates normal expression precedence, e.g., goto
+				// *i+3; => goto *(i+3); whereas normal operator precedence yields goto (*i)+3;
+				{ $$ = new StatementNode(StatementNode::Goto, $3); }
+		| CONTINUE ';'
+				// A semantic check is required to ensure this statement appears only in the body of an
+				// iteration statement.
+				{ $$ = new StatementNode(StatementNode::Continue, 0, 0); }
+		| CONTINUE no_attr_identifier ';'		// CFA, multi-level continue
+				// A semantic check is required to ensure this statement appears only in the body of an
+				// iteration statement, and the target of the transfer appears only at the start of an
+				// iteration statement.
+				{ $$ = new StatementNode(StatementNode::Continue, $2); }
+		| BREAK ';'
+				// A semantic check is required to ensure this statement appears only in the body of an
+				// iteration statement.
+				{ $$ = new StatementNode(StatementNode::Break, 0, 0); }
+		| BREAK no_attr_identifier ';'				// CFA, multi-level exit
+				// A semantic check is required to ensure this statement appears only in the body of an
+				// iteration statement, and the target of the transfer appears only at the start of an
+				// iteration statement.
+				{ $$ = new StatementNode(StatementNode::Break, $2 ); }
+		| RETURN comma_expression_opt ';'
+				{ $$ = new StatementNode(StatementNode::Return, $2, 0); }
+		| THROW assignment_expression ';'
+				{ $$ = new StatementNode(StatementNode::Throw, $2, 0); }
+		| THROW ';'
+				{ $$ = new StatementNode(StatementNode::Throw, 0, 0); }
+		;
+
+exception_statement:
+		TRY compound_statement handler_list
+				{ $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
+		| TRY compound_statement finally_clause
+				{ $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
+		| TRY compound_statement handler_list finally_clause
+				{ 
+					$3->set_link($4);
+					$$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3))));
+				}
+		;
+
+handler_list:
+				// There must be at least one catch clause
+		handler_clause
+				// ISO/IEC 9899:1999 Section 15.3(6) If present, a "..." handler shall be the last handler for
+				// its try block.
+		| CATCH '(' ELLIPSIS ')' compound_statement
+				{ $$ = StatementNode::newCatchStmt( 0, $5, true ); }
+		| handler_clause CATCH '(' ELLIPSIS ')' compound_statement
+				{ $$ = $1->set_link( StatementNode::newCatchStmt( 0, $6, true ) ); }
+		;
+
+handler_clause:
+		CATCH '(' push push exception_declaration pop ')' compound_statement pop
+				{ $$ = StatementNode::newCatchStmt($5, $8); }
+		| handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
+				{ $$ = $1->set_link( StatementNode::newCatchStmt($6, $9) ); }
+		;
+
+finally_clause:
+		FINALLY compound_statement
+				{ $$ = new StatementNode(StatementNode::Finally, 0, $2);
+					std::cout << "Just created a finally node" << std::endl;
+				}
+		;
+
+exception_declaration:
+				// A semantic check is required to ensure type_specifier does not create a new type, e.g.:
+				//
+				//		catch ( struct { int i; } x ) ...
+				//
+				// This new type cannot catch any thrown type because of name equivalence among types.
+		type_specifier
+		| type_specifier declarator
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $2->addType( $1 );
+				}
+		| type_specifier variable_abstract_declarator
+				{ $$ = $2->addType( $1 ); }
+		| new_abstract_declarator_tuple no_attr_identifier // CFA
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $1->addName( $2 );
+				}
+		| new_abstract_declarator_tuple					// CFA
+		;
+
+asm_statement:
+		ASM type_qualifier_list_opt '(' constant_expression ')' ';'
+				{ $$ = new StatementNode(StatementNode::Asm, 0, 0); }
+		| ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ')' ';' // remaining GCC
+				{ $$ = new StatementNode(StatementNode::Asm, 0, 0); }
+		| ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ')' ';'
+				{ $$ = new StatementNode(StatementNode::Asm, 0, 0); }
+		| ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ':'
+						asm_clobbers_list ')' ';'
+				{ $$ = new StatementNode(StatementNode::Asm, 0, 0); }
+		;
+
+asm_operands_opt:										// GCC
+		// empty
+		| asm_operands_list
+		;
+
+asm_operands_list:										// GCC
+		asm_operand
+		| asm_operands_list ',' asm_operand
+		;
+
+asm_operand:											// GCC
+		STRINGliteral '(' constant_expression ')'		{}
+		;
+
+asm_clobbers_list:										// GCC
+		STRINGliteral									{}
+		| asm_clobbers_list ',' STRINGliteral
+		;
+
+//******************************* DECLARATIONS *********************************
+
+declaration_list_opt:									// used at beginning of switch statement
+		pop
+				{ $$ = 0; }
+		| declaration_list
+		;
+
+declaration_list:
+		declaration
+		| declaration_list push declaration
+				{ $$ = $1->appendList( $3 ); }
+		;
+
+old_declaration_list_opt:								// used to declare parameter types in K&R style functions
+		pop
+				{ $$ = 0; }
+		| old_declaration_list
+		;
+
+old_declaration_list:
+		old_declaration
+		| old_declaration_list push old_declaration
+				{ $$ = $1->appendList( $3 ); }
+		;
+
+label_declaration_opt:									// GCC, local label
+		// empty
+		| label_declaration_list
+		;
+
+label_declaration_list:									// GCC, local label
+		LABEL label_list ';'
+		| label_declaration_list LABEL label_list ';'
+		;
+
+label_list:												// GCC, local label
+		no_attr_identifier_or_typedef_name				{}
+		| label_list ',' no_attr_identifier_or_typedef_name {}
+		;
+
+declaration:											// CFA, new & old style declarations
+		new_declaration
+		| old_declaration
+		;
+
+// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and
+// function declarations. CFA declarations use the same declaration tokens as in C; however, CFA places
+// declaration modifiers to the left of the base type, while C declarations place modifiers to the right of
+// the base type. CFA declaration modifiers are interpreted from left to right and the entire type
+// specification is distributed across all variables in the declaration list (as in Pascal).  ANSI C and the
+// new CFA declarations may appear together in the same program block, but cannot be mixed within a specific
+// declaration.
+//
+//			CFA					C
+//		[10] int x;			int x[10];		// array of 10 integers
+//		[10] * char y;		char *y[10];	// array of 10 pointers to char
+
+new_declaration:										// CFA
+		new_variable_declaration pop ';'
+		| new_typedef_declaration pop ';'
+		| new_function_declaration pop ';'
+		| type_declaring_list pop ';'
+		| context_specifier pop ';'
+		;
+
+new_variable_declaration:								// CFA
+		new_variable_specifier initializer_opt
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $1;
+				}
+		| declaration_qualifier_list new_variable_specifier initializer_opt
+				// declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
+				// necessary to preclude them as a type_qualifier cannot appear in that context.
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $2->addQualifiers( $1 );
+				}
+		| new_variable_declaration pop ',' push identifier_or_typedef_name initializer_opt
+				{
+					typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
+					$$ = $1->appendList( $1->cloneType( $5 ) );
+				}
+		;
+
+new_variable_specifier:									// CFA
+				// A semantic check is required to ensure asm_name only appears on declarations with implicit
+				// or explicit static storage-class
+		new_abstract_declarator_no_tuple identifier_or_typedef_name asm_name_opt
+				{
+					typedefTable.setNextIdentifier( *$2 );
+					$$ = $1->addName( $2 );
+				}
+		| new_abstract_tuple identifier_or_typedef_name asm_name_opt
+				{
+					typedefTable.setNextIdentifier( *$2 );
+					$$ = $1->addName( $2 );
+				}
+		| type_qualifier_list new_abstract_tuple identifier_or_typedef_name asm_name_opt
+				{
+					typedefTable.setNextIdentifier( *$3 );
+					$$ = $2->addQualifiers( $1 )->addName( $3 );
+				}
+		;
+
+new_function_declaration:								// CFA
+		new_function_specifier
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $1;
+				}
+		| declaration_qualifier_list new_function_specifier
+				// declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
+				// necessary to preclude them as a type_qualifier cannot appear in this context.
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $2->addQualifiers( $1 );
+				}
+		| new_function_declaration pop ',' push identifier_or_typedef_name
+				{
+					typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
+					$$ = $1->appendList( $1->cloneType( $5 ) );
+				}
+		;
+
+new_function_specifier:									// CFA
+		'[' push pop ']' identifier '(' push new_parameter_type_list_opt pop ')'
+				{
+					typedefTable.setNextIdentifier( *($5) );
+					$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
+				}
+		| '[' push pop ']' TYPEDEFname '(' push new_parameter_type_list_opt pop ')'
+				{
+					typedefTable.setNextIdentifier( *($5) );
+					$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
+				}
+				// identifier_or_typedef_name must be broken apart because of the sequence:
+				//
+				//   '[' ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
+				//   '[' ']' type_specifier
+				//
+				// type_specifier can resolve to just TYPEDEFname (e.g. typedef int T; int f( T );). Therefore
+				// this must be flattened to allow lookahead to the '(' without having to reduce
+				// identifier_or_typedef_name.
+		| new_abstract_tuple identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
+				// To obtain LR(1), this rule must be factored out from function return type (see
+				//   new_abstract_declarator).
+				{
+					$$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
+				}
+		| new_function_return identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
+				{
+					$$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
+				}
+		;
+
+new_function_return:									// CFA
+		'[' push new_parameter_list pop ']'
+				{ $$ = DeclarationNode::newTuple( $3 ); }
+		| '[' push new_parameter_list pop ',' push new_abstract_parameter_list pop ']'
+				// To obtain LR(1), the last new_abstract_parameter_list is added into this flattened rule to
+				// lookahead to the ']'.
+				{ $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
+		;
+
+new_typedef_declaration:								// CFA
+		TYPEDEF new_variable_specifier
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $2->addTypedef();
+				}
+		| TYPEDEF new_function_specifier
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $2->addTypedef();
+				}
+		| new_typedef_declaration pop ',' push no_attr_identifier
+				{
+					typedefTable.addToEnclosingScope( *$5, TypedefTable::TD);
+					$$ = $1->appendList( $1->cloneType( $5 ) );
+				}
+		;
+
+// Traditionally typedef is part of storage-class specifier for syntactic convenience only. Here, it is
+// factored out as a separate form of declaration, which syntactically precludes storage-class specifiers and
+// initialization.
+
+typedef_declaration:
+		TYPEDEF type_specifier declarator
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $3->addType( $2 )->addTypedef();
+				}
+		| typedef_declaration pop ',' push declarator
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
+				}
+		| type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2)
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
+				}
+		| type_specifier TYPEDEF declarator
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $3->addType( $1 )->addTypedef();
+				}
+		| type_specifier TYPEDEF type_qualifier_list declarator
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::TD);
+					$$ = $4->addQualifiers($1)->addTypedef()->addType($1);
+				}
+		;
+
+typedef_expression:										// GCC, naming expression type
+		TYPEDEF no_attr_identifier '=' assignment_expression
+				{
+					typedefTable.addToEnclosingScope(*($2), TypedefTable::TD);
+					$$ = DeclarationNode::newName( 0 ); // XXX
+				}
+		| typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
+				{
+					typedefTable.addToEnclosingScope(*($5), TypedefTable::TD);
+					$$ = DeclarationNode::newName( 0 ); // XXX
+				}
+		;
+
+old_declaration:
+		declaring_list pop ';'
+		| typedef_declaration pop ';'
+		| typedef_expression pop ';'					// GCC, naming expression type
+		| sue_declaration_specifier pop ';'
+		;
+
+declaring_list:
+				// A semantic check is required to ensure asm_name only appears on declarations with implicit
+				// or explicit static storage-class
+		declaration_specifier declarator asm_name_opt initializer_opt
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = ($2->addType( $1 ))->addInitializer($4);
+				}
+		| declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $1->appendList( $1->cloneBaseType( $4->addInitializer($6) ) );
+				}
+		;
+
+declaration_specifier:									// type specifier + storage class
+		basic_declaration_specifier
+		| sue_declaration_specifier
+		| typedef_declaration_specifier
+		| typegen_declaration_specifier
+		;
+
+type_specifier:											// declaration specifier - storage class
+		basic_type_specifier
+		| sue_type_specifier
+		| typedef_type_specifier
+		| typegen_type_specifier
+		;
+
+type_qualifier_list_opt:								// GCC, used in asm_statement
+		// empty
+				{ $$ = 0; }
+		| type_qualifier_list
+		;
+
+type_qualifier_list:
+				// A semantic check is necessary to ensure a type qualifier is appropriate for the kind of
+				// declaration.
+				//
+				// ISO/IEC 9899:1999 Section 6.7.3(4) : If the same qualifier appears more than once in the
+				// same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is
+				// the same as if it appeared only once.
+		type_qualifier
+		| type_qualifier_list type_qualifier
+				{ $$ = $1->addQualifiers( $2 ); }
+		;
+
+type_qualifier:
+		type_qualifier_name
+		| attribute
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); }
+		;
+
+type_qualifier_name:
+		CONST
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }
+		| RESTRICT
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
+		| VOLATILE
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
+		| LVALUE										// CFA
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
+		| ATOMIC
+				{ $$ = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }
+		| FORALL '('
+				{
+					typedefTable.enterScope();
+				}
+		  type_parameter_list ')'						// CFA
+				{
+					typedefTable.leaveScope();
+					$$ = DeclarationNode::newForall( $4 );
+				}
+		;
+
+declaration_qualifier_list:
+		storage_class_list
+		| type_qualifier_list storage_class_list		// remaining OBSOLESCENT (see 2)
+				{ $$ = $1->addQualifiers( $2 ); }
+		| declaration_qualifier_list type_qualifier_list storage_class_list
+				{ $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
+		;
+
+storage_class_list:
+				// A semantic check is necessary to ensure a storage class is appropriate for the kind of
+				// declaration and that only one of each is specified, except for inline, which can appear
+				// with the others.
+				//
+				// ISO/IEC 9899:1999 Section 6.7.1(2) : At most, one storage-class specifier may be given in
+				// the declaration specifiers in a declaration.
+		storage_class
+		| storage_class_list storage_class
+				{ $$ = $1->addQualifiers( $2 ); }
+		;
+
+storage_class:
+		storage_class_name
+		;
+
+storage_class_name:
+		EXTERN
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
+		| STATIC
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
+		| AUTO
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
+		| REGISTER
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
+		| INLINE										// C99
+				// INLINE is essentially a storage class specifier for functions, and hence, belongs here.
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }
+		| FORTRAN										// C99
+				{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Fortran ); }
+		;
+
+basic_type_name:
+		CHAR
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
+		| DOUBLE
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
+		| FLOAT
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
+		| INT
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
+		| LONG
+				{ $$ = DeclarationNode::newModifier( DeclarationNode::Long ); }
+		| SHORT
+				{ $$ = DeclarationNode::newModifier( DeclarationNode::Short ); }
+		| SIGNED
+				{ $$ = DeclarationNode::newModifier( DeclarationNode::Signed ); }
+		| UNSIGNED
+				{ $$ = DeclarationNode::newModifier( DeclarationNode::Unsigned ); }
+		| VOID
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
+		| BOOL											// C99
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
+		| COMPLEX										// C99
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }
+		| IMAGINARY										// C99
+				{ $$ = DeclarationNode::newBasicType( DeclarationNode::Imaginary ); }
+		;
+
+basic_declaration_specifier:
+				// A semantic check is necessary for conflicting storage classes.
+		basic_type_specifier
+		| declaration_qualifier_list basic_type_specifier
+				{ $$ = $2->addQualifiers( $1 ); }
+		| basic_declaration_specifier storage_class		// remaining OBSOLESCENT (see 2)
+				{ $$ = $1->addQualifiers( $2 ); }
+		| basic_declaration_specifier storage_class type_qualifier_list
+				{ $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
+		| basic_declaration_specifier storage_class basic_type_specifier
+				{ $$ = $3->addQualifiers( $2 )->addType( $1 ); }
+		;
+
+basic_type_specifier:
+		direct_type_name
+		| type_qualifier_list_opt indirect_type_name type_qualifier_list_opt
+				{ $$ = $2->addQualifiers( $1 )->addQualifiers( $3 ); }
+		;
+
+direct_type_name:
+				// A semantic check is necessary for conflicting type qualifiers.
+		basic_type_name
+		| type_qualifier_list basic_type_name
+				{ $$ = $2->addQualifiers( $1 ); }
+		| direct_type_name type_qualifier
+				{ $$ = $1->addQualifiers( $2 ); }
+		| direct_type_name basic_type_name
+				{ $$ = $1->addType( $2 ); }
+		;
+
+indirect_type_name:
+		TYPEOF '(' type_name ')'						// GCC: typeof(x) y;
+				{ $$ = $3; }
+		| TYPEOF '(' comma_expression ')'				// GCC: typeof(a+b) y;
+				{ $$ = DeclarationNode::newTypeof( $3 ); }
+		| ATTR_TYPEGENname '(' type_name ')'			// CFA: e.g., @type(x) y;
+				{ $$ = DeclarationNode::newAttr( $1, $3 ); }
+		| ATTR_TYPEGENname '(' comma_expression ')'		// CFA: e.g., @type(a+b) y;
+				{ $$ = DeclarationNode::newAttr( $1, $3 ); }
+		;
+
+sue_declaration_specifier:
+		sue_type_specifier
+		| declaration_qualifier_list sue_type_specifier
+				{ $$ = $2->addQualifiers( $1 ); }
+		| sue_declaration_specifier storage_class		// remaining OBSOLESCENT (see 2)
+				{ $$ = $1->addQualifiers( $2 ); }
+		| sue_declaration_specifier storage_class type_qualifier_list
+				{ $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
+		;
+
+sue_type_specifier:
+		elaborated_type_name							// struct, union, enum
+		| type_qualifier_list elaborated_type_name
+				{ $$ = $2->addQualifiers( $1 ); }
+		| sue_type_specifier type_qualifier
+				{ $$ = $1->addQualifiers( $2 ); }
+		;
+
+typedef_declaration_specifier:
+		typedef_type_specifier
+		| declaration_qualifier_list typedef_type_specifier
+				{ $$ = $2->addQualifiers( $1 ); }
+		| typedef_declaration_specifier storage_class	// remaining OBSOLESCENT (see 2)
+				{ $$ = $1->addQualifiers( $2 ); }
+		| typedef_declaration_specifier storage_class type_qualifier_list
+				{ $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
+		;
+
+typedef_type_specifier:									// typedef types
+		TYPEDEFname
+				{ $$ = DeclarationNode::newFromTypedef( $1 ); }
+		| type_qualifier_list TYPEDEFname
+				{ $$ = DeclarationNode::newFromTypedef( $2 )->addQualifiers( $1 ); }
+		| typedef_type_specifier type_qualifier
+				{ $$ = $1->addQualifiers( $2 ); }
+		;
+
+elaborated_type_name:
+		aggregate_name
+		| enum_name
+		;
+
+aggregate_name:
+		aggregate_key '{' field_declaration_list '}'
+				{ $$ = DeclarationNode::newAggregate( $1, 0, 0, 0, $3 ); }
+		| aggregate_key no_attr_identifier_or_typedef_name
+				{ $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, 0 ); }
+		| aggregate_key no_attr_identifier_or_typedef_name '{' field_declaration_list '}'
+				{ $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, $4 ); }
+		| aggregate_key '(' push type_parameter_list pop ')' '{' field_declaration_list '}' // CFA
+				{ $$ = DeclarationNode::newAggregate( $1, 0, $4, 0, $8 ); }
+		| aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name // CFA
+				{ $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, 0 ); }
+		| aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
+				{ $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, $9 ); }
+		| aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' '{' field_declaration_list '}' // CFA
+				{ $$ = DeclarationNode::newAggregate( $1, 0, $4, $8, $11 ); }
+		| aggregate_key '(' push type_name_list pop ')' no_attr_identifier_or_typedef_name // CFA
+				// push and pop are only to prevent S/R conflicts
+				{ $$ = DeclarationNode::newAggregate( $1, $7, 0, $4, 0 ); }
+		| aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
+				{ $$ = DeclarationNode::newAggregate( $1, $10, $4, $8, $12 ); }
+		;
+
+aggregate_key:
+		STRUCT attribute_list_opt
+				{ $$ = DeclarationNode::Struct; }
+		| UNION attribute_list_opt
+				{ $$ = DeclarationNode::Union; }
+		;
+
+field_declaration_list:
+		field_declaration
+				{ $$ = $1; }
+		| field_declaration_list field_declaration
+				{ $$ = $1->appendList( $2 ); }
+		;
+
+field_declaration:
+		new_field_declaring_list ';'					// CFA, new style field declaration
+		| EXTENSION new_field_declaring_list ';'		// GCC
+				{ $$ = $2; }
+		| field_declaring_list ';'
+		| EXTENSION field_declaring_list ';'			// GCC
+				{ $$ = $2; }
+		;
+
+new_field_declaring_list:								// CFA, new style field declaration
+		new_abstract_declarator_tuple					// CFA, no field name
+		| new_abstract_declarator_tuple no_attr_identifier_or_typedef_name
+				{ $$ = $1->addName( $2 ); }
+		| new_field_declaring_list ',' no_attr_identifier_or_typedef_name
+				{ $$ = $1->appendList( $1->cloneType( $3 ) ); }
+		| new_field_declaring_list ','					// CFA, no field name
+				{ $$ = $1->appendList( $1->cloneType( 0 ) ); }
+		;
+
+field_declaring_list:
+		type_specifier field_declarator
+				{ $$ = $2->addType( $1 ); }
+		| field_declaring_list ',' attribute_list_opt field_declarator
+				{ $$ = $1->appendList( $1->cloneBaseType( $4 ) ); }
+		;
+
+field_declarator:
+		// empty
+				{ $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
+		| bit_subrange_size								// no field name
+				{ $$ = DeclarationNode::newBitfield( $1 ); }
+		| variable_declarator bit_subrange_size_opt
+				// A semantic check is required to ensure bit_subrange only appears on base type int.
+				{ $$ = $1->addBitfield( $2 ); }
+		| typedef_redeclarator bit_subrange_size_opt
+				// A semantic check is required to ensure bit_subrange only appears on base type int.
+				{ $$ = $1->addBitfield( $2 ); }
+		| variable_abstract_declarator					// CFA, no field name
+		;
+
+bit_subrange_size_opt:
+		// empty
+				{ $$ = 0; }
+		| bit_subrange_size
+				{ $$ = $1; }
+		;
+
+bit_subrange_size:
+		':' constant_expression
+				{ $$ = $2; }
+		;
+
+enum_key:
+		ENUM attribute_list_opt
+		;
+
+enum_name:
+		enum_key '{' enumerator_list comma_opt '}'
+				{ $$ = DeclarationNode::newEnum( 0, $3 ); }
+		| enum_key no_attr_identifier_or_typedef_name '{' enumerator_list comma_opt '}'
+				{ $$ = DeclarationNode::newEnum( $2, $4 ); }
+		| enum_key no_attr_identifier_or_typedef_name
+				{ $$ = DeclarationNode::newEnum( $2, 0 ); }
+		;
+
+enumerator_list:
+		no_attr_identifier_or_typedef_name enumerator_value_opt
+				{ $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
+		| enumerator_list ',' no_attr_identifier_or_typedef_name enumerator_value_opt
+				{ $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
+		;
+
+enumerator_value_opt:
+		// empty
+				{ $$ = 0; }
+		| '=' constant_expression
+				{ $$ = $2; }
+		;
+
+// Minimum of one parameter after which ellipsis is allowed only at the end.
+
+new_parameter_type_list_opt:							// CFA
+		// empty
+				{ $$ = 0; }
+		| new_parameter_type_list
+		;
+
+new_parameter_type_list:								// CFA, abstract + real
+		new_abstract_parameter_list
+		| new_parameter_list
+		| new_parameter_list pop ',' push new_abstract_parameter_list
+				{ $$ = $1->appendList( $5 ); }
+		| new_abstract_parameter_list pop ',' push ELLIPSIS
+				{ $$ = $1->addVarArgs(); }
+		| new_parameter_list pop ',' push ELLIPSIS
+				{ $$ = $1->addVarArgs(); }
+		;
+
+new_parameter_list:										// CFA
+				// To obtain LR(1) between new_parameter_list and new_abstract_tuple, the last
+				// new_abstract_parameter_list is factored out from new_parameter_list, flattening the rules
+				// to get lookahead to the ']'.
+		new_parameter_declaration
+		| new_abstract_parameter_list pop ',' push new_parameter_declaration
+				{ $$ = $1->appendList( $5 ); }
+		| new_parameter_list pop ',' push new_parameter_declaration
+				{ $$ = $1->appendList( $5 ); }
+		| new_parameter_list pop ',' push new_abstract_parameter_list pop ',' push new_parameter_declaration
+				{ $$ = $1->appendList( $5 )->appendList( $9 ); }
+		;
+
+new_abstract_parameter_list:							// CFA, new & old style abstract
+		new_abstract_parameter_declaration
+		| new_abstract_parameter_list pop ',' push new_abstract_parameter_declaration
+				{ $$ = $1->appendList( $5 ); }
+		;
+
+parameter_type_list_opt:
+		// empty
+				{ $$ = 0; }
+		| parameter_type_list
+		;
+
+parameter_type_list:
+		parameter_list
+		| parameter_list pop ',' push ELLIPSIS
+				{ $$ = $1->addVarArgs(); }
+		;
+
+parameter_list:											// abstract + real
+		abstract_parameter_declaration
+		| parameter_declaration
+		| parameter_list pop ',' push abstract_parameter_declaration
+				{ $$ = $1->appendList( $5 ); }
+		| parameter_list pop ',' push parameter_declaration
+				{ $$ = $1->appendList( $5 ); }
+		;
+
+// Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different
+// semantics for typedef name by using typedef_parameter_redeclarator instead of typedef_redeclarator, and
+// function prototypes.
+
+new_parameter_declaration:								// CFA, new & old style parameter declaration
+		parameter_declaration
+		| new_identifier_parameter_declarator_no_tuple identifier_or_typedef_name assignment_opt
+				{ $$ = $1->addName( $2 ); }
+		| new_abstract_tuple identifier_or_typedef_name assignment_opt
+				// To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
+				{ $$ = $1->addName( $2 ); }
+		| type_qualifier_list new_abstract_tuple identifier_or_typedef_name assignment_opt
+				{ $$ = $2->addName( $3 )->addQualifiers( $1 ); }
+		| new_function_specifier
+		;
+
+new_abstract_parameter_declaration:						// CFA, new & old style parameter declaration
+		abstract_parameter_declaration
+		| new_identifier_parameter_declarator_no_tuple
+		| new_abstract_tuple
+				// To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
+		| type_qualifier_list new_abstract_tuple
+				{ $$ = $2->addQualifiers( $1 ); }
+		| new_abstract_function
+		;
+
+parameter_declaration:
+		declaration_specifier identifier_parameter_declarator assignment_opt
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
+				}
+		| declaration_specifier typedef_parameter_redeclarator assignment_opt
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					$$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
+				}
+		;
+
+abstract_parameter_declaration:
+		declaration_specifier
+		| declaration_specifier abstract_parameter_declarator
+				{ $$ = $2->addType( $1 ); }
+		;
+
+// ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
+// parameter." Because the scope of the K&R-style parameter-list sees the typedef first, the following is
+// based only on identifiers.  The ANSI-style parameter-list can redefine a typedef name.
+
+identifier_list:										// K&R-style parameter list => no types
+		no_attr_identifier
+				{ $$ = DeclarationNode::newName( $1 ); }
+		| identifier_list ',' no_attr_identifier
+				{ $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
+		;
+
+identifier_or_typedef_name:
+		identifier
+		| TYPEDEFname
+		| TYPEGENname
+		;
+
+no_01_identifier_or_typedef_name:
+		no_01_identifier
+		| TYPEDEFname
+		| TYPEGENname
+		;
+
+no_attr_identifier_or_typedef_name:
+		no_attr_identifier
+		| TYPEDEFname
+		| TYPEGENname
+		;
+
+type_name_no_function:									// sizeof, alignof, cast (constructor)
+		new_abstract_declarator_tuple					// CFA
+		| type_specifier
+		| type_specifier variable_abstract_declarator
+				{ $$ = $2->addType( $1 ); }
+		;
+
+type_name:												// typeof, assertion
+		new_abstract_declarator_tuple					// CFA
+		| new_abstract_function							// CFA
+		| type_specifier
+		| type_specifier abstract_declarator
+				{ $$ = $2->addType( $1 ); }
+		;
+
+initializer_opt:
+		// empty
+				{ $$ = 0; }
+		| '=' initializer								{ $$ = $2; }
+		;
+
+initializer:
+		assignment_expression							{ $$ = new InitializerNode($1); }
+		| '{' initializer_list comma_opt '}'			{ $$ = new InitializerNode($2, true); }
+		;
+
+initializer_list:
+		initializer
+		| designation initializer						{ $$ = $2->set_designators( $1 ); }
+		| initializer_list ',' initializer				{ $$ = (InitializerNode *)( $1->set_link($3) ); }
+		| initializer_list ',' designation initializer
+				{ $$ = (InitializerNode *)( $1->set_link( $4->set_designators($3) ) ); }
+		;
+
+// There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem is
+// use of '=' to separator the designator from the initializer value, as in:
+//
+//		int x[10] = { [1] = 3 };
+//
+// The string "[1] = 3" can be parsed as a designator assignment or a tuple assignment.  To disambiguate this
+// case, CFA changes the syntax from "=" to ":" as the separator between the designator and initializer. GCC
+// does uses ":" for field selection. The optional use of the "=" in GCC, or in this case ":", cannot be
+// supported either due to shift/reduce conflicts
+
+designation:
+		designator_list ':'								// C99, CFA uses ":" instead of "="
+		| no_attr_identifier_or_typedef_name ':'		// GCC, field name
+						{ $$ = new VarRefNode( $1 ); }
+		;
+
+designator_list:										// C99
+		designator
+		| designator_list designator						{ $$ = (ExpressionNode *)($1->set_link( $2 )); }
+		;
+
+designator:
+		'.' no_attr_identifier_or_typedef_name			// C99, field name
+				{ $$ = new VarRefNode( $2 ); }
+		| '[' push assignment_expression pop ']'		// C99, single array element
+				// assignment_expression used instead of constant_expression because of shift/reduce conflicts
+				// with tuple.
+				{ $$ = $3; }
+		| '[' push subrange pop ']'						// CFA, multiple array elements
+				{ $$ = $3; }
+		| '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $3, $5); }
+		| '.' '[' push field_list pop ']'				// CFA, tuple field selector
+				{ $$ = $4; }
+		;
+
+// The CFA type system is based on parametric polymorphism, the ability to declare functions with type
+// parameters, rather than an object-oriented type system. This required four groups of extensions:
+//
+// Overloading: function, data, and operator identifiers may be overloaded.
+//
+// Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used
+//     for object and incomplete types, and "ftype" is used for function types. Type declarations with
+//     initializers provide definitions of new types. Type declarations with storage class "extern" provide
+//     opaque types.
+//
+// Polymorphic functions: A forall clause declares a type parameter. The corresponding argument is inferred at
+//     the call site. A polymorphic function is not a template; it is a function, with an address and a type.
+//
+// Specifications and Assertions: Specifications are collections of declarations parameterized by one or more
+//     types. They serve many of the purposes of abstract classes, and specification hierarchies resemble
+//     subclass hierarchies. Unlike classes, they can define relationships between types.  Assertions declare
+//     that a type or types provide the operations declared by a specification.  Assertions are normally used
+//     to declare requirements on type arguments of polymorphic functions.
+
+typegen_declaration_specifier:							// CFA
+		typegen_type_specifier
+		| declaration_qualifier_list typegen_type_specifier
+				{ $$ = $2->addQualifiers( $1 ); }
+		| typegen_declaration_specifier storage_class	// remaining OBSOLESCENT (see 2)
+				{ $$ = $1->addQualifiers( $2 ); }
+		| typegen_declaration_specifier storage_class type_qualifier_list
+				{ $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
+		;
+
+typegen_type_specifier:									// CFA
+		TYPEGENname '(' type_name_list ')'
+				{ $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
+		| type_qualifier_list TYPEGENname '(' type_name_list ')'
+				{ $$ = DeclarationNode::newFromTypeGen( $2, $4 )->addQualifiers( $1 ); }
+		| typegen_type_specifier type_qualifier
+				{ $$ = $1->addQualifiers( $2 ); }
+		;
+
+type_parameter_list:									// CFA
+		type_parameter assignment_opt
+		| type_parameter_list ',' type_parameter assignment_opt
+				{ $$ = $1->appendList( $3 ); }
+		;
+
+type_parameter:											// CFA
+		type_class no_attr_identifier_or_typedef_name
+				{ typedefTable.addToEnclosingScope(*($2), TypedefTable::TD); }
+		  assertion_list_opt
+				{ $$ = DeclarationNode::newTypeParam( $1, $2 )->addAssertions( $4 ); }
+		| type_specifier identifier_parameter_declarator
+		;
+
+type_class:												// CFA
+		TYPE
+				{ $$ = DeclarationNode::Type; }
+		| DTYPE
+				{ $$ = DeclarationNode::Ftype; }
+		| FTYPE
+				{ $$ = DeclarationNode::Dtype; }
+		;
+
+assertion_list_opt:										// CFA
+		// empty
+				{ $$ = 0; }
+		| assertion_list_opt assertion
+				{ $$ = $1 == 0 ? $2 : $1->appendList( $2 ); }
+		;
+
+assertion:												// CFA
+		'|' no_attr_identifier_or_typedef_name '(' type_name_list ')'
+				{
+					typedefTable.openContext( *($2) );
+					$$ = DeclarationNode::newContextUse( $2, $4 );
+				}
+		| '|' '{' push context_declaration_list '}'
+				{ $$ = $4; }
+		| '|' '(' push type_parameter_list pop ')' '{' push context_declaration_list '}' '(' type_name_list ')'
+				{ $$ = 0; }
+		;
+
+type_name_list:											// CFA
+		type_name
+				{ $$ = new TypeValueNode( $1 ); }
+		| assignment_expression
+		| type_name_list ',' type_name
+				{ $$ = (ExpressionNode *)($1->set_link(new TypeValueNode( $3 ))); }
+		| type_name_list ',' assignment_expression
+				{ $$ = (ExpressionNode *)($1->set_link($3)); }
+		;
+
+type_declaring_list:									// CFA
+		TYPE type_declarator
+				{ $$ = $2; }
+		| storage_class_list TYPE type_declarator
+				{ $$ = $3->addQualifiers( $1 ); }
+		| type_declaring_list ',' type_declarator
+				{ $$ = $1->appendList( $3->copyStorageClasses( $1 ) ); }
+		;
+
+type_declarator:										// CFA
+		type_declarator_name assertion_list_opt
+				{ $$ = $1->addAssertions( $2 ); }
+		| type_declarator_name assertion_list_opt '=' type_name
+				{ $$ = $1->addAssertions( $2 )->addType( $4 ); }
+		;
+
+type_declarator_name:									// CFA
+		no_attr_identifier_or_typedef_name
+				{
+					typedefTable.addToEnclosingScope(*($1), TypedefTable::TD);
+					$$ = DeclarationNode::newTypeDecl( $1, 0 );
+				}
+		| no_01_identifier_or_typedef_name '(' push type_parameter_list pop ')'
+				{
+					typedefTable.addToEnclosingScope(*($1), TypedefTable::TG);
+					$$ = DeclarationNode::newTypeDecl( $1, $4 );
+				}
+		;
+
+context_specifier:										// CFA
+		CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{' '}'
+				{
+					typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
+					$$ = DeclarationNode::newContext( $2, $5, 0 );
+				}
+		| CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{'
+				{
+					typedefTable.enterContext( *($2) );
+					typedefTable.enterScope();
+				}
+		  context_declaration_list '}'
+				{
+					typedefTable.leaveContext();
+					typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
+					$$ = DeclarationNode::newContext( $2, $5, $10 );
+				}
+		;
+
+context_declaration_list:								// CFA
+		context_declaration
+		| context_declaration_list push context_declaration
+				{ $$ = $1->appendList( $3 ); }
+		;
+
+context_declaration:									// CFA
+		new_context_declaring_list pop ';'
+		| context_declaring_list pop ';'
+		;
+
+new_context_declaring_list:								// CFA
+		new_variable_specifier
+				{
+					typedefTable.addToEnclosingScope2( TypedefTable::ID );
+					$$ = $1;
+				}
+		| new_function_specifier
+				{
+					typedefTable.addToEnclosingScope2( TypedefTable::ID );
+					$$ = $1;
+				}
+		| new_context_declaring_list pop ',' push identifier_or_typedef_name
+				{
+					typedefTable.addToEnclosingScope2( *($5), TypedefTable::ID );
+					$$ = $1->appendList( $1->cloneType( $5 ) );
+				}
+		;
+
+context_declaring_list:									// CFA
+		type_specifier declarator
+				{
+					typedefTable.addToEnclosingScope2( TypedefTable::ID );
+					$$ = $2->addType( $1 );
+				}
+		| context_declaring_list pop ',' push declarator
+				{
+					typedefTable.addToEnclosingScope2( TypedefTable::ID );
+					$$ = $1->appendList( $1->cloneBaseType( $5 ) );
+				}
+		;
+
+//***************************** EXTERNAL DEFINITIONS *****************************
+
+translation_unit:
+		// empty
+				{}										// empty input file
+		| external_definition_list
+				{
+					if ( theTree ) {
+						theTree->appendList( $1 );
+					} else {
+						theTree = $1;
+					}
+				}
+		;
+
+external_definition_list:
+		external_definition
+		| external_definition_list push external_definition
+				{ $$ = ($1 != NULL ) ? $1->appendList( $3 ) : $3; }
+		;
+
+external_definition_list_opt:
+		// empty
+				{ $$ = 0; }
+		| external_definition_list
+		;
+
+external_definition:
+		declaration
+		| function_definition
+		| asm_statement									// GCC, global assembler statement
+				{}
+		| EXTERN STRINGliteral
+				{
+					linkageStack.push( linkage );
+					linkage = LinkageSpec::fromString( *$2 );
+				}
+		  '{' external_definition_list_opt '}'			// C++-style linkage specifier
+				{
+					linkage = linkageStack.top();
+					linkageStack.pop();
+					$$ = $5;
+				}
+		| EXTENSION external_definition
+				{ $$ = $2; }
+		;
+
+function_definition:
+		new_function_specifier compound_statement		// CFA
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $1->addFunctionBody( $2 );
+				}
+		| declaration_qualifier_list new_function_specifier compound_statement // CFA
+				// declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
+				// necessary to preclude them as a type_qualifier cannot appear in this context.
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
+				}
+
+		| declaration_specifier function_declarator compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addFunctionBody( $3 )->addType( $1 );
+				}
+
+				// These rules are a concession to the "implicit int" type_specifier because there is a
+				// significant amount of code with functions missing a type-specifier on the return type.
+				// Parsing is possible because function_definition does not appear in the context of an
+				// expression (nested functions would preclude this concession). A function prototype
+				// declaration must still have a type_specifier. OBSOLESCENT (see 1)
+		| function_declarator compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $1->addFunctionBody( $2 );
+				}
+		| type_qualifier_list function_declarator compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
+				}
+		| declaration_qualifier_list function_declarator compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
+				}
+		| declaration_qualifier_list type_qualifier_list function_declarator compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $3->addFunctionBody( $4 )->addQualifiers( $2 )->addQualifiers( $1 );
+				}
+
+				// Old-style K&R function definition, OBSOLESCENT (see 4)
+		| declaration_specifier old_function_declarator push old_declaration_list_opt compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addType( $1 );
+				}
+		| old_function_declarator push old_declaration_list_opt compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $1->addOldDeclList( $3 )->addFunctionBody( $4 );
+				}
+		| type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
+				}
+
+				// Old-style K&R function definition with "implicit int" type_specifier, OBSOLESCENT (see 4)
+		| declaration_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
+				}
+		| declaration_qualifier_list type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
+				{
+					typedefTable.addToEnclosingScope( TypedefTable::ID );
+					typedefTable.leaveScope();
+					$$ = $3->addOldDeclList( $5 )->addFunctionBody( $6 )->addQualifiers( $2 )->addQualifiers( $1 );
+				}
+		;
+
+declarator:
+		variable_declarator
+		| function_declarator
+		| typedef_redeclarator
+		;
+
+subrange:
+		constant_expression '~' constant_expression		// CFA, integer subrange
+				{ $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $1, $3); }
+		;
+
+asm_name_opt:											// GCC
+		// empty
+		| ASM '(' string_literal_list ')' attribute_list_opt
+		;
+
+attribute_list_opt:										// GCC
+		// empty
+		| attribute_list
+		;
+
+attribute_list:											// GCC
+		attribute
+		| attribute_list attribute
+		;
+
+attribute:												// GCC
+		ATTRIBUTE '(' '(' attribute_parameter_list ')' ')'
+		;
+
+attribute_parameter_list:								// GCC
+		attrib
+		| attribute_parameter_list ',' attrib
+		;
+
+attrib:													// GCC
+		// empty
+		| any_word
+		| any_word '(' comma_expression_opt ')'
+		;
+
+any_word:												// GCC
+		identifier_or_typedef_name {}
+		| storage_class_name {}
+		| basic_type_name {}
+		| type_qualifier {}
+		;
+
+// ============================================================================
+// The following sections are a series of grammar patterns used to parse declarators. Multiple patterns are
+// necessary because the type of an identifier in wrapped around the identifier in the same form as its usage
+// in an expression, as in:
+//
+//		int (*f())[10] { ... };
+//		... (*f())[3] += 1;		// definition mimics usage
+//
+// Because these patterns are highly recursive, changes at a lower level in the recursion require copying some
+// or all of the pattern. Each of these patterns has some subtle variation to ensure correct syntax in a
+// particular context.
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// The set of valid declarators before a compound statement for defining a function is less than the set of
+// declarators to define a variable or function prototype, e.g.:
+//
+//		valid declaration		invalid definition
+//		-----------------		------------------
+//		int f;						int f {}
+//		int *f;						int *f {}
+//		int f[10];				int f[10] {}
+//		int (*f)(int);				int (*f)(int) {}
+//
+// To preclude this syntactic anomaly requires separating the grammar rules for variable and function
+// declarators, hence variable_declarator and function_declarator.
+// ----------------------------------------------------------------------------
+
+// This pattern parses a declaration of a variable that is not redefining a typedef name. The pattern
+// precludes declaring an array of functions versus a pointer to an array of functions.
+
+variable_declarator:
+		paren_identifier attribute_list_opt
+		| variable_ptr
+		| variable_array attribute_list_opt
+		| variable_function attribute_list_opt
+		;
+
+paren_identifier:
+		identifier
+				{
+					typedefTable.setNextIdentifier( *($1) );
+					$$ = DeclarationNode::newName( $1 );
+				}
+		| '(' paren_identifier ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+variable_ptr:
+		'*' variable_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list variable_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' variable_ptr ')'
+				{ $$ = $2; }
+		;
+
+variable_array:
+		paren_identifier array_dimension
+				{ $$ = $1->addArray( $2 ); }
+		| '(' variable_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' variable_array ')' multi_array_dimension	// redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' variable_array ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+variable_function:
+		'(' variable_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' variable_function ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses a function declarator that is not redefining a typedef name. Because functions cannot
+// be nested, there is no context where a function definition can redefine a typedef name. To allow nested
+// functions requires further separation of variable and function declarators in typedef_redeclarator.  The
+// pattern precludes returning arrays and functions versus pointers to arrays and functions.
+
+function_declarator:
+		function_no_ptr attribute_list_opt
+		| function_ptr
+		| function_array attribute_list_opt
+		;
+
+function_no_ptr:
+		paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $1->addParamList( $4 ); }
+		| '(' function_ptr ')' '(' push parameter_type_list_opt pop ')'
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' function_no_ptr ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+function_ptr:
+		'*' function_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list function_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' function_ptr ')'
+				{ $$ = $2; }
+		;
+
+function_array:
+		'(' function_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' function_array ')' multi_array_dimension	// redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' function_array ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses an old-style K&R function declarator (OBSOLESCENT, see 4) that is not redefining a
+// typedef name (see function_declarator for additional comments). The pattern precludes returning arrays and
+// functions versus pointers to arrays and functions.
+
+old_function_declarator:
+		old_function_no_ptr
+		| old_function_ptr
+		| old_function_array
+		;
+
+old_function_no_ptr:
+		paren_identifier '(' identifier_list ')'		// function_declarator handles empty parameter
+				{ $$ = $1->addIdList( $3 ); }
+		| '(' old_function_ptr ')' '(' identifier_list ')'
+				{ $$ = $2->addIdList( $5 ); }
+		| '(' old_function_no_ptr ')'					// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+old_function_ptr:
+		'*' old_function_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list old_function_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' old_function_ptr ')'
+				{ $$ = $2; }
+		;
+
+old_function_array:
+		'(' old_function_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' old_function_array ')' multi_array_dimension // redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' old_function_array ')'					// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses a declaration for a variable or function prototype that redefines a typedef name, e.g.:
+//
+//		typedef int foo;
+//		{
+//		   int foo; // redefine typedef name in new scope
+//		}
+//
+// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
+// returning arrays and functions versus pointers to arrays and functions.
+
+typedef_redeclarator:
+		paren_typedef attribute_list_opt
+		| typedef_ptr
+		| typedef_array attribute_list_opt
+		| typedef_function attribute_list_opt
+		;
+
+paren_typedef:
+		TYPEDEFname
+				{
+				typedefTable.setNextIdentifier( *($1) );
+				$$ = DeclarationNode::newName( $1 );
+				}
+		| '(' paren_typedef ')'
+				{ $$ = $2; }
+		;
+
+typedef_ptr:
+		'*' typedef_redeclarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list typedef_redeclarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' typedef_ptr ')'
+				{ $$ = $2; }
+		;
+
+typedef_array:
+		paren_typedef array_dimension
+				{ $$ = $1->addArray( $2 ); }
+		| '(' typedef_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' typedef_array ')' multi_array_dimension	// redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' typedef_array ')'							// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+typedef_function:
+		paren_typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $1->addParamList( $4 ); }
+		| '(' typedef_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' typedef_function ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses a declaration for a parameter variable or function prototype that is not redefining a
+// typedef name and allows the C99 array options, which can only appear in a parameter list.  The pattern
+// precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
+// and functions versus pointers to arrays and functions.
+
+identifier_parameter_declarator:
+		paren_identifier attribute_list_opt
+		| identifier_parameter_ptr
+		| identifier_parameter_array attribute_list_opt
+		| identifier_parameter_function attribute_list_opt
+		;
+
+identifier_parameter_ptr:
+		'*' identifier_parameter_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list identifier_parameter_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' identifier_parameter_ptr ')'
+				{ $$ = $2; }
+		;
+
+identifier_parameter_array:
+		paren_identifier array_parameter_dimension
+				{ $$ = $1->addArray( $2 ); }
+		| '(' identifier_parameter_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' identifier_parameter_array ')'			// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+identifier_parameter_function:
+		paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $1->addParamList( $4 ); }
+		| '(' identifier_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' identifier_parameter_function ')'			// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses a declaration for a parameter variable or function prototype that is redefining a
+// typedef name, e.g.:
+//
+//		typedef int foo;
+//		int f( int foo ); // redefine typedef name in new scope
+//
+// and allows the C99 array options, which can only appear in a parameter list.  In addition, the pattern
+// handles the special meaning of parenthesis around a typedef name:
+//
+//		ISO/IEC 9899:1999 Section 6.7.5.3(11) : "In a parameter declaration, a single typedef name in
+//		parentheses is taken to be an abstract declarator that specifies a function with a single parameter,
+//		not as redundant parentheses around the identifier."
+//
+// which precludes the following cases:
+//
+//		typedef float T;
+//		int f( int ( T [5] ) );						// see abstract_parameter_declarator
+//		int g( int ( T ( int ) ) );				// see abstract_parameter_declarator
+//		int f( int f1( T a[5] ) );				// see identifier_parameter_declarator
+//		int g( int g1( T g2( int p ) ) );		// see identifier_parameter_declarator
+//
+// In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type
+// list, and not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes
+// declaring an array of functions versus a pointer to an array of functions, and returning arrays and
+// functions versus pointers to arrays and functions.
+
+typedef_parameter_redeclarator:
+		typedef attribute_list_opt
+		| typedef_parameter_ptr
+		| typedef_parameter_array attribute_list_opt
+		| typedef_parameter_function attribute_list_opt
+		;
+
+typedef:
+		TYPEDEFname
+				{
+					typedefTable.setNextIdentifier( *($1) );
+					$$ = DeclarationNode::newName( $1 );
+				}
+		;
+
+typedef_parameter_ptr:
+		'*' typedef_parameter_redeclarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list typedef_parameter_redeclarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' typedef_parameter_ptr ')'
+				{ $$ = $2; }
+		;
+
+typedef_parameter_array:
+		typedef array_parameter_dimension
+				{ $$ = $1->addArray( $2 ); }
+		| '(' typedef_parameter_ptr ')' array_parameter_dimension
+				{ $$ = $2->addArray( $4 ); }
+		;
+
+typedef_parameter_function:
+		typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $1->addParamList( $4 ); }
+		| '(' typedef_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		;
+
+// This pattern parses a declaration of an abstract variable or function prototype, i.e., there is no
+// identifier to which the type applies, e.g.:
+//
+//		sizeof( int );
+//		sizeof( int [10] );
+//
+// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
+// returning arrays and functions versus pointers to arrays and functions.
+
+abstract_declarator:
+		abstract_ptr
+		| abstract_array attribute_list_opt
+		| abstract_function attribute_list_opt
+		;
+
+abstract_ptr:
+		'*'
+				{ $$ = DeclarationNode::newPointer( 0 ); }
+		| '*' type_qualifier_list
+				{ $$ = DeclarationNode::newPointer( $2 ); }
+		| '*' abstract_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list abstract_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' abstract_ptr ')'
+				{ $$ = $2; }
+		;
+
+abstract_array:
+		array_dimension
+		| '(' abstract_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' abstract_array ')' multi_array_dimension	// redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' abstract_array ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+abstract_function:
+		'(' push parameter_type_list_opt pop ')'		// empty parameter list OBSOLESCENT (see 3)
+				{ $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
+		| '(' abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' abstract_function ')'						// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+array_dimension:
+				// Only the first dimension can be empty.
+		'[' push pop ']'
+				{ $$ = DeclarationNode::newArray( 0, 0, false ); }
+		| '[' push pop ']' multi_array_dimension
+				{ $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $5 ); }
+		| multi_array_dimension
+		;
+
+multi_array_dimension:
+		'[' push assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $3, 0, false ); }
+		| '[' push '*' pop ']'								// C99
+				{ $$ = DeclarationNode::newVarArray( 0 ); }
+		| multi_array_dimension '[' push assignment_expression pop ']'
+				{ $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
+		| multi_array_dimension '[' push '*' pop ']'		// C99
+				{ $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
+		;
+
+// This pattern parses a declaration of a parameter abstract variable or function prototype, i.e., there is no
+// identifier to which the type applies, e.g.:
+//
+//		int f( int );			// abstract variable parameter; no parameter name specified
+//		int f( int (int) );		// abstract function-prototype parameter; no parameter name specified
+//
+// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
+// returning arrays and functions versus pointers to arrays and functions.
+
+abstract_parameter_declarator:
+		abstract_parameter_ptr
+		| abstract_parameter_array attribute_list_opt
+		| abstract_parameter_function attribute_list_opt
+		;
+
+abstract_parameter_ptr:
+		'*'
+				{ $$ = DeclarationNode::newPointer( 0 ); }
+		| '*' type_qualifier_list
+				{ $$ = DeclarationNode::newPointer( $2 ); }
+		| '*' abstract_parameter_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list abstract_parameter_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' abstract_parameter_ptr ')'
+				{ $$ = $2; }
+		;
+
+abstract_parameter_array:
+		array_parameter_dimension
+		| '(' abstract_parameter_ptr ')' array_parameter_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' abstract_parameter_array ')'				// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+abstract_parameter_function:
+		'(' push parameter_type_list_opt pop ')'		// empty parameter list OBSOLESCENT (see 3)
+				{ $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
+		| '(' abstract_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' abstract_parameter_function ')'			// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+array_parameter_dimension:
+				// Only the first dimension can be empty or have qualifiers.
+		array_parameter_1st_dimension
+		| array_parameter_1st_dimension multi_array_dimension
+				{ $$ = $1->addArray( $2 ); }
+		| multi_array_dimension
+		;
+
+// The declaration of an array parameter has additional syntax over arrays in normal variable declarations:
+//
+//		ISO/IEC 9899:1999 Section 6.7.5.2(1) : "The optional type qualifiers and the keyword static shall
+//		appear only in a declaration of a function parameter with an array type, and then only in the
+//		outermost array type derivation."
+
+array_parameter_1st_dimension:
+		'[' push pop ']'
+				{ $$ = DeclarationNode::newArray( 0, 0, false ); }
+		// multi_array_dimension handles the '[' '*' ']' case
+		| '[' push type_qualifier_list '*' pop ']'		// remaining C99
+				{ $$ = DeclarationNode::newVarArray( $3 ); }
+		| '[' push type_qualifier_list pop ']'
+				{ $$ = DeclarationNode::newArray( 0, $3, false ); }
+		// multi_array_dimension handles the '[' assignment_expression ']' case
+		| '[' push type_qualifier_list assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $4, $3, false ); }
+		| '[' push STATIC type_qualifier_list_opt assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $5, $4, true ); }
+		| '[' push type_qualifier_list STATIC assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $5, $3, true ); }
+		;
+
+// This pattern parses a declaration of an abstract variable, i.e., there is no identifier to which the type
+// applies, e.g.:
+//
+//		sizeof( int ); // abstract variable; no identifier name specified
+//
+// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
+// returning arrays and functions versus pointers to arrays and functions.
+
+variable_abstract_declarator:
+		variable_abstract_ptr
+		| variable_abstract_array attribute_list_opt
+		| variable_abstract_function attribute_list_opt
+		;
+
+variable_abstract_ptr:
+		'*'
+				{ $$ = DeclarationNode::newPointer( 0 ); }
+		| '*' type_qualifier_list
+				{ $$ = DeclarationNode::newPointer( $2 ); }
+		| '*' variable_abstract_declarator
+				{ $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
+		| '*' type_qualifier_list variable_abstract_declarator
+				{ $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
+		| '(' variable_abstract_ptr ')'
+				{ $$ = $2; }
+		;
+
+variable_abstract_array:
+		array_dimension
+		| '(' variable_abstract_ptr ')' array_dimension
+				{ $$ = $2->addArray( $4 ); }
+		| '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis
+				{ $$ = $2->addArray( $4 ); }
+		| '(' variable_abstract_array ')'				// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+variable_abstract_function:
+		'(' variable_abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
+				{ $$ = $2->addParamList( $6 ); }
+		| '(' variable_abstract_function ')'			// redundant parenthesis
+				{ $$ = $2; }
+		;
+
+// This pattern parses a new-style declaration for a parameter variable or function prototype that is either
+// an identifier or typedef name and allows the C99 array options, which can only appear in a parameter list.
+
+new_identifier_parameter_declarator_tuple:				// CFA
+		new_identifier_parameter_declarator_no_tuple
+		| new_abstract_tuple
+		| type_qualifier_list new_abstract_tuple
+				{ $$ = $2->addQualifiers( $1 ); }
+		;
+
+new_identifier_parameter_declarator_no_tuple:			// CFA
+		new_identifier_parameter_ptr
+		| new_identifier_parameter_array
+		;
+
+new_identifier_parameter_ptr:							// CFA
+		'*' type_specifier
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' type_specifier
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		| '*' new_abstract_function
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' new_abstract_function
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		| '*' new_identifier_parameter_declarator_tuple
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' new_identifier_parameter_declarator_tuple
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		;
+
+new_identifier_parameter_array:							// CFA
+				// Only the first dimension can be empty or have qualifiers. Empty dimension must be factored
+				// out due to shift/reduce conflict with new-style empty (void) function return type.
+		'[' push pop ']' type_specifier
+				{ $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| new_array_parameter_1st_dimension type_specifier
+				{ $$ = $2->addNewArray( $1 ); }
+		| '[' push pop ']' multi_array_dimension type_specifier
+				{ $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| new_array_parameter_1st_dimension multi_array_dimension type_specifier
+				{ $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
+		| multi_array_dimension type_specifier
+				{ $$ = $2->addNewArray( $1 ); }
+		| '[' push pop ']' new_identifier_parameter_ptr
+				{ $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| new_array_parameter_1st_dimension new_identifier_parameter_ptr
+				{ $$ = $2->addNewArray( $1 ); }
+		| '[' push pop ']' multi_array_dimension new_identifier_parameter_ptr
+				{ $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| new_array_parameter_1st_dimension multi_array_dimension new_identifier_parameter_ptr
+				{ $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
+		| multi_array_dimension new_identifier_parameter_ptr
+				{ $$ = $2->addNewArray( $1 ); }
+		;
+
+new_array_parameter_1st_dimension:
+		'[' push type_qualifier_list '*' pop ']'		// remaining C99
+				{ $$ = DeclarationNode::newVarArray( $3 ); }
+		| '[' push type_qualifier_list assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $4, $3, false ); }
+		| '[' push declaration_qualifier_list assignment_expression pop ']'
+				// declaration_qualifier_list must be used because of shift/reduce conflict with
+				// assignment_expression, so a semantic check is necessary to preclude them as a
+				// type_qualifier cannot appear in this context.
+				{ $$ = DeclarationNode::newArray( $4, $3, true ); }
+		| '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']'
+				{ $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); }
+		;
+
+// This pattern parses a new-style declaration of an abstract variable or function prototype, i.e., there is
+// no identifier to which the type applies, e.g.:
+//
+//		[int] f( int );				// abstract variable parameter; no parameter name specified
+//		[int] f( [int] (int) );		// abstract function-prototype parameter; no parameter name specified
+//
+// These rules need LR(3):
+//
+//		new_abstract_tuple identifier_or_typedef_name
+//		'[' new_parameter_list ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
+//
+// since a function return type can be syntactically identical to a tuple type:
+//
+//		[int, int] t;
+//		[int, int] f( int );
+//
+// Therefore, it is necessary to look at the token after identifier_or_typedef_name to know when to reduce
+// new_abstract_tuple. To make this LR(1), several rules have to be flattened (lengthened) to allow the
+// necessary lookahead. To accomplish this, new_abstract_declarator has an entry point without tuple, and
+// tuple declarations are duplicated when appearing with new_function_specifier.
+
+new_abstract_declarator_tuple:							// CFA
+		new_abstract_tuple
+		| type_qualifier_list new_abstract_tuple
+				{ $$ = $2->addQualifiers( $1 ); }
+		| new_abstract_declarator_no_tuple
+		;
+
+new_abstract_declarator_no_tuple:						// CFA
+		new_abstract_ptr
+		| new_abstract_array
+		;
+
+new_abstract_ptr:										// CFA
+		'*' type_specifier
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' type_specifier
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		| '*' new_abstract_function
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' new_abstract_function
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		| '*' new_abstract_declarator_tuple
+				{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
+		| type_qualifier_list '*' new_abstract_declarator_tuple
+				{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
+		;
+
+new_abstract_array:										// CFA
+				// Only the first dimension can be empty. Empty dimension must be factored out due to
+				// shift/reduce conflict with empty (void) function return type.
+		'[' push pop ']' type_specifier
+				{ $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| '[' push pop ']' multi_array_dimension type_specifier
+				{ $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| multi_array_dimension type_specifier
+				{ $$ = $2->addNewArray( $1 ); }
+		| '[' push pop ']' new_abstract_ptr
+				{ $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| '[' push pop ']' multi_array_dimension new_abstract_ptr
+				{ $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		| multi_array_dimension new_abstract_ptr
+				{ $$ = $2->addNewArray( $1 ); }
+		;
+
+new_abstract_tuple:										// CFA
+		'[' push new_abstract_parameter_list pop ']'
+				{ $$ = DeclarationNode::newTuple( $3 ); }
+		;
+
+new_abstract_function:									// CFA
+		'[' push pop ']' '(' new_parameter_type_list_opt ')'
+				{ $$ = DeclarationNode::newFunction( 0, DeclarationNode::newTuple( 0 ), $6, 0 ); }
+		| new_abstract_tuple '(' push new_parameter_type_list_opt pop ')'
+				{ $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
+		| new_function_return '(' push new_parameter_type_list_opt pop ')'
+				{ $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
+		;
+
+// 1) ISO/IEC 9899:1999 Section 6.7.2(2) : "At least one type specifier shall be given in the declaration
+//    specifiers in each declaration, and in the specifier-qualifier list in each structure declaration and
+//    type name."
+//
+// 2) ISO/IEC 9899:1999 Section 6.11.5(1) : "The placement of a storage-class specifier other than at the
+//    beginning of the declaration specifiers in a declaration is an obsolescent feature."
+//
+// 3) ISO/IEC 9899:1999 Section 6.11.6(1) : "The use of function declarators with empty parentheses (not
+//    prototype-format parameter type declarators) is an obsolescent feature."
+//
+// 4) ISO/IEC 9899:1999 Section 6.11.7(1) : "The use of function definitions with separate parameter
+//    identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an
+//    obsolescent feature.
+
+//************************* MISCELLANEOUS ********************************
+
+comma_opt:												// redundant comma
+		// empty
+		| ','
+		;
+
+assignment_opt:
+		// empty
+				{ $$ = 0; }
+		| '=' assignment_expression
+				{ $$ = $2; }
+		;
+
+%%
+// ----end of grammar----
+
+void yyerror( char *string ) {
+	using std::cout;
+	using std::endl;
+	cout << "Error ";
+	if ( yyfilename ) {
+		cout << "in file " << yyfilename << " ";
+	}
+	cout << "at line " << yylineno << " reading token \"" << *(yylval.tok.str) << "\"" << endl;
+}
+
+// Local Variables: //
+// fill-column: 110 //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/lex.h
===================================================================
--- src/Parser/lex.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/lex.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,50 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// lex.h -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Sat Sep 22 08:58:10 2001
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 12:18:48 2015
+// Update Count     : 334
+//
+
+#ifndef PARSER_LEX_H
+#define PARSER_LEX_H
+
+int yylex();
+void yyerror(char *);
+
+// External declarations for information sharing between lexer and scanner
+#include "TypedefTable.h"
+extern TypedefTable typedefTable;
+
+// current location in the input
+extern int yylineno;
+extern char *yyfilename;
+
+struct Location {
+    char *file;
+    int line;
+};
+
+class Token {
+  public:
+    std::string *str;
+    Location loc;
+
+    operator std::string *() { return str; }
+};
+
+#endif // PARSER_LEX_H
+
+// Local Variables: //
+// fill-column: 110 //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/lex.l
===================================================================
--- src/Parser/lex.l	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/lex.l	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,406 @@
+/*
+ * Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+ *
+ * The contents of this file are covered under the licence agreement in the
+ * file "LICENCE" distributed with Cforall.
+ * 
+ * lex.l -- 
+ * 
+ * Author           : Peter A. Buhr
+ * Created On       : Sat Sep 22 08:58:10 2001
+ * Last Modified By : Peter A. Buhr
+ * Last Modified On : Tue May 19 15:41:54 2015
+ * Update Count     : 331
+ */
+
+%option yylineno
+
+%{
+// This lexer assumes the program has been preprocessed by cpp. Hence, all user level preprocessor directive
+// have been performed and removed from the source. The only exceptions are preprocessor directives passed to
+// the compiler (e.g., line-number directives) and C/C++ style comments, which are ignored.
+
+//**************************** Includes and Defines ****************************
+
+#include <string>
+
+#include "lex.h"
+#include "ParseNode.h"
+#include "cfa.tab.h"									// YACC generated definitions based on C++ grammar
+
+char *yyfilename;
+std::string *strtext;									// accumulate parts of character and string constant value
+
+#define WHITE_RETURN(x)									// do nothing
+#define NEWLINE_RETURN()	WHITE_RETURN('\n')
+#define RETURN_VAL(x)		yylval.tok.str = new std::string(yytext); \
+		                        yylval.tok.loc.file = yyfilename; \
+		                        yylval.tok.loc.line = yylineno; \
+		                        return(x)
+#define RETURN_STR(x)		yylval.tok.str = strtext; \
+		                        yylval.tok.loc.file = yyfilename; \
+		                        yylval.tok.loc.line = yylineno; \
+		                        return(x)
+
+#define KEYWORD_RETURN(x)	RETURN_VAL(x)				// keyword
+#define IDENTIFIER_RETURN()	RETURN_VAL((typedefTable.isIdentifier(yytext) ? IDENTIFIER : typedefTable.isTypedef(yytext) ? TYPEDEFname : TYPEGENname))
+//#define ATTRIBUTE_RETURN()	RETURN_VAL((typedefTable.isIdentifier(yytext) ? ATTR_IDENTIFIER : typedefTable.isTypedef(yytext) ? ATTR_TYPEDEFname : ATTR_TYPEGENname))
+#define ATTRIBUTE_RETURN()	RETURN_VAL(ATTR_IDENTIFIER)
+
+#define ASCIIOP_RETURN()	RETURN_VAL((int)yytext[0])	// single character operator
+#define NAMEDOP_RETURN(x)	RETURN_VAL(x)				// multichar operator, with a name
+
+#define NUMERIC_RETURN(x)	rm_underscore(); RETURN_VAL(x) // numeric constant
+
+void rm_underscore() {
+	// remove underscores in numeric constant
+	int j = 0;
+	for ( int i = 0; yytext[i] != '\0'; i += 1 ) {
+		if ( yytext[i] != '_' ) {
+			yytext[j] = yytext[i];
+			j += 1;
+		} // if
+	} // for
+	yyleng = j;
+	yytext[yyleng] = '\0';
+}
+
+%}
+
+octal [0-7]
+nonzero [1-9]
+decimal [0-9]
+hex [0-9a-fA-F]
+universal_char "\\"((u"_"?{hex_quad})|(U"_"?{hex_quad}{2}))
+
+				// identifier, GCC: $ in identifier
+identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})*
+
+				// quoted identifier
+quoted_identifier "`"{identifier}"`"
+
+				// attribute identifier, GCC: $ in identifier
+attr_identifier "@"{identifier}
+
+				// numeric constants, CFA: '_' in constant
+hex_quad {hex}("_"?{hex}){3}
+integer_suffix "_"?(([uU][lL]?)|([uU]("ll"|"LL")?)|([lL][uU]?)|("ll"|"LL")[uU]?)
+
+octal_digits ({octal})|({octal}({octal}|"_")*{octal})
+octal_prefix "0""_"?
+octal_constant (("0")|({octal_prefix}{octal_digits})){integer_suffix}?
+
+nonzero_digits ({nonzero})|({nonzero}({decimal}|"_")*{decimal})
+decimal_constant {nonzero_digits}{integer_suffix}?
+
+hex_digits ({hex})|({hex}({hex}|"_")*{hex})
+hex_prefix "0"[xX]"_"?
+hex_constant {hex_prefix}{hex_digits}{integer_suffix}?
+
+decimal_digits ({decimal})|({decimal}({decimal}|"_")*{decimal})
+fractional_constant ({decimal_digits}?"."{decimal_digits})|({decimal_digits}".")
+exponent "_"?[eE]"_"?[+-]?{decimal_digits}
+floating_suffix "_"?[flFL]
+floating_constant (({fractional_constant}{exponent}?)|({decimal_digits}{exponent})){floating_suffix}?
+
+binary_exponent "_"?[pP]"_"?[+-]?{decimal_digits}
+hex_fractional_constant ({hex_digits}?"."{hex_digits})|({hex_digits}".")
+hex_floating_constant {hex_prefix}(({hex_fractional_constant}{binary_exponent})|({hex_digits}{binary_exponent})){floating_suffix}?
+
+				// character escape sequence, GCC: \e => esc character
+simple_escape "\\"[abefnrtv'"?\\]
+				// ' stop highlighting
+octal_escape "\\"{octal}("_"?{octal}){0,2}
+hex_escape "\\""x""_"?{hex_digits}
+escape_seq {simple_escape}|{octal_escape}|{hex_escape}|{universal_char}
+
+				// display/white-space characters
+h_tab [\011]
+form_feed [\014]
+v_tab [\013]
+c_return [\015]
+h_white [ ]|{h_tab}
+
+				// operators
+op_unary_only "~"|"!"
+op_unary_binary "+"|"-"|"*"
+op_unary_pre_post "++"|"--"
+op_unary {op_unary_only}|{op_unary_binary}|{op_unary_pre_post}
+
+op_binary_only "/"|"%"|"^"|"&"|"|"|"<"|">"|"="|"=="|"!="|"<<"|">>"|"<="|">="|"+="|"-="|"*="|"/="|"%="|"&="|"|="|"^="|"<<="|">>="
+op_binary_over {op_unary_binary}|{op_binary_only}
+op_binary_not_over "?"|"->"|"&&"|"||"
+operator {op_unary_pre_post}|{op_binary_over}|{op_binary_not_over}
+
+%x COMMENT
+%x BKQUOTE
+%x QUOTE
+%x STRING
+
+%%
+				   /* line directives */
+^{h_white}*"#"{h_white}*[0-9]+{h_white}*["][^"\n]+["][^\n]*"\n" {
+	/* " stop highlighting */
+	char *end_num;
+	char *begin_string, *end_string;
+	char *filename;
+	long lineno, length;
+	lineno = strtol( yytext + 1, &end_num, 0 );
+	begin_string = strchr( end_num, '"' );
+	if ( begin_string ) {
+		end_string = strchr( begin_string + 1, '"' );
+		if ( end_string ) {
+			length = end_string - begin_string - 1;
+			filename = new char[ length + 1 ];
+			memcpy( filename, begin_string + 1, length );
+			filename[ length ] = '\0';
+			//std::cout << "file " << filename << " line " << lineno << std::endl;
+			yylineno = lineno;
+			yyfilename = filename;
+		} // if
+	} // if
+}
+
+				/* ignore preprocessor directives (for now) */
+^{h_white}*"#"[^\n]*"\n" ;
+
+				/* ignore C style comments */
+"/*"			{ BEGIN COMMENT; }
+<COMMENT>.|\n		;
+<COMMENT>"*/"		{ BEGIN 0; }
+
+				/* ignore C++ style comments */
+"//"[^\n]*"\n"		;
+
+				/* ignore whitespace */
+{h_white}+		{ WHITE_RETURN(' '); }
+({v_tab}|{c_return}|{form_feed})+ { WHITE_RETURN(' '); }
+({h_white}|{v_tab}|{c_return}|{form_feed})*"\n" { NEWLINE_RETURN(); }
+
+				/* keywords */
+_Alignas		{ KEYWORD_RETURN(ALIGNAS); }			// C11
+_Alignof		{ KEYWORD_RETURN(ALIGNOF); }			// C11
+__alignof		{ KEYWORD_RETURN(ALIGNOF); }			// GCC
+__alignof__		{ KEYWORD_RETURN(ALIGNOF); }			// GCC
+asm				{ KEYWORD_RETURN(ASM); }
+__asm			{ KEYWORD_RETURN(ASM); }				// GCC
+__asm__			{ KEYWORD_RETURN(ASM); }				// GCC
+_Atomic			{ KEYWORD_RETURN(ATOMIC); }				// C11
+__attribute		{ KEYWORD_RETURN(ATTRIBUTE); }			// GCC
+__attribute__	{ KEYWORD_RETURN(ATTRIBUTE); }			// GCC
+auto			{ KEYWORD_RETURN(AUTO); }
+_Bool			{ KEYWORD_RETURN(BOOL); }				// C99
+break			{ KEYWORD_RETURN(BREAK); }
+case			{ KEYWORD_RETURN(CASE); }
+catch			{ KEYWORD_RETURN(CATCH); }				// CFA
+char			{ KEYWORD_RETURN(CHAR); }
+choose			{ KEYWORD_RETURN(CHOOSE); }				// CFA
+_Complex		{ KEYWORD_RETURN(COMPLEX); }			// C99
+__complex		{ KEYWORD_RETURN(COMPLEX); }			// GCC
+__complex__		{ KEYWORD_RETURN(COMPLEX); }			// GCC
+const			{ KEYWORD_RETURN(CONST); }
+__const			{ KEYWORD_RETURN(CONST); }				// GCC
+__const__		{ KEYWORD_RETURN(CONST); }				// GCC
+context			{ KEYWORD_RETURN(CONTEXT); }			// CFA
+continue		{ KEYWORD_RETURN(CONTINUE); }
+default			{ KEYWORD_RETURN(DEFAULT); }
+do				{ KEYWORD_RETURN(DO); }
+double			{ KEYWORD_RETURN(DOUBLE); }
+dtype			{ KEYWORD_RETURN(DTYPE); }				// CFA
+else			{ KEYWORD_RETURN(ELSE); }
+enum			{ KEYWORD_RETURN(ENUM); }
+__extension__	{ KEYWORD_RETURN(EXTENSION); }			// GCC
+extern			{ KEYWORD_RETURN(EXTERN); }
+fallthru		{ KEYWORD_RETURN(FALLTHRU); }			// CFA
+finally			{ KEYWORD_RETURN(FINALLY); }			// CFA
+float			{ KEYWORD_RETURN(FLOAT); }
+__float128		{ KEYWORD_RETURN(FLOAT); }				// GCC
+for				{ KEYWORD_RETURN(FOR); }
+forall			{ KEYWORD_RETURN(FORALL); }				// CFA
+fortran			{ KEYWORD_RETURN(FORTRAN); }
+ftype			{ KEYWORD_RETURN(FTYPE); }				// CFA
+_Generic		{ KEYWORD_RETURN(GENERIC); }			// C11
+goto			{ KEYWORD_RETURN(GOTO); }
+if				{ KEYWORD_RETURN(IF); }
+_Imaginary		{ KEYWORD_RETURN(IMAGINARY); }			// C99
+__imag			{ KEYWORD_RETURN(IMAGINARY); }			// GCC
+__imag__		{ KEYWORD_RETURN(IMAGINARY); }			// GCC
+inline			{ KEYWORD_RETURN(INLINE); }				// C99
+__inline		{ KEYWORD_RETURN(INLINE); }				// GCC
+__inline__		{ KEYWORD_RETURN(INLINE); }				// GCC
+int				{ KEYWORD_RETURN(INT); }
+__int128		{ KEYWORD_RETURN(INT); }				// GCC
+__label__		{ KEYWORD_RETURN(LABEL); }				// GCC
+long			{ KEYWORD_RETURN(LONG); }
+lvalue			{ KEYWORD_RETURN(LVALUE); }				// CFA
+_Noreturn		{ KEYWORD_RETURN(NORETURN); }			// C11
+register		{ KEYWORD_RETURN(REGISTER); }
+restrict		{ KEYWORD_RETURN(RESTRICT); }			// C99
+__restrict		{ KEYWORD_RETURN(RESTRICT); }			// GCC
+__restrict__	{ KEYWORD_RETURN(RESTRICT); }			// GCC
+return			{ KEYWORD_RETURN(RETURN); }
+short			{ KEYWORD_RETURN(SHORT); }
+signed			{ KEYWORD_RETURN(SIGNED); }
+__signed		{ KEYWORD_RETURN(SIGNED); }				// GCC
+__signed__		{ KEYWORD_RETURN(SIGNED); }				// GCC
+sizeof			{ KEYWORD_RETURN(SIZEOF); }
+static			{ KEYWORD_RETURN(STATIC); }
+_Static_assert	{ KEYWORD_RETURN(STATICASSERT); }		// C11
+struct			{ KEYWORD_RETURN(STRUCT); }
+switch			{ KEYWORD_RETURN(SWITCH); }
+_Thread_local	{ KEYWORD_RETURN(THREADLOCAL); }		// C11
+throw			{ KEYWORD_RETURN(THROW); }				// CFA
+try				{ KEYWORD_RETURN(TRY); }				// CFA
+type			{ KEYWORD_RETURN(TYPE); }				// CFA
+typedef			{ KEYWORD_RETURN(TYPEDEF); }
+typeof			{ KEYWORD_RETURN(TYPEOF); }				// GCC
+__typeof		{ KEYWORD_RETURN(TYPEOF); }				// GCC
+__typeof__		{ KEYWORD_RETURN(TYPEOF); }				// GCC
+union			{ KEYWORD_RETURN(UNION); }
+unsigned		{ KEYWORD_RETURN(UNSIGNED); }
+void			{ KEYWORD_RETURN(VOID); }
+volatile		{ KEYWORD_RETURN(VOLATILE); }
+__volatile		{ KEYWORD_RETURN(VOLATILE); }			// GCC
+__volatile__	{ KEYWORD_RETURN(VOLATILE); }			// GCC
+while			{ KEYWORD_RETURN(WHILE); }
+
+				/* identifier */
+{identifier}	{ IDENTIFIER_RETURN(); }
+{attr_identifier} { ATTRIBUTE_RETURN(); }
+"`"			{ BEGIN BKQUOTE; }
+<BKQUOTE>{identifier} { IDENTIFIER_RETURN(); }
+<BKQUOTE>"`"	{ BEGIN 0; }
+
+				/* numeric constants */
+"0"				{ NUMERIC_RETURN(ZERO); }				// CFA
+"1"				{ NUMERIC_RETURN(ONE); }				// CFA
+{decimal_constant}	{ NUMERIC_RETURN(INTEGERconstant); }
+{octal_constant}	{ NUMERIC_RETURN(INTEGERconstant); }
+{hex_constant}		{ NUMERIC_RETURN(INTEGERconstant); }
+{floating_constant}	{ NUMERIC_RETURN(FLOATINGconstant); }
+{hex_floating_constant}	{ NUMERIC_RETURN(FLOATINGconstant); }
+
+				/* character constant, allows empty value */
+"L"?"_"?[']		{ BEGIN QUOTE; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); }
+<QUOTE>[^'\\\n]* { *strtext += std::string( yytext ); }
+<QUOTE>['\n]	{ BEGIN 0; *strtext += std::string( yytext); RETURN_STR(CHARACTERconstant); }
+				/* ' stop highlighting */
+
+				/* string constant */
+"L"?"_"?["]		{ BEGIN STRING; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); }
+<STRING>[^"\\\n]* { *strtext += std::string( yytext ); }
+<STRING>["\n]	{ BEGIN 0; *strtext += std::string( yytext); RETURN_STR(STRINGliteral); }
+				/* " stop highlighting */
+
+<QUOTE,STRING>{escape_seq} { rm_underscore(); *strtext += std::string( yytext ); }
+<QUOTE,STRING>[\\]	{ *strtext += std::string( yytext ); } // unknown escape character
+
+				/* punctuation */
+"["				{ ASCIIOP_RETURN(); }
+"]"				{ ASCIIOP_RETURN(); }
+"("				{ ASCIIOP_RETURN(); }
+")"				{ ASCIIOP_RETURN(); }
+"{"				{ ASCIIOP_RETURN(); }
+"}"				{ ASCIIOP_RETURN(); }
+","				{ ASCIIOP_RETURN(); }					// also operator
+":"				{ ASCIIOP_RETURN(); }
+";"				{ ASCIIOP_RETURN(); }
+"."				{ ASCIIOP_RETURN(); }					// also operator
+"..."			{ NAMEDOP_RETURN(ELLIPSIS); }
+
+				/* alternative C99 brackets, "<:" & "<:<:" handled by preprocessor */
+"<:"			{ RETURN_VAL('['); }
+":>"			{ RETURN_VAL(']'); }
+"<%"			{ RETURN_VAL('{'); }
+"%>"			{ RETURN_VAL('}'); }
+
+				/* operators */
+"!"				{ ASCIIOP_RETURN(); }
+"+"				{ ASCIIOP_RETURN(); }
+"-"				{ ASCIIOP_RETURN(); }
+"*"				{ ASCIIOP_RETURN(); }
+"/"				{ ASCIIOP_RETURN(); }
+"%"				{ ASCIIOP_RETURN(); }
+"^"				{ ASCIIOP_RETURN(); }
+"~"				{ ASCIIOP_RETURN(); }
+"&"				{ ASCIIOP_RETURN(); }
+"|"				{ ASCIIOP_RETURN(); }
+"<"				{ ASCIIOP_RETURN(); }
+">"				{ ASCIIOP_RETURN(); }
+"="				{ ASCIIOP_RETURN(); }
+"?"				{ ASCIIOP_RETURN(); }
+
+"++"			{ NAMEDOP_RETURN(ICR); }
+"--"			{ NAMEDOP_RETURN(DECR); }
+"=="			{ NAMEDOP_RETURN(EQ); }
+"!="			{ NAMEDOP_RETURN(NE); }
+"<<"			{ NAMEDOP_RETURN(LS); }
+">>"			{ NAMEDOP_RETURN(RS); }
+"<="			{ NAMEDOP_RETURN(LE); }
+">="			{ NAMEDOP_RETURN(GE); }
+"&&"			{ NAMEDOP_RETURN(ANDAND); }
+"||"			{ NAMEDOP_RETURN(OROR); }
+"->"			{ NAMEDOP_RETURN(ARROW); }
+"+="			{ NAMEDOP_RETURN(PLUSassign); }
+"-="			{ NAMEDOP_RETURN(MINUSassign); }
+"*="			{ NAMEDOP_RETURN(MULTassign); }
+"/="			{ NAMEDOP_RETURN(DIVassign); }
+"%="			{ NAMEDOP_RETURN(MODassign); }
+"&="			{ NAMEDOP_RETURN(ANDassign); }
+"|="			{ NAMEDOP_RETURN(ORassign); }
+"^="			{ NAMEDOP_RETURN(ERassign); }
+"<<="			{ NAMEDOP_RETURN(LSassign); }
+">>="			{ NAMEDOP_RETURN(RSassign); }
+
+				/* CFA, operator identifier */
+{op_unary}"?"	{ IDENTIFIER_RETURN(); }				// unary
+"?"({op_unary_pre_post}|"()"|"[?]") { IDENTIFIER_RETURN(); }
+"?"{op_binary_over}"?"	{ IDENTIFIER_RETURN(); }		// binary
+	/*
+	  This rule handles ambiguous cases with operator identifiers, e.g., "int *?*?()", where the string "*?*?"
+	  can be lexed as "*"/"?*?" or "*?"/"*?". Since it is common practise to put a unary operator juxtaposed
+	  to an identifier, e.g., "*i", users will be annoyed if they cannot do this with respect to operator
+	  identifiers. Even with this special hack, there are 5 general cases that cannot be handled. The first
+	  case is for the function-call identifier "?()":
+
+	  int * ?()();	// declaration: space required after '*'
+	  * ?()();	// expression: space required after '*'
+
+	  Without the space, the string "*?()" is ambiguous without N character look ahead; it requires scanning
+	  ahead to determine if there is a '(', which is the start of an argument/parameter list.
+
+	  The 4 remaining cases occur in expressions:
+
+	  i++?i:0;		// space required before '?'
+	  i--?i:0;		// space required before '?'
+	  i?++i:0;		// space required after '?'
+	  i?--i:0;		// space required after '?'
+
+	  In the first two cases, the string "i++?" is ambiguous, where this string can be lexed as "i"/"++?" or
+	  "i++"/"?"; it requires scanning ahead to determine if there is a '(', which is the start of an argument
+	  list.  In the second two cases, the string "?++x" is ambiguous, where this string can be lexed as
+	  "?++"/"x" or "?"/"++x"; it requires scanning ahead to determine if there is a '(', which is the start of
+	  an argument list.
+	*/
+{op_unary}"?"(({op_unary_pre_post}|"[?]")|({op_binary_over}"?")) {
+	// 1 or 2 character unary operator ?
+	int i = yytext[1] == '?' ? 1 : 2;
+	yyless( i );		// put back characters up to first '?'
+	if ( i > 1 ) {
+		NAMEDOP_RETURN( yytext[0] == '+' ? ICR : DECR );
+	} else {
+		ASCIIOP_RETURN();
+	} // if
+}
+
+				/* unknown characters */
+.			{ printf("unknown character(s):\"%s\" on line %d\n", yytext, yylineno); }
+
+%%
+
+// Local Variables: //
+// fill-column: 110 //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/module.mk
===================================================================
--- src/Parser/module.mk	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/module.mk	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,54 @@
+######################### -*- Mode: Makefile-Gmake -*- ########################
+##
+## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+##
+## The contents of this file are covered under the licence agreement in the
+## file "LICENCE" distributed with Cforall.
+##
+## module.mk -- 
+##
+## Author           : Richard C. Bilson
+## Created On       : Sat May 16 15:29:09 2015
+## Last Modified By : Peter A. Buhr
+## Last Modified On : Thu May 21 21:17:07 2015
+## Update Count     : 2
+###############################################################################
+
+YACC=bison
+YFLAGS=-d --debug -v
+LEX=flex
+LFLAGS=
+
+SRC += Parser/cfa.y \
+       Parser/lex.l \
+       Parser/TypedefTable.cc \
+       Parser/ParseNode.cc \
+       Parser/DeclarationNode.cc \
+       Parser/ExpressionNode.cc \
+       Parser/StatementNode.cc \
+       Parser/InitializerNode.cc \
+       Parser/TypeData.cc \
+       Parser/LinkageSpec.cc \
+       Parser/parseutility.cc \
+       Parser/Parser.cc
+
+EXTRA_OUTPUT += Parser/cfa.tab.cc \
+                Parser/cfa.tab.h \
+		Parser/lex.yy.cc \
+		Parser/cfa.output
+
+LIBS += -lfl
+
+Parser/Parser.cc: Parser/cfa.tab.h
+
+Parser/cfa.tab.cc: Parser/cfa.y
+	$(YACC) $(YFLAGS) $< --file-prefix=Parser/cfa
+	-mv Parser/cfa.tab.c Parser/cfa.tab.cc
+
+Parser/cfa.tab.h: Parser/cfa.tab.cc
+
+Parser/lex.yy.cc: Parser/lex.l Parser/cfa.tab.h Parser/TypedefTable.h
+	$(LEX) $(LFLAGS) -o$@ $< 
+
+Parser/lex.yy.o: Parser/lex.yy.cc Parser/ParseNode.h
+	$(CXX) $(CXXFLAGS) -Wno-unused -c -o $@ $<
Index: src/Parser/parseutility.cc
===================================================================
--- src/Parser/parseutility.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/parseutility.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,31 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// parseutility.cc -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:30:39 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:31:33 2015
+// Update Count     : 2
+// 
+
+#include "parseutility.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+
+Expression *notZeroExpr( Expression *orig ) {
+	UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
+	comparison->get_args().push_back( orig );
+	comparison->get_args().push_back( new NameExpr( "0" ) );
+	return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Parser/parseutility.h
===================================================================
--- src/Parser/parseutility.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Parser/parseutility.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,29 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// parseutility.h -- 
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Sat May 16 15:31:46 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat May 16 15:32:58 2015
+// Update Count     : 2
+//
+
+#ifndef PARSEUTILITY_H
+#define PARSEUTILITY_H
+
+#include "SynTree/SynTree.h"
+
+Expression *notZeroExpr( Expression *orig );
+
+#endif // PARSEUTILITY_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
