PageRenderTime 91ms CodeModel.GetById 19ms app.highlight 67ms RepoModel.GetById 1ms app.codeStats 0ms

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