@@ -396,7 +396,7 @@ final class Parsley[+A] private [parsley] (private [parsley] val internal: front
396
396
*/
397
397
def <**> [B ](pf : => Parsley [A => B ]): Parsley [B ] = lift.lift2[A , A => B , B ]((x, f) => f(x), this , pf).uo(" <**>" )
398
398
399
- // FIXME: move into nodes
399
+ // FIXME: names move into nodes
400
400
@ inline private def lseq [B ](q : => Parsley [B ], name : String ): Parsley [A ] = new Parsley (new frontend.<* (this .internal, q.internal)).uo(name)
401
401
@ inline private def rseq [B ](q : => Parsley [B ], name : String ): Parsley [B ] = new Parsley (new frontend.*> (this .internal, q.internal)).uo(name)
402
402
@@ -1020,7 +1020,7 @@ object Parsley extends ParsleyImpl with PlatformSpecific {
1020
1020
* problem: a recursion point inside one of these strict fields
1021
1021
* will cause an infinite loop at runtime! This can be fixed by
1022
1022
* ensuring that this becomes part of a lazy argument. This is
1023
- * a solution described by the [[combinator$.sequence `sequence` ]]
1023
+ * a solution described by the [[combinator$.sequence[A]* `sequence`]]
1024
1024
* combinator, for instance: `p <::> sequence(q, .., r)` will ensure
1025
1025
* that the `sequence` is in a lazy position in `<::>` meaning that
1026
1026
* even if any of `q` to `r` must be lazy, they can go in the strict
@@ -1097,6 +1097,7 @@ private [parsley] abstract class ParsleyImpl {
1097
1097
* @group basic
1098
1098
*/
1099
1099
final def fresh [A ](x : => A ): Parsley [A ] = new Parsley (new singletons.Fresh (x))
1100
+ @ inline private [parsley] final def transFresh [A ](x : => A ) = fresh(x).ut() // FIXME: switch round?
1100
1101
1101
1102
/** This combinator parses its first argument `either`, and then parses either `left` or `right` depending on its result.
1102
1103
*
@@ -1306,12 +1307,40 @@ private [parsley] abstract class ParsleyImpl {
1306
1307
* @group iter
1307
1308
*/
1308
1309
final def many [A ](p : Parsley [A ]): Parsley [List [A ]] = many(p, List )
1310
+ /** This combinator repeatedly parses a given parser '''zero''' or more times, collecting the results into a type `C` via a `Factory[A, C]`.
1311
+ *
1312
+ * Parses a given parser, `p`, repeatedly until it fails. If `p` failed having consumed input,
1313
+ * this combinator fails. Otherwise when `p` fails '''without consuming input''', this combinator
1314
+ * will return all of the results, `x,,1,,` through `x,,n,,` (with `n >= 0`), in a structure: `C(x,,1,,, .., x,,n,,)`.
1315
+ * If `p` was never successful, an empty `C` is returned.
1316
+ *
1317
+ * @example {{{
1318
+ * scala> import parsley.character.string
1319
+ * scala> import parsley.Parsley.many
1320
+ * scala> val p = many(string("ab"), Vector)
1321
+ * scala> p.parse("")
1322
+ * val res0 = Success(Vector.empty)
1323
+ * scala> p.parse("ab")
1324
+ * val res1 = Success(Vector("ab"))
1325
+ * scala> p.parse("abababab")
1326
+ * val res2 = Success(Vector("ab", "ab", "ab", "ab"))
1327
+ * scala> p.parse("aba")
1328
+ * val res3 = Failure(..)
1329
+ * }}}
1330
+ *
1331
+ * @param p the parser to execute multiple times.
1332
+ * @param factory a way to construct the result type `C`
1333
+ * @tparam C a structure that can store `A`s inside it.
1334
+ * @return a parser that parses `p` until it fails, returning all of all the successful results.
1335
+ * @since 5.0.0
1336
+ * @group iter
1337
+ */
1338
+ final def many [A , C ](p : Parsley [A ], factory : Factory [A , C ]): Parsley [C ] = secretSome(fresh(factory.newBuilder), p, " many" )
1309
1339
// this is needed for Scala 2 to avoid manual ascription (and ascribes cleaner), but isn't really needed for Scala 3 and increases doc/API footprint
1310
- // we can add them later if we really wanted to
1340
+ // we can add them later if we really wanted to. Alternatively, p.many(factory) would remove this problem entirely and provide better intellisense.
1311
1341
// final private [parsley] def many[A, CC[_]](p: Parsley[A], factory: IterableFactory[CC]): Parsley[CC[A]] = many[A, CC[A]](p, factory)
1312
1342
// this is needed for Scala 2 (or manual ascription on A+C) for ArraySeq, but isn't really needed for Scala 3, and saves 2.12 work
1313
1343
// final def many[Ev[_], A: Ev, CC[_]](p: Parsley[A], factory: EvidenceIterableFactory[CC, Ev]): Parsley[CC[A]] = many[A, CC[A]](p, factory)
1314
- final private [parsley] def many [A , C ](p : Parsley [A ], factory : Factory [A , C ]): Parsley [C ] = new Parsley (new frontend.Many (p.internal, factory))
1315
1344
1316
1345
/** This combinator repeatedly parses a given parser '''one''' or more times, collecting the results into a list.
1317
1346
*
@@ -1339,15 +1368,40 @@ private [parsley] abstract class ParsleyImpl {
1339
1368
* @since 4.5.0
1340
1369
* @group iter
1341
1370
*/
1342
- final def some [A ](p : Parsley [A ]): Parsley [List [A ]] = (p <::> many(p).ut()).uo(" some" )
1343
- private [parsley] final def some [A , C ](p : Parsley [A ], factory : Factory [A , C ]): Parsley [C ] = secretSome(p, p, factory).uo(" some" )
1344
- // This could be generalised to be the new many, where many(p, factory) = secretSome(fresh(factory.newBuilder), p, factory)
1345
- private [parsley] final def secretSome [A , C ](init : Parsley [A ], p : Parsley [A ], factory : Factory [A , C ]): Parsley [C ] = {
1346
- secretSome(init.map(factory.newBuilder += _).ut(), p)
1371
+ final def some [A ](p : Parsley [A ]): Parsley [List [A ]] = some(p, List )
1372
+ /** This combinator repeatedly parses a given parser '''one''' or more times, collecting the results into a type `C` via a `Factory[A, C]`.
1373
+ *
1374
+ * Parses a given parser, `p`, repeatedly until it fails. If `p` failed having consumed input,
1375
+ * this combinator fails. Otherwise when `p` fails '''without consuming input''', this combinator
1376
+ * will return all of the results, `x,,1,,` through `x,,n,,` (with `n >= 1`), in a structure: `C(x,,1,,, .., x,,n,,)`.
1377
+ * If `p` was not successful at least one time, this combinator fails.
1378
+ *
1379
+ * @example {{{
1380
+ * scala> import parsley.character.string
1381
+ * scala> import parsley.Parsley.some
1382
+ * scala> val p = some(string("ab"), Vector)
1383
+ * scala> p.parse("")
1384
+ * val res0 = Failure(..)
1385
+ * scala> p.parse("ab")
1386
+ * val res1 = Success(Vector("ab"))
1387
+ * scala> p.parse("abababab")
1388
+ * val res2 = Success(Vector("ab", "ab", "ab", "ab"))
1389
+ * scala> p.parse("aba")
1390
+ * val res3 = Failure(..)
1391
+ * }}}
1392
+ *
1393
+ * @param p the parser to execute multiple times.
1394
+ * @param factory a way to construct the result type `C`.
1395
+ * @tparam C a structure that can store `A`s inside it.
1396
+ * @return a parser that parses `p` until it fails, returning all of all the successful results.
1397
+ * @since 5.0.0
1398
+ * @group iter
1399
+ */
1400
+ final def some [A , C ](p : Parsley [A ], factory : Factory [A , C ]): Parsley [C ] = secretSome(p, p, factory, " some" )
1401
+ private [parsley] final def secretSome [A , C ](init : Parsley [A ], p : Parsley [A ], factory : Factory [A , C ], debugName : String ): Parsley [C ] = {
1402
+ secretSome(init.map(factory.newBuilder += _).ut(), p, debugName)
1347
1403
}
1348
- private [parsley] final def secretSome [A , C ](init : Parsley [mutable.Builder [A , C ]], p : Parsley [A ]): Parsley [C ] = {
1349
- val pf = transPure[(mutable.Builder [A , C ], A ) => mutable.Builder [A , C ]](_ += _)
1350
- // Can't use the regular foldLeft1 here, because we need a fresh Builder each time.
1351
- expr.infix.secretLeft1(init, p, pf, null ).map(_.result())
1404
+ private [parsley] final def secretSome [A , C ](init : Parsley [mutable.Builder [A , C ]], p : Parsley [A ], debugName : String ): Parsley [C ] = {
1405
+ new Parsley (new frontend.Many (init.internal, p.internal, debugName))
1352
1406
}
1353
1407
}
0 commit comments