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]
8 //#include "definitions.h"
14 #pragma implementation "lyxlex.h"
19 #include "filetools.h"
21 // $Id: lyxlex.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $
23 #if !defined(lint) && !defined(WITH_WARNINGS)
24 static char vcid[] = "$Id: lyxlex.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $";
28 LyXLex::LyXLex(keyword_item* tab, int num)
29 : table(tab), no_items(num)
38 void LyXLex::pushTable(keyword_item* tab, int num)
40 pushed_table *tmppu = new pushed_table;
42 tmppu->table_elem = table;
43 tmppu->table_siz = no_items;
50 void LyXLex::popTable()
53 lyxerr.print("LyXLex error: nothing to pop!");
57 table = tmp->table_elem;
58 no_items = tmp->table_siz;
59 tmp->table_elem = NULL;
65 void LyXLex::printTable()
67 lyxerr.print(LString("\nNumber of tags: ")+no_items);
68 for(int i=0; i<no_items; i++)
69 lyxerr.print(LString("table[")+i+
70 "]: tag: `"+table[i].tag+
71 "' code:"+(long)table[i].code);
72 lyxerr.print(LString());
76 void LyXLex::printError(LString const & message)
78 LString tmpmsg = message;
79 tmpmsg.subst("$$Token",GetString());
80 lyxerr.print("LyX: "+tmpmsg+" [around line "+lineno+" of file "
81 +MakeDisplayPath(name)+']');
85 bool LyXLex::setFile(LString const & filename)
88 lyxerr.print("Error in LyXLex::setFile: file already set.");
89 file = fopen(filename.c_str(), "r");
93 return (file ? true : false);
97 void LyXLex::setFile(FILE *f)
100 lyxerr.print("Error in LyXLex::setFile: file already set.");
103 lineno = 0; // this is bogus if the file already has been read from
109 //NOTE: possible bug.
110 if (next() && status==LEX_TOKEN)
111 return search_kw(buff);
117 int LyXLex::GetInteger()
122 printError("Bad integer `$$Token'");
128 float LyXLex::GetFloat()
131 return (float)strtod(buff, (char**)NULL);
133 printError("Bad float `$$Token'");
139 LString LyXLex::GetString() const
141 return LString(buff);
145 // I would prefer to give a tag number instead of an explicit token
146 // here, but it is not possible because Buffer::readLyXformat2 uses
147 // explicit tokens (JMarc)
148 LString LyXLex::getLongString(LString const &endtoken)
151 bool firstline = true;
155 // blank line in the file being read
158 LString const token = GetString().strip().frontStrip();
160 lyxerr.debug("LongString: `"+GetString()+'\'', Error::LEX_PARSER);
162 // We do a case independent comparison, like search_kw
164 if (strcasecmp(token.c_str(), endtoken.c_str()) != 0) {
165 LString tmpstr = GetString();
168 while(i < tmpstr.length()
169 && tmpstr[i] == ' ') {
174 lyxerr.debug("Prefix = `"+prefix+'\'',
179 && tmpstr.prefixIs(prefix.c_str())) {
180 tmpstr.substring(prefix.length(),
183 str += tmpstr + '\n';
185 else // token == endtoken
189 printError("Long string not ended by `" + endtoken + '\'');
195 bool LyXLex::GetBool()
197 if (strcmp(buff, "true") == 0)
199 else if (strcmp(buff, "false") != 0)
200 printError("Bad boolean `$$Token'. Use \"false\" or \"true\"");
205 bool LyXLex::EatLine()
208 int c = '\0'; // getc() returns an int
210 while (!feof(file) && c!='\n' && i!=(LEX_MAX_BUFF-1)) {
215 if (i==(LEX_MAX_BUFF-1) && c !='\n') {
216 printError("Line too long");
217 c = '\n'; // Pretend we had an end of line
218 lineno--; // but don't increase line counter (netto effect)
219 i++; // and preserve last character read.
223 buff[--i] = '\0'; // i can never be 0 here, so no danger
233 int LyXLex::search_kw(char const * const tag) const
235 int m, k=0 , l= 0, r=no_items;
240 if (lyxerr.debugging(Error::LEX_PARSER)) {
242 my_l+="LyXLex::search_kw: elem " ;
246 my_l+=" search tag ";
252 k = strcasecmp(table[m].tag, tag);
254 return table[m].code;
256 if (k<0) l = m+1; else r = m;
262 bool LyXLex::next(bool esc)
266 int c; // getc() returns an int
271 while (!feof(file) && !status) {
274 // Read rest of line (fast :-)
275 fgets(buff, sizeof(buff), file);
286 } while (c!='\"' && c!='\n' && !feof(file) &&
287 i!=(LEX_MAX_BUFF-2));
289 if (i==(LEX_MAX_BUFF-2)) {
290 printError("Line too long");
291 c = '\"'; // Pretend we got a "
296 printError("Missing quote");
307 continue; /* Skip ','s */
309 if (c > ' ' && !feof(file)) {
314 } while (c > ' ' && c != ',' && !feof(file) &&
315 (i != LEX_MAX_BUFF-1) );
316 if (i == LEX_MAX_BUFF-1) {
317 printError("Line too long");
323 if (c=='\r' && !feof(file)) {
324 // The Windows support has lead to the
325 // possibility of "\r\n" at the end of
326 // a line. This will stop LyX choking
327 // when it expected to find a '\n'
335 if (status) return true;
337 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
341 int c; // getc() returns an int
346 while (!feof(file) && !status) {
350 if (c==',') continue;
357 // escape the next char
362 } while (c > ' ' && c != ',' && !feof(file) &&
363 (i != LEX_MAX_BUFF-1) );
364 if (i == LEX_MAX_BUFF-1) {
365 printError("Line too long");
373 // Read rest of line (fast :-)
374 fgets(buff, sizeof(buff), file);
382 bool escaped = false;
386 if (c == '\r') continue;
388 // escape the next char
394 if (!escaped && c == '\"') break;
395 } while (c!='\n' && !feof(file) &&
396 i!=(LEX_MAX_BUFF-2));
398 if (i==(LEX_MAX_BUFF-2)) {
399 printError("Line too long");
400 c = '\"'; // Pretend we got a "
405 printError("Missing quote");
415 if (c > ' ' && !feof(file)) {
419 // escape the next char
425 } while (c > ' ' && c != ',' && !feof(file) &&
426 (i != LEX_MAX_BUFF-1) );
427 if (i == LEX_MAX_BUFF-1) {
428 printError("Line too long");
439 if (status) return true;
441 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
448 bool LyXLex::nextToken()
450 int c; // getc() returns an int
454 while (!feof(file) && !status) {
457 if (c >= ' ' && !feof(file)) {
459 if (c == '\\') { // first char == '\\'
463 } while (c > ' ' && c != '\\' && !feof(file) &&
464 i != (LEX_MAX_BUFF-1));
469 } while (c >= ' ' && c != '\\' && !feof(file)
470 && i != (LEX_MAX_BUFF-1));
473 if (i == (LEX_MAX_BUFF-1)) {
474 printError("Line too long");
477 if (c == '\\') ungetc(c,file); // put it back
486 if (status) return true;
488 status = (feof(file)) ? LEX_FEOF: LEX_UNDEF;
494 int LyXLex::FindToken(char const* string[])
499 if (strcmp(buff, "default")) {
500 for (i=0; string[i][0] && strcmp(string[i], buff); i++);
502 printError("Unknown argument `$$Token'");
507 printError("file ended while scanning string token");
512 int LyXLex::CheckToken(char const* string[], int print_error)
516 if (strcmp(buff, "default")) {
517 for (i=0; string[i][0] && strcmp(string[i], buff); i++);
520 printError("Unknown argument `$$Token'");