anchor.diff:        | fn=COUNT OPEN! STAR CLOSE! { $agg = evalAgg("count", $fn.type); }
       ;
   
  -/*
  -fieldAccess returns [PostAggregator p]
  -    : IDENT { $p = new FieldAccessPostAggregator($IDENT.text, $IDENT.text); }
  -    ;
  -*/
  -
   constant returns [ConstantPostAggregator c]
  -    : value=INTEGER { int v = Integer.parseInt($value.text); $c = new ConstantPostAggregator(Integer.toString(v), v); }
  -    | value=DOUBLE  { double v = Double.parseDouble($value.text); $c = new ConstantPostAggregator(Double.toString(v), v); }
  -    ;
  -
  -timeAndDimFilter
  -    : t=timeFilter (AND f=dimFilter)? {
  -        if($f.ctx != null) this.filter = $f.filter;
  -        this.intervals = Lists.newArrayList($t.interval);
  +    : value=DOUBLE  { double v = Double.parseDouble($value.text); $c = new ConstantPostAggregator(Double.toString(v), v); }
  +    ;
  +
  +/* time filters must be top level filters */
  +timeAndDimFilter returns [DimFilter filter, org.joda.time.Interval interval]
  +    : t=timeFilter (AND f=dimFilter)?  {
  +        if($f.ctx != null) $filter = $f.filter;
  +        $interval = $t.interval;
       }
       | (f=dimFilter)? AND t=timeFilter {
  -        if($f.ctx != null) this.filter = $f.filter;
  -        this.intervals = Lists.newArrayList($t.interval);
  +        if($f.ctx != null) $filter = $f.filter;
  +        $interval = $t.interval;
       }
       ;
   
  
positive.code:     }
      ;
  
  timeFilter returns [org.joda.time.Interval interval]
      : 'timestamp' 'between' s=timestamp AND e=timestamp {
          $interval = new org.joda.time.Interval(new DateTime(unescape($s.text)), new DateTime(unescape($e.text)));
      }
      ;
  
  timestamp
      : INTEGER | QUOTED_STRING
      ;
  
negative.code:     ;
  
  where_stmt
      : 'where' f=timeAndDimFilter {
          if($f.filter != null) this.filter = $f.filter;
          this.intervals = Lists.newArrayList($f.interval);
      }
      ;
  
  groupby_stmt
      : GROUP 'by' groupByExpression ( COMMA! groupByExpression )*
      ;
  
  groupByExpression
      : gran=granularityFn {this.granularity = $gran.granularity;}
      | dim=IDENT { this.groupByDimensions.put($dim.text, new DefaultDimensionSpec($dim.text, $dim.text)); }
      ;
  
  datasource
  