Как указал Стефан в комментарии, вы можете разделить оператор-синтаксический анализатор на два отдельных синтаксических анализатора и поместить свой собственный синтаксический анализатор в середине для пространственно разделенных выражений. Следующий код демонстрирует это:
#I "../packages/FParsec.1.0.1/lib/net40-client"
#r "FParsec"
#r "FParsecCS"
open FParsec
open System.Numerics
type Expr =
| Int of BigInteger
| Add of Expr * Expr
| Mul of Expr * Expr
| Pow of Expr * Expr
let str s = pstring s >>. spaces
let pInt : Parser<_, unit> = many1Satisfy isDigit |>> BigInteger.Parse .>> spaces
let high = OperatorPrecedenceParser<Expr,unit,unit>()
let low = OperatorPrecedenceParser<Expr,unit,unit>()
let pHighExpr = high.ExpressionParser .>> spaces
let pLowExpr = low.ExpressionParser .>> spaces
high.TermParser <-
choice
[ pInt |>> Int
between (str "(") (str ")") pLowExpr ]
low.TermParser <-
many1 pHighExpr |>> (function [f] -> f | fs -> List.reduce (fun f g -> Mul(f, g)) fs) .>> spaces
low.AddOperator(InfixOperator("+", spaces, 10, Associativity.Left, fun f g -> Add(f, g)))
high.AddOperator(InfixOperator("^", spaces, 20, Associativity.Right, fun f g -> Pow(f, g)))
run (spaces >>. pLowExpr .>> eof) "1 2 + 3 4^5 6"
выход:
Add (Mul (Int 1,Int 2),Mul (Mul (Int 3,Pow (Int 4,Int 5)),Int 6))
1 * 2 + 3 * 4^5 * 6
, который представляет, как ожидалось.
Я не пробовал это, но я думаю, что вы можете реализовать это с помощью [OperatorPrecedenceParser] (http://www.quanttec.com/fparsec/reference/operatorprecedenceparser.html), сделав ваш обычный синтаксический анализатор пробелов не принятым пробелом между идентификаторами и добавлением оператора инфикса для '' '' пробельной строки с «послепорядком-парсером», которая терпит неудачу, не потребляя вход, если пробелу не соответствует идентификатор. –
Но это не будет анализировать '(x) (y) = x * y'? –
Возможно, вы могли бы проанализировать второй термин в parens, используя «(« постфиксный оператор, который анализирует термин и заключительный параграф с помощью парсера после строки ». Более чистый подход без хакерских« »и« («операторов» был бы для синтаксического анализа совпадающих терминов в качестве последовательности терминов. Чтобы правильно обрабатывать приоритет, вам, вероятно, понадобится отдельный экземпляр OPP для всех (верхнего уровня) терминов в последовательности, отличной от первой. Этот другой OPP будет включать только операторов, которые имеют более высокий приоритет, чем умножение (и без префикса +/-). –