Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

Commit

Permalink
Merge pull request #121 from erickt/range
Browse files Browse the repository at this point in the history
Add support for range expressions
  • Loading branch information
erickt authored Nov 1, 2016
2 parents a9a1fae + c57a09e commit c8b852d
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
100 changes: 100 additions & 0 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,12 @@ impl<F> ExprBuilder<F>
}).span(span)
}

pub fn range(self) -> ExprRangeBuilder<F> {
ExprRangeBuilder {
builder: self,
}
}

pub fn build_repeat(self, lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> F::Result {
self.build_expr_kind(ast::ExprKind::Repeat(lhs, rhs))
}
Expand Down Expand Up @@ -1437,6 +1443,100 @@ impl<F> Invoke<P<ast::Expr>> for ExprIndexLhsBuilder<F>

//////////////////////////////////////////////////////////////////////////////

pub struct ExprRangeBuilder<F> {
builder: ExprBuilder<F>,
}

impl<F> ExprRangeBuilder<F>
where F: Invoke<P<ast::Expr>>,
{
pub fn from(self) -> ExprBuilder<Self> {
ExprBuilder::with_callback(self)
}

pub fn to(self) -> ExprBuilder<ExprRangeToBuilder<F>> {
self.from_opt(None).to()
}

pub fn to_inclusive(self) -> ExprBuilder<ExprRangeToBuilder<F>> {
self.from_opt(None).to_inclusive()
}

pub fn from_opt(self, from: Option<P<ast::Expr>>) -> ExprRangeFromBuilder<F> {
ExprRangeFromBuilder {
builder: self.builder,
from: from,
}
}

pub fn build(self) -> F::Result {
self.from_opt(None).build()
}
}

impl<F> Invoke<P<ast::Expr>> for ExprRangeBuilder<F>
where F: Invoke<P<ast::Expr>>,
{
type Result = ExprRangeFromBuilder<F>;

fn invoke(self, from: P<ast::Expr>) -> ExprRangeFromBuilder<F> {
self.from_opt(Some(from))
}
}

//////////////////////////////////////////////////////////////////////////////

pub struct ExprRangeFromBuilder<F> {
builder: ExprBuilder<F>,
from: Option<P<ast::Expr>>,
}

impl<F> ExprRangeFromBuilder<F>
where F: Invoke<P<ast::Expr>>,
{
pub fn to(self) -> ExprBuilder<ExprRangeToBuilder<F>> {
ExprBuilder::with_callback(ExprRangeToBuilder {
builder: self,
limit: ast::RangeLimits::HalfOpen,
})
}

pub fn to_inclusive(self) -> ExprBuilder<ExprRangeToBuilder<F>> {
ExprBuilder::with_callback(ExprRangeToBuilder {
builder: self,
limit: ast::RangeLimits::Closed,
})
}

pub fn build(self) -> F::Result {
self.to_opt(None, ast::RangeLimits::HalfOpen)
}

pub fn to_opt(self, to: Option<P<ast::Expr>>, limit: ast::RangeLimits) -> F::Result {
let kind = ast::ExprKind::Range(self.from, to, limit);
self.builder.build_expr_kind(kind)
}
}

//////////////////////////////////////////////////////////////////////////////

pub struct ExprRangeToBuilder<F> {
builder: ExprRangeFromBuilder<F>,
limit: ast::RangeLimits,
}

impl<F> Invoke<P<ast::Expr>> for ExprRangeToBuilder<F>
where F: Invoke<P<ast::Expr>>,
{
type Result = F::Result;

fn invoke(self, expr: P<ast::Expr>) -> F::Result {
self.builder.to_opt(Some(expr), self.limit)
}
}

//////////////////////////////////////////////////////////////////////////////

pub struct ExprRepeatBuilder<F> {
builder: ExprBuilder<F>,
}
Expand Down
62 changes: 62 additions & 0 deletions tests/test_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,68 @@ fn test_index() {
);
}

#[test]
fn test_range() {
let builder = AstBuilder::new();

assert_eq!(
builder.expr().range().build(),
builder.expr().build_expr_kind(
ast::ExprKind::Range(
None,
None,
ast::RangeLimits::HalfOpen)
)
);

assert_eq!(
builder.expr().range().from()
.usize(0)
.build(),
builder.expr().build_expr_kind(
ast::ExprKind::Range(
Some(builder.expr().usize(0)),
None,
ast::RangeLimits::HalfOpen)
)
);

assert_eq!(
builder.expr().range()
.to().usize(10),
builder.expr().build_expr_kind(
ast::ExprKind::Range(
None,
Some(builder.expr().usize(10)),
ast::RangeLimits::HalfOpen)
)
);

assert_eq!(
builder.expr().range()
.from().usize(0)
.to().usize(10),
builder.expr().build_expr_kind(
ast::ExprKind::Range(
Some(builder.expr().usize(0)),
Some(builder.expr().usize(10)),
ast::RangeLimits::HalfOpen)
)
);

assert_eq!(
builder.expr().range()
.from().usize(0)
.to_inclusive().usize(10),
builder.expr().build_expr_kind(
ast::ExprKind::Range(
Some(builder.expr().usize(0)),
Some(builder.expr().usize(10)),
ast::RangeLimits::Closed)
)
);
}

#[test]
fn test_repeat() {
let builder = AstBuilder::new();
Expand Down

0 comments on commit c8b852d

Please sign in to comment.