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.print("LyXLex error: nothing to pop!");
48 table = tmp->table_elem;
49 no_items = tmp->table_siz;
56 void LyXLex::printTable()
58 lyxerr.print(string("\nNumber of tags: ") + tostr(no_items));
59 for(int i=0; i<no_items; i++)
60 lyxerr.print(string("table[")+ tostr(i) +
61 "]: tag: `" + table[i].tag +
62 "' code:" + tostr(table[i].code));
63 lyxerr.print(string());
67 void LyXLex::printError(string const & message)
69 string tmpmsg = subst(message, "$$Token", GetString());
70 lyxerr.print("LyX: " + tmpmsg + " [around line " + tostr(lineno) + " of file "
71 + MakeDisplayPath(name) + ']');
75 bool LyXLex::setFile(string const & filename)
78 lyxerr.print("Error in LyXLex::setFile: file already set.");
79 file = fopen(filename.c_str(), "r");
83 return (file ? true : false);
87 void LyXLex::setFile(FILE * f)
90 lyxerr.print("Error in LyXLex::setFile: file already set.");
93 lineno = 0; // this is bogus if the file already has been read from
100 if (next() && status==LEX_TOKEN)
101 return search_kw(buff);
107 int LyXLex::GetInteger()
112 printError("Bad integer `$$Token'");
118 float LyXLex::GetFloat()
121 return (float)strtod(buff, (char**)0);
123 printError("Bad float `$$Token'");
129 string LyXLex::GetString() const
135 // I would prefer to give a tag number instead of an explicit token
136 // here, but it is not possible because Buffer::readLyXformat2 uses
137 // explicit tokens (JMarc)
138 string LyXLex::getLongString(string const & endtoken)
141 bool firstline = true;
145 // blank line in the file being read
148 string const token = frontStrip(strip(GetString()), " \t");
150 lyxerr.debug("LongString: `"+GetString()+'\'', Error::LEX_PARSER);
152 // We do a case independent comparison, like search_kw
154 if (compare_no_case(token, endtoken) != 0) {
155 string tmpstr = GetString();
158 while(i < tmpstr.length()
159 && tmpstr[i] == ' ') {
164 lyxerr.debug("Prefix = `"+prefix+'\'',
169 && prefixIs(tmpstr, prefix.c_str())) {
170 tmpstr.erase(0, prefix.length() - 1);
172 str += tmpstr + '\n';
174 else // token == endtoken
178 printError("Long string not ended by `" + endtoken + '\'');
184 bool LyXLex::GetBool()
186 if (compare(buff, "true") == 0)
188 else if (compare(buff, "false") != 0)
189 printError("Bad boolean `$$Token'. Use \"false\" or \"true\"");
194 bool LyXLex::EatLine()
197 int c = '\0'; // getc() returns an int
199 while (!feof(file) && c!='\n' && i!=(LEX_MAX_BUFF-1)) {
204 if (i==(LEX_MAX_BUFF-1) && c !='\n') {
205 printError("Line too long");
206 c = '\n'; // Pretend we had an end of line
207 --lineno; // but don't increase line counter (netto effect)
208 ++i; // and preserve last character read.
212 buff[--i] = '\0'; // i can never be 0 here, so no danger
222 int LyXLex::search_kw(char const * const tag) const
224 int m, k=0 , l= 0, r=no_items;
229 if (lyxerr.debugging(Error::LEX_PARSER)) {
231 my_l+="LyXLex::search_kw: elem " ;
235 my_l+=" search tag ";
241 k = compare_no_case(table[m].tag, tag);
243 return table[m].code;
245 if (k<0) l = m+1; else r = m;
251 bool LyXLex::next(bool esc)
255 int c; // getc() returns an int
260 while (!feof(file) && !status) {
263 // Read rest of line (fast :-)
264 fgets(buff, sizeof(buff), file);
275 } while (c!='\"' && c!='\n' && !feof(file) &&
276 i!=(LEX_MAX_BUFF-2));
278 if (i==(LEX_MAX_BUFF-2)) {
279 printError("Line too long");
280 c = '\"'; // Pretend we got a "
285 printError("Missing quote");
296 continue; /* Skip ','s */
298 if (c > ' ' && !feof(file)) {
303 } while (c > ' ' && c != ',' && !feof(file) &&
304 (i != LEX_MAX_BUFF-1) );
305 if (i == LEX_MAX_BUFF-1) {
306 printError("Line too long");
312 if (c== '\r' && !feof(file)) {
313 // The Windows support has lead to the
314 // possibility of "\r\n" at the end of
315 // a line. This will stop LyX choking
316 // when it expected to find a '\n'
324 if (status) return true;
326 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
330 int c; // getc() returns an int
335 while (!feof(file) && !status) {
339 if (c==',') continue;
346 // escape the next char
351 } while (c > ' ' && c != ',' && !feof(file) &&
352 (i != LEX_MAX_BUFF-1) );
353 if (i == LEX_MAX_BUFF-1) {
354 printError("Line too long");
362 // Read rest of line (fast :-)
363 fgets(buff, sizeof(buff), file);
371 bool escaped = false;
375 if (c == '\r') continue;
377 // escape the next char
383 if (!escaped && c == '\"') break;
384 } while (c!='\n' && !feof(file) &&
385 i!=(LEX_MAX_BUFF-2));
387 if (i==(LEX_MAX_BUFF-2)) {
388 printError("Line too long");
389 c = '\"'; // Pretend we got a "
394 printError("Missing quote");
404 if (c > ' ' && !feof(file)) {
408 // escape the next char
414 } while (c > ' ' && c != ',' && !feof(file) &&
415 (i != LEX_MAX_BUFF-1) );
416 if (i == LEX_MAX_BUFF-1) {
417 printError("Line too long");
428 if (status) return true;
430 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
437 bool LyXLex::nextToken()
439 int c; // getc() returns an int
443 while (!feof(file) && !status) {
446 if (c >= ' ' && !feof(file)) {
448 if (c == '\\') { // first char == '\\'
452 } while (c > ' ' && c != '\\' && !feof(file) &&
453 i != (LEX_MAX_BUFF-1));
458 } while (c >= ' ' && c != '\\' && !feof(file)
459 && i != (LEX_MAX_BUFF-1));
462 if (i == (LEX_MAX_BUFF-1)) {
463 printError("Line too long");
466 if (c == '\\') ungetc(c,file); // put it back
475 if (status) return true;
477 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
483 int LyXLex::FindToken(char const * str[])
488 if (compare(buff, "default")) {
489 for (i = 0; str[i][0] && compare(str[i], buff); ++i);
491 printError("Unknown argument `$$Token'");
496 printError("file ended while scanning string token");
501 int LyXLex::CheckToken(char const * str[], int print_error)
505 if (compare(buff, "default")) {
506 for (i = 0; str[i][0] && compare(str[i], buff); i++);
509 printError("Unknown argument `$$Token'");