@@ -19,16 +19,33 @@ package cron4s
19
19
import _root_ .atto ._
20
20
import Atto ._
21
21
import cats .implicits ._
22
-
23
22
import cron4s .expr ._
24
23
25
24
package object atto {
26
25
import CronField ._
27
26
import CronUnit ._
28
27
29
- private val sexagesimal : Parser [Int ] = int.filter(x => x >= 0 && x < 60 )
30
- private val decimal : Parser [Int ] = int.filter(x => x >= 0 )
31
- private val literal : Parser [String ] = takeWhile1(_ >= ' ' )
28
+ private def oneOrTwoDigitsPositiveInt : Parser [Int ] = {
29
+
30
+ val getDigits = for {
31
+ d1 <- digit
32
+ d2 <- opt(digit)
33
+ } yield d2.fold(s " $d1" )(x => s " $d1$x" )
34
+
35
+ getDigits.flatMap(s =>
36
+ try {
37
+ ok(s.toInt)
38
+ } catch {
39
+ // scala-js can't parse non-alpha digits so we just fail in that case.
40
+ case _ : java.lang.NumberFormatException =>
41
+ err[Int ](" https://github.com/scala-js/scala-js/issues/2935" )
42
+ }
43
+ )
44
+ } namedOpaque " oneOrTwoDigitsPositiveInt"
45
+
46
+ private val sexagesimal : Parser [Int ] = oneOrTwoDigitsPositiveInt.filter(x => x >= 0 && x < 60 )
47
+
48
+ private val literal : Parser [String ] = takeWhile1(x => x != ' ' && x != '-' )
32
49
33
50
private val hyphen : Parser [Char ] = elem(_ == '-' , " hyphen" )
34
51
private val comma : Parser [Char ] = elem(_ == ',' , " comma" )
@@ -54,17 +71,17 @@ package object atto {
54
71
// Hours
55
72
56
73
val hours : Parser [ConstNode [Hour ]] =
57
- decimal .filter(x => (x >= 0 ) && (x < 24 )).map(ConstNode [Hour ](_))
74
+ oneOrTwoDigitsPositiveInt .filter(x => (x >= 0 ) && (x < 24 )).map(ConstNode [Hour ](_))
58
75
59
76
// Days Of Month
60
77
61
78
val daysOfMonth : Parser [ConstNode [DayOfMonth ]] =
62
- decimal .filter(x => (x >= 1 ) && (x <= 31 )).map(ConstNode [DayOfMonth ](_))
79
+ oneOrTwoDigitsPositiveInt .filter(x => (x >= 1 ) && (x <= 31 )).map(ConstNode [DayOfMonth ](_))
63
80
64
81
// Months
65
82
66
83
private [this ] val numericMonths =
67
- decimal .filter(_ <= 12 ).map(ConstNode [Month ](_))
84
+ oneOrTwoDigitsPositiveInt .filter(x => (x >= 0 ) && (x <= 12 ) ).map(ConstNode [Month ](_))
68
85
69
86
private [this ] val textualMonths =
70
87
literal.filter(Months .textValues.contains).map { value =>
@@ -78,7 +95,7 @@ package object atto {
78
95
// Days Of Week
79
96
80
97
private [this ] val numericDaysOfWeek =
81
- decimal .filter(_ < 7 ).map(ConstNode [DayOfWeek ](_))
98
+ oneOrTwoDigitsPositiveInt .filter(x => (x >= 0 ) && (x <= 6 ) ).map(ConstNode [DayOfWeek ](_))
82
99
83
100
private [this ] val textualDaysOfWeek =
84
101
literal.filter(DaysOfWeek .textValues.contains).map { value =>
@@ -111,9 +128,10 @@ package object atto {
111
128
unit : CronUnit [F ]
112
129
): Parser [SeveralNode [F ]] = {
113
130
def compose (b : => Parser [EnumerableNode [F ]]) =
114
- sepBy1(b, comma)
115
- .filter(_.size > 1 )
116
- .map(values => SeveralNode .fromSeq[F ](values.toList).get)
131
+ sepBy(b, comma)
132
+ .collect {
133
+ case first :: second :: tail => SeveralNode (first, second, tail:_* )
134
+ }
117
135
118
136
compose(between(base).map(between2Enumerable) | base.map(const2Enumerable))
119
137
}
@@ -122,7 +140,7 @@ package object atto {
122
140
unit : CronUnit [F ]
123
141
): Parser [EveryNode [F ]] = {
124
142
def compose (b : => Parser [DivisibleNode [F ]]) =
125
- ((b <~ slash) ~ decimal .filter(_ > 0 )).map {
143
+ ((b <~ slash) ~ oneOrTwoDigitsPositiveInt .filter(_ > 0 )).map {
126
144
case (exp, freq) => EveryNode [F ](exp, freq)
127
145
}
128
146
@@ -166,8 +184,9 @@ package object atto {
166
184
} yield CronExpr (sec, min, hour, day, month, weekDay)
167
185
168
186
def parse (e : String ): Either [Error , CronExpr ] =
169
- (cron.parseOnly(e): @ unchecked) match {
187
+ (phrase( cron) .parseOnly(e): @ unchecked) match {
170
188
case ParseResult .Done (_, result) => Right (result)
189
+ case ParseResult .Fail (" " , _, _) => Left (ExprTooShort )
171
190
case ParseResult .Fail (rest, _, msg) =>
172
191
val position = e.length() - rest.length() + 1
173
192
Left (ParseFailed (msg, position, Some (rest)))
0 commit comments