3 people like it.
Like the snippet!
A Simple Parser
This is a basic parser that I wrote which takes heavily from the examples in Dom Syme's Expert F# book and http://fsharpforfunandprofit.com/posts/pattern-matching-command-line/
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:
|
let splitString (s : string) =
s.Split([|' '|])
type Token =
|SOURCE
|REGISTRY
|ZIP
|SERVICE
|DESTINATION
|MAXDAYS
|SMTPSERVER
|FROMEMAIL
|SUCCESSEMAIL
|FAILUREEMAIL
|VALUE of string
let tokenize (args : string[]) =
[for x in args do
let token =
match x with
| "-o" -> SOURCE
| "-r" -> REGISTRY
| "-z" -> ZIP
| "-v" -> SERVICE
| "-d" -> DESTINATION
| "-m" -> MAXDAYS
| "-t" -> SMTPSERVER
| "-e" -> FROMEMAIL
| "-s" -> SUCCESSEMAIL
| "-f" -> FAILUREEMAIL
| _ -> VALUE x
yield token]
type Zip = ZipFiles | DoNotZipFiles
type Options = {
Source : string;
Registry : string;
Zip : Zip;
Service : string;
Destination : string;
MaxDays : int;
SmtpServer : string;
FromEmail : string;
SuccessEmail : string;
FailureEmail : string;
}
let isWholeNumber s = String.forall (fun c -> System.Char.IsDigit(c)) s
// Strips VALUE tokens from top of list, returning the rest of the list
let returnNonValueTail tokenList =
tokenList
|>List.toSeq
|>Seq.skipWhile (fun t -> match t with VALUE y -> true | _ -> false)
|>Seq.toList
// Takes VALUE tokens from the top of the list, contatenates their associated strings and returns the contatenated string.
let returnConcatHeadValues tokenList =
tokenList
|> List.toSeq
|> Seq.takeWhile (fun t -> match t with VALUE y -> true | _ -> false)
|> Seq.fold (fun acc elem -> match elem with VALUE y -> acc + " " + y | _ -> acc) " "
|> fun s -> s.Trim()
let rec parseTokenListRec tokenList optionsSoFar =
match tokenList with
| [] -> optionsSoFar
| SOURCE::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Source = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the source argument."
| REGISTRY::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Registry = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the registry argument."
| ZIP::t -> parseTokenListRec t {optionsSoFar with Zip = ZipFiles}
| SERVICE::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Service = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the service argument."
| DESTINATION::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Destination = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the destination argument."
| MAXDAYS::t ->
match t with
|VALUE x::tt when (isWholeNumber x) -> parseTokenListRec tt {optionsSoFar with MaxDays = int x}
| _ -> failwith "Expected a whole number to be supplied after the maxdays argument."
| SMTPSERVER::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with SmtpServer = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the smtp server argument."
| FROMEMAIL::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with FromEmail = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the from email argument."
| SUCCESSEMAIL::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with SuccessEmail = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the success email argument."
| FAILUREEMAIL::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with FailureEmail = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the failure email argument."
| VALUE x::t -> failwith (sprintf "Encountered a value ('%s') without an associated argument." x)
let parseArgs args =
let tokenList = tokenize(args)
let defaultOptions = {
Source = "";
Registry = "";
Zip = DoNotZipFiles;
Service = "";
Destination = "";
MaxDays = 0;
SmtpServer = "";
FromEmail = "";
SuccessEmail = "";
FailureEmail = "";
}
parseTokenListRec tokenList defaultOptions
|
val splitString : s:string -> string []
Full name: Script.splitString
val s : string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
System.String.Split([<System.ParamArray>] separator: char []) : string []
System.String.Split(separator: string [], options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], count: int) : string []
System.String.Split(separator: string [], count: int, options: System.StringSplitOptions) : string []
System.String.Split(separator: char [], count: int, options: System.StringSplitOptions) : string []
type Token =
| SOURCE
| REGISTRY
| ZIP
| SERVICE
| DESTINATION
| MAXDAYS
| SMTPSERVER
| FROMEMAIL
| SUCCESSEMAIL
| FAILUREEMAIL
...
Full name: Script.Token
union case Token.SOURCE: Token
union case Token.REGISTRY: Token
union case Token.ZIP: Token
union case Token.SERVICE: Token
union case Token.DESTINATION: Token
union case Token.MAXDAYS: Token
union case Token.SMTPSERVER: Token
union case Token.FROMEMAIL: Token
union case Token.SUCCESSEMAIL: Token
union case Token.FAILUREEMAIL: Token
union case Token.VALUE: string -> Token
val tokenize : args:string [] -> Token list
Full name: Script.tokenize
val args : string []
val x : string
val token : Token
type Zip =
| ZipFiles
| DoNotZipFiles
Full name: Script.Zip
union case Zip.ZipFiles: Zip
union case Zip.DoNotZipFiles: Zip
type Options =
{Source: string;
Registry: string;
Zip: Zip;
Service: string;
Destination: string;
MaxDays: int;
SmtpServer: string;
FromEmail: string;
SuccessEmail: string;
FailureEmail: string;}
Full name: Script.Options
Options.Source: string
Options.Registry: string
Multiple items
Options.Zip: Zip
--------------------
type Zip =
| ZipFiles
| DoNotZipFiles
Full name: Script.Zip
Options.Service: string
Options.Destination: string
Options.MaxDays: int
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<_>
Options.SmtpServer: string
Options.FromEmail: string
Options.SuccessEmail: string
Options.FailureEmail: string
val isWholeNumber : s:string -> bool
Full name: Script.isWholeNumber
module String
from Microsoft.FSharp.Core
val forall : predicate:(char -> bool) -> str:string -> bool
Full name: Microsoft.FSharp.Core.String.forall
val c : char
namespace System
type Char =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 1 overload
static val MaxValue : char
static val MinValue : char
static member ConvertFromUtf32 : utf32:int -> string
static member ConvertToUtf32 : highSurrogate:char * lowSurrogate:char -> int + 1 overload
static member GetNumericValue : c:char -> float + 1 overload
...
end
Full name: System.Char
System.Char.IsDigit(c: char) : bool
System.Char.IsDigit(s: string, index: int) : bool
val returnNonValueTail : tokenList:Token list -> Token list
Full name: Script.returnNonValueTail
val tokenList : Token list
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 toSeq : list:'T list -> seq<'T>
Full name: Microsoft.FSharp.Collections.List.toSeq
module Seq
from Microsoft.FSharp.Collections
val skipWhile : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.skipWhile
val t : Token
val y : string
val toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toList
val returnConcatHeadValues : tokenList:Token list -> string
Full name: Script.returnConcatHeadValues
val takeWhile : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.takeWhile
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State
Full name: Microsoft.FSharp.Collections.Seq.fold
val acc : string
val elem : Token
System.String.Trim() : string
System.String.Trim([<System.ParamArray>] trimChars: char []) : string
val parseTokenListRec : tokenList:Token list -> optionsSoFar:Options -> Options
Full name: Script.parseTokenListRec
val optionsSoFar : Options
val t : Token list
val tt : Token list
val failwith : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.failwith
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val parseArgs : args:string [] -> Options
Full name: Script.parseArgs
val defaultOptions : Options
More information