1 module calcool.app;
2 
3 version (CLI_APP) {
4     import std.stdio;
5     import std.getopt;
6     import std.file;
7     import std.format;
8 
9     import calcool.parser;
10     import calcool.token;
11     import calcool.exceptions;
12 
13     enum usage = q{Usage: calcool [OPTION] [ARGUMENT]
14 	-h : Print this help message
15 	-i : Set input file (each expression separated by newline)
16 	-c : Calculate the given expression};
17 
18     enum quitIfTooManyArgs(int maxArgs) = format!q{
19                 if (argnum > %d) {
20                     stderr.writeln(
21                             "Too many arguments: use -c for an expression or -i for an input file");
22                     return 1;
23                 }
24     }(maxArgs);
25 
26     int main(string[] args) {
27         string inputPath = null;
28         string inputExpression = null;
29         const argnum = args.length;
30 
31         GetoptResult opts;
32         try {
33             opts = getopt(args, "i", &inputPath, "c", &inputExpression);
34         } catch (Exception e) {
35             stderr.writefln("Error: %s\n", e.msg);
36             return 1;
37         }
38 
39         auto p = new Parser();
40         if (opts.helpWanted) {
41             writeln(usage);
42         } else if (inputPath !is null) {
43             mixin(quitIfTooManyArgs!3);
44             if (exists(inputPath) && isFile(inputPath)) {
45                 p.setInput(File(inputPath));
46                 run(p);
47             } else {
48                 stderr.writefln("Error: can't open file '%s'\n", inputPath);
49                 return 1;
50             }
51         } else if (inputExpression !is null) {
52             mixin(quitIfTooManyArgs!3);
53             return run(p, inputExpression);
54         } else {
55             mixin(quitIfTooManyArgs!1);
56             run(p);
57         }
58         return 0;
59     }
60 
61     void run(ref Parser p) {
62         import std.stdio : writeln, stderr;
63 
64         while (true) {
65             try {
66                 p.parseExpression().evaluate().writeln();
67             } catch (CalcoolException ce) {
68                 stderr.writeln(ce.msg);
69             } catch (EofException e) {
70                 break;
71             } catch (Exception e) {
72                 stderr.writefln("Error: %s", e.msg);
73                 break;
74             }
75         }
76     }
77 
78     int run(ref Parser p, string input) {
79         import std.stdio : writeln, stderr;
80 
81         try {
82             p.evaluateFromString(input).writeln();
83         } catch (CalcoolException ce) {
84             stderr.writefln(ce.msg);
85             return 1;
86         } catch (Exception e) {
87             return 2;
88         }
89         return 0;
90     }
91 }