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)
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." << endl;
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::PARSER] << "LongString: `"
151 << GetString() << '\'' << endl;
153 // We do a case independent comparison, like search_kw
155 if (compare_no_case(token, endtoken) != 0) {
156 string tmpstr = GetString();
159 while(i < tmpstr.length()
160 && tmpstr[i] == ' ') {
165 lyxerr[Debug::PARSER] << "Prefix = `" << prefix
170 && prefixIs(tmpstr, prefix.c_str())) {
171 tmpstr.erase(0, prefix.length() - 1);
173 str += tmpstr + '\n';
175 else // token == endtoken
179 printError("Long string not ended by `" + endtoken + '\'');
185 bool LyXLex::GetBool()
187 if (compare(buff, "true") == 0)
189 else if (compare(buff, "false") != 0)
190 printError("Bad boolean `$$Token'. Use \"false\" or \"true\"");
195 bool LyXLex::EatLine()
198 int c = '\0'; // getc() returns an int
200 while (!feof(file) && c!='\n' && i!=(LEX_MAX_BUFF-1)) {
205 if (i==(LEX_MAX_BUFF-1) && c !='\n') {
206 printError("Line too long");
207 c = '\n'; // Pretend we had an end of line
208 --lineno; // but don't increase line counter (netto effect)
209 ++i; // and preserve last character read.
213 buff[--i] = '\0'; // i can never be 0 here, so no danger
223 int LyXLex::search_kw(char const * const tag) const
225 int m, k=0 , l= 0, r=no_items;
230 if (lyxerr.debugging(Debug::PARSER)) {
231 lyxerr << "LyXLex::search_kw: elem " << m
232 << " tag " << table[m].tag
233 << " search tag " << tag
238 k = compare_no_case(table[m].tag, tag);
240 return table[m].code;
242 if (k<0) l = m+1; else r = m;
248 bool LyXLex::next(bool esc)
252 int c; // getc() returns an int
257 while (!feof(file) && !status) {
260 // Read rest of line (fast :-)
261 fgets(buff, sizeof(buff), file);
272 } while (c!='\"' && c!='\n' && !feof(file) &&
273 i!=(LEX_MAX_BUFF-2));
275 if (i==(LEX_MAX_BUFF-2)) {
276 printError("Line too long");
277 c = '\"'; // Pretend we got a "
282 printError("Missing quote");
293 continue; /* Skip ','s */
295 if (c > ' ' && !feof(file)) {
300 } while (c > ' ' && c != ',' && !feof(file) &&
301 (i != LEX_MAX_BUFF-1) );
302 if (i == LEX_MAX_BUFF-1) {
303 printError("Line too long");
309 if (c== '\r' && !feof(file)) {
310 // The Windows support has lead to the
311 // possibility of "\r\n" at the end of
312 // a line. This will stop LyX choking
313 // when it expected to find a '\n'
321 if (status) return true;
323 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
327 int c; // getc() returns an int
332 while (!feof(file) && !status) {
336 if (c==',') continue;
343 // escape the next char
348 } while (c > ' ' && c != ',' && !feof(file) &&
349 (i != LEX_MAX_BUFF-1) );
350 if (i == LEX_MAX_BUFF-1) {
351 printError("Line too long");
359 // Read rest of line (fast :-)
360 fgets(buff, sizeof(buff), file);
368 bool escaped = false;
372 if (c == '\r') continue;
374 // escape the next char
380 if (!escaped && c == '\"') break;
381 } while (c!='\n' && !feof(file) &&
382 i!=(LEX_MAX_BUFF-2));
384 if (i==(LEX_MAX_BUFF-2)) {
385 printError("Line too long");
386 c = '\"'; // Pretend we got a "
391 printError("Missing quote");
401 if (c > ' ' && !feof(file)) {
405 // escape the next char
411 } while (c > ' ' && c != ',' && !feof(file) &&
412 (i != LEX_MAX_BUFF-1) );
413 if (i == LEX_MAX_BUFF-1) {
414 printError("Line too long");
425 if (status) return true;
427 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
434 bool LyXLex::nextToken()
436 int c; // getc() returns an int
440 while (!feof(file) && !status) {
443 if (c >= ' ' && !feof(file)) {
445 if (c == '\\') { // first char == '\\'
449 } while (c > ' ' && c != '\\' && !feof(file) &&
450 i != (LEX_MAX_BUFF-1));
455 } while (c >= ' ' && c != '\\' && !feof(file)
456 && i != (LEX_MAX_BUFF-1));
459 if (i == (LEX_MAX_BUFF-1)) {
460 printError("Line too long");
463 if (c == '\\') ungetc(c,file); // put it back
472 if (status) return true;
474 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
480 int LyXLex::FindToken(char const * str[])
485 if (compare(buff, "default")) {
486 for (i = 0; str[i][0] && compare(str[i], buff); ++i);
488 printError("Unknown argument `$$Token'");
493 printError("file ended while scanning string token");
498 int LyXLex::CheckToken(char const * str[], int print_error)
502 if (compare(buff, "default")) {
503 for (i = 0; str[i][0] && compare(str[i], buff); i++);
506 printError("Unknown argument `$$Token'");