/fparsec/main/Test/OperatorPrecedenceParserTests.fs

http://github.com/sandersn/fing · F# · 499 lines · 380 code · 111 blank · 8 comment · 3 complexity · 4b8c0751ada37cfdbbc729ef057b30db MD5 · raw file

  1. // Copyright (c) Stephan Tolksdorf 2008-2009
  2. // License: Simplified BSD License. See accompanying documentation.
  3. module FParsec.Test.OperatorPrecedenceParserTests
  4. open FParsec
  5. open FParsec.Error
  6. open FParsec.Primitives
  7. open FParsec.CharParsers
  8. open FParsec.OperatorPrecedenceParser
  9. open FParsec.Test.Test
  10. // the tests for this module are somewhat ad hoc and ugly...
  11. type Expr2 = Op of State<unit>*Expr2*Expr2
  12. | Pre of State<unit>*Expr2
  13. | Post of State<unit>*Expr2
  14. | Tern of State<unit>*State<unit>*Expr2*Expr2*Expr2
  15. | Value of State<unit>*int
  16. type Expr = O1 of Expr*Expr
  17. | O2 of Expr*Expr
  18. | Pre1 of Expr
  19. | Pre2 of Expr
  20. | Po1 of Expr
  21. | Po2 of Expr
  22. | Val of int
  23. | T1 of Expr*Expr*Expr
  24. | T2 of Expr*Expr*Expr
  25. let ws = spaces
  26. let ws1 = spaces1
  27. let testRemove (opp: OperatorPrecedenceParser<_,_>) (op: PrecedenceParserOp<_,_>) =
  28. try opp.AddOperator(op); Fail()
  29. with :? System.ArgumentException -> ()
  30. opp.RemoveOperator(op) |> True
  31. opp.AddOperator(op)
  32. match op with
  33. | PrefixOp (str,_,_,_,_)
  34. | PrefixOp' (str,_,_,_,_) -> opp.RemovePrefixOp(str) |> True
  35. | PostfixOp (str,_,_,_,_)
  36. | PostfixOp' (str,_,_,_,_) -> opp.RemovePostfixOp(str) |> True
  37. | InfixOp (str,_,_,_,_)
  38. | InfixOp' (str,_,_,_,_) -> opp.RemoveInfixOp(str) |> True
  39. | TernaryOp (str,_,str2,_, _,_,_)
  40. | TernaryOp' (str,_,str2,_,_,_,_) -> opp.RemoveTernaryOp(str, str2) |> True
  41. let testRemoveSeq opp ops =
  42. let ops = Seq.toArray ops
  43. shuffleArray ops
  44. for op in ops do
  45. testRemove opp op
  46. let testOpParser() =
  47. let opp = new OperatorPrecedenceParser<_,_>()
  48. let expr = opp.ExpressionParser
  49. opp.TermParser <- preturn 0
  50. // check "greedy" op parsing, correct sorting and finding in internal op data structure
  51. opp.AddOperator(PrefixOp("\u0302", ws, 1, true, fun _ -> 0))
  52. opp.AddOperator(PrefixOp("\u0303", ws, 1, true, fun _ -> 1))
  53. opp.AddOperator(PrefixOp("\u0203", ws, 1, true, fun _ -> 2))
  54. opp.AddOperator(PrefixOp("\u0403", ws, 1, true, fun _ -> 3))
  55. opp.AddOperator(PrefixOp("\u0503", ws, 1, true, fun _ -> 4))
  56. opp.AddOperator(PrefixOp("\u0103", ws, 1, true, fun _ -> 5))
  57. opp.AddOperator(PrefixOp("\u0304", ws, 1, true, fun _ -> -1))
  58. opp.AddOperator(PrefixOp("\u0303\u0303", ws, 1, true, fun _ -> 6))
  59. opp.AddOperator(PrefixOp("\u0303\u0302", ws, 1, true, fun _ -> 7))
  60. opp.AddOperator(PrefixOp("\u0303\u0304", ws, 1, true, fun _ -> 8))
  61. opp.AddOperator(PrefixOp("\u0203\u0202", ws, 1, true, fun _ -> 9))
  62. opp.AddOperator(PrefixOp("\u0203\u0203", ws, 1, true, fun _ -> 10))
  63. opp.AddOperator(PrefixOp("\u0203\u0204", ws, 1, true, fun _ -> 11))
  64. opp.AddOperator(PrefixOp("\u0403\u0404", ws, 1, true, fun _ -> 12))
  65. opp.AddOperator(PrefixOp("\u0403\u0403", ws, 1, true, fun _ -> 13))
  66. opp.AddOperator(PrefixOp("\u0403\u0402", ws, 1, true, fun _ -> 14))
  67. opp.AddOperator(PrefixOp("\u0503\u0403", ws, 1, true, fun _ -> 15))
  68. opp.AddOperator(PrefixOp("\u0503\u0402", ws, 1, true, fun _ -> 16))
  69. opp.AddOperator(PrefixOp("\u0503\u0404", ws, 1, true, fun _ -> 17))
  70. opp.AddOperator(PrefixOp("\u0103\u0103\u0103\u0103", ws, 1, true, fun _ -> 18))
  71. opp.AddOperator(PrefixOp("\u0103\u0103\u0103", ws, 1, true, fun _ -> 19))
  72. opp.AddOperator(PrefixOp("\u0103\u0102\u0102", ws, 1, true, fun _ -> 20))
  73. opp.AddOperator(PrefixOp("\u0103\u0102", ws, 1, true, fun _ -> 21))
  74. opp.AddOperator(PrefixOp("\u0103\u0103", ws, 1, true, fun _ -> 22))
  75. opp.AddOperator(PrefixOp("\u0103\u0101", ws, 1, true, fun _ -> 23))
  76. opp.AddOperator(PrefixOp("\u0303\u0303\u0303", ws, 1, true, fun _ -> 24))
  77. opp.AddOperator(PrefixOp("\u0303\u0303\u0303\u0303", ws, 1, true, fun _ -> 25))
  78. opp.AddOperator(PrefixOp("\u0303\u0302\u0302", ws, 1, true, fun _ -> 26))
  79. opp.AddOperator(PrefixOp("\u0203\u0202\u0202\u0202", ws, 1, true, fun _ -> 27))
  80. opp.AddOperator(PrefixOp("\u0203\u0202\u0202", ws, 1, true, fun _ -> 28))
  81. opp.AddOperator(PrefixOp("\u0203\u0203\u0203", ws, 1, true, fun _ -> 29))
  82. opp.AddOperator(PrefixOp("\u0403\u0403\u0403", ws, 1, true, fun _ -> 30))
  83. opp.AddOperator(PrefixOp("\u0403\u0402\u0402", ws, 1, true, fun _ -> 31))
  84. opp.AddOperator(PrefixOp("\u0403\u0402\u0402\u402", ws, 1, true, fun _ -> 32))
  85. let expectedPrefix = expectedError "prefix operator"
  86. let ROk content result parser = ROkE content content.Length result expectedPrefix parser
  87. let ROkI content i result parser = ROkE content i result expectedPrefix parser
  88. expr |> ROk "\u0302" 0
  89. expr |> ROk "\u0303" 1
  90. expr |> ROk "\u0303" 1
  91. expr |> ROk "\u0203" 2
  92. expr |> ROk "\u0403" 3
  93. expr |> ROk "\u0503" 4
  94. expr |> ROk "\u0103" 5
  95. expr |> ROk "\u0304" -1
  96. expr |> ROk "\u0303\u0303" 6
  97. expr |> ROk "\u0303\u0302" 7
  98. expr |> ROk "\u0303\u0304" 8
  99. expr |> ROk "\u0203\u0202" 9
  100. expr |> ROk "\u0203\u0203" 10
  101. expr |> ROk "\u0203\u0204" 11
  102. expr |> ROk "\u0403\u0404" 12
  103. expr |> ROk "\u0403\u0403" 13
  104. expr |> ROk "\u0403\u0402" 14
  105. expr |> ROk "\u0503\u0403" 15
  106. expr |> ROk "\u0503\u0402" 16
  107. expr |> ROk "\u0503\u0404" 17
  108. expr |> ROk "\u0103\u0103\u0103\u0103" 18
  109. expr |> ROk "\u0103\u0103\u0103" 19
  110. expr |> ROkI "\u0103\u0103\u0103\u0102" 3 19
  111. expr |> ROk "\u0103\u0102\u0102" 20
  112. expr |> ROk "\u0103\u0102" 21
  113. expr |> ROk "\u0103\u0103" 22
  114. expr |> ROk "\u0103\u0101" 23
  115. expr |> ROkI "\u0103\u0101\u0102" 2 23
  116. expr |> ROk "\u0303\u0303\u0303" 24
  117. expr |> ROk "\u0303\u0303\u0303\u0302" 24
  118. expr |> ROk "\u0303\u0303\u0303\u0303" 25
  119. expr |> ROk "\u0303\u0302\u0302" 26
  120. expr |> ROk "\u0203\u0202\u0202\u0202" 27
  121. expr |> ROk "\u0203\u0202\u0202" 28
  122. expr |> ROkI "\u0203\u0202\u0202\u0201" 3 28
  123. expr |> ROk "\u0203\u0203\u0203" 29
  124. expr |> ROk "\u0403\u0403\u0403" 30
  125. expr |> ROk "\u0403\u0402\u0402" 31
  126. expr |> ROk "\u0403\u0402\u0402\u402" 32
  127. expr |> ROkI "\u0403\u0402\u0402\u0401" 3 31
  128. // check whitespace parsing and parser state propagation
  129. let testOpParser wsParser termParser =
  130. opp.AddOperator(PrefixOp("+", wsParser, 1, true, fun x -> x + 1))
  131. opp.TermParser <- termParser
  132. let expr2 = pipe2 (many (pchar '+' >>? wsParser <?> "prefix operator")) termParser
  133. (fun ps i -> i + List.length ps)
  134. checkParserStr expr expr2 ""
  135. checkParserStr expr expr2 "+"
  136. checkParserStr expr expr2 "1"
  137. checkParserStr expr expr2 "+"
  138. checkParserStr expr expr2 "+ "
  139. checkParserStr expr expr2 "+1"
  140. checkParserStr expr expr2 "+ 1"
  141. checkParserStr expr expr2 "++"
  142. checkParserStr expr expr2 "+ +"
  143. checkParserStr expr expr2 "+ + "
  144. checkParserStr expr expr2 "++1"
  145. checkParserStr expr expr2 "++ 1"
  146. checkParserStr expr expr2 "+ + 1"
  147. opp.RemovePrefixOp("+") |> True
  148. let withMsg m p = p .>> (fail m <|>% ())
  149. testOpParser (ws |> withMsg "e1") (preturn 0 |> withMsg "e2")
  150. testOpParser (fail "e1") (preturn 0 |> withMsg "e2" )
  151. testOpParser (ws |> withMsg "e1") (pint32 |> withMsg "e2")
  152. testOpParser (ws1 |> withMsg "e1") (preturn 0 |> withMsg "e2")
  153. testOpParser (ws1 |> withMsg "e1") (pint32 |> withMsg "e2")
  154. let testTernary2ndOpParser opWsParser =
  155. let wsm = (ws |> withMsg "e1")
  156. let term = (pint32 |> withMsg "e2") .>> wsm
  157. opp.TermParser <- term
  158. opp.AddOperator(TernaryOp("?", opWsParser, ":", opWsParser, 1, Assoc.Left, fun x y z -> x + y + z))
  159. let expr2 =
  160. let expect label = fun state -> Reply(Ok, (), (expectedError label), state)
  161. let term = expect "prefix operator" >>. term
  162. let op1 = pstring "?" >>? opWsParser <?> "infix operator"
  163. let op2 = expect "infix operator" >>. (pstring ":" >>? opWsParser <?> "':'")
  164. pipe2 term (tuple2 (op1 >>. term) (op2 >>. term .>> expect "infix operator") <|>% (0,0))
  165. (fun x (y,z) -> x + y + z)
  166. checkParserStr expr expr2 "1 ?"
  167. checkParserStr expr expr2 "1 ?"
  168. checkParserStr expr expr2 "1 ?: 3"
  169. checkParserStr expr expr2 "1 ? : 3"
  170. checkParserStr expr expr2 "1 ? 2"
  171. checkParserStr expr expr2 "1 ? 2: "
  172. checkParserStr expr expr2 "1 ? 2 "
  173. checkParserStr expr expr2 "1 ? 2 :"
  174. checkParserStr expr expr2 "1 ? 2 :3"
  175. checkParserStr expr expr2 "1 ? 2 : "
  176. checkParserStr expr expr2 "1 ? 2 : 3"
  177. opp.RemoveTernaryOp("?", ":") |> True
  178. testTernary2ndOpParser (ws |> withMsg "e")
  179. testTernary2ndOpParser (ws1 |> withMsg "e")
  180. testRemoveSeq opp opp.Operators
  181. let testAlternativeOpConstructors() =
  182. let opp = new OperatorPrecedenceParser<_,_>()
  183. let expr = opp.ExpressionParser
  184. let str = skipString
  185. let getState = fun state -> Reply<_,_>(state, state)
  186. let term = pipe2 getState (pint32 .>> ws) (fun state x -> Value(state, x))
  187. opp.TermParser <- term
  188. opp.AddOperator(PrefixOp'("-", ws, 1, true, fun state x -> Pre(state, x)))
  189. opp.AddOperator(PostfixOp'("++", ws, 1, true, fun state x -> Post(state, x)))
  190. opp.AddOperator(InfixOp'("*", ws, 1, Assoc.Left, fun state x y -> Op(state, x, y)))
  191. opp.AddOperator(TernaryOp'("?", ws, ":", ws, 1, Assoc.Left, fun state1 state2 x y z -> Tern(state1, state2, x, y, z)))
  192. let op = getState .>> many1SatisfyL (fun c -> match c with '*' | '+' | '-' | '?' | ':' -> true | _ -> false) "operator" .>> ws
  193. let expr2 =
  194. pipe3 (tuple4 term op term op) (tuple2 op term) (tuple2 op (tuple2 op term))
  195. (fun (v12, sMult, v3, sPlusPlus) (sQMark, v4) (sColon, (sMinus, v5)) ->
  196. Tern(sQMark, sColon, Op(sMult, v12, Post(sPlusPlus, v3)), v4, Pre(sMinus, v5)))
  197. .>> (str "xx" <?> "infix or postfix operator" <|>% ())
  198. checkParserStr expr expr2 "12 * 3++ ? 4 : -5"
  199. testRemoveSeq opp opp.Operators
  200. let testPrecAndAssoc() =
  201. let opp = new OperatorPrecedenceParser<_,_>()
  202. let expr = opp.ExpressionParser
  203. opp.TermParser <- pint32 .>> ws |>> Val
  204. opp.AddOperator(InfixOp("o1l", ws, 1, Assoc.Left, fun x y -> O1(x,y)))
  205. opp.AddOperator(InfixOp("o1r", ws, 1, Assoc.Right, fun x y -> O1(x,y)))
  206. opp.AddOperator(InfixOp("o1n", ws, 1, Assoc.None, fun x y -> O1(x,y)))
  207. opp.AddOperator(InfixOp("o2l", ws, 1, Assoc.Left, fun x y -> O2(x,y)))
  208. opp.AddOperator(InfixOp("o2r", ws, 1, Assoc.Right, fun x y -> O2(x,y)))
  209. opp.AddOperator(InfixOp("o2n", ws, 1, Assoc.None, fun x y -> O2(x,y)))
  210. opp.AddOperator(InfixOp("o1l*", ws, 2, Assoc.Left, fun x y -> O1(x,y)))
  211. opp.AddOperator(InfixOp("o1l**", ws, 3, Assoc.Left, fun x y -> O1(x,y)))
  212. opp.AddOperator(InfixOp("o1r*", ws, 2, Assoc.Right, fun x y -> O1(x,y)))
  213. opp.AddOperator(InfixOp("o1n*", ws, 2, Assoc.None, fun x y -> O1(x,y)))
  214. opp.AddOperator(InfixOp("o2l*", ws, 2, Assoc.Left, fun x y -> O2(x,y)))
  215. opp.AddOperator(InfixOp("o2r*", ws, 2, Assoc.Right, fun x y -> O2(x,y)))
  216. opp.AddOperator(InfixOp("o2n*", ws, 2, Assoc.None, fun x y -> O2(x,y)))
  217. opp.AddOperator(TernaryOp("t1l", ws, "tt1l", ws, 1, Assoc.Left, fun x y z -> T1(x,y,z)))
  218. opp.AddOperator(TernaryOp("t1r", ws, "tt1r", ws, 1, Assoc.Right, fun x y z -> T1(x,y,z)))
  219. opp.AddOperator(TernaryOp("t1n", ws, "tt1n", ws, 1, Assoc.None, fun x y z -> T1(x,y,z)))
  220. opp.AddOperator(TernaryOp("t2l", ws, "tt2l", ws, 1, Assoc.Left, fun x y z -> T2(x,y,z)))
  221. opp.AddOperator(TernaryOp("t2r", ws, "tt2r", ws, 1, Assoc.Right, fun x y z -> T2(x,y,z)))
  222. opp.AddOperator(TernaryOp("t2n", ws, "tt2n", ws, 1, Assoc.None, fun x y z -> T2(x,y,z)))
  223. opp.AddOperator(TernaryOp("t1l*", ws, "tt1l*", ws, 2, Assoc.Left, fun x y z -> T1(x,y,z)))
  224. opp.AddOperator(TernaryOp("t1l**", ws, "tt1l**", ws, 3, Assoc.Left, fun x y z -> T1(x,y,z)))
  225. opp.AddOperator(TernaryOp("t1r*", ws, "tt1r*", ws, 2, Assoc.Right, fun x y z -> T1(x,y,z)))
  226. opp.AddOperator(TernaryOp("t1n*", ws, "tt1n*", ws, 2, Assoc.None, fun x y z -> T1(x,y,z)))
  227. opp.AddOperator(TernaryOp("t2l*", ws, "tt2l*", ws, 2, Assoc.Left, fun x y z -> T2(x,y,z)))
  228. opp.AddOperator(TernaryOp("t2r*", ws, "tt2r*", ws, 2, Assoc.Right, fun x y z -> T2(x,y,z)))
  229. opp.AddOperator(TernaryOp("t2n*", ws, "tt2n*", ws, 2, Assoc.None, fun x y z -> T2(x,y,z)))
  230. opp.AddOperator(PostfixOp("po1", ws, 1, true, fun x -> Po1(x)))
  231. opp.AddOperator(PostfixOp("po1n", ws, 1, false, fun x -> Po1(x)))
  232. opp.AddOperator(PostfixOp("po2", ws, 1, true, fun x -> Po2(x)))
  233. opp.AddOperator(PostfixOp("po2n", ws, 1, false, fun x -> Po2(x)))
  234. opp.AddOperator(PostfixOp("po1*", ws, 2, true, fun x -> Po1(x)))
  235. opp.AddOperator(PostfixOp("po1n*", ws, 2, false, fun x -> Po1(x)))
  236. opp.AddOperator(PostfixOp("po2*", ws, 2, true, fun x -> Po2(x)))
  237. opp.AddOperator(PostfixOp("po2n*", ws, 2, false, fun x -> Po2(x)))
  238. // do some tests without prefix operators defined (there's a separate code branch in OPP.ParseExpression)
  239. let expectedInfixOrPostfix = expectedError "infix or postfix operator"
  240. let ROk content result parser = ROkE content content.Length result expectedInfixOrPostfix parser
  241. expr |> RError "" 0 (expectedError "integer number (32-bit, signed)")
  242. expr |> ROk "1 o1l 2 o2l 3" (O2(O1(Val(1),Val(2)),Val(3)))
  243. expr |> ROk "1 o1r* 2 o2r 3" (O2(O1(Val(1),Val(2)),Val(3)))
  244. expr |> ROk "1 o1r 2 o2r 3" (O1(Val(1),O2(Val(2),Val(3))))
  245. expr |> ROk "1 o1l 2 o2l* 3" (O1(Val(1),O2(Val(2),Val(3))))
  246. expr |> ROk "1 o1n 2 po1n" (O1(Val(1), Po1(Val(2))))
  247. // add prefix operators
  248. opp.AddOperator(PrefixOp("pre1", ws, 1, true, fun x -> Pre1(x)))
  249. expr |> RError "po1" 0 (unexpectedError "postfix operator 'po1' (precedence: 1)")
  250. opp.AddOperator(PrefixOp("pre1n", ws, 1, false, fun x -> Pre1(x)))
  251. opp.AddOperator(PrefixOp("pre2", ws, 1, true, fun x -> Pre2(x)))
  252. opp.AddOperator(PrefixOp("pre2n", ws, 1, false, fun x -> Pre2(x)))
  253. opp.AddOperator(PrefixOp("pre1*", ws, 2, true, fun x -> Pre1(x)))
  254. opp.AddOperator(PrefixOp("pre1n*", ws, 2, false, fun x -> Pre1(x)))
  255. opp.AddOperator(PrefixOp("pre2*", ws, 2, true, fun x -> Pre2(x)))
  256. opp.AddOperator(PrefixOp("pre2n*", ws, 2, false, fun x -> Pre2(x)))
  257. // add operators a second time with opposite fixity
  258. opp.AddOperator(PrefixOp("o1l", ws, 1, true, fun x -> failwith "o1l"))
  259. opp.AddOperator(PrefixOp("o1r", ws, 1, true, fun x -> failwith "o1r"))
  260. opp.AddOperator(PrefixOp("o1n", ws, 1, true, fun x -> failwith "o1n"))
  261. opp.AddOperator(PrefixOp("o2l", ws, 1, true, fun x -> failwith "o2l"))
  262. opp.AddOperator(PrefixOp("o2r", ws, 1, true, fun x -> failwith "o2r"))
  263. opp.AddOperator(PrefixOp("o2n", ws, 1, true, fun x -> failwith "o2n"))
  264. opp.AddOperator(PrefixOp("o1l*", ws, 2, true, fun x -> failwith "o1l*"))
  265. opp.AddOperator(PrefixOp("o1l**", ws, 3, true, fun x -> failwith "o1l**"))
  266. opp.AddOperator(PrefixOp("o1r*", ws, 2, true, fun x -> failwith "o1r*"))
  267. opp.AddOperator(PrefixOp("o1n*", ws, 2, true, fun x -> failwith "o1n*"))
  268. opp.AddOperator(PrefixOp("o2l*", ws, 2, true, fun x -> failwith "o2l*"))
  269. opp.AddOperator(PrefixOp("o2r*", ws, 2, true, fun x -> failwith "o2r*"))
  270. opp.AddOperator(PrefixOp("o2n*", ws, 2, true, fun x -> failwith "o2n*"))
  271. opp.AddOperator(PrefixOp("t1l", ws, 1, true, fun x -> failwith "t1l"))
  272. opp.AddOperator(PrefixOp("t1r", ws, 1, true, fun x -> failwith "t1r"))
  273. opp.AddOperator(PrefixOp("t1n", ws, 1, true, fun x -> failwith "t1n"))
  274. opp.AddOperator(PrefixOp("t2l", ws, 1, true, fun x -> failwith "t2l"))
  275. opp.AddOperator(PrefixOp("t2r", ws, 1, true, fun x -> failwith "t2r"))
  276. opp.AddOperator(PrefixOp("t2n", ws, 1, true, fun x -> failwith "t2n"))
  277. opp.AddOperator(PrefixOp("t1l*", ws, 2, true, fun x -> failwith "t1l*"))
  278. opp.AddOperator(PrefixOp("t1l**", ws, 3, true, fun x -> failwith "t1l**"))
  279. opp.AddOperator(PrefixOp("t1r*", ws, 2, true, fun x -> failwith "t1r*"))
  280. opp.AddOperator(PrefixOp("t1n*", ws, 2, true, fun x -> failwith "t1n*"))
  281. opp.AddOperator(PrefixOp("t2l*", ws, 2, true, fun x -> failwith "t2l*"))
  282. opp.AddOperator(PrefixOp("t2r*", ws, 2, true, fun x -> failwith "t2r*"))
  283. opp.AddOperator(PrefixOp("t2n*", ws, 2, true, fun x -> failwith "t2n*"))
  284. opp.AddOperator(PrefixOp("po1", ws, 1, true, fun x -> failwith "po1"))
  285. opp.AddOperator(PrefixOp("po1n", ws, 1, true, fun x -> failwith "po1n"))
  286. opp.AddOperator(PrefixOp("po2", ws, 1, true, fun x -> failwith "po2"))
  287. opp.AddOperator(PrefixOp("po2n", ws, 1, true, fun x -> failwith "po2n"))
  288. opp.AddOperator(PrefixOp("po1*", ws, 2, true, fun x -> failwith "po1*"))
  289. opp.AddOperator(PrefixOp("po1n*", ws, 2, true, fun x -> failwith "po1n*"))
  290. opp.AddOperator(PrefixOp("po2*", ws, 2, true, fun x -> failwith "po2*"))
  291. opp.AddOperator(PrefixOp("po2n*", ws, 2, true, fun x -> failwith "po2n*"))
  292. opp.AddOperator(InfixOp("pre1", ws, 1, Assoc.Left, fun x y -> failwith "pre1"))
  293. opp.AddOperator(InfixOp("pre1n", ws, 1, Assoc.Left, fun x y -> failwith "pre1n"))
  294. opp.AddOperator(PostfixOp("pre2", ws, 1, true, fun x -> failwith "pre2"))
  295. opp.AddOperator(PostfixOp("pre2n", ws, 1, true, fun x -> failwith "pre2n"))
  296. opp.AddOperator(InfixOp("pre1*", ws, 2, Assoc.Left, fun x y -> failwith "pre1*"))
  297. opp.AddOperator(InfixOp("pre1n*", ws, 2, Assoc.Left, fun x y -> failwith "pre1n*"))
  298. opp.AddOperator(PostfixOp("pre2*", ws, 2, true, fun x -> failwith "pre2*"))
  299. opp.AddOperator(PostfixOp("pre2n*", ws, 2, true, fun x -> failwith "pre2n"))
  300. expr |> ROk "1 o1l 2 o2l 3" (O2(O1(Val(1),Val(2)),Val(3)))
  301. expr |> ROk "1 o1r* 2 o2r 3" (O2(O1(Val(1),Val(2)),Val(3)))
  302. expr |> ROk "1 o1r 2 o2r 3" (O1(Val(1),O2(Val(2),Val(3))))
  303. expr |> ROk "1 o1l 2 o2l* 3" (O1(Val(1),O2(Val(2),Val(3))))
  304. expr |> ROk "1 t1l 2 tt1l 3 t2l 4 tt2l 5" (T2(T1(Val(1),Val(2),Val(3)),Val(4),Val(5)))
  305. expr |> ROk "1 t1r* 2 tt1r* 3 t2r 4 tt2r 5" (T2(T1(Val(1),Val(2),Val(3)),Val(4),Val(5)))
  306. expr |> ROk "1 t1r 2 tt1r 3 t2r 4 tt2r 5" (T1(Val(1),Val(2),T2(Val(3),Val(4),Val(5))))
  307. expr |> ROk "1 t1l 2 tt1l 3 t2l* 4 tt2l* 5" (T1(Val(1),Val(2),T2(Val(3),Val(4),Val(5))))
  308. expr |> ROk "1 t1l* 2 po1 tt1l* 3 t2l* 4 o1l 5 tt2l* 6" (T2(T1(Val(1),Po1(Val(2)),Val(3)),O1(Val(4),Val(5)),Val(6)))
  309. expr |> ROk "1 t1n 2 o1n 3 tt1n 4" (T1(Val(1),O1(Val(2),Val(3)),Val(4)))
  310. expr |> ROk "1 o1l pre1 2" (O1(Val(1), Pre1(Val(2))))
  311. expr |> ROk "1 o1l pre1* 2" (O1(Val(1), Pre1(Val(2))))
  312. expr |> ROk "1 o1l* pre1 2" (O1(Val(1), Pre1(Val(2))))
  313. expr |> ROk "1 o1l 2 po1" (O1(Val(1), Po1(Val(2))))
  314. expr |> ROk "1 o1l 2 po1*" (O1(Val(1), Po1(Val(2))))
  315. expr |> ROk "1 o1l* 2 po1" (Po1(O1(Val(1), Val(2))))
  316. expr |> ROk "1 o1l pre1 2 po1" (O1(Val(1), Po1(Pre1(Val(2)))))
  317. expr |> ROk "1 o1l pre1* 2 po1" (O1(Val(1), Po1(Pre1(Val(2)))))
  318. expr |> ROk "1 o1l pre1 2 po1*" (O1(Val(1), Pre1(Po1(Val(2)))))
  319. expr |> ROk "1 o1l* pre1 2 po1" (Po1(O1(Val(1), Pre1(Val(2)))))
  320. expr |> ROk "1 o1r* pre1 2 po1" (Po1(O1(Val(1), Pre1(Val(2)))))
  321. expr |> ROk "1 o1l* pre1 2 po1*" (O1(Val(1), Pre1(Po1(Val(2)))))
  322. expr |> ROk "1 o1l 2 po1*" (O1(Val(1), Po1(Val(2))))
  323. expr |> ROk "1 o1l* 2 po1" (Po1(O1(Val(1), Val(2))))
  324. expr |> ROk "1 o1l pre1 pre2 2" (O1(Val(1), Pre1(Pre2(Val(2)))))
  325. expr |> ROk "1 o1l pre1* pre2 2" (O1(Val(1), Pre1(Pre2(Val(2)))))
  326. expr |> ROk "1 o1l pre1 pre2* 2" (O1(Val(1), Pre1(Pre2(Val(2)))))
  327. expr |> ROk "1 o1l 2 po1 po2" (O1(Val(1), Po2(Po1(Val(2)))))
  328. expr |> ROk "1 o1l* 2 po1 po2" (Po2(Po1(O1(Val(1), Val(2)))))
  329. expr |> ROk "1 o1l* 2 po1 po2*" (Po2(Po1(O1(Val(1), Val(2)))))
  330. expr |> ROk "1 o1l* 2 po1* po2" (Po2(O1(Val(1), Po1(Val(2)))))
  331. expr |> ROk "1 o1l pre1 2 po1 po2" (O1(Val(1), Po2(Po1(Pre1(Val(2))))))
  332. expr |> ROk "1 o1l pre1 2 po1* po2" (O1(Val(1), Po2(Pre1(Po1(Val(2))))))
  333. expr |> ROk "1 o1l pre1 2 po1* po2*" (O1(Val(1), Pre1(Po2(Po1(Val(2))))))
  334. expr |> ROk "1 o1l pre1 2 po1 po2*" (O1(Val(1), Po2(Po1(Pre1(Val(2))))))
  335. expr |> ROk "1 o1l* pre1 2 po1 po2" (Po2(Po1(O1(Val(1), Pre1(Val(2))))))
  336. expr |> ROk "1 o1l* pre1 2 po1* po2" (Po2(O1(Val(1), Pre1(Po1(Val(2))))))
  337. expr |> ROk "1 o1l* pre1 2 po1* po2" (Po2(O1(Val(1), Pre1(Po1(Val(2))))))
  338. expr |> ROk "pre1 1 o1l 2 po1" (O1(Pre1(Val(1)), Po1(Val(2))))
  339. expr |> ROk "pre1 1 o1l* 2 po1" (Po1(Pre1(O1(Val(1), Val(2)))))
  340. expr |> ROk "pre1* 1 o1l* 2 po1" (Po1(O1(Pre1(Val(1)), Val(2))))
  341. expr |> ROk "pre1 1 o1l* 2 po1*" (Pre1(O1(Val(1), Po1(Val(2)))))
  342. expr |> ROk "pre1 1 o1l** 2 po1*" (Pre1(Po1(O1(Val(1), Val(2)))))
  343. opp.OperatorConflictHandler <- fun _ _ _ _ -> "conflict"
  344. let conflictE = messageError "conflict"
  345. expr |> ROk "pre1n 1 o1n 2" (O1(Pre1(Val(1)), Val(2)))
  346. expr |> ROk "1 po1n o1n 2" (O1(Po1(Val(1)), Val(2)))
  347. expr |> ROk "1 o1n pre1n 2" (O1(Val(1), Pre1(Val(2))))
  348. expr |> ROk "1 o1n 2 po1n" (O1(Val(1), Po1(Val(2))))
  349. expr |> ROk "1 o1l* 2 o2r 3" (O2(O1(Val(1),Val(2)),Val(3)))
  350. expr |> ROk "1 o1l 2 o2r* 3" (O1(Val(1),O2(Val(2),Val(3))))
  351. expr |> RError "1 o1l 2 o2r 3" 9 conflictE
  352. expr |> RError "1 o1l 2 o2n 3" 9 conflictE
  353. expr |> RError "1 o1n 2 o2n 3" 9 conflictE
  354. expr |> ROk "1 t1l* 2 tt1l* 3 t2r 4 tt2r 5" (T2(T1(Val(1),Val(2),Val(3)),Val(4),Val(5)))
  355. expr |> ROk "1 t1l 2 tt1l 3 t2r* 4 tt2r* 5" (T1(Val(1),Val(2),T2(Val(3),Val(4),Val(5))))
  356. expr |> RError "1 t1l 2 tt1l 3 t2r 4 tt2r 5" 17 conflictE
  357. expr |> RError "1 t1l 2 tt1l 3 o1r 4" 17 conflictE
  358. expr |> RError "1 o1r 2 t1l 3 tt1l 4" 9 conflictE
  359. expr |> ROk "pre1n 1 po1" (Po1(Pre1(Val(1))))
  360. expr |> ROk "pre1 1 po1n" (Po1(Pre1(Val(1))))
  361. expr |> ROk "pre1n* 1 po1n" (Po1(Pre1(Val(1))))
  362. expr |> ROk "pre1n 1 po1n*" (Pre1(Po1(Val(1))))
  363. expr |> RError "pre1n 1 po1n" 9 conflictE
  364. expr |> ROk "pre1 pre2n 1" (Pre1(Pre2(Val(1))))
  365. expr |> ROk "pre1n pre2 1" (Pre1(Pre2(Val(1))))
  366. expr |> ROk "pre1n* pre2n 1" (Pre1(Pre2(Val(1))))
  367. expr |> ROk "pre1n pre2n* 1" (Pre1(Pre2(Val(1))))
  368. expr |> RError "pre1n pre2n 1" 7 conflictE
  369. expr |> ROk "1 po1 po2n" (Po2(Po1(Val(1))))
  370. expr |> ROk "1 po1n po2" (Po2(Po1(Val(1))))
  371. expr |> ROk "1 po1n* po2n" (Po2(Po1(Val(1))))
  372. expr |> ROk "1 po1n po2n*" (Po2(Po1(Val(1))))
  373. expr |> RError "1 po1n po2n" 9 conflictE
  374. opp.OperatorConflictHandler <- fun _ _ _ _ -> null
  375. expr |> ROk "1 o1l 2 o2r 3" (O2(O1(Val(1),Val(2)),Val(3)))
  376. expr |> ROk "1 o1r 2 o2n 3" (O2(O1(Val(1),Val(2)),Val(3)))
  377. expr |> ROk "1 o1n 2 o2n 3" (O2(O1(Val(1),Val(2)),Val(3)))
  378. expr |> ROk "1 t1l 2 tt1l 3 t2r 4 tt2r 5" (T2(T1(Val(1),Val(2),Val(3)),Val(4),Val(5)))
  379. expr |> ROk "1 t1l 2 tt1l 3 o1r 4" (O1(T1(Val(1),Val(2),Val(3)), Val(4)))
  380. expr |> ROk "1 o1r 2 t1l 3 tt1l 4" (T1(O1(Val(1),Val(2)),Val(3), Val(4)))
  381. expr |> ROk "pre1n 1 po1n" (Po1(Pre1(Val(1))))
  382. expr |> ROk "pre1n pre2n 1" (Pre1(Pre2(Val(1))))
  383. expr |> ROk "1 po1n po2n" (Po2(Po1(Val(1))))
  384. testRemoveSeq opp opp.Operators
  385. let run() =
  386. testOpParser()
  387. testAlternativeOpConstructors()
  388. testPrecAndAssoc()