]> git.lyx.org Git - lyx.git/blob - src/lyxlex.C
the convert patch
[lyx.git] / src / lyxlex.C
1 /**
2  * \file lyxlex.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author John Levon
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "lyxlex.h"
17
18 #include "debug.h"
19 #include "lyxlex_pimpl.h"
20
21 #include "support/convert.h"
22 #include "support/lstrings.h"
23
24 using lyx::support::compare_ascii_no_case;
25 using lyx::support::isStrDbl;
26 using lyx::support::isStrInt;
27 using lyx::support::ltrim;
28 using lyx::support::prefixIs;
29 using lyx::support::subst;
30 using lyx::support::trim;
31
32 using std::endl;
33 using std::string;
34 using std::istream;
35 using std::ostream;
36
37
38 LyXLex::LyXLex(keyword_item * tab, int num)
39         : pimpl_(new Pimpl(tab, num))
40 {}
41
42
43 LyXLex::~LyXLex()
44 {
45         delete pimpl_;
46 }
47
48
49 bool LyXLex::isOK() const
50 {
51         return pimpl_->is.good();
52 }
53
54
55 void LyXLex::setLineNo(int l)
56 {
57         pimpl_->lineno = l;
58 }
59
60
61 int LyXLex::getLineNo() const
62 {
63         return pimpl_->lineno;
64 }
65
66
67 istream & LyXLex::getStream()
68 {
69         return pimpl_->is;
70 }
71
72
73 void LyXLex::pushTable(keyword_item * tab, int num)
74 {
75         pimpl_->pushTable(tab, num);
76 }
77
78
79 void LyXLex::popTable()
80 {
81         pimpl_->popTable();
82 }
83
84
85 void LyXLex::printTable(ostream & os)
86 {
87         pimpl_->printTable(os);
88 }
89
90
91 void LyXLex::printError(string const & message) const
92 {
93         pimpl_->printError(message);
94 }
95
96
97 bool LyXLex::setFile(string const & filename)
98 {
99         return pimpl_->setFile(filename);
100 }
101
102
103 void LyXLex::setStream(istream & i)
104 {
105         pimpl_->setStream(i);
106 }
107
108
109 void LyXLex::setCommentChar(char c)
110 {
111         pimpl_->setCommentChar(c);
112 }
113
114 int LyXLex::lex()
115 {
116         return pimpl_->lex();
117 }
118
119
120 int LyXLex::getInteger() const
121 {
122         if (isStrInt(pimpl_->getString()))
123                 return convert<int>(pimpl_->getString());
124         pimpl_->printError("Bad integer `$$Token'");
125         return -1;
126 }
127
128
129 double LyXLex::getFloat() const
130 {
131         // replace comma with dot in case the file was written with
132         // the wrong locale (should be rare, but is easy enough to
133         // avoid).
134         string const str = subst(pimpl_->getString(), ",", ".");
135         if (isStrDbl(str))
136                 return convert<double>(str);
137         pimpl_->printError("Bad float `$$Token'");
138         return -1;
139 }
140
141
142 string const LyXLex::getString() const
143 {
144         return pimpl_->getString();
145 }
146
147
148 // I would prefer to give a tag number instead of an explicit token
149 // here, but it is not possible because Buffer::readDocument uses
150 // explicit tokens (JMarc)
151 string const LyXLex::getLongString(string const & endtoken)
152 {
153         string str, prefix;
154         bool firstline = true;
155
156         while (isOK()) {
157                 if (!eatLine())
158                         // blank line in the file being read
159                         continue;
160
161                 string const token = trim(getString(), " \t");
162
163                 lyxerr[Debug::PARSER] << "LongString: `"
164                                       << getString() << '\'' << endl;
165
166                 // We do a case independent comparison, like search_kw does.
167                 if (compare_ascii_no_case(token, endtoken) == 0)
168                         break;
169
170                 string tmpstr = getString();
171                 if (firstline) {
172                         string::size_type i(tmpstr.find_first_not_of(' '));
173                         if (i != string::npos)
174                                 prefix = tmpstr.substr(0, i);
175                         firstline = false;
176                         lyxerr[Debug::PARSER]
177                                 << "Prefix = `" << prefix << "\'" << endl;
178                 }
179
180                 // further lines in long strings may have the same
181                 // whitespace prefix as the first line. Remove it.
182                 if (prefix.length() && prefixIs(tmpstr, prefix)) {
183                         tmpstr.erase(0, prefix.length() - 1);
184                 }
185
186                 str += ltrim(tmpstr, "\t") + '\n';
187         }
188
189         if (!isOK()) {
190                 printError("Long string not ended by `" + endtoken + '\'');
191         }
192
193         return str;
194 }
195
196
197 bool LyXLex::getBool() const
198 {
199         if (pimpl_->getString() == "true") {
200                 return true;
201         } else if (pimpl_->getString() != "false") {
202                 pimpl_->printError("Bad boolean `$$Token'. "
203                                    "Use \"false\" or \"true\"");
204         }
205         return false;
206 }
207
208
209 bool LyXLex::eatLine()
210 {
211         return pimpl_->eatLine();
212 }
213
214
215 bool LyXLex::next(bool esc)
216 {
217         return pimpl_->next(esc);
218 }
219
220
221 bool LyXLex::nextToken()
222 {
223         return pimpl_->nextToken();
224 }
225
226
227 void LyXLex::pushToken(string const & pt)
228 {
229         pimpl_->pushToken(pt);
230 }
231
232 LyXLex::operator void const *() const
233 {
234         // This behaviour is NOT the same as the std::streams which would
235         // use fail() here. However, our implementation of getString() et al.
236         // can cause the eof() and fail() bits to be set, even though we
237         // haven't tried to read 'em.
238         return pimpl_->is.bad() ? 0 : this;
239 }
240
241
242 bool LyXLex::operator!() const
243 {
244         return pimpl_->is.bad();
245 }
246
247
248 LyXLex & LyXLex::operator>>(std::string & s)
249 {
250         if (isOK()) {
251                 next();
252                 s = getString();
253         }
254         return *this;
255 }
256
257
258 LyXLex & LyXLex::operator>>(double & s)
259 {
260         if (isOK()) {
261                 next();
262                 s = getFloat();
263         }
264         return *this;
265 }
266
267
268 LyXLex & LyXLex::operator>>(int & s)
269 {
270         if (isOK()) {
271                 next();
272                 s = getInteger();
273         }
274         return *this;
275 }
276
277
278 LyXLex & LyXLex::operator>>(unsigned int & s)
279 {
280         if (isOK()) {
281                 next();
282                 s = getInteger();
283         }
284         return *this;
285 }
286
287
288 LyXLex & LyXLex::operator>>(bool & s)
289 {
290         if (isOK()) {
291                 next();
292                 s = getBool();
293         }
294         return *this;
295 }