3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "texparser.h"
22 using std::istringstream;
29 CatCode theCatcode[256];
31 void skipSpaceTokens(istream & is, char c)
33 // skip trailing spaces
34 while (catcode(c) == catSpace || catcode(c) == catNewline)
37 //cerr << "putting back: " << c << "\n";
44 fill(theCatcode, theCatcode + 256, catOther);
45 fill(theCatcode + 'a', theCatcode + 'z' + 1, catLetter);
46 fill(theCatcode + 'A', theCatcode + 'Z' + 1, catLetter);
48 theCatcode[int('\\')] = catEscape;
49 theCatcode[int('{')] = catBegin;
50 theCatcode[int('}')] = catEnd;
51 theCatcode[int('$')] = catMath;
52 theCatcode[int('&')] = catAlign;
53 theCatcode[10] = catNewline;
54 theCatcode[int('#')] = catParameter;
55 theCatcode[int('^')] = catSuper;
56 theCatcode[int('_')] = catSub;
57 theCatcode[0x7f] = catIgnore;
58 theCatcode[int(' ')] = catSpace;
59 theCatcode[int('\t')] = catSpace;
60 theCatcode[13] = catIgnore;
61 theCatcode[int('~')] = catActive;
62 theCatcode[int('%')] = catComment;
65 theCatcode[int('@')] = catLetter;
75 mode_type asMode(mode_type oldmode, string const & str)
77 if (str == "mathmode")
79 if (str == "textmode" || str == "forcetext")
85 CatCode catcode(unsigned char c)
96 ostream & operator<<(ostream & os, Token const & t)
99 os << '\\' << t.cs() << ' ';
100 else if (t.cat() == catLetter)
102 else if (t.cat() == catNewline)
103 os << "[\\n," << t.cat() << "]\n";
105 os << '[' << t.character() << ',' << t.cat() << ']';
110 string Token::asString() const
112 return cs_.size() ? cs_ : string(1, char_);
116 string Token::asInput() const
118 return char_ ? string(1, char_) : '\\' + cs_ + ' ';
127 Parser::Parser(istream & is)
128 : lineno_(0), pos_(0)
134 Parser::Parser(string const & s)
135 : lineno_(0), pos_(0)
142 void Parser::push_back(Token const & t)
144 tokens_.push_back(t);
148 void Parser::pop_back()
154 Token const & Parser::prev_token() const
156 static const Token dummy;
157 return pos_ > 0 ? tokens_[pos_ - 1] : dummy;
161 Token const & Parser::next_token() const
163 static const Token dummy;
164 return good() ? tokens_[pos_] : dummy;
168 Token const & Parser::get_token()
170 static const Token dummy;
171 //cerr << "looking at token " << tokens_[pos_] << " pos: " << pos_ << '\n';
172 return good() ? tokens_[pos_++] : dummy;
176 void Parser::skip_spaces()
179 if (next_token().cat() == catSpace || next_token().cat() == catNewline)
181 else if (next_token().cat() == catComment)
182 while (next_token().cat() != catNewline)
190 void Parser::putback()
196 bool Parser::good() const
198 return pos_ < tokens_.size();
202 char Parser::getChar()
205 error("The input stream is not well...");
206 return tokens_[pos_++].character();
210 string Parser::getArg(char left, char right)
220 while ((c = getChar()) != right && good())
227 string Parser::getOpt()
229 string const res = getArg('[', ']');
230 return res.size() ? '[' + res + ']' : string();
234 void Parser::tokenize(istream & is)
236 static bool init_done = false;
245 //cerr << "reading c: " << c << "\n";
247 switch (catcode(c)) {
251 if (catcode(c) == catNewline) {
254 //} while (catcode(c) == catNewline);
255 push_back(Token("par"));
257 push_back(Token('\n', catNewline));
264 push_back(Token(c, catComment));
265 while (is.get(c) && catcode(c) != catNewline)
266 push_back(Token(c, catLetter));
267 push_back(Token(c, catNewline));
270 if (catcode(c) == catNewline) {
271 push_back(Token("par"));
282 error("unexpected end of input");
285 if (catcode(c) == catLetter) {
287 while (is.get(c) && catcode(c) == catLetter)
289 skipSpaceTokens(is, c);
298 push_back(Token(c, catcode(c)));
300 skipSpaceTokens(is, c);
306 cerr << "ignoring a char: " << int(c) << "\n";
311 push_back(Token(c, catcode(c)));
317 void Parser::dump() const
319 cerr << "\nTokens: ";
320 for (unsigned i = 0; i < tokens_.size(); ++i) {
325 cerr << " pos: " << pos_ << "\n";
329 void Parser::error(string const & msg)
331 cerr << "Line ~" << lineno_ << ": parse error: " << msg << endl;
337 string Parser::verbatimOption()
340 if (next_token().character() == '[') {
341 Token t = get_token();
342 for (Token t = get_token(); t.character() != ']' && good(); t = get_token()) {
343 if (t.cat() == catBegin) {
345 res += '{' + verbatim_item() + '}';
354 string Parser::verbatim_item()
359 if (next_token().cat() == catBegin) {
360 Token t = get_token(); // skip brace
362 for (Token t = get_token(); t.cat() != catEnd && good(); t = get_token()) {
363 if (t.cat() == catBegin) {
365 res += '{' + verbatim_item() + '}';
372 return get_token().asInput();
376 void Parser::setCatCode(char c, CatCode cat)
378 theCatcode[(unsigned char)c] = cat;
382 CatCode Parser::getCatCode(char c) const
384 return theCatcode[(unsigned char)c];