def make_relation expr, pred
exprs = expr.delimited1(comma)
relation = nil
lazy_relation = lazy{relation}
term_relation = word {|w|TableRelation.new w} | operator['('] >> lazy_relation << operator[')']
sub_relation = sequence(term_relation, (keyword[:as].optional >> word).optional) do |rel, name|
case when name.nil?: rel else AliasRelation.new(rel, name) end
end
joined_relation = sub_relation.postfix(join_maker(lazy{joined_relation}, pred))
where_clause = keyword[:where] >> pred
order_element = sequence(expr, (keyword[:asc] >> true | keyword[:desc] >> false).optional(true),
&ctor(OrderElement))
order_elements = order_element.separated1(comma)
exprs = expr.separated1(comma)
order_by_clause = keyword[:order] >> keyword[:by] >> order_elements
group_by = keyword[:group] >> keyword[:by] >> exprs
group_by_clause = sequence(group_by, (keyword[:having] >> pred).optional, &ctor(GroupByClause))
relation = sub_relation | sequence(keyword[:select],
keyword[:distinct].optional(false), exprs,
keyword[:from], joined_relation,
where_clause.optional, group_by_clause.optional, order_by_clause.optional
) do |_, distinct, projected, _, from, where, groupby, orderby|
SelectRelation.new(projected, distinct, from, where, groupby, orderby)
end
relation = sequence(relation, (keyword[:limit] >> token(:number, &To_i)).optional) do |rel, limit|
case when limit.nil?: rel else LimitRelation.new(rel, limit) end
end
relation = relation.infixl(union_maker)
end