-
Notifications
You must be signed in to change notification settings - Fork 0
/
Example.fs
85 lines (81 loc) · 3.19 KB
/
Example.fs
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
namespace ParseExample
open System
open System.Globalization
open WoofWare.PrattParser
[<RequireQualifiedAccess>]
module Example =
let private atom (inputString : string) (token : Token) : Expr option =
match token.Type with
| TokenType.ConstInt ->
let start, len = token.Trivia
Int32.Parse (inputString.AsSpan().Slice (start, len), NumberStyles.None, CultureInfo.InvariantCulture)
|> Expr.constInt
|> Some
| TokenType.Var ->
let start, len = token.Trivia
Some (Expr.var (inputString.Substring (start, len)))
| TokenType.Plus
| TokenType.Minus
| TokenType.Times
| TokenType.Equal
| TokenType.Factorial
| TokenType.If
| TokenType.Then
| TokenType.Else
| TokenType.ArrayIndex
| TokenType.RightSquareBracket
| TokenType.LeftBracket
| TokenType.RightBracket -> None
let parser =
Parser.make (fun token -> token.Type) atom
|> Parser.withUnaryPostfix TokenType.Factorial (11, ()) Expr.factorial
|> Parser.withUnaryPrefix TokenType.Plus ((), 9) id
|> Parser.withUnaryPrefix TokenType.Minus ((), 9) Expr.unaryMinus
|> Parser.withInfix TokenType.Plus (5, 6) Expr.plus
|> Parser.withInfix TokenType.Minus (5, 6) Expr.minus
|> Parser.withInfix TokenType.Times (7, 8) Expr.times
|> Parser.withInfix TokenType.Equal (2, 1) Expr.equal
|> Parser.withBracketLike
TokenType.LeftBracket
{
ConsumeBeforeInitialToken = false
ConsumeAfterFinalToken = false
BoundaryTokens = [ TokenType.RightBracket ]
Construct = Seq.exactlyOne >> Expr.paren
}
|> Parser.withBracketLike
TokenType.If
{
ConsumeBeforeInitialToken = false
ConsumeAfterFinalToken = true
BoundaryTokens = [ TokenType.Then ; TokenType.Else ]
Construct =
fun s ->
match s with
| [ ifClause ; thenClause ; elseClause ] -> Expr.ifThenElse ifClause thenClause elseClause
| _ -> failwith "logic error"
}
|> Parser.withBracketLike
TokenType.If
{
ConsumeBeforeInitialToken = false
ConsumeAfterFinalToken = true
BoundaryTokens = [ TokenType.Then ]
Construct =
fun s ->
match s with
| [ ifClause ; thenClause ] -> Expr.ifThen ifClause thenClause
| _ -> failwith "logic error"
}
|> Parser.withBracketLike
TokenType.ArrayIndex
{
ConsumeBeforeInitialToken = true
ConsumeAfterFinalToken = false
BoundaryTokens = [ TokenType.RightSquareBracket ]
Construct =
fun s ->
match s with
| [ arg ; contents ] -> Expr.arrayIndex arg contents
| _ -> failwith "logic error"
}