forked from cmatheja/fsharp-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.fs
98 lines (83 loc) · 3.48 KB
/
Program.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
86
87
88
89
90
91
92
93
94
95
96
97
98
open FSharp.Text.Lexing
open System
open Newtonsoft.Json
open AST
exception ParseError of Position * string * Exception
let parse parser src =
let lexbuf = LexBuffer<char>.FromString src
let parser = parser Lexer.tokenize
try
Ok(parser lexbuf)
with
| e ->
let pos = lexbuf.EndPos
let line = pos.Line
let column = pos.Column
let message = e.Message
let lastToken = new String(lexbuf.Lexeme)
eprintf "Parse failed at line %d, column %d:\n" line column
eprintf "Last token: %s" lastToken
eprintf "\n"
Error(ParseError(pos, lastToken, e))
let rec evaluate: expr -> float =
function
| Num x -> x
| TimesExpr (a, b) -> evaluate a * evaluate b
| DivExpr (a, b) -> evaluate a / evaluate b
| PlusExpr (a, b) -> evaluate a + evaluate b
| MinusExpr (a, b) -> evaluate a - evaluate b
| PowExpr (a, b) -> evaluate a ** evaluate b
| UPlusExpr a -> evaluate a
| UMinusExpr a -> -evaluate a
// Please do not change the main function, with exception to the "calc" case.
// The other cases are needed for the validation and evaluation tools!
[<EntryPoint>]
let main (args) =
match args |> List.ofArray with
| "calc" :: input ->
match parse Parser.start (String.concat " " input) with
| Ok ast ->
Console.Error.WriteLine("> {0}", ast)
Console.WriteLine("{0}", evaluate ast)
| Error e -> Console.Error.WriteLine("Parse error: {0}", e)
0
| [ "graph"; src; input ] ->
let input = JsonConvert.DeserializeObject<Graph.Input> input
let output: Graph.Output = Graph.analysis src input
Console.WriteLine("{0}", JsonConvert.SerializeObject output)
0
| [ "interpreter"; src; input ] ->
let input = JsonConvert.DeserializeObject<Interpreter.Input> input
let output: Interpreter.Output = Interpreter.analysis src input
Console.WriteLine("{0}", JsonConvert.SerializeObject output)
0
| [ "program-verification"; src; input ] ->
let input = JsonConvert.DeserializeObject<ProgramVerification.Input> input
let output: ProgramVerification.Output = ProgramVerification.analysis src input
Console.WriteLine("{0}", JsonConvert.SerializeObject output)
0
| [ "sign"; src; input ] ->
let input = JsonConvert.DeserializeObject<SignAnalysis.Input> input
let output: SignAnalysis.Output = SignAnalysis.analysis src input
Console.WriteLine("{0}", JsonConvert.SerializeObject output)
0
| [ "security"; src; input ] ->
let input = JsonConvert.DeserializeObject<Security.Input> input
let output: Security.Output = Security.analysis src input
Console.WriteLine("{0}", JsonConvert.SerializeObject output)
0
| _ ->
let commands =
[ "calc <EXPRESSION...>"
"graph <SRC> <INPUT>"
"interpreter <SRC> <INPUT>"
"pv <SRC> <INPUT>"
"sign <SRC> <INPUT>"
"security <SRC> <INPUT>" ]
Console.Error.WriteLine(
"\x1B[1;31merror:\x1B[0m unrecognized input: \x1B[0;33m'{0}'\x1B[0m\n\n{1}\n\nAvailable commands:\n{2}",
String.concat " " args,
"\x1B[1mUsage: dotnet run\x1B[0m <COMMAND>",
(List.fold (fun acc cmd -> acc + sprintf " - \x1B[1m%s\x1B[0m\n" cmd) "" commands)
)
1