Index: translator/Parser/DeclarationNode.cc
===================================================================
--- translator/Parser/DeclarationNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/DeclarationNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,1076 @@
+#include <string>
+#include <list>
+#include <iterator>
+#include <algorithm>
+#include <cassert>
+
+#include "ParseNode.h"
+#include "TypeData.h"
+#include "utility.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "SemanticError.h"
+#include "UniqueName.h"
+#include "LinkageSpec.h"
+
+using namespace std;
+
+/* these must remain in the same order as the corresponding DeclarationNode enumerations */
+const char *DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue" };
+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
+  "static",
+  "auto",
+  "extern",
+  "register",
+  "inline",
+  "fortran",
+};
+
+void
+DeclarationNode::print( std::ostream &os, int indent ) const
+{
+  os << string(indent,  ' ');
+  if( name == "" ) {
+///     os << "An unnamed ";
+  } else {
+    os << name << ": a ";
+  }
+  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;
+  }
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newQualifier( Qualifier q )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData();
+  newnode->type->qualifiers.push_back( q );
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newStorageClass( StorageClass sc )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->storageClasses.push_back( sc );
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newBasicType( BasicType bt )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Basic );
+  newnode->type->basic->typeSpec.push_back( bt );
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newModifier( Modifier mod )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Basic );
+  newnode->type->basic->modifiers.push_back( mod );
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newForall( DeclarationNode* forall )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Unknown );
+  newnode->type->forall = forall;
+  return newnode;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newEnumConstant( std::string* name, ExpressionNode *constant )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->name = assign_strptr( name );
+  // do something with the constant
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newName( std::string* name )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->name = assign_strptr( name );
+  return newnode;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newPointer( DeclarationNode *qualifiers )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Pointer );
+  return newnode->addQualifiers( qualifiers );
+}
+
+/* static class method */
+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 );
+}
+
+/* static class method */
+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 );
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newBitfield( ExpressionNode *size )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->bitfieldWidth = size;
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newTuple( DeclarationNode *members )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Tuple );
+  newnode->type->tuple->members = members;
+  return newnode;
+}
+
+/* static class method */
+DeclarationNode *
+DeclarationNode::newTypeof( ExpressionNode *expr )
+{
+  DeclarationNode *newnode = new DeclarationNode;
+  newnode->type = new TypeData( TypeData::Typeof );
+  newnode->type->typeexpr->expr = expr;
+  return newnode;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+    } else {
+      return 0;
+    }
+  } else {
+    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;
+	}
+      }
+      Declaration *decl = cur->build();
+      if( decl ) {
+        *out++ = decl;
+      }
+    } catch( SemanticError &e ) {
+      errors.append( e );
+    }
+    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+  }
+  if( !errors.isEmpty() ) {
+    throw errors;
+  }
+}
+
+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 );
+        }
+      }
+    } catch( SemanticError &e ) {
+      errors.append( e );
+    }
+    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+  }
+  if( !errors.isEmpty() ) {
+    throw errors;
+  }
+}
+
+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 );
+    }
+    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
+  }
+  if( !errors.isEmpty() ) {
+    throw errors;
+  }
+}
+
+Declaration *
+DeclarationNode::build() const
+{
+
+  if( !type ) {
+    if( buildInline() ) {
+      throw SemanticError( "invalid inline specification in declaration of ", this );
+    } else {
+      return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) );
+    }
+  } else {
+    Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildInline(), linkage, maybeBuild< Initializer >(initializer) );
+    return newDecl;
+  }
+  // we should never get here
+  assert( false );
+  return 0;
+}
+
+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 );
+    }
+    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();
+  }
+}
+
+Declaration::StorageClass 
+DeclarationNode::buildStorageClass() const
+{
+  static const Declaration::StorageClass scMap[] = {  
+    Declaration::Static,
+    Declaration::Auto,
+    Declaration::Extern,
+    Declaration::Register,
+    Declaration::NoStorageClass, // 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 ) {
+      ret = scMap[ *i ];
+    } else {
+      throw SemanticError( "invalid combination of storage classes in declaration of ", this );
+    }
+  }
+  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;
+  } else {
+    std::list< StorageClass >::const_iterator next = std::find( ++first, storageClasses.end(), Inline );
+    if( next == storageClasses.end() ) {
+      return true;
+    } else {
+      throw SemanticError( "duplicate inline specification in declaration of ", this );
+    }
+  }
+  // we should never get here
+  return false;
+}
Index: translator/Parser/ExpressionNode.cc
===================================================================
--- translator/Parser/ExpressionNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/ExpressionNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,804 @@
+/* -*- C++ -*- */
+#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;
+  }
+}
+
+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;
+  }
+}
+
+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 = "";
+  }
+
+  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;
+	}
+
+	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;
+  }
+  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();
+    }
+    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() ) );
+        }
+      }
+
+    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());
+        }
+      }
+    
+    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());
+        }
+      }
+    
+
+    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;
+}
Index: translator/Parser/InitializerNode.cc
===================================================================
--- translator/Parser/InitializerNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/InitializerNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,103 @@
+#include "ParseNode.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "utility.h"
+#include "SemanticError.h"
+// #include <cstdlib> // for strtol
+#include <cassert>
+
+
+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 )
+  : 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 << ", ";
+	  }
+	  os << ")";
+	}
+
+      if (expr) expr->printOneLine(os);
+    }
+  else  // It's an aggregate
+    {
+      os << "[--";
+      if( next_init() != 0 )
+	next_init()->printOneLine(os);
+
+      if (aggregate) os << "--]";
+    }
+
+  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 );
+
+      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 );
+    }
+
+  return 0;
+}
+
+
Index: translator/Parser/LinkageSpec.cc
===================================================================
--- translator/Parser/LinkageSpec.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/LinkageSpec.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: LinkageSpec.cc,v 1.3 2003/01/29 14:55:08 rcbilson Exp $
+ *
+ */
+
+#include <string>
+#include <cassert>
+
+#include "LinkageSpec.h"
+#include "SemanticError.h"
+
+/* static class method */
+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 );
+  }
+}
+
+/* static class method */
+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 "";
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+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;
+}
+
+/* static class method */
+bool 
+LinkageSpec::isOverloadable( Type t )
+{
+  return isDecoratable( t );
+}
+
+/* static class method */
+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;
+}
+
Index: translator/Parser/LinkageSpec.h
===================================================================
--- translator/Parser/LinkageSpec.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/LinkageSpec.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: LinkageSpec.h,v 1.3 2003/01/29 14:55:08 rcbilson Exp $
+ *
+ */
+
+#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 /* #ifndef LINKAGESPEC_H */
Index: translator/Parser/ParseNode.cc
===================================================================
--- translator/Parser/ParseNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/ParseNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,94 @@
+/* -*- C++ -*- */
+#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: //
+// mode: C++                //
+// compile-command: "gmake" //
+// End: //
Index: translator/Parser/ParseNode.h
===================================================================
--- translator/Parser/ParseNode.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/ParseNode.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,516 @@
+#ifndef PARSENODE_H
+#define PARSENODE_H
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <iterator>
+
+#include "utility.h"
+#include "SynTree/SynTree.h"
+#include "SynTree/Declaration.h"
+#include "SemanticError.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() { /* can't 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 };
+  enum StorageClass { Static, Auto, Extern, 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 {
+      }
+    } catch( SemanticError &e ) {
+      errors.append( e );
+    }
+    cur = dynamic_cast< NodeType* >( cur->get_link() );
+  }
+  if( !errors.isEmpty() ) {
+    throw errors;
+  }
+}
+
+// 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 /* #ifndef PARSENODE_H */
+
+// Local Variables: //
+// mode: C++ //
+// compile-command: "gmake" //
+// End: //
Index: translator/Parser/Parser.cc
===================================================================
--- translator/Parser/Parser.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/Parser.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: Parser.cc,v 1.6 2002/11/15 20:07:18 rcbilson Exp $
+ *
+ */
+
+#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;
+/* end of globals */
+
+Parser *Parser::theParser = 0;
+
+Parser::Parser(): parseTree( 0 ), parseStatus( 1 ) {}
+
+Parser::~Parser()
+{
+  delete parseTree;
+}
+
+/* static class method */
+Parser &
+Parser::get_parser()
+{
+  if( theParser == 0 ) {
+    theParser = new Parser;
+  }
+  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;
+}
+
Index: translator/Parser/Parser.h
===================================================================
--- translator/Parser/Parser.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/Parser.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * A singleton class to encapsulate the bison-generated parser
+ *
+ * $Id: Parser.h,v 1.4 2002/09/09 16:47:14 rcbilson Exp $
+ *
+ */
+
+#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 /* #ifndef PARSER_H */
Index: translator/Parser/StatementNode.cc
===================================================================
--- translator/Parser/StatementNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/StatementNode.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,437 @@
+/* -*- C++ -*- */
+#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(void) : 
+  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(void){
+  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(void) const {
+  return control;
+}
+
+StatementNode *StatementNode::get_block(void) const {
+  return block;
+}
+
+StatementNode::Type StatementNode::get_type(void) 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:
+    // try{
+    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;
+  }
+
+  // shouldn't be here
+}
+
+CompoundStmtNode::CompoundStmtNode(void)
+  : 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: //
+// mode: C++                //
+// compile-command: "gmake -f ../Makefile" //
+// End: //
Index: translator/Parser/TypeData.cc
===================================================================
--- translator/Parser/TypeData.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/TypeData.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,1074 @@
+#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;
+    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;
+    }
+  }
+  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::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::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;
+}
+
Index: translator/Parser/TypeData.h
===================================================================
--- translator/Parser/TypeData.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/TypeData.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,128 @@
+#ifndef TYPEDATA_H
+#define TYPEDATA_H
+
+#include <list>
+#include "ParseNode.h"
+#include "SynTree/SynTree.h"
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SemanticError.h"
+#include "LinkageSpec.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 that will later be 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 /* #ifndef TYPEDATA_H */
Index: translator/Parser/TypedefTable.cc
===================================================================
--- translator/Parser/TypedefTable.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/TypedefTable.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,190 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: TypedefTable.cc,v 1.7 2004/09/14 17:21:12 rcbilson Exp $
+ *
+ */
+
+#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(); i++) {
+	list<Entry> &declList = (*i).second;
+	while (!declList.empty() && declList.front().scope == currentScope) {
+	    declList.pop_front();
+	}
+	if( declList.empty() ) {
+	  table.erase( 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 );
+    }
+}
Index: translator/Parser/TypedefTable.h
===================================================================
--- translator/Parser/TypedefTable.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/TypedefTable.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: TypedefTable.h,v 1.5 2003/05/11 15:24:05 rcbilson Exp $
+ *
+ */
+
+#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);
+    void leaveScope(void);
+    void enterContext( std::string contextName );
+    void leaveContext(void);
+
+    void print(void) const;
+};
+
+#endif /* ifndef TYPEDEFTABLE_H */
Index: translator/Parser/cfa.y
===================================================================
--- translator/Parser/cfa.y	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/cfa.y	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,2746 @@
+/*                               -*- Mode: C -*-
+ *
+ * CForall Grammar Version 1.0, Copyright (C) Peter A. Buhr 2001 -- Permission is granted to copy this
+ *	grammar and to use it within software systems.  THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT
+ *	ANY EXPRESS OR IMPLIED WARRANTIES.
+ *
+ * cfa.y --
+ *
+ * Author           : Peter A. Buhr
+ * Created On       : Sat Sep  1 20:22:55 2001
+ * Last Modified By : Peter A. Buhr
+ * Last Modified On : Mon Nov  3 11:21:43 2003
+ * Update Count     : 856
+ */
+
+/* This grammar is based on the ANSI99 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 C. All of ANSI99 is parsed, except for:
+
+   1. designation with '=' (use ':' instead)
+
+   Most of the syntactic extensions from ANSI90 to ANSI99 C are marked with the comment "ANSI99". 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 ANSI99 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						/* ANSI99 */
+%token FORTRAN						/* ANSI99, extension ISO/IEC 9899:1999 Section J.5.9(1) */
+%token CONST VOLATILE
+%token RESTRICT						/* ANSI99 */
+%token FORALL LVALUE					/* CFA */
+%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
+%token BOOL COMPLEX IMAGINARY				/* ANSI99 */
+%token TYPEOF LABEL					/* GCC */
+%token ENUM STRUCT UNION
+%token TYPE FTYPE DTYPE CONTEXT				/* CFA */
+%token SIZEOF
+%token ALIGNOF 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						/* ANSI99, extension ISO/IEC 9899:1999 Section J.5.10(1) */
+
+/* names and constants: lexer differentiates between identifier and typedef names */
+%token<tok> 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 '}' /* ANSI99 */
+		{ $$ = 0; }
+	;
+
+argument_expression_list:
+	argument_expression
+	| argument_expression_list ',' argument_expression
+						{ $$ = (ExpressionNode *)($1->set_link($3)); }
+	;
+
+argument_expression:
+	/* empty */					/* use default argument */
+		{ $$ = 0; }
+	| 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 */
+		{
+		  if( $2 == 0 ) {
+		    $$ = $1;
+		  } else {
+		    $$ = 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 '}'			/* ANSI99, intermix declarations and statements */
+		{ $$ = new CompoundStmtNode( $5 ); }
+	;
+
+block_item_list:					/* ANSI99 */
+	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 /* ANSI99 */
+		/* 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::Const ); }
+	;
+
+type_qualifier_name:
+	CONST
+		{ $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }
+	| RESTRICT
+		{ $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
+	| VOLATILE
+		{ $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
+	| LVALUE					/* CFA */
+		{ $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
+	| 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:
+	AUTO
+		{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
+	| EXTERN
+		{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
+	| REGISTER
+		{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
+	| STATIC
+		{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
+	| INLINE					/* ANSI99 */
+		/* INLINE is essentially a storage class specifier for functions, and hence, belongs here. */
+		{ $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }
+	| FORTRAN					/* ANSI99 */
+		{ $$ = 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						/* ANSI99 */
+		{ $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
+	| COMPLEX					/* ANSI99 */
+		{ $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }
+	| IMAGINARY					/* ANSI99 */
+		{ $$ = 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 */					/* CFA, no field name */
+		{ $$ = DeclarationNode::newName( 0 ); /* XXX */ }
+	| 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 ANSI99 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 ':'				/* ANSI99, CFA uses ":" instead of "=" */
+	| no_attr_identifier_or_typedef_name ':'		/* GCC, field name */
+						       { $$ = new VarRefNode( $1 ); }
+	;
+
+designator_list:					/* ANSI99 */
+	designator
+	| designator_list designator                   { $$ = (ExpressionNode *)($1->set_link( $2 )); }
+	;
+
+designator:
+	'.' no_attr_identifier_or_typedef_name		/* ANSI99, field name */
+						       { $$ = new VarRefNode( $2 ); }
+	| '[' push assignment_expression pop ']'	/* ANSI99, 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
+		{
+		  if( $1 ) {
+		    $$ = $1->appendList( $3 );
+		  } else {
+		    $$ = $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 ANSI99 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 ANSI99 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 ']'				/* ANSI99 */
+		{ $$ = DeclarationNode::newVarArray( 0 ); }
+	| multi_array_dimension '[' push assignment_expression pop ']'
+		{ $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
+	| multi_array_dimension '[' push '*' pop ']'	/* ANSI99 */
+		{ $$ = $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 ); }
+	| '[' push type_qualifier_list '*' pop ']'	/* remaining ANSI99 */
+		{ $$ = DeclarationNode::newVarArray( $3 ); }
+	| '[' push type_qualifier_list assignment_expression pop ']'
+		{ $$ = DeclarationNode::newArray( $4, $3, false ); }
+	| '[' push STATIC assignment_expression pop ']'
+		{ $$ = DeclarationNode::newArray( $4, 0, true ); }
+	| '[' push STATIC type_qualifier_list assignment_expression pop ']'
+		{ $$ = DeclarationNode::newArray( $5, $4, 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 ANSI99 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 ANSI99 */
+		{ $$ = 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;
+    if( yyfilename ) {
+      cout << yyfilename << ":" << endl;
+    }
+    cout << yylineno << ": syntax error reading token " << *(yylval.tok.str) << endl;
+}
+
+/* Local Variables: */
+/* fill-column: 110 */
+/* compile-command: "gmake" */
+/* End: */
Index: translator/Parser/lex.h
===================================================================
--- translator/Parser/lex.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/lex.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: lex.h,v 1.2 2003/11/07 19:45:31 rcbilson Exp $
+ *
+ * Prototypes that enable Roskind's c5.y to compile with g++
+ * Richard Bilson       5 Jan 2001
+ *
+ */
+
+#ifndef PARSER_LEX_H
+#define PARSER_LEX_H
+
+int yylex();
+void yyerror(char *);
+extern "C" {
+#include <malloc.h>
+}
+
+/* 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 // ifndef PARSER_LEX_H
Index: translator/Parser/lex.l
===================================================================
--- translator/Parser/lex.l	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/lex.l	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,372 @@
+/*                               -*- Mode: C -*- 
+ * 
+ * CForall Lexer Version 1.0, Copyright (C) Peter A. Buhr 2001 -- Permission is granted to copy this
+ *	grammar and to use it within software systems.  THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT
+ *	ANY EXPRESS OR IMPLIED WARRANTIES.
+ * 
+ * lex.l -- 
+ * 
+ * Author           : Peter A. Buhr
+ * Created On       : Sat Sep 22 08:58:10 2001
+ * Last Modified By : Peter A. Buhr
+ * Last Modified On : Sat Nov  1 18:09:47 2003
+ * Update Count     : 197
+ */
+
+%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;
+
+#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 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 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 constant or escape sequence */
+    int j = 0;
+    for ( int i = 0; i < yyleng; 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})*
+
+	/* attribute identifier, GCC: $ in identifier */
+attr_identifier "@"{identifier}
+
+	/*  numeric constants, CFA: '_' in constant */
+hex_quad {hex}{4}
+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'"?\\]
+octal_escape "\\"{octal}{1,3}
+hex_escape "\\""x"{hex}+
+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
+
+%%
+	/* line directives */
+^{h_white}*"#"{h_white}*[0-9]+{h_white}*["][^"\n]+["][^\n]*"\n" {
+	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;
+	  }
+	}
+}
+
+	/* 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 */
+__alignof		{KEYWORD_RETURN(ALIGNOF);}	/* GCC */
+__alignof__		{KEYWORD_RETURN(ALIGNOF);}	/* GCC */
+asm			{KEYWORD_RETURN(ASM);}
+__asm			{KEYWORD_RETURN(ASM);}		/* GCC */
+__asm__			{KEYWORD_RETURN(ASM);}		/* GCC */
+__attribute		{KEYWORD_RETURN(ATTRIBUTE);}	/* GCC */
+__attribute__		{KEYWORD_RETURN(ATTRIBUTE);}	/* GCC */
+auto			{KEYWORD_RETURN(AUTO);}
+_Bool			{KEYWORD_RETURN(BOOL);}		/* ANSI99 */
+break			{KEYWORD_RETURN(BREAK);}
+case			{KEYWORD_RETURN(CASE);}
+catch			{KEYWORD_RETURN(CATCH);}	/* CFA */
+char			{KEYWORD_RETURN(CHAR);}
+choose			{KEYWORD_RETURN(CHOOSE);}
+_Complex		{KEYWORD_RETURN(COMPLEX);}	/* ANSI99 */
+__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);}
+continue		{KEYWORD_RETURN(CONTINUE);}
+default			{KEYWORD_RETURN(DEFAULT);}
+do			{KEYWORD_RETURN(DO);}
+double			{KEYWORD_RETURN(DOUBLE);}
+dtype			{KEYWORD_RETURN(DTYPE);}
+else			{KEYWORD_RETURN(ELSE);}
+enum			{KEYWORD_RETURN(ENUM);}
+__extension__		{KEYWORD_RETURN(EXTENSION);}	/* GCC */
+extern			{KEYWORD_RETURN(EXTERN);}
+fallthru		{KEYWORD_RETURN(FALLTHRU);}
+finally			{KEYWORD_RETURN(FINALLY);}	/* CFA */
+float			{KEYWORD_RETURN(FLOAT);}
+for			{KEYWORD_RETURN(FOR);}
+forall			{KEYWORD_RETURN(FORALL);}
+fortran			{KEYWORD_RETURN(FORTRAN);}
+ftype			{KEYWORD_RETURN(FTYPE);}
+goto			{KEYWORD_RETURN(GOTO);}
+if			{KEYWORD_RETURN(IF);}
+_Imaginary		{KEYWORD_RETURN(IMAGINARY);}	/* ANSI99 */
+__imag			{KEYWORD_RETURN(IMAGINARY);}	/* GCC */
+__imag__		{KEYWORD_RETURN(IMAGINARY);}	/* GCC */
+inline			{KEYWORD_RETURN(INLINE);}	/* ANSI99 */
+__inline		{KEYWORD_RETURN(INLINE);}	/* GCC */
+__inline__		{KEYWORD_RETURN(INLINE);}	/* GCC */
+int			{KEYWORD_RETURN(INT);}
+__label__		{KEYWORD_RETURN(LABEL);}	/* GCC */
+long			{KEYWORD_RETURN(LONG);}
+lvalue			{KEYWORD_RETURN(LVALUE);}
+register		{KEYWORD_RETURN(REGISTER);}
+restrict		{KEYWORD_RETURN(RESTRICT);}	/* ANSI99 */
+__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);}
+struct			{KEYWORD_RETURN(STRUCT);}
+switch			{KEYWORD_RETURN(SWITCH);}
+throw			{KEYWORD_RETURN(THROW);}	/* CFA */
+try			{KEYWORD_RETURN(TRY);}		/* CFA */
+type			{KEYWORD_RETURN(TYPE);}
+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();}
+
+	/* 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"?[']([^'\\\n]|{escape_seq})*['] {RETURN_VAL(CHARACTERconstant);}
+
+	/* string constant */
+"L"?["]([^"\\\n]|{escape_seq})*["] {RETURN_VAL(STRINGliteral);}
+
+	/* 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 ANSI99 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: 100 */
+/* compile-command: "gmake" */
+/* End: */
Index: translator/Parser/module.mk
===================================================================
--- translator/Parser/module.mk	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/module.mk	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,44 @@
+###
+### This file is part of the Cforall project
+###
+### $Id: module.mk,v 1.12 2005/08/30 19:11:40 rcbilson Exp $
+###
+
+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: translator/Parser/parseutility.cc
===================================================================
--- translator/Parser/parseutility.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/parseutility.cc	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,20 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: parseutility.cc,v 1.2 2005/08/29 20:14:15 rcbilson Exp $
+ *
+ */
+
+#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 ) );
+}
Index: translator/Parser/parseutility.h
===================================================================
--- translator/Parser/parseutility.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
+++ translator/Parser/parseutility.h	(revision 51b734528489f81a5af985bfee9aa3b6625b9774)
@@ -0,0 +1,15 @@
+/*
+ * This file is part of the Cforall project
+ *
+ * $Id: parseutility.h,v 1.2 2005/08/29 20:14:15 rcbilson Exp $
+ *
+ */
+
+#ifndef PARSER_PARSEUTILITY_H
+#define PARSER_PARSEUTILITY_H
+
+#include "SynTree/SynTree.h"
+
+Expression *notZeroExpr( Expression *orig );
+
+#endif /* #ifndef PARSER_PARSEUTILITY_H */
