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