1 // Generalized simple lexical analizer.
2 // It can be used for simple syntax parsers, like lyxrc,
3 // texclass and others to come. [asierra30/03/96]
12 #pragma implementation "lyxlex.h"
17 #include "support/filetools.h"
19 LyXLex::LyXLex(keyword_item * tab, int num)
20 : table(tab), no_items(num)
29 void LyXLex::pushTable(keyword_item * tab, int num)
31 pushed_table * tmppu = new pushed_table;
33 tmppu->table_elem = table;
34 tmppu->table_siz = no_items;
41 void LyXLex::popTable()
44 lyxerr << "LyXLex error: nothing to pop!" << endl;
48 table = tmp->table_elem;
49 no_items = tmp->table_siz;
56 void LyXLex::printTable()
58 lyxerr << "\nNumber of tags: " << no_items << endl;
59 for(int i= 0; i < no_items; ++i)
60 lyxerr << "table[" << i
61 << "]: tag: `" << table[i].tag
62 << "' code:" << table[i].code << endl;
67 void LyXLex::printError(string const & message) const
69 string tmpmsg = subst(message, "$$Token", GetString());
70 lyxerr << "LyX: " << tmpmsg << " [around line " << lineno
71 << " of file " << MakeDisplayPath(name) << ']' << endl;
75 bool LyXLex::setFile(string const & filename)
78 lyxerr << "Error in LyXLex::setFile: file already set." <<endl;
79 file = fopen(filename.c_str(), "r");
83 return (file ? true : false);
87 void LyXLex::setFile(FILE * f)
90 lyxerr << "Error in LyXLex::setFile: file already set."
94 lineno = 0; // this is bogus if the file already has been read from
100 //NOTE: possible bug.
101 if (next() && status == LEX_TOKEN)
102 return search_kw(buff);
108 int LyXLex::GetInteger() const
113 printError("Bad integer `$$Token'");
119 float LyXLex::GetFloat() const
124 printError("Bad float `$$Token'");
130 string LyXLex::GetString() const
136 // I would prefer to give a tag number instead of an explicit token
137 // here, but it is not possible because Buffer::readLyXformat2 uses
138 // explicit tokens (JMarc)
139 string LyXLex::getLongString(string const & endtoken)
142 bool firstline = true;
146 // blank line in the file being read
149 string const token = frontStrip(strip(GetString()), " \t");
151 lyxerr[Debug::PARSER] << "LongString: `"
152 << GetString() << '\'' << endl;
154 // We do a case independent comparison, like search_kw
156 if (compare_no_case(token, endtoken) != 0) {
157 string tmpstr = GetString();
160 while(i < tmpstr.length()
161 && tmpstr[i] == ' ') {
166 lyxerr[Debug::PARSER] << "Prefix = `" << prefix
171 && prefixIs(tmpstr, prefix.c_str())) {
172 tmpstr.erase(0, prefix.length() - 1);
174 str += tmpstr + '\n';
176 else // token == endtoken
180 printError("Long string not ended by `" + endtoken + '\'');
186 bool LyXLex::GetBool() const
188 if (compare(buff, "true") == 0)
190 else if (compare(buff, "false") != 0)
191 printError("Bad boolean `$$Token'. Use \"false\" or \"true\"");
196 bool LyXLex::EatLine()
199 int c = '\0'; // getc() returns an int
201 while (!feof(file) && c!= '\n' && i!= (LEX_MAX_BUFF-1)) {
206 if (i == (LEX_MAX_BUFF-1) && c != '\n') {
207 printError("Line too long");
208 c = '\n'; // Pretend we had an end of line
209 --lineno; // but don't increase line counter (netto effect)
210 ++i; // and preserve last character read.
214 buff[--i] = '\0'; // i can never be 0 here, so no danger
224 int LyXLex::search_kw(char const * const tag) const
226 int m, k = 0 , l = 0, r = no_items;
231 if (lyxerr.debugging(Debug::PARSER)) {
232 lyxerr << "LyXLex::search_kw: elem " << m
233 << " tag " << table[m].tag
234 << " search tag " << tag
239 k = compare_no_case(table[m].tag, tag);
241 return table[m].code;
243 if (k < 0) l = m + 1; else r = m;
249 bool LyXLex::next(bool esc)
252 int c; // getc() returns an int
255 while (!feof(file) && !status) {
258 // Read rest of line (fast :-)
259 fgets(buff, sizeof(buff), file);
270 } while (c!= '\"' && c!= '\n' && !feof(file) &&
271 i!= (LEX_MAX_BUFF-2));
273 if (i == (LEX_MAX_BUFF-2)) {
274 printError("Line too long");
275 c = '\"'; // Pretend we got a "
280 printError("Missing quote");
291 continue; /* Skip ','s */
293 if (c > ' ' && !feof(file)) {
298 } while (c > ' ' && c != ',' && !feof(file) &&
299 (i != LEX_MAX_BUFF-1) );
300 if (i == LEX_MAX_BUFF-1) {
301 printError("Line too long");
307 if (c == '\r' && !feof(file)) {
308 // The Windows support has lead to the
309 // possibility of "\r\n" at the end of
310 // a line. This will stop LyX choking
311 // when it expected to find a '\n'
319 if (status) return true;
321 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
325 int c; // getc() returns an int
328 while (!feof(file) && !status) {
332 if (c == ',') continue;
339 // escape the next char
344 } while (c > ' ' && c != ',' && !feof(file) &&
345 (i != LEX_MAX_BUFF-1) );
346 if (i == LEX_MAX_BUFF-1) {
347 printError("Line too long");
355 // Read rest of line (fast :-)
356 fgets(buff, sizeof(buff), file);
364 bool escaped = false;
368 if (c == '\r') continue;
370 // escape the next char
376 if (!escaped && c == '\"') break;
377 } while (c!= '\n' && !feof(file) &&
378 i!= (LEX_MAX_BUFF-2));
380 if (i == (LEX_MAX_BUFF-2)) {
381 printError("Line too long");
382 c = '\"'; // Pretend we got a "
387 printError("Missing quote");
397 if (c > ' ' && !feof(file)) {
401 // escape the next char
407 } while (c > ' ' && c != ',' && !feof(file) &&
408 (i != LEX_MAX_BUFF-1) );
409 if (i == LEX_MAX_BUFF-1) {
410 printError("Line too long");
421 if (status) return true;
423 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
430 bool LyXLex::nextToken()
433 while (!feof(file) && !status) {
434 int c = getc(file); // getc() returns an int
436 if (c >= ' ' && !feof(file)) {
438 if (c == '\\') { // first char == '\\'
442 } while (c > ' ' && c != '\\' && !feof(file) &&
443 i != (LEX_MAX_BUFF-1));
448 } while (c >= ' ' && c != '\\' && !feof(file)
449 && i != (LEX_MAX_BUFF-1));
452 if (i == (LEX_MAX_BUFF-1)) {
453 printError("Line too long");
456 if (c == '\\') ungetc(c, file); // put it back
465 if (status) return true;
467 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
473 int LyXLex::FindToken(char const * str[])
478 if (compare(buff, "default")) {
479 for (i = 0; str[i][0] && compare(str[i], buff); ++i);
481 printError("Unknown argument `$$Token'");
486 printError("file ended while scanning string token");
491 int LyXLex::CheckToken(char const * str[], int print_error)
495 if (compare(buff, "default")) {
496 for (i = 0; str[i][0] && compare(str[i], buff); ++i);
499 printError("Unknown argument `$$Token'");