Прежде чем перейти к синтаксису стрелок, я хочу прокомментировать ваш ws
парсер.Использование |>> (fun _ -> ())
немного неэффективно, поскольку FParsec должен создать результирующий объект, а затем сразу же выбросить его.Встроенные парсеры spaces
и spaces1
, вероятно, лучше подойдут вам, поскольку им не нужно создавать объект результата.
ТеперьЧто касается проблемы, с которой вы боретесь, мне кажется, что вы хотите рассмотреть анализатор стрелок немного по-другому.Как насчет того, чтобы рассматривать его как серию типов, разделенных ->
, и использовать семейство sepBy
комбинаторов синтаксического анализа?Примерно так:
let arrow = spaces1 >>. pstring "->" .>> spaces1
let arrowlist = sepBy1 ty' arrow
let arrowtype = arrowlist |>> (fun types ->
types |> List.reduce (fun ty1 ty2 -> ArrowType(ty1, ty2))
Обратите внимание, что синтаксический анализатор arrowlist
будет также совпадать с простым Int
, поскольку определение sepBy1
не "должно быть вхотя бы один разделитель списка ", а точнее" в списке должен быть хотя бы один элемент ".Таким образом, чтобы различать тип Int
и тип стрелки, вам нужно сделать что-то вроде:
let typeAlone = ty' .>> notFollowedBy arrow
let typeOrArrow = attempt typeAlone <|> arrowtype
Здесь необходимо использовать attempt
, чтобы символы, используемые ty'
будет возвращен, если присутствует стрелка.
Есть усложняющий фактор, который я вообще не учел, так как вы упомянули, что не хотите скобок.Но если вы решите, что хотите иметь типы стрелок с типами стрелок (то есть функции, которые принимают функции в качестве входных данных), вы захотите проанализировать такие типы, как (Int -> Int) -> (Int -> Float) -> Char
.Это усложнит использование sepBy
, и я вообще не обращался к нему.Если вам понадобится более сложный анализ, включая скобки, возможно, вы захотите использовать OperatorPrecedenceParser
.Но для ваших простых нужд, где скобки не используются, sepBy1
выглядит как ваша лучшая ставка.
Наконец, я должен дать WARNING : я вообще не проверял это,просто набрал это в поле Stack Overflow.Пример кода, который я дал вам, предназначен не для того, чтобы работать как есть, а для того, чтобы дать вам представление о том, как действовать дальше.Если вам нужен пример «как есть», я с радостью постараюсь вам его дать, но сейчас у меня нет времени на это.