Parsing “x y z” with the precedence of multiply

坚强是说给别人听的谎言 提交于 2019-12-04 07:46:11

As Stephan pointed out in a comment you can split the operator parser into two separate parsers and put your own parser in the middle for space-separated expressions. The following code demonstrates this:

#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"

The output is:

Add (Mul (Int 1,Int 2),Mul (Mul (Int 3,Pow (Int 4,Int 5)),Int 6))

which represents 1 * 2 + 3 * 4^5 * 6 as expected.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!