How to resolve FParsec error "Combinator" many "has been applied to a parser that succeeds without consuming ..."

I have a parser that seems straightforward enough. I added this subparator to the end to give information about common parsing errors, since all the other subparallels failed -

/// Read the rest of a line as an error.
let readError =
    parse {
        let! restOfLineStr = restOfLine true
        return makeViolation ("Read error on: " + restOfLineStr + ".") }

/// Read an expression.
do readExprRef :=
    choice
        [attempt readBoolean
         attempt readCharacter
         attempt readString
         attempt readInt
         attempt readError] // just now added this sub-parser, and get the issue

However, as soon as I add readError as a choice, I get a terrible FParsec error about thread consumption at runtime - The combinator 'many' was applied to a parser that succeeds without consuming input and without changing the parser state in any other way.I don’t understand why I get this, since I use the remainder of the string to be analyzed to create the structure of the error used (here “violation”) .

Can someone help me figure this out? Am I not mistaken for parser signaling errors for the user? If not, how can I fix this?

!

* *

, -

/// The expression structure.
type Expr =
| Violation of Expr
| Boolean of bool
| Character of char
| String of string
| Int of int

/// Make a violation from a string.
let makeViolation str = Violation (String str)

/// Read whitespace character as a string.
let spaceAsStr = anyOf whitespaceChars |>> fun chr -> string chr

/// Read a line comment.
let lineComment = pchar lineCommentChar >>. restOfLine true

/// Read a multiline comment.
/// TODO: make multiline comments nest.
let multilineComment =
    between
        (pstring openMultilineCommentStr)
        (pstring closeMultilineCommentStr)
        (charsTillString closeMultilineCommentStr false System.Int32.MaxValue)

/// Read whitespace text.
let whitespace = lineComment <|> multilineComment <|> spaceAsStr

/// Skip any white space characters.
let skipWhitespace = skipMany whitespace

/// Skip at least one white space character.
let skipWhitespace1 = skipMany1 whitespace

/// Read a boolean.
let readBoolean = 
    parse {
        do! skipWhitespace
        let! booleanValue = readStr trueStr <|> readStr falseStr
        return Boolean (booleanValue = trueStr) }

/// Read a character.
let readCharacter =
    parse {
        // TODO: enable reading of escaped chars
        do! skipWhitespace
        let! chr = between skipSingleQuote skipSingleQuote (manyChars (noneOf "\'"))
        return Character chr.[0] }

/// Read a string.
let readString =
    parse {
        // TODO: enable reading of escaped chars
        do! skipWhitespace
        let! str = between skipDoubleQuote skipDoubleQuote (manyChars (noneOf "\""))
        return String str }

/// Read an int.
let readInt =
    parse {
        do! skipWhitespace
        let! value = pint32
        let! _ = opt (skipString intSuffixStr)
        do! notFollowedByLetterOrNameChar
        do! notFollowedByDot
        return Int value }

. , , , readError. restOfLine , ?

* *

, readError . " ", , -

/// Read the end of input.
let readEndOfInput = skipWhitespace >>. eof

// Read multiple exprs.
let readExprs = many readExpr

// Read exprs until the end of the input.
let readExprsTillEnd = readExprs .>> readEndOfInput

readExprsTillEnd, exprs .

, !

+5
1

, , . attempt? , .

do readExprRef :=
    choice
        [attempt readBoolean
         attempt readCharacter
         attempt readString
         attempt readInt
         readError]

FParsec, , .

UPDATE:

readError , - readExpr many, . ,

run (many readError) "" ;;

, many , , .

restOfLine http://www.quanttec.com/fparsec/reference/charparsers.html#members.restOfLine, .

, , , .

, , readError, , readExpr ,

let readExprs = many readExpr .>> eof

, eof - eof, FParsec .

, http://www.quanttec.com/fparsec/users-guide/customizing-error-messages.html

+1

All Articles