Branch data Line data Source code
1 : : #include "lex/Lexer.hpp"
2 : : #include "parse/ASTDumper.hpp"
3 : : #include "parse/Parser.hpp"
4 : : #include "parse/Sema.hpp"
5 : : #include <cerrno>
6 : : #include <cstdlib>
7 : : #include <cstring>
8 : : #include <fstream>
9 : : #include <iostream>
10 : : #include <mutable/Options.hpp>
11 : : #include <mutable/util/ArgParser.hpp>
12 : : #include <mutable/util/Diagnostic.hpp>
13 : : #include <mutable/util/fn.hpp>
14 : :
15 : :
16 : : using namespace m;
17 : : using namespace m::ast;
18 : :
19 : :
20 : 0 : void usage(std::ostream &out, const char *name)
21 : : {
22 : 0 : out << "Performs semantic analysis of the input.\n"
23 : 0 : << "USAGE:\n\t" << name << " [<FILE>...]"
24 : 0 : << std::endl;
25 : 0 : }
26 : :
27 : 0 : int main(int argc, const char **argv)
28 : : {
29 : : /*----- Parse command line arguments. ----------------------------------------------------------------------------*/
30 : 0 : ArgParser AP;
31 : : #define ADD(TYPE, VAR, INIT, SHORT, LONG, DESCR, CALLBACK)\
32 : : VAR = INIT;\
33 : : {\
34 : : AP.add<TYPE>(SHORT, LONG, DESCR, CALLBACK);\
35 : : }
36 [ # # # # ]: 0 : ADD(bool, Options::Get().show_help, false, /* Type, Var, Init */
37 : : "-h", "--help", /* Short, Long */
38 : : "prints this help message", /* Description */
39 : : [&](bool) { Options::Get().show_help = true; }); /* Callback */
40 [ # # # # ]: 0 : ADD(bool, Options::Get().has_color, false, /* Type, Var, Init */
41 : : nullptr, "--color", /* Short, Long */
42 : : "use colors", /* Description */
43 : : [&](bool) { Options::Get().has_color = true; }); /* Callback */
44 [ # # # # ]: 0 : ADD(bool, Options::Get().ast, false, /* Type, Var, Init */
45 : : nullptr, "--ast", /* Short, Long */
46 : : "print AST", /* Description */
47 : : [&](bool) { Options::Get().ast = true; }); /* Callback */
48 [ # # # # ]: 0 : ADD(bool, Options::Get().quiet, false, /* Type, Var, Init */
49 : : "-q", "--quiet", /* Short, Long */
50 : : "work in quiet mode", /* Description */
51 : : [&](bool) { Options::Get().quiet = true; }); /* Callback */
52 : : #undef ADD
53 [ # # ]: 0 : AP.parse_args(argc, argv);
54 : :
55 [ # # # # ]: 0 : if (Options::Get().show_help) {
56 [ # # ]: 0 : usage(std::cout, argv[0]);
57 [ # # # # ]: 0 : std::cout << "WHERE\n" << AP;
58 : 0 : std::exit(EXIT_SUCCESS);
59 : : }
60 : :
61 [ # # # # ]: 0 : auto args = AP.args();
62 [ # # ]: 0 : if (args.empty())
63 [ # # ]: 0 : args.push_back("-"); // start in interactive mode
64 : :
65 : : std::istream *in;
66 : :
67 : 0 : /* Create the diagnostics object. */
68 [ # # # # ]: 0 : Diagnostic diag(Options::Get().has_color, std::cout, std::cerr);
69 : :
70 : 0 : bool sema_error = false;
71 [ # # ]: 0 : Catalog &C = Catalog::Get();
72 : :
73 : : /* Process all the inputs. */
74 [ # # ]: 0 : for (auto filename : args) {
75 [ # # # # ]: 0 : if (streq(filename, "-")) {
76 : : /* read from stdin */
77 : 0 : in = &std::cin;
78 : 0 : } else {
79 : : /* read from file */
80 [ # # # # ]: 0 : in = new std::ifstream(filename, std::ios_base::in);
81 : : }
82 : :
83 [ # # # # ]: 0 : if (in->fail()) {
84 [ # # ]: 0 : if (in == &std::cin)
85 [ # # ]: 0 : std::cerr << "Failed to open stdin: ";
86 : : else
87 [ # # # # : 0 : std::cerr << "Failed to open the file '" << filename << "': ";
# # ]
88 [ # # # # ]: 0 : std::cerr << strerror(errno) << std::endl;
89 : 0 : }
90 : :
91 [ # # # # ]: 0 : Lexer lexer(diag, C.get_pool(), filename, *in);
92 [ # # ]: 0 : Parser parser(lexer);
93 [ # # ]: 0 : Sema sema(diag);
94 : :
95 [ # # # # : 0 : while (parser.token()) {
# # ]
96 [ # # ]: 0 : auto stmt = parser.parse_Stmt();
97 [ # # # # ]: 0 : if (diag.num_errors()) {
98 [ # # ]: 0 : diag.clear();
99 : 0 : continue;
100 : : }
101 [ # # ]: 0 : auto cmd = sema.analyze(std::move(stmt));
102 [ # # # # ]: 0 : sema_error = sema_error or diag.num_errors();
103 [ # # # # ]: 0 : if (diag.num_errors()) {
104 [ # # ]: 0 : diag.clear();
105 : 0 : continue;
106 : : }
107 [ # # # # : 0 : if (Options::Get().ast) cmd->ast().dump(std::cout);
# # # # ]
108 [ # # # # ]: 0 : if (is<const DDLCommand>(cmd))
109 [ # # ]: 0 : cmd->execute(diag);
110 [ # # # ]: 0 : }
111 : :
112 [ # # ]: 0 : if (in != &std::cin)
113 [ # # ]: 0 : delete in;
114 : 0 : }
115 : :
116 : 0 : std::exit(sema_error ? EXIT_FAILURE : EXIT_SUCCESS);
117 : 0 : }
|