Skip to content

Commit

Permalink
Make iterator work with a child axis
Browse files Browse the repository at this point in the history
  • Loading branch information
satabin committed Sep 26, 2023
1 parent 072df6b commit ddc7d7e
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ private[fs2] abstract class QueryCompiler[InTag, OutTag, Path] {
type Pattern
type Guard

protected val emitSelected: Boolean = true

/** A single char to be matched in a path */
type Char

Expand Down Expand Up @@ -121,9 +123,12 @@ private[fs2] abstract class QueryCompiler[InTag, OutTag, Path] {
val pat: builder.Guardable = tagOf(pattern).fold(anyNode)(aNode(_))
if (!finalTgt) {
q1(pat.when(guard)) -> q2(x1, copyArgs: _*) ~ q1(x2, copyArgs: _*)
} else {
} else if (emitSelected) {
q1(pat.when(guard)) -> end(x1, (copyArgs :+ copy(qcopy(x1))): _*) ~ q2(x1, copyArgs: _*) ~
q1(x2, copyArgs: _*)
} else {
q1(pat.when(guard)) -> end(x1, (copyArgs :+ qcopy(x1)): _*) ~ q2(x1, copyArgs: _*) ~
q1(x2, copyArgs: _*)
}
states1
}
Expand Down
1 change: 1 addition & 0 deletions json/src/main/scala-2/fs2/data/json/jq/literals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ object literals {
case Jq.Field(name) => q"_root_.fs2.data.json.jq.Jq.Field($name)"
case Jq.Index(idx) => q"_root_.fs2.data.json.jq.Jq.Index($idx)"
case Jq.Slice(idx1, idx2) => q"_root_.fs2.data.json.jq.Jq.Slice($idx1, $idx2)"
case Jq.Child => q"_root_.fs2.data.json.jq.Jq.Child"
case Jq.RecursiveDescent => q"_root_.fs2.data.json.jq.Jq.RecursiveDescent"
case Jq.Sequence(qs) =>
q"_root_.fs2.data.json.jq.Jq.Sequence(_root_.cats.data.NonEmptyChain.fromNonEmptyList(${qs.toNonEmptyList.widen[Jq]}))"
Expand Down
1 change: 1 addition & 0 deletions json/src/main/scala-3/fs2/data/json/jq/literals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ package object literals {
case Jq.Field(name) => '{ Jq.Field(${ Expr(name) }) }
case Jq.Index(idx) => '{ Jq.Index(${ Expr(idx) }) }
case Jq.Slice(idx1, idx2) => '{ Jq.Slice(${ Expr(idx1) }, ${ Expr(idx2) }) }
case Jq.Child => '{ Jq.Child }
case Jq.RecursiveDescent => '{ Jq.RecursiveDescent }
case Jq.Sequence(qs) =>
'{ Jq.Sequence(NonEmptyChain.fromNonEmptyList(${ Expr(qs.toNonEmptyList) })) }
Expand Down
10 changes: 6 additions & 4 deletions json/src/main/scala/fs2/data/json/jq/JqParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,15 @@ object JqParser {
.withContext("string, index, slice 'min:max' (with min <= max), slice 'idx:', or slice ':idx'")

val step: P[Filter] =
(P.char('.') *> P
(ch('.') *> P
.oneOf(
identifier.map(Jq.Field(_)) ::
access.backtrack ::
Nil) ~ access.backtrack.repAs0[Filter])
.map { case (fst, snd) =>
fst ~ snd
Nil)
.? ~ access.backtrack.repAs0[Filter])
.map {
case (Some(fst), snd) => fst ~ snd
case (None, access) => Jq.Identity ~ access
}
.repAs[Filter]

Expand Down
3 changes: 2 additions & 1 deletion json/src/main/scala/fs2/data/json/jq/ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ object Jq {
final case class Field(name: String) extends SimpleFilter
final case class Index(idx: Int) extends SimpleFilter
final case class Slice(start: Int, end: Option[Int]) extends SimpleFilter
final case object RecursiveDescent extends SimpleFilter
case object RecursiveDescent extends SimpleFilter
private[jq] final case object Child extends SimpleFilter
final case class Sequence(jqs: NonEmptyChain[SimpleFilter]) extends Filter

final case class Iterator(filter: Filter, inner: Jq) extends Jq
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,7 @@ private[jq] class ESPCompiledJq[F[_]: RaiseThrowable](val esp: JqESP[F]) extends
def apply(in: Stream[F, Token]): Stream[F, Token] =
in.through(JsonTagger.pipe)
.through(esp.pipe)
.mapAccumulate(0) {
case (0, TaggedJson.StartObjectValue(_)) =>
(0, None)
case (depth, TaggedJson.Raw(Token.StartObject)) =>
(depth + 1, Some(Token.StartObject))
case (depth, TaggedJson.Raw(Token.EndObject)) =>
(depth - 1, Some(Token.EndObject))
case (depth, TaggedJson.Raw(t)) =>
(depth, Some(t))
case (depth, TaggedJson.StartArrayElement(_)) =>
(depth, None)
case (depth, TaggedJson.EndArrayElement) =>
(depth, None)
case (depth, TaggedJson.StartObjectValue(name)) =>
(depth, Some(Token.Key(name)))
case (depth, TaggedJson.EndObjectValue) =>
(depth, None)
case (depth, TaggedJson.StartJson) =>
(depth, None)
case (depth, TaggedJson.EndJson) =>
(depth, None)
}
.map(_._2)
.map(untag(_))
.unNone

def andThen(that: CompiledJq[F]): CompiledJq[F] =
Expand Down
16 changes: 13 additions & 3 deletions json/src/main/scala/fs2/data/json/jq/internal/ESPJqCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ private[jq] class ESPJqCompiler[F[_]](implicit F: MonadThrow[F], defer: Defer[F]
extends QueryCompiler[TaggedJson, TaggedJson, Filter]
with Compiler[F] {

override protected val emitSelected: Boolean = false

private type State[T] = StateT[F, Int, T]

private def nextIdent: State[String] =
Expand Down Expand Up @@ -75,6 +77,9 @@ private[jq] class ESPJqCompiler[F[_]](implicit F: MonadThrow[F], defer: Defer[F]
Regular.chars[TaggedMatcher](TaggedMatcher.StartArray) ~ Regular.chars(TaggedMatcher.Slice(start, end))
case Jq.Index(idx) =>
Regular.chars[TaggedMatcher](TaggedMatcher.StartArray) ~ Regular.chars(TaggedMatcher.Index(idx))
case Jq.Child =>
(Regular.chars[TaggedMatcher](TaggedMatcher.StartArray) ||
Regular.chars[TaggedMatcher](TaggedMatcher.StartObject)) ~ Regular.any
case Jq.RecursiveDescent =>
((Regular.chars[TaggedMatcher](TaggedMatcher.StartArray) ||
Regular.chars[TaggedMatcher](TaggedMatcher.StartObject)) ~ Regular.any).rep
Expand Down Expand Up @@ -247,7 +252,7 @@ private[jq] class ESPJqCompiler[F[_]](implicit F: MonadThrow[F], defer: Defer[F]
val forClause: Query[TaggedJson, Filter] =
Query.ForClause(
v,
prefix ~ prefix1 ~ filter,
prefix ~ prefix1 ~ filter ~ Jq.Child,
Query.Node(
TaggedJson.Raw(Token.StartArray),
Query.Sequence(
Expand Down Expand Up @@ -295,7 +300,7 @@ private[jq] class ESPJqCompiler[F[_]](implicit F: MonadThrow[F], defer: Defer[F]
val forClause: Query[TaggedJson, Filter] =
Query.ForClause(
v,
prefix ~ prefix1 ~ filter,
prefix ~ prefix1 ~ filter ~ Jq.Child,
Query.Node(
TaggedJson.Raw(Token.StartObject),
Query.Sequence(
Expand All @@ -311,10 +316,15 @@ private[jq] class ESPJqCompiler[F[_]](implicit F: MonadThrow[F], defer: Defer[F]
raiseError(
JqException(s"object constructors may have only one iterator element, but got ${iterators.size}"))
}
case Jq.Iterator(filter, inner) =>
case Jq.Iterator(filter, inner: Constructor) =>
for {
v <- nextIdent
inner <- preprocess(Jq.Identity, inner)
} yield Query.ForClause(v, prefix ~ filter ~ Jq.Child, inner)
case Jq.Iterator(filter, inner) =>
for {
v <- nextIdent
inner <- preprocess(Jq.Child, inner)
} yield Query.ForClause(v, prefix ~ filter, inner)
case filter: Filter =>
pure(Query.Ordpath(prefix ~ filter))
Expand Down

0 comments on commit ddc7d7e

Please sign in to comment.