Skip to content

Commit 63bacd8

Browse files
committed
doc(patterns): documentation for preventative errors
1 parent 55a57cd commit 63bacd8

File tree

1 file changed

+89
-9
lines changed

1 file changed

+89
-9
lines changed

parsley/shared/src/main/scala/parsley/errors/patterns.scala

+89-9
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ object patterns {
3636
* @define atomicNonTerminal
3737
* when this parser is not to be considered as a terminal error, use `atomic` around the ''entire'' combinator to
3838
* allow for backtracking if this parser succeeds (and therefore fails).
39-
*
40-
* @define Ensures this parser does not succeed, failing with a
4139
*/
4240
implicit final class VerifiedErrors[P, A](p: P)(implicit con: P => Parsley[A]) {
4341
/** Ensures this parser does not succeed, failing with a specialised error based on this parsers result if it does.
@@ -117,7 +115,7 @@ object patterns {
117115
* the given `errGen` with width the same as the parsed data. However, if this parser fails, no input is consumed
118116
* and an empty error is generated. This parser will produce no labels if it fails.
119117
*
120-
* @param err
118+
* @param err the generator that produces the error message.
121119
* @since 4.4.0
122120
* @note $autoAmend
123121
* @note $atomicNonTerminal
@@ -134,20 +132,102 @@ object patterns {
134132
@inline private def verifiedWithVanillaRaw(reasonGen: A => Option[String]) = verifiedWithVanilla(_ => VanillaGen.RawItem, reasonGen)
135133
}
136134

137-
// TODO: document!
135+
/** This class exposes combinators related to the ''Preventative Errors'' parser design pattern.
136+
*
137+
* This extension class operates on values that are convertible to parsers. The combinators it enables
138+
* allow for the parsing of known illegal values, providing richer error messages in case they succeed.
139+
*
140+
* @constructor This constructor should not be called manually, it is designed to be used via Scala's implicit resolution.
141+
* @param p the value that this class is enabling methods on.
142+
* @param con a conversion that allows values convertible to parsers to be used.
143+
* @tparam P the type of base value that this class is used on (the conversion to `Parsley`) is summoned automatically.
144+
* @since 4.4.0
145+
*
146+
* @define autoAmend
147+
* when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the
148+
* parse (as if [[parsley.errors.combinator$.amend `amend`]] had been used) and the caret will span the entire
149+
* successful parse of this parser.
150+
*
151+
* @define atomicNonTerminal
152+
* when this parser is not to be considered as a terminal error, use `atomic` around the ''entire'' combinator to
153+
* allow for backtracking if this parser succeeds (and therefore fails).
154+
*/
138155
implicit final class PreventativeErrors[P, A](p: P)(implicit con: P => Parsley[A]) {
139-
// TODO: document and test
156+
// TODO: test
157+
/** Ensures this parser does not succeed, failing with a specialised error based on this parsers result if it does.
158+
*
159+
* If this parser succeeds, input is consumed and this combinator will fail, producing an error message
160+
* based on the parsed result. However, if this parser fails, no input is consumed and this combinator succeeds.
161+
* This parser will produce no evidence of running if it succeeds.
162+
*
163+
* @param msggen the function that generates the error messages from the parsed value.
164+
* @since 4.4.0
165+
* @note $autoAmend
166+
* @note $atomicNonTerminal
167+
*/
140168
def preventativeFail(msggen: A => Seq[String]): Parsley[Unit] = this.preventWith(new SpecialisedGen[A] {
141169
override def messages(x: A) = msggen(x)
142170
})
143-
// TODO: document and test
171+
172+
// TODO: test
173+
/** Ensures this parser does not succeed, failing with a fixed specialised error if it does.
174+
*
175+
* If this parser succeeds, input is consumed and this combinator will fail, producing an error message with the
176+
* given messages. However, if this parser fails, no input is consumed and this combinator succeeds.
177+
* This parser will produce no evidence of running if it succeeds.
178+
*
179+
* @param msg0 the first message in the error message.
180+
* @param msgs the remaining messages that will make up the error message.
181+
* @since 4.4.0
182+
* @note $autoAmend
183+
* @note $atomicNonTerminal
184+
*/
144185
def preventativeFail(msg0: String, msgs: String*): Parsley[Unit] = this.preventativeFail(_ => msg0 +: msgs)
145-
// TODO: document and test
186+
187+
// TODO: test
188+
/** Ensures this parser does not succeed, failing with a vanilla error with an unexpected message and caret spanning the parse and a reason generated
189+
* from this parser's result.
190+
*
191+
* If this parser succeeds, input is consumed and this combinator will fail, producing an unexpected message the same width as
192+
* the parse along with a reason generated from the successful parse along with the given labels. However, if this parser fails, no input is
193+
* consumed and this combinator succeeds. This parser will produce no evidence of running if it succeeds.
194+
*
195+
* @param reason a function that produces a reason for the error given the parsed result.
196+
* @param labels the labels that should be expected if this parser hadn't succeeded.
197+
* @since 4.4.0
198+
* @note $autoAmend
199+
* @note $atomicNonTerminal
200+
*/
146201
def preventativeExplain(reason: A => String, labels: String*): Parsley[Unit] = this.preventWithVanillaRaw(x => Some(reason(x)), labels: _*)
147-
// TODO: document and test
202+
203+
// TODO: test
204+
/** Ensures this parser does not succeed, failing with a vanilla error with an unexpected message and caret spanning the parse and a given reason.
205+
*
206+
* If this parser succeeds, input is consumed and this combinator will fail, producing an unexpected message the same width as
207+
* the parse along with the given reason and given labels. However, if this parser fails, no input is consumed and this combinator succeeds.
208+
* This parser will produce no evidence of running if it succeeds.
209+
*
210+
* @param reason the reason that this parser is illegal.
211+
* @param labels the labels that should be expected if this parser hadn't succeeded.
212+
* @since 4.4.0
213+
* @note $autoAmend
214+
* @note $atomicNonTerminal
215+
*/
148216
def preventativeExplain(reason: String, labels: String*): Parsley[Unit] = this.preventativeExplain(_ => reason, labels: _*)
149217

150-
// TODO: document and test
218+
// TODO: test
219+
/** Ensures this parser does not succeed, failing with an error as described by the given `ErrorGen` object.
220+
*
221+
* If this parser succeeds, input is consumed and this combinator will fail, producing an error message using
222+
* the given `errGen` with width the same as the parsed data along with the given labels. However, if this parser
223+
* fails, no input is consumed and this combinator succeeds. This parser will produce no evidence of running if it succeeds.
224+
*
225+
* @param err the generator that produces the error message.
226+
* @param labels the labels that should be expected if this parser hadn't succeeded.
227+
* @since 4.4.0
228+
* @note $autoAmend
229+
* @note $atomicNonTerminal
230+
*/
151231
def preventWith(err: ErrorGen[A], labels: String*) = {
152232
val inner: Parsley[Either[(A, Int), Unit]] = withWidth(atomic(con(p)).newHide) <+> unit
153233
val labelledErr = labels match {

0 commit comments

Comments
 (0)