86 people like it.

Top-Down-Operator-Precedence Parser

F# implementation of a generic Top-Down-Operator-Precedence Parser as described in this paper http://portal.acm.org/citation.cfm?id=512931 Example starts at line ~300

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
245: 
246: 
247: 
248: 
249: 
250: 
251: 
252: 
253: 
254: 
255: 
256: 
257: 
258: 
259: 
260: 
261: 
262: 
263: 
264: 
265: 
266: 
267: 
268: 
269: 
270: 
271: 
272: 
273: 
274: 
275: 
276: 
277: 
278: 
279: 
280: 
281: 
282: 
283: 
284: 
285: 
286: 
287: 
288: 
289: 
290: 
291: 
292: 
293: 
294: 
295: 
296: 
297: 
298: 
299: 
300: 
301: 
302: 
303: 
304: 
305: 
306: 
307: 
308: 
309: 
310: 
311: 
312: 
313: 
314: 
315: 
316: 
317: 
318: 
319: 
320: 
321: 
322: 
323: 
324: 
325: 
326: 
327: 
328: 
329: 
330: 
331: 
332: 
333: 
334: 
335: 
336: 
337: 
338: 
339: 
340: 
341: 
342: 
343: 
344: 
345: 
346: 
347: 
348: 
349: 
350: 
351: 
352: 
353: 
354: 
355: 
356: 
357: 
358: 
359: 
360: 
361: 
362: 
363: 
364: 
365: 
366: 
367: 
368: 
369: 
370: 
371: 
372: 
373: 
374: 
375: 
376: 
377: 
378: 
379: 
380: 
381: 
382: 
383: 
384: 
385: 
386: 
387: 
388: 
389: 
390: 
391: 
392: 
393: 
394: 
395: 
396: 
397: 
398: 
399: 
400: 
401: 
402: 
403: 
404: 
405: 
406: 
407: 
408: 
409: 
410: 
411: 
412: 
413: 
414: 
415: 
416: 
417: 
418: 
419: 
420: 
421: 
422: 
423: 
424: 
425: 
426: 
427: 
428: 
429: 
430: 
431: 
432: 
433: 
434: 
435: 
436: 
437: 
438: 
439: 
440: 
441: 
442: 
443: 
444: 
445: 
446: 
447: 
448: 
449: 
450: 
451: 
452: 
453: 
454: 
455: 
456: 
457: 
458: 
459: 
460: 
461: 
462: 
463: 
464: 
465: 
466: 
467: 
468: 
469: 
470: 
471: 
472: 
473: 
474: 
475: 
476: 
477: 
478: 
479: 
480: 
481: 
482: 
483: 
484: 
485: 
486: 
487: 
488: 
489: 
490: 
491: 
492: 
493: 
494: 
495: 
496: 
497: 
498: 
499: 
500: 
501: 
502: 
503: 
504: 
505: 
506: 
507: 
508: 
509: 
510: 
511: 
512: 
513: 
514: 
515: 
516: 
517: 
518: 
519: 
520: 
521: 
522: 
523: 
524: 
525: 
526: 
527: 
528: 
529: 
530: 
531: 
532: 
533: 
534: 
535: 
536: 
537: 
538: 
539: 
540: 
541: 
542: 
543: 
544: 
545: 
546: 
547: 
module Parser = 
  
  (*
  F# implementation of a generic Top-Down-Operator-Precedence Parser 
  as described in this paper http://portal.acm.org/citation.cfm?id=512931.

  The parser has been extended to allow for statements in comparison to Pratt's
  original algorithm which only parsed languages which use expression-only grammar.

  The parsers is "impure" in the sense that is uses a ref-cell for storing the
  input in the T<_, _, _> record class, this is soley for performance reasons
  as it's to expensive to create a new record object for every consumed token.
  Certain functions also throw exceptions, which generally also is considered impure.

  The parser produces nice error message in this style:

  Error on line: 5 col: 9
  4: if(x == y) {
  5:   print'x equals y');
  ----------^
  Unexpected: #string "x equals y"

  More information:
  * http://en.wikipedia.org/wiki/Vaughan_Pratt (Original Inventor)
  * http://en.wikipedia.org/wiki/Pratt_parser (Alias name)
  * http://effbot.org/zone/simple-top-down-parsing.htm (Python implementation)
  * http://javascript.crockford.com/tdop/tdop.html (JavaScript implementation)
  *)

  type Pos = int * int

  type T<'a, 'b, 'c> when 'c : comparison = {
      Input : 'a list ref
      Lines : string option

      Type : 'a -> 'c
      Position : 'a -> Pos
      PrettyPrint : ('a -> string) option

      //Parser definitions and binding powers
      BindingPower : Map<'c, int>
      Null : Map<'c, 'a -> T<'a, 'b, 'c> -> 'b>
      Stmt : Map<'c, 'a -> T<'a, 'b, 'c> -> 'b>
      Left : Map<'c, 'a -> 'b -> T<'a, 'b, 'c> -> 'b>
  }
  
  type Pattern<'a, 'b, 'c> when 'c : comparison 
    = Sym of 'c
    | Get of (T<'a, 'b, 'c> -> 'b)

  //Errors
  type Exn (msg, pos) = 
    inherit System.Exception(msg)
    member x.Position = pos

  (*
    Creates a string error snippet 
    that points out the exact source position
    where the error occured, for example:
  
    4: if(x == y) {
    5:   print'x equals y');
    ----------^
  *)
  let errorSource pos source =
    
    let splitLines (text:string) = 
      let text = text.Replace("\r\n", "\n").Replace("\r", "\n")
      System.Text.RegularExpressions.Regex.Split(text, "\n")

    let lineNum (input:int) n = 
      (input.ToString()).PadLeft(n, '0')

    let stringRepeat n input =
      if System.String.IsNullOrEmpty input then input
      else
        let result = new System.Text.StringBuilder(input.Length * n)
        result.Insert(0, input, n).ToString()

    match source with
    | None -> ""
    | Some(source:string) -> 
      let source = source |> splitLines 
      let result = ref ""
      let line, column = pos

      if line <= source.Length && line > 1 then
        let nr = line.ToString()
        let nrl = nr.Length

        //previous line
        let pline = line - 1
        if pline >= 1 then 
          let num = lineNum pline nrl
          result := num+": "+source.[pline-1]+"\n"

        //current line
        let text = source.[line-1]
        if column <= text.Length then
          let arrow = "-" |> stringRepeat (nrl + column)
          result := !result+nr+": "+text+"\n"+arrow+"^\n"

      !result

  let exn msg = Exn(msg, (0, 0)) |> raise
  let exnLine pos msg = 
    let line = sprintf "Error on line: %i col: %i\n" (fst pos) (snd pos)
    Exn(line + msg, pos) |> raise

  let private unexpectedEnd () = "Unexpected end of input" |> exn
  let private unexpectedToken token parser =
    let type' =
      match parser.PrettyPrint with
      | None -> (token |> parser.Type).ToString()
      | Some f -> token |> f

    let pos = token |> parser.Position
    let source = parser.Lines |> errorSource pos 
    let expected = sprintf "Unexpected: %s" type'
    (source + expected) |> exnLine pos

  let inline private getBindingPower tok parser = 
    let pwr = parser.BindingPower.TryFind (parser.Type tok)
    match pwr with Some pwr -> pwr | _ -> 0

  let current parser =  
    match !parser.Input with
    | token::_ -> token
    | _ -> unexpectedEnd ()

  let currentTry parser = 
    match !parser.Input with
    | token::_ -> Some token
    | _ -> None

  let currentType parser = 
    parser |> current |> parser.Type

  let currentTypeTry parser =
    match parser |> currentTry with
    | Some token -> Some(token |> parser.Type)
    | _ -> None

  let skip parser =
    match !parser.Input with
    | _::input -> parser.Input := input
    | _ -> unexpectedEnd ()

  let skipIf type' parser =
    match !parser.Input with
    | token::xs when parser.Type token = type' -> 
      parser.Input := xs

    | token::_ -> 
      unexpectedToken token parser

    | _ -> unexpectedEnd ()

  let skipCurrent parser =
    let current = parser |> current
    parser |> skip
    current
   
  let exprPwr rbpw parser =
    let rec expr left =
      match parser |> currentTry with
      | Some token when rbpw < (parser |> getBindingPower token) -> 
        parser |> skip

        let type' = parser.Type token
        let led = 
          match parser.Left.TryFind type' with
          | None -> unexpectedToken token parser
          | Some led -> led

        led token left parser |> expr

      | _ -> left

    let tok = parser |> skipCurrent
    let type' = parser.Type tok
    let nud =
      match parser.Null.TryFind type' with
      | None -> unexpectedToken tok parser
      | Some nud -> nud

    nud tok parser |> expr 

  let expr parser = 
    parser |> exprPwr 0

  let exprSkip type' parser =
    let expr = parser |> expr
    parser |> skipIf type'
    expr

  let rec exprList parser =
    match !parser.Input with
    | [] -> []
    | _ -> (parser |> expr) :: (parser |> exprList)

  let stmt term parser =
    let token = parser |> current
    match parser.Stmt.TryFind (token |> parser.Type) with
    | Some stmt -> parser |> skip; stmt token parser
    | None -> parser |> exprSkip term

  let rec stmtList term parser =
    match !parser.Input with
    | [] -> []
    | _ -> (parser |> stmt term) :: (parser |> stmtList term)

  let match' pattern parser =
    let rec match' acc pattern parser =
      match pattern with
      | [] -> acc |> List.rev

      | Sym(symbol)::pattern -> 
        parser |> skipIf symbol
        parser |> match' acc pattern

      | Get(f)::pattern ->
        let acc = (f parser) :: acc
        parser |> match' acc pattern 

    parser |> match' [] pattern

  (*
    Convenience functions exposed for 
    easing parser definition and usage
  *)

  let create<'a, 'b, 'c when 'c : comparison> type' position prettyPrint = {
    Input = ref []
    Lines = None
    
    Type = type'
    Position = position
    PrettyPrint = prettyPrint
    
    BindingPower = Map.empty<'c, int>
    Null = Map.empty<'c, 'a -> T<'a, 'b, 'c> -> 'b>
    Stmt = Map.empty<'c, 'a -> T<'a, 'b, 'c> -> 'b>
    Left = Map.empty<'c, 'a -> 'b -> T<'a, 'b, 'c> -> 'b>
  }
  
  let matchError () = exn "Match pattern failed"
  let smd token funct parser = {parser with T.Stmt = parser.Stmt.Add(token, funct)}
  let nud token funct parser = {parser with T.Null = parser.Null.Add(token, funct)}
  let led token funct parser = {parser with T.Left = parser.Left.Add(token, funct)}
  let bpw token power parser = {parser with T.BindingPower = parser.BindingPower.Add(token, power)}
  
  (*Defines a left-associative infix operator*)
  let infix f typ pwr p =
    let infix tok left p = 
      f tok left (p |> exprPwr pwr)

    p |> bpw typ pwr |> led typ infix
    
  (*Defines a right-associative infix operator*)
  let infixr f typ pwr p =
    let lpwr = pwr - 1

    let infix tok left p = 
      f tok left (p |> exprPwr lpwr)

    p |> bpw typ pwr |> led typ infix

  (*Defines a prefix/unary operator*)
  let prefix f typ pwr p =
    let prefix tok parser = 
      f tok (parser |> exprPwr pwr)

    p |> nud typ prefix

  (*Defines a constant*)
  let constant symbol value p =
    p |> nud symbol (fun _ _ -> value)
    
  (*  
    Runs the parser and treats all 
    top level construct as expressions 
  *)
  let runExpr input source parser =
    {parser with 
      T.Input = ref input
      T.Lines = source
    } |> exprList
    
  (*  
    Runs the parser and treats all 
    top level construct as statements 
  *)
  let runStmt input source term parser =
    {parser with 
      T.Input = ref input
      T.Lines = source
    } |> stmtList term

(*
  Example parser for a very simple grammar
*)

//AST Types
type UnaryOp
  = Plus
  | Minus
  
type BinaryOp
  = Multiply
  | Add
  | Subtract
  | Divide
  | Assign
  | Equals

type Ast
  = Number of int
  | Identifier of string
  | String of string
  | Binary of BinaryOp * Ast * Ast
  | Unary of UnaryOp * Ast
  | Ternary of Ast * Ast * Ast // test * ifTrue * ifFalse
  | If of Ast * Ast * Ast option // test + ifTrue and possibly ifFalse (else branch)
  | Call of Ast * Ast list // target + arguments list
  | Block of Ast list // statements list
  | True
  | False

//Shorthand types for convenience
module P = Parser
type Token = string * string * (Parser.Pos)
type P = Parser.T<Token, Ast, string>

//Utility functions for extracting values out of Token
let type' ((t, _, _):Token) = t
let value ((_, v, _):Token) = v
let pos ((_, _, p):Token) = p
let value_num (t:Token) = t |> value |> int

//Utility functions for creating new tokens
let number value pos : Token = "#number", value, pos
let string value pos : Token = "#string", value, pos
let identifier name pos : Token = "#identifier", name, pos

let symbol type' pos : Token = type', "", pos
let add = symbol "+"
let sub = symbol "-"
let mul = symbol "*"
let div = symbol "/"
let assign = symbol "="
let equals = symbol "=="
let lparen = symbol "("
let rparen = symbol ")"
let lbrace = symbol "{"
let rbrace = symbol "}"
let comma = symbol ","
let qmark = symbol "?"
let colon = symbol ":"
let scolon = symbol ";"
let if' = symbol "if"
let true' = symbol "true"
let else' = symbol "else"

//Utility functions for converting tokens to binary and unary operators
let toBinaryOp tok =
  match type' tok with
  | "=" -> BinaryOp.Assign
  | "+" -> BinaryOp.Add
  | "-" -> BinaryOp.Subtract
  | "*" -> BinaryOp.Multiply
  | "/" -> BinaryOp.Divide
  | "==" -> BinaryOp.Equals
  | _ -> P.exn (sprintf "Couldn't convert %s-token to BinaryOp" (type' tok))

let toUnaryOp tok =
  match type' tok with
  | "+" -> UnaryOp.Plus
  | "-" -> UnaryOp.Minus
  | _ -> P.exn (sprintf "Couldn't convert %s-token to UnaryOp" (type' tok))

//Utility function for defining infix operators
let infix = 
  P.infix (fun token left right -> 
    Binary(token |> toBinaryOp, left, right))
  
//Utility function for defining prefix operators
let prefix =
  P.prefix (fun token ast ->
    Unary(token |> toUnaryOp, ast))

//Utility function for defining constants
let constant typ value p =
  p |> P.nud typ (fun _ _ -> value)

//Utility function for parsing a block 
let block p =
  let rec stmts p =
    match p |> P.currentTypeTry with
    | None -> []
    | Some "}" -> p |> P.skip; []
    | _ -> (p |> P.stmt ";") :: (stmts p)

  p |> P.skipIf "{"
  Block(p |> stmts)

//Pretty printing function for error messages
let prettyPrint (tok:Token) =
  match tok with
  | "#number", value, _ -> sprintf "#number %s" value
  | "#identifier", name, _ -> sprintf "#identifier %s" name
  | "#string", value, _ -> sprintf "#string \"%s\"" value
  | type', _, _ -> type'

//The parser definition
let example_parser =
  (P.create type' pos (Some prettyPrint))

  //Literals and identifiers
  |> P.nud "#number" (fun t _ -> t |> value |> int |> Number) 
  |> P.nud "#identifier" (fun t _ -> t |> value |> Identifier)
  |> P.nud "#string" (fun t _ -> t |> value |> String)

  //Constants
  |> constant "true" Ast.True
  |> constant "false" Ast.False
  
  //Infix Operators <expr> <op> <expr>
  |> infix "==" 40
  |> infix "+" 50
  |> infix "-" 50
  |> infix "*" 60
  |> infix "/" 60
  |> infix "=" 80

  //Prefix Operators <op> <expr>
  |> prefix "+" 70
  |> prefix "-" 70
  
  //Grouping expressions (<expr>)
  |> P.nud "(" (fun t p -> p |> P.exprSkip ")")

  //Ternary operator <expr> ? <expr> : <expr>
  |> P.bpw "?" 70
  |> P.led "?" (fun _ left p ->
      let ternary = [P.Get P.expr; P.Sym ":"; P.Get P.expr]
      match p |> P.match' ternary with
      | ifTrue::ifFalse::_ -> Ternary(left, ifTrue, ifFalse)
      | _ -> P.matchError()
    )

  //If/Else statement if(<condition>) { <exprs } [else { <exprs> }]
  |> P.smd "if" (fun _ p ->
      let if' = [P.Sym "("; P.Get P.expr; P.Sym ")"; P.Get block]
      let else' = [P.Sym "else"; P.Get block]

      match p |> P.match' if' with
      | test::ifTrue::_ -> 
        match p |> P.match' else' with
        | ifFalse::_ -> If(test, ifTrue, Some(ifFalse))
        | _ -> If(test, ifTrue, None)
      | _ -> P.matchError()
    )

  //Function call
  |> P.bpw "(" 80
  |> P.led "(" (fun _ func p ->
      let rec args (p:P) =
        match p |> P.currentType with
        | ")" -> p |> P.skip; []
        | "," -> p |> P.skip; args p
        | _ -> (p |> P.expr) :: args p

      Call(func, args p)
    )
    
//Code to parse
(*
1: x = 5;
2: y = 5;
3: 
4: if(x == y) {
5:   print("x equals y");
6: } else {
7:   print("x doesn't equal y");
8: }
*)

let code = @"x = 5;
y = 5;

if(x == y) {
  print('x equals y');
} else {
  print('x doesn't equal y');
}"

//The code in tokens, manually entered
//since we don't have a lexer to produce
//the tokens for us
let tokens = 
  [
    //x = 5;
    identifier "x" (1, 1)
    assign (1, 3)
    number "5" (1, 5)
    scolon (1, 6)

    //y = 5;
    identifier "y" (2, 1)
    assign (2, 3)
    number "5" (2, 5)
    scolon (2, 6)

    //if(x == y) {
    if' (4, 1)
    lparen (4, 3)
    identifier "x" (4, 4)
    equals (4, 6)
    identifier "y" (4, 9)
    rparen (4, 10)
    lbrace (4, 12)

    //print("x equals y");
    identifier "print" (5, 3)
    lparen (5, 8)
    string "x equals y" (5, 9)
    rparen (5, 21)
    scolon (5, 22)

    //} else {
    rbrace (6, 1)
    else' (6, 3)
    lbrace (6, 7)

    //print("x doesn't equal y");
    identifier "print" (7, 3)
    lparen (7, 7)
    string "x doesn't equal y" (7, 9)
    rparen (7, 27)
    scolon (7, 28)

    //}
    rbrace (8, 1)
  ]

let ast = example_parser |> P.runStmt tokens (Some code) ";"
type Pos = int * int

Full name: Script.Parser.Pos
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
type T<'a,'b,'c (requires comparison)> =
  {Input: 'a list ref;
   Lines: string option;
   Type: 'a -> 'c;
   Position: 'a -> Pos;
   PrettyPrint: ('a -> string) option;
   BindingPower: Map<'c,int>;
   Null: Map<'c,('a -> T<'a,'b,'c> -> 'b)>;
   Stmt: Map<'c,('a -> T<'a,'b,'c> -> 'b)>;
   Left: Map<'c,('a -> 'b -> T<'a,'b,'c> -> 'b)>;}

Full name: Script.Parser.T<_,_,_>
T.Input: 'a list ref
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
Multiple items
val ref : value:'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
T.Lines: string option
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
T.Type: 'a -> 'c
T.Position: 'a -> Pos
T.PrettyPrint: ('a -> string) option
T.BindingPower: Map<'c,int>
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
T.Null: Map<'c,('a -> T<'a,'b,'c> -> 'b)>
T.Stmt: Map<'c,('a -> T<'a,'b,'c> -> 'b)>
T.Left: Map<'c,('a -> 'b -> T<'a,'b,'c> -> 'b)>
type Pattern<'a,'b,'c (requires comparison)> =
  | Sym of 'c
  | Get of (T<'a,'b,'c> -> 'b)

Full name: Script.Parser.Pattern<_,_,_>
union case Pattern.Sym: 'c -> Pattern<'a,'b,'c>
union case Pattern.Get: (T<'a,'b,'c> -> 'b) -> Pattern<'a,'b,'c>
Multiple items
type Exn =
  inherit Exception
  new : msg:string * pos:(int * int) -> Exn
  member Position : int * int

Full name: Script.Parser.Exn

--------------------
new : msg:string * pos:(int * int) -> Exn
val msg : string
val pos : int * int
namespace System
Multiple items
type Exception =
  new : unit -> Exception + 2 overloads
  member Data : IDictionary
  member GetBaseException : unit -> Exception
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member GetType : unit -> Type
  member HelpLink : string with get, set
  member InnerException : Exception
  member Message : string
  member Source : string with get, set
  member StackTrace : string
  ...

Full name: System.Exception

--------------------
System.Exception() : unit
System.Exception(message: string) : unit
System.Exception(message: string, innerException: exn) : unit
System.Exception(info: System.Runtime.Serialization.SerializationInfo, context: System.Runtime.Serialization.StreamingContext) : unit
val x : Exn
member Exn.Position : int * int

Full name: Script.Parser.Exn.Position
val errorSource : int * int -> source:string option -> string

Full name: Script.Parser.errorSource
val source : string option
val splitLines : (string -> string [])
val text : string
System.String.Replace(oldValue: string, newValue: string) : string
System.String.Replace(oldChar: char, newChar: char) : string
namespace System.Text
namespace System.Text.RegularExpressions
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
System.Text.RegularExpressions.Regex(pattern: string) : unit
System.Text.RegularExpressions.Regex(pattern: string, options: System.Text.RegularExpressions.RegexOptions) : unit
System.Text.RegularExpressions.Regex.Split(input: string, pattern: string) : string []
System.Text.RegularExpressions.Regex.Split(input: string, pattern: string, options: System.Text.RegularExpressions.RegexOptions) : string []
val lineNum : (int -> int -> string)
val input : int
val n : int
System.Int32.ToString() : string
System.Int32.ToString(provider: System.IFormatProvider) : string
System.Int32.ToString(format: string) : string
System.Int32.ToString(format: string, provider: System.IFormatProvider) : string
val stringRepeat : (int -> string -> string)
val input : string
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
System.String(value: nativeptr<char>) : unit
System.String(value: nativeptr<sbyte>) : unit
System.String(value: char []) : unit
System.String(c: char, count: int) : unit
System.String(value: nativeptr<char>, startIndex: int, length: int) : unit
System.String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
System.String(value: char [], startIndex: int, length: int) : unit
System.String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: System.Text.Encoding) : unit
System.String.IsNullOrEmpty(value: string) : bool
val result : System.Text.StringBuilder
Multiple items
type StringBuilder =
  new : unit -> StringBuilder + 5 overloads
  member Append : value:string -> StringBuilder + 18 overloads
  member AppendFormat : format:string * arg0:obj -> StringBuilder + 4 overloads
  member AppendLine : unit -> StringBuilder + 1 overload
  member Capacity : int with get, set
  member Chars : int -> char with get, set
  member Clear : unit -> StringBuilder
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EnsureCapacity : capacity:int -> int
  member Equals : sb:StringBuilder -> bool
  ...

Full name: System.Text.StringBuilder

--------------------
System.Text.StringBuilder() : unit
System.Text.StringBuilder(capacity: int) : unit
System.Text.StringBuilder(value: string) : unit
System.Text.StringBuilder(value: string, capacity: int) : unit
System.Text.StringBuilder(capacity: int, maxCapacity: int) : unit
System.Text.StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
property System.String.Length: int
System.Text.StringBuilder.Insert(index: int, value: obj) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: uint64) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: uint32) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: uint16) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: decimal) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: float) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: float32) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: int64) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: int) : System.Text.StringBuilder
   (+0 other overloads)
System.Text.StringBuilder.Insert(index: int, value: char []) : System.Text.StringBuilder
   (+0 other overloads)
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val source : string
val source : string []
val result : string ref
val line : int
val column : int
property System.Array.Length: int
val nr : string
val nrl : int
val pline : int
val num : string
val arrow : string
Multiple items
val exn : msg:string -> 'a

Full name: Script.Parser.exn

--------------------
type exn = System.Exception

Full name: Microsoft.FSharp.Core.exn
val raise : exn:System.Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
val exnLine : int * int -> msg:string -> 'a

Full name: Script.Parser.exnLine
val line : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val private unexpectedEnd : unit -> 'a

Full name: Script.Parser.unexpectedEnd
val private unexpectedToken : token:'a -> parser:T<'a,'b,'c> -> 'd (requires comparison)

Full name: Script.Parser.unexpectedToken
val token : 'a
val parser : T<'a,'b,'c> (requires comparison)
val type' : string
val f : ('a -> string)
val pos : Pos
val expected : string
val private getBindingPower : tok:'a -> parser:T<'a,'b,'c> -> int (requires comparison)

Full name: Script.Parser.getBindingPower
val tok : 'a
val pwr : int option
member Map.TryFind : key:'Key -> 'Value option
val pwr : int
val current : parser:T<'a,'b,'c> -> 'a (requires comparison)

Full name: Script.Parser.current
val currentTry : parser:T<'a,'b,'c> -> 'a option (requires comparison)

Full name: Script.Parser.currentTry
val currentType : parser:T<'a,'b,'c> -> 'c (requires comparison)

Full name: Script.Parser.currentType
val currentTypeTry : parser:T<'a,'b,'c> -> 'c option (requires comparison)

Full name: Script.Parser.currentTypeTry
val skip : parser:T<'a,'b,'c> -> unit (requires comparison)

Full name: Script.Parser.skip
val input : 'a list
val skipIf : type':'a -> parser:T<'b,'c,'a> -> unit (requires comparison)

Full name: Script.Parser.skipIf
val type' : 'a (requires comparison)
val parser : T<'b,'c,'a> (requires comparison)
T.Input: 'b list ref
val token : 'b
val xs : 'b list
T.Type: 'b -> 'a
val skipCurrent : parser:T<'a,'b,'c> -> 'a (requires comparison)

Full name: Script.Parser.skipCurrent
val current : 'a
val exprPwr : rbpw:int -> parser:T<'a,'b,'c> -> 'b (requires comparison)

Full name: Script.Parser.exprPwr
val rbpw : int
val expr : ('b -> 'b)
val left : 'b
val type' : 'c (requires comparison)
val led : ('a -> 'b -> T<'a,'b,'c> -> 'b) (requires comparison)
val nud : ('a -> T<'a,'b,'c> -> 'b) (requires comparison)
val expr : parser:T<'a,'b,'c> -> 'b (requires comparison)

Full name: Script.Parser.expr
val exprSkip : type':'a -> parser:T<'b,'c,'a> -> 'c (requires comparison)

Full name: Script.Parser.exprSkip
val expr : 'c
val exprList : parser:T<'a,'b,'c> -> 'b list (requires comparison)

Full name: Script.Parser.exprList
val stmt : term:'a -> parser:T<'b,'c,'a> -> 'c (requires comparison)

Full name: Script.Parser.stmt
val term : 'a (requires comparison)
T.Stmt: Map<'a,('b -> T<'b,'c,'a> -> 'c)>
val stmt : ('b -> T<'b,'c,'a> -> 'c) (requires comparison)
val stmtList : term:'a -> parser:T<'b,'c,'a> -> 'c list (requires comparison)

Full name: Script.Parser.stmtList
val match' : pattern:Pattern<'a,'b,'c> list -> parser:T<'a,'b,'c> -> 'b list (requires comparison)

Full name: Script.Parser.match'
val pattern : Pattern<'a,'b,'c> list (requires comparison)
val match' : ('d list -> Pattern<'e,'d,'f> list -> T<'e,'d,'f> -> 'd list) (requires comparison)
val acc : 'd list
val pattern : Pattern<'e,'d,'f> list (requires comparison)
val parser : T<'e,'d,'f> (requires comparison)
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val rev : list:'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.rev
val symbol : 'f (requires comparison)
val f : (T<'e,'d,'f> -> 'd) (requires comparison)
val create : type':('a -> 'c) -> position:('a -> Pos) -> prettyPrint:('a -> string) option -> T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.create
val type' : ('a -> 'c) (requires comparison)
val position : ('a -> Pos)
val prettyPrint : ('a -> string) option
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.empty
val matchError : unit -> 'a

Full name: Script.Parser.matchError
val smd : token:'a -> funct:('b -> T<'b,'c,'a> -> 'c) -> parser:T<'b,'c,'a> -> T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.smd
val token : 'a (requires comparison)
val funct : ('b -> T<'b,'c,'a> -> 'c) (requires comparison)
member Map.Add : key:'Key * value:'Value -> Map<'Key,'Value>
val nud : token:'a -> funct:('b -> T<'b,'c,'a> -> 'c) -> parser:T<'b,'c,'a> -> T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.nud
T.Null: Map<'a,('b -> T<'b,'c,'a> -> 'c)>
val led : token:'a -> funct:('b -> 'c -> T<'b,'c,'a> -> 'c) -> parser:T<'b,'c,'a> -> T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.led
val funct : ('b -> 'c -> T<'b,'c,'a> -> 'c) (requires comparison)
T.Left: Map<'a,('b -> 'c -> T<'b,'c,'a> -> 'c)>
val bpw : token:'a -> power:int -> parser:T<'b,'c,'a> -> T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.bpw
val power : int
T.BindingPower: Map<'a,int>
val infix : f:('a -> 'b -> 'b -> 'b) -> typ:'c -> pwr:int -> p:T<'a,'b,'c> -> T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.infix
val f : ('a -> 'b -> 'b -> 'b)
val typ : 'c (requires comparison)
val p : T<'a,'b,'c> (requires comparison)
val infix : ('a -> 'b -> T<'d,'b,'e> -> 'b) (requires comparison)
val p : T<'d,'b,'e> (requires comparison)
val infixr : f:('a -> 'b -> 'b -> 'b) -> typ:'c -> pwr:int -> p:T<'a,'b,'c> -> T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.infixr
val lpwr : int
val prefix : f:('a -> 'b -> 'b) -> typ:'c -> pwr:int -> p:T<'a,'b,'c> -> T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.prefix
val f : ('a -> 'b -> 'b)
val prefix : ('a -> T<'d,'b,'e> -> 'b) (requires comparison)
val parser : T<'d,'b,'e> (requires comparison)
val constant : symbol:'a -> value:'b -> p:T<'c,'b,'a> -> T<'c,'b,'a> (requires comparison)

Full name: Script.Parser.constant
val symbol : 'a (requires comparison)
val value : 'b
val p : T<'c,'b,'a> (requires comparison)
val runExpr : input:'a list -> source:string option -> parser:T<'a,'b,'c> -> 'b list (requires comparison)

Full name: Script.Parser.runExpr
val runStmt : input:'a list -> source:string option -> term:'b -> parser:T<'a,'c,'b> -> 'c list (requires comparison)

Full name: Script.Parser.runStmt
val term : 'b (requires comparison)
val parser : T<'a,'c,'b> (requires comparison)
type UnaryOp =
  | Plus
  | Minus

Full name: Script.UnaryOp
union case UnaryOp.Plus: UnaryOp
union case UnaryOp.Minus: UnaryOp
type BinaryOp =
  | Multiply
  | Add
  | Subtract
  | Divide
  | Assign
  | Equals

Full name: Script.BinaryOp
union case BinaryOp.Multiply: BinaryOp
union case BinaryOp.Add: BinaryOp
union case BinaryOp.Subtract: BinaryOp
union case BinaryOp.Divide: BinaryOp
union case BinaryOp.Assign: BinaryOp
union case BinaryOp.Equals: BinaryOp
type Ast =
  | Number of int
  | Identifier of string
  | String of string
  | Binary of BinaryOp * Ast * Ast
  | Unary of UnaryOp * Ast
  | Ternary of Ast * Ast * Ast
  | If of Ast * Ast * Ast option
  | Call of Ast * Ast list
  | Block of Ast list
  | True
  ...

Full name: Script.Ast
union case Ast.Number: int -> Ast
union case Ast.Identifier: string -> Ast
Multiple items
union case Ast.String: string -> Ast

--------------------
module String

from Microsoft.FSharp.Core
union case Ast.Binary: BinaryOp * Ast * Ast -> Ast
union case Ast.Unary: UnaryOp * Ast -> Ast
union case Ast.Ternary: Ast * Ast * Ast -> Ast
union case Ast.If: Ast * Ast * Ast option -> Ast
union case Ast.Call: Ast * Ast list -> Ast
union case Ast.Block: Ast list -> Ast
union case Ast.True: Ast
union case Ast.False: Ast
module Parser

from Script
type Token = string * string * Parser.Pos

Full name: Script.Token
type P = Parser.T<Token,Ast,string>

Full name: Script.P
val type' : string * string * Parser.Pos -> string

Full name: Script.type'
val t : string
val value : string * string * Parser.Pos -> string

Full name: Script.value
val v : string
val pos : string * string * Parser.Pos -> Parser.Pos

Full name: Script.pos
val p : Parser.Pos
val value_num : string * string * Parser.Pos -> int

Full name: Script.value_num
val t : Token
val number : value:string -> int * int -> Token

Full name: Script.number
val value : string
val pos : Parser.Pos
Multiple items
val string : value:string -> int * int -> Token

Full name: Script.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
val identifier : name:string -> int * int -> Token

Full name: Script.identifier
val name : string
val symbol : type':string -> int * int -> Token

Full name: Script.symbol
val add : (Parser.Pos -> Token)

Full name: Script.add
val sub : (Parser.Pos -> Token)

Full name: Script.sub
val mul : (Parser.Pos -> Token)

Full name: Script.mul
val div : (Parser.Pos -> Token)

Full name: Script.div
val assign : (Parser.Pos -> Token)

Full name: Script.assign
val equals : (Parser.Pos -> Token)

Full name: Script.equals
val lparen : (Parser.Pos -> Token)

Full name: Script.lparen
val rparen : (Parser.Pos -> Token)

Full name: Script.rparen
val lbrace : (Parser.Pos -> Token)

Full name: Script.lbrace
val rbrace : (Parser.Pos -> Token)

Full name: Script.rbrace
val comma : (Parser.Pos -> Token)

Full name: Script.comma
val qmark : (Parser.Pos -> Token)

Full name: Script.qmark
val colon : (Parser.Pos -> Token)

Full name: Script.colon
val scolon : (Parser.Pos -> Token)

Full name: Script.scolon
val if' : (Parser.Pos -> Token)

Full name: Script.if'
val true' : (Parser.Pos -> Token)

Full name: Script.true'
val else' : (Parser.Pos -> Token)

Full name: Script.else'
val toBinaryOp : string * string * Parser.Pos -> BinaryOp

Full name: Script.toBinaryOp
val tok : Token
val exn : msg:string -> 'a

Full name: Script.Parser.exn
val toUnaryOp : string * string * Parser.Pos -> UnaryOp

Full name: Script.toUnaryOp
val infix : (string -> int -> Parser.T<Token,Ast,string> -> Parser.T<Token,Ast,string>)

Full name: Script.infix
val infix : f:('a -> 'b -> 'b -> 'b) -> typ:'c -> pwr:int -> p:Parser.T<'a,'b,'c> -> Parser.T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.infix
val token : Token
val left : Ast
val right : Ast
val prefix : (string -> int -> Parser.T<Token,Ast,string> -> Parser.T<Token,Ast,string>)

Full name: Script.prefix
val prefix : f:('a -> 'b -> 'b) -> typ:'c -> pwr:int -> p:Parser.T<'a,'b,'c> -> Parser.T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.prefix
val ast : Ast
val constant : typ:'a -> value:'b -> p:Parser.T<'c,'b,'a> -> Parser.T<'c,'b,'a> (requires comparison)

Full name: Script.constant
val typ : 'a (requires comparison)
val p : Parser.T<'c,'b,'a> (requires comparison)
val nud : token:'a -> funct:('b -> Parser.T<'b,'c,'a> -> 'c) -> parser:Parser.T<'b,'c,'a> -> Parser.T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.nud
val block : p:Parser.T<'a,Ast,string> -> Ast

Full name: Script.block
val p : Parser.T<'a,Ast,string>
val stmts : (Parser.T<'b,'c,string> -> 'c list)
val p : Parser.T<'b,'c,string>
val currentTypeTry : parser:Parser.T<'a,'b,'c> -> 'c option (requires comparison)

Full name: Script.Parser.currentTypeTry
val skip : parser:Parser.T<'a,'b,'c> -> unit (requires comparison)

Full name: Script.Parser.skip
val stmt : term:'a -> parser:Parser.T<'b,'c,'a> -> 'c (requires comparison)

Full name: Script.Parser.stmt
val skipIf : type':'a -> parser:Parser.T<'b,'c,'a> -> unit (requires comparison)

Full name: Script.Parser.skipIf
val prettyPrint : string * string * Parser.Pos -> string

Full name: Script.prettyPrint
val example_parser : Parser.T<Token,Ast,string>

Full name: Script.example_parser
val create : type':('a -> 'c) -> position:('a -> Parser.Pos) -> prettyPrint:('a -> string) option -> Parser.T<'a,'b,'c> (requires comparison)

Full name: Script.Parser.create
val p : Parser.T<Token,Ast,string>
val exprSkip : type':'a -> parser:Parser.T<'b,'c,'a> -> 'c (requires comparison)

Full name: Script.Parser.exprSkip
val bpw : token:'a -> power:int -> parser:Parser.T<'b,'c,'a> -> Parser.T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.bpw
val led : token:'a -> funct:('b -> 'c -> Parser.T<'b,'c,'a> -> 'c) -> parser:Parser.T<'b,'c,'a> -> Parser.T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.led
val ternary : Parser.Pattern<'a,'b,string> list
union case Parser.Pattern.Get: (Parser.T<'a,'b,'c> -> 'b) -> Parser.Pattern<'a,'b,'c>
val expr : parser:Parser.T<'a,'b,'c> -> 'b (requires comparison)

Full name: Script.Parser.expr
union case Parser.Pattern.Sym: 'c -> Parser.Pattern<'a,'b,'c>
val match' : pattern:Parser.Pattern<'a,'b,'c> list -> parser:Parser.T<'a,'b,'c> -> 'b list (requires comparison)

Full name: Script.Parser.match'
val ifTrue : Ast
val ifFalse : Ast
val smd : token:'a -> funct:('b -> Parser.T<'b,'c,'a> -> 'c) -> parser:Parser.T<'b,'c,'a> -> Parser.T<'b,'c,'a> (requires comparison)

Full name: Script.Parser.smd
val if' : Parser.Pattern<'a,Ast,string> list
val else' : Parser.Pattern<'a,Ast,string> list
val test : Ast
val func : Ast
val args : (P -> Ast list)
val p : P
val currentType : parser:Parser.T<'a,'b,'c> -> 'c (requires comparison)

Full name: Script.Parser.currentType
val code : string

Full name: Script.code
val tokens : Token list

Full name: Script.tokens
val ast : Ast list

Full name: Script.ast
val runStmt : input:'a list -> source:string option -> term:'b -> parser:Parser.T<'a,'c,'b> -> 'c list (requires comparison)

Full name: Script.Parser.runStmt

More information

Link:http://fssnip.net/2X
Posted:6 years ago
Author:fholm
Tags: parsers , parser