Как разобрать последовательность слов, разделенных двойными пробелами, используя fparsec? - PullRequest
0 голосов
/ 19 сентября 2018

С учетом ввода:

alpha beta gamma  one two three

Как я могу разобрать это в следующем?

[["alpha"; "beta"; "gamma"]; ["one"; "two"; "three"]]

Я могу написать это, когда есть лучший разделитель (например, __), как тогда

sepBy (sepBy word (pchar ' ')) (pstring "__")

работает, но в случае двойного пробела pchar в первом sepBy занимает первый пробел, а затем синтаксический анализатор дает сбой.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Руководство по FParsec говорит , что в sepBy p sep, если sep успешен и последующий p завершается неудачей (без изменения состояния), весь sepBy также завершается неудачей.Следовательно, ваша цель:

  1. сделать разделитель с ошибкой , если он встретит более одного пробела;
  2. до возврат так что «внутренний» цикл sepBy благополучно закрылся и передал управление «внешнему» циклу sepBy.

Вот как это сделать:

// this is your word parser; it can be different of course,
// I just made it as simple as possible;
let pWord = many1Satisfy isAsciiLetter

// this is the Inner separator to separate individual words
let pSepInner =
    pchar ' '
    .>> notFollowedBy (pchar ' ') // guard rule to prevent 2nd space
    |> attempt                    // a wrapper that would fail NON-fatally

// this is the Outer separator
let pSepOuter =
    pchar ' '
    |> many1  // loop

// this is the parser that would return String list list
let pMain =
    pWord
    |> sepBy <| pSepInner         // the Inner loop
    |> sepBy <| pSepOuter         // the Outer loop

Использование:

run pMain "alpha beta gamma  one two three"
Success: [["alpha"; "beta"; "gamma"]; ["one"; "two"; "three"]]
0 голосов
/ 19 сентября 2018

Я бы порекомендовал заменить sepBy word (pchar ' ') на что-то вроде этого:

let pOneSpace = pchar ' ' .>> notFollowedBy (pchar ' ')
let pTwoSpaces = pstring "  "
// Or if two spaces are allowed as separators but *not* three spaces...
let pTwoSpaces = pstring "  " .>> notFollowedBy (pchar ' ')
sepBy (sepBy word pOneSpace) pTwoSpaces

Примечание: не проверялось (так как у меня сейчас нет времени), просто набрал текст в поле для ответов.Так что проверь, если я где-то допустил ошибку.

...