首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用FParsec解析带有多个参数的前缀函数(如Pow() )

如何使用FParsec解析带有多个参数的前缀函数(如Pow() )
EN

Stack Overflow用户
提问于 2016-11-01 19:35:02
回答 1查看 235关注 0票数 1

我尝试使用3+2,2解析前缀函数,比如Pow( FParsec )。我在示例文件中阅读了计算器教程,如下所示。这些例子都是一元前缀函数。我想知道如何使用FParsec.OperatorPrecedenceParser实现多个输入的前缀函数。

http://www.quanttec.com/fparsec/reference/operatorprecedenceparser.html#members.PrefixOperator

代码语言:javascript
复制
let number = pfloat .>> ws

let opp = new OperatorPrecedenceParser<float,unit,unit>()
let expr = opp.ExpressionParser
opp.TermParser <- number <|> between (str_ws "(") (str_ws ")") expr


opp.AddOperator(InfixOperator("+", ws, 1, Associativity.Left, (+)))
opp.AddOperator(InfixOperator("-", ws, 1, Associativity.Left, (-)))
opp.AddOperator(InfixOperator("*", ws, 2, Associativity.Left, (*)))
opp.AddOperator(InfixOperator("/", ws, 2, Associativity.Left, (/)))
opp.AddOperator(InfixOperator("^", ws, 3, Associativity.Right, fun x y -> System.Math.Pow(x, y)))
opp.AddOperator(PrefixOperator("-", ws, 4, true, fun x -> -x))

let ws1 = nextCharSatisfiesNot isLetter >>. ws
opp.AddOperator(PrefixOperator("log", ws1, 4, true, System.Math.Log))
opp.AddOperator(PrefixOperator("exp", ws1, 4, true, System.Math.Exp))

更新1

我按照字符串后解析器示例编写了一个快速脚本,因为我需要实际应用程序http://www.quanttec.com/fparsec/users-guide/tips-and-tricks.html#parsing-f-infix-operators的字符串后解析器。

abs(pow(1,2))可以被解析,但是pow(abs(1),2)不能被解析。我对如何使用前缀函数作为identWithArgs输入的一部分感到困惑。

代码语言:javascript
复制
#I @"..\packages\FParsec.1.0.2\lib\net40-client"
#r "FParsecCS.dll"
#r "FParsec.dll"

open FParsec

type PrefixFunc = POW
type Expr =
  | InfixOpExpr of string * Expr * Expr
  | PrefixOpExpr of string * Expr
  | PrefixFuncExpr of PrefixFunc * Expr list 
  | Number of int

let ws = spaces
let ws1 = spaces1
let str s = pstring s
let str_ws s = ws >>. str s .>> ws
let strci s = pstringCI s
let strci_ws s = ws >>. strci s .>> ws
let strciret_ws s x = ws >>. strci s .>> ws >>% x

let isSymbolicOperatorChar = isAnyOf "!%&*+-./<=>@^|~?"
let remainingOpChars_ws = manySatisfy isSymbolicOperatorChar .>> ws

let primitive = pint32 .>> ws |>> Number
let argList = sepBy primitive (str_ws ",")
let argListInParens = between (str_ws "(") (str_ws ")") argList
let prefixFunc = strciret_ws "pow" POW 
let identWithArgs =
    pipe2 prefixFunc argListInParens (fun funcId args -> PrefixFuncExpr(funcId, args))

let opp = new OperatorPrecedenceParser<Expr, string, unit>()
opp.TermParser <-
  primitive <|>
  identWithArgs <|>
  between (pstring "(") (pstring ")") opp.ExpressionParser

// a helper function for adding infix operators to opp
let addSymbolicInfixOperators prefix precedence associativity =
    let op = InfixOperator(prefix, remainingOpChars_ws,
                           precedence, associativity, (),
                           fun remOpChars expr1 expr2 ->
                               InfixOpExpr(prefix + remOpChars, expr1, expr2))
    opp.AddOperator(op)

// the operator definitions:
addSymbolicInfixOperators "*"  10 Associativity.Left
addSymbolicInfixOperators "**" 20 Associativity.Right

opp.AddOperator(PrefixOperator("abs",remainingOpChars_ws,3,true,(),fun remOpChars expr -> PrefixOpExpr("abs", expr)))
opp.AddOperator(PrefixOperator("log",remainingOpChars_ws,3,true,(),fun remOpChars expr -> PrefixOpExpr("log", expr)))

run opp.ExpressionParser "abs(pow(1,2))"
run opp.ExpressionParser "pow(abs(1),2)"
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-11 02:06:29

一年后,我开始重新审视这个问题,终于意识到了这个问题。

我已经更改了以下代码

代码语言:javascript
复制
let argList = sepBy primitive (str_ws ",")

到以下

代码语言:javascript
复制
let opp = new OperatorPrecedenceParser<Expr, string, unit>()
let argList = sepBy opp.ExpressionParser (str_ws ",")

我把OperatorPrecedenceParser带到了代码的开头。然后,通过将opp.ExpressionParser直接放入argList中,实现递归调用它。

我刚刚意识到OperatorPrecedenceParser与createParserForwardedToRef非常相似。它首先创建一个解析器,然后再编写实现。FParsec必须以这种方式实现递归。类似于它的JSON示例解析器。

在此改变之后,可以解析abs(pow(1,2))和pow(abs(1),2)。希望这能帮助其他曾经遇到这个问题的人。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40367378

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档