this repo has no description
1#include "RezLexer.h"
2
3#include <boost/wave.hpp>
4#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
5#include <boost/wave/token_ids.hpp>
6#include <boost/regex.hpp>
7
8#include "RezLexerWaveToken.h"
9#include "RezWorld.h"
10#include "Diagnostic.h"
11
12namespace wave = boost::wave;
13
14using namespace boost::wave;
15
16static std::string readContents(std::istream&& instream)
17{
18 instream.unsetf(std::ios::skipws);
19
20 return std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
21 std::istreambuf_iterator<char>());
22}
23
24static std::string preFilter(std::string str)
25{
26 boost::regex endif("#endif[^\r\n]*");
27 str = boost::regex_replace(str, endif, "#endif");
28
29 boost::regex dollar_escape("\\\\\\$([a-zA-Z0-9][a-zA-Z0-9])");
30 str = boost::regex_replace(str, dollar_escape, "\\\\0x$1");
31
32 if(str.size() == 0 || str[str.size()-1] != '\n')
33 str += "\n";
34 return str;
35}
36
37struct load_file_to_string_filtered
38{
39 template <typename IterContextT>
40 class inner
41 {
42 public:
43 template <typename PositionT>
44 static void init_iterators(IterContextT &iter_ctx,
45 PositionT const &act_pos, language_support language)
46 {
47 typedef typename IterContextT::iterator_type iterator_type;
48
49 // read in the file
50 std::ifstream instream(iter_ctx.filename.c_str());
51 if (!instream.is_open()) {
52 BOOST_WAVE_THROW_CTX(iter_ctx.ctx, preprocess_exception,
53 bad_include_file, iter_ctx.filename.c_str(), act_pos);
54 return;
55 }
56
57 iter_ctx.instring = preFilter(readContents(std::move(instream)));
58
59 iter_ctx.first = iterator_type(
60 iter_ctx.instring.begin(), iter_ctx.instring.end(),
61 PositionT(iter_ctx.filename), language);
62 iter_ctx.last = iterator_type();
63 }
64
65 private:
66 std::string instring;
67 };
68};
69
70
71
72typedef wave::cpplexer::lex_iterator<
73 wave::cpplexer::lex_token<> >
74 lex_iterator_type;
75typedef wave::context<
76 std::string::iterator, lex_iterator_type,
77 load_file_to_string_filtered>
78 context_type;
79typedef context_type::iterator_type pp_iterator_type;
80
81struct RezLexer::Priv
82{
83 std::string input;
84 context_type ctx;
85 pp_iterator_type iter;
86
87 Priv(std::string data, std::string name)
88 : input(data), ctx(input.begin(), input.end(), name.c_str())
89 {
90 }
91};
92
93static std::string readInitial(RezWorld& world, std::string filename)
94{
95 std::ifstream in(filename);
96 if(!in.is_open())
97 {
98 world.problem(Diagnostic(Diagnostic::error,
99 "could not open " + filename, yy::location()));
100 }
101 return readContents(std::move(in));
102}
103
104RezLexer::RezLexer(RezWorld& world, std::string filename)
105 : RezLexer(world, filename, readInitial(world,filename))
106{
107}
108
109
110
111RezLexer::RezLexer(RezWorld& world, std::string filename, const std::string &data)
112 : world(world), curFile(filename), lastLocation(&curFile)
113{
114 pImpl.reset(new Priv(preFilter(data), filename));
115
116 pImpl->ctx.add_macro_definition("DeRez=0");
117 pImpl->ctx.add_macro_definition("Rez=1");
118 pImpl->ctx.add_macro_definition("true=1");
119 pImpl->ctx.add_macro_definition("false=0");
120 pImpl->ctx.add_macro_definition("TRUE=1");
121 pImpl->ctx.add_macro_definition("FALSE=0");
122
123 pImpl->iter = pImpl->ctx.begin();
124}
125
126RezLexer::~RezLexer()
127{
128
129}
130
131
132
133void RezLexer::addDefine(std::string str)
134{
135 pImpl->ctx.add_macro_definition(str);
136}
137
138void RezLexer::addIncludePath(std::string path)
139{
140 std::size_t pos = path.find(':');
141 if(pos == std::string::npos)
142 {
143 pImpl->ctx.add_include_path(path.c_str());
144 }
145 else
146 {
147 addIncludePath(path.substr(0,pos));
148 addIncludePath(path.substr(pos + 1));
149 }
150}
151
152bool RezLexer::atEnd()
153{
154 return pImpl->iter == pImpl->ctx.end();
155}
156
157RezLexer::WaveToken RezLexer::nextWave()
158{
159 try
160 {
161 if(pImpl->iter == pImpl->ctx.end())
162 return WaveToken();
163 else
164 {
165 WaveToken tok = *pImpl->iter++;
166 return tok;
167 }
168 }
169 catch(const preprocess_exception& e)
170 {
171 curFile = e.file_name();
172 auto yypos = yy::position(&curFile, e.line_no(), e.column_no());
173 yy::location loc(yypos);
174 lastLocation = loc;
175
176 world.problem(Diagnostic(
177 e.severity_level(e.get_errorcode()) >= util::severity_error
178 ? Diagnostic::error
179 : Diagnostic::warning,
180 preprocess_exception::error_text(e.get_errorcode()), loc));
181 if(e.is_recoverable())
182 return nextWave();
183 else
184 return WaveToken();
185 }
186}
187
188RezLexer::WaveToken RezLexer::peekWave()
189{
190 return pImpl->iter == pImpl->ctx.end() ? WaveToken() : *pImpl->iter;
191}
192