У меня есть парсер, который кажется достаточно прямым. Я добавил этот суб-парсер до конца, чтобы дать информацию об общих ошибок синтаксического анализа, так как все остальные суб-парсеры не удалось -Как разрешить ошибку FParsec «Комбинатор« многие »был применен к парсеру, который преуспевает, не потребляя ...»
/// 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
Однако, как только я добавляю Ошибка чтения как выбор, я получаю страшились FParsec ошибку о потоке потребление во время выполнения - The combinator 'many' was applied to a parser that succeeds without consuming input and without changing the parser state in any other way.
Я не понимаю, почему я получаю это, так как я использую анализируемый остаток строки для создания структуры используемой ошибки (здесь «нарушение»).
Может кто-нибудь помочь мне понять это? Я не ошибаюсь в ошибках сигнализации парсера для пользователя? Если нет, как я могу это исправить?
Благодарим вас за помощь!
* Подробнее *
Вот еще какой-то код, который может иметь отношение -
/// 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 не потреблять вход, даже не пробелы?
* Заключение *
Оказывается, что подход к ошибкам отчетов с анализатором Ошибка чтения является неправильным. Правильный подход заключается в использовании «до конца» парсер, как так -
/// 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 во входном потоке.
Еще раз спасибо, Густаво!
Вы можете разместить больше кода? В частности, тело функции makeViolation. – Gustavo
Готово. BTW, Густаво, я большой поклонник вашего блога. Надеюсь, что Дон Симе смотрит на работу, которую вы сделали - получение функторов, аппликаций и монадов без HK или TC огромно! Интересно, можем ли мы также получить от вас стрелы в какой-то форме;) –
Спасибо Брайан за ваши отзывы о моей работе с Typeclasses. Я также надеюсь, что люди из команды F # могут добавить дополнительную поддержку для этой техники, иначе они будут зависеть от команды CLR для реализации реальной поддержки Typeclasses на уровне .NET. Что касается стрелок, вы посмотрели http://stackoverflow.com/questions/4034802/how-would-i-translate-a-haskell-type-class-into-f? В проекте содержится больше информации о стрелках на http://code.google.com/p/fsharp-typeclasses. – Gustavo