1 #include <sngcpp/lexer/CppLexer.hpp>
2 #include <soulng/lexer/XmlParsingLog.hpp>
3 #include <sngcpp/parser/SourceFile.hpp>
4 #include <sngcpp/ast/InitDone.hpp>
5 #include <sngcpp/pp/InitDone.hpp>
6 #include <sngcpp/pp/PP.hpp>
7 #include <soulng/util/InitDone.hpp>
8 #include <soulng/util/Path.hpp>
9 #include <soulng/util/TextUtils.hpp>
10 #include <iostream>
11 #include <stdexcept>
12
13 using namespace soulng::util;
14 using namespace sngcpp::pp;
15 using namespace soulng::lexer;
16
17 void PrintUsage()
18 {
19 std::cout << "sngcpp parser tester" << std::endl;
20 std::cout << "usage: sngcppparsertester [options] { file.cpp | file.hpp }" << std::endl;
21 std::cout << "options:" << std::endl;
22 std::cout << "--help | -h" << std::endl;
23 std::cout << " Print help and exit." << std::endl;
24 std::cout << "--verbose | -v" << std::endl;
25 std::cout << " Be verbose." << std::endl;
26 std::cout << "--root DIR" << std::endl;
27 std::cout << " Set root directory to DIR." << std::endl;
28 std::cout << "--include PATH" << std::endl;
29 std::cout << " Set include path to PATH." << std::endl;
30 std::cout << "--debug | -d" << std::endl;
31 std::cout << " Debug parsing." << std::endl;
32 }
33
34 struct Initializer
35 {
36 Initializer()
37 {
38 soulng::util::Init();
39 sngcpp::pp::Init();
40 sngcpp::ast::Init();
41 }
42 ~Initializer()
43 {
44 sngcpp::ast::Done();
45 sngcpp::pp::Done();
46 soulng::util::Done();
47 }
48 };
49
50 int main(int argc, const char** argv)
51 {
52 Initializer initializer;
53 try
54 {
55 bool verbose = false;
56 bool debug = false;
57 std::string root;
58 std::string includePath;
59 std::vector<std::string> fileNames;
60 for (int i = 1; i < argc; ++i)
61 {
62 std::string arg = argv[i];
63 if (StartsWith(arg, "--"))
64 {
65 if (arg == "--help")
66 {
67 PrintUsage();
68 return 1;
69 }
70 else if (arg == "--verbose")
71 {
72 verbose = true;
73 }
74 else if (arg == "--root")
75 {
76 ++i;
77 if (i < argc)
78 {
79 arg = argv[i];
80 root = GetFullPath(arg);
81 }
82 else
83 {
84 throw std::runtime_error("argument expected");
85 }
86 }
87 else if (arg == "--include")
88 {
89 ++i;
90 if (i < argc)
91 {
92 arg = argv[i];
93 includePath = GetFullPath(arg);
94 }
95 else
96 {
97 throw std::runtime_error("argument expected");
98 }
99 }
100 else if (arg == "--debug")
101 {
102 debug = true;
103 }
104 else
105 {
106 throw std::runtime_error("unknown option '" + arg + "'");
107 }
108 }
109 else if (StartsWith(arg, "-"))
110 {
111 std::string options = arg.substr(1);
112 if (options.empty())
113 {
114 throw std::runtime_error("unknown option '" + arg + "'");
115 }
116 for (char o : options)
117 {
118 if (o == 'h')
119 {
120 PrintUsage();
121 return 1;
122 }
123 else if (o == 'v')
124 {
125 verbose = true;
126 }
127 else if (o == 'd')
128 {
129 debug = true;
130 }
131 else
132 {
133 throw std::runtime_error("unknown option '-" + std::string(1, o) + "'");
134 }
135 }
136 }
137 else
138 {
139 fileNames.push_back(GetFullPath(arg));
140 }
141 }
142 EvaluationContext evaluationContext;
143 std::vector<std::std::unique_ptr<SourceFileNode>>sourceFiles;
144 int fileIndex = 0;
145 for (const std::string& fileName : fileNames)
146 {
147 if (verbose)
148 {
149 std::cout << "> " << fileName << std::endl;
150 }
151 PP pp(evaluationContext);
152 if (!root.empty())
153 {
154 pp.root = root;
155 pp.rootMode = true;
156 }
157 if (!includePath.empty())
158 {
159 pp.includePath = Split(includePath, ';');
160 }
161 pp.Define(sngcpp::pp::ndebug);
162 if (verbose)
163 {
164 pp.verbose = true;
165 }
166 Preprocess(fileName, &pp);
167 std::unique_ptr<std::u32string> content(new std::u32string(std::move(pp.text)));
168 XmlParsingLog log(std::cerr);
169 CppLexer lexer(content->c_str(), content->c_str() + content->length(), fileName, fileIndex);
170 lexer.SetSeparatorChar('\n');
171 if (debug)
172 {
173 lexer.SetLog(&log);
174 }
175 std::unique_ptr<SourceFileNode> sourceFile(new SourceFileNode(lexer.GetSpan(), fileName, Path::GetFileName(fileName), U""));
176 sourceFile->SetSourceFileIndex(fileIndex);
177 SourceFileParser::Parse(lexer, sourceFile.get());
178 sourceFile->SetContent(std::move(content));
179 sourceFile->SetHeaderFilePaths(std::move(pp.headerFilePaths));
180 sourceFiles.push_back(std::move(sourceFile));
181 ++fileIndex;
182 }
183 }
184 catch (const std::exception& ex;)
185 {
186 std::cerr << ex.what() << std::endl;
187 return 1;
188 }
189 return 0;
190 }