X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxlex.C;h=958c7a14e680b33cbbc6b05140ae4026a77c1e63;hb=32ef0d04c48a1751abbb5e3b17d1bec25f22c255;hp=213abecfbfb038cce4b6eb97363f3e545f1a68ff;hpb=27de1486ca34aaad446adb798d71a77d6f6304da;p=lyx.git diff --git a/src/lyxlex.C b/src/lyxlex.C index 213abecfbf..958c7a14e6 100644 --- a/src/lyxlex.C +++ b/src/lyxlex.C @@ -1,523 +1,264 @@ -// Generalized simple lexical analizer. -// It can be used for simple syntax parsers, like lyxrc, -// texclass and others to come. [asierra30/03/96] -// -// (C) 1996 Lyx Team. +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1996-2001 The LyX Team. + * + * Generalized simple lexical analizer. + * It can be used for simple syntax parsers, like lyxrc, + * texclass and others to come. [asierra30/03/96] + * + * ====================================================== */ #include -//#include "definitions.h" - -#include -#include #ifdef __GNUG__ #pragma implementation "lyxlex.h" #endif #include "lyxlex.h" -#include "error.h" -#include "filetools.h" +#include "lyxlex_pimpl.h" +#include "debug.h" +#include "support/filetools.h" +#include "support/lstrings.h" + +using std::ostream; +using std::istream; +using std::endl; + + +LyXLex::LyXLex(keyword_item * tab, int num) + : pimpl_(new Pimpl(tab, num)) +{} + + +LyXLex::~LyXLex() +{ + delete pimpl_; +} + + +bool LyXLex::isOK() const +{ + return pimpl_->is.good(); +} -// $Id: lyxlex.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $ -#if !defined(lint) && !defined(WITH_WARNINGS) -static char vcid[] = "$Id: lyxlex.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $"; -#endif /* lint */ +void LyXLex::setLineNo(int l) +{ + pimpl_->lineno = l; +} + + +int LyXLex::getLineNo() const +{ + return pimpl_->lineno; +} -LyXLex::LyXLex(keyword_item* tab, int num) - : table(tab), no_items(num) +string const LyXLex::text() const { - file = NULL; - owns_file = false; - status = 0; - pushed = NULL; + return &pimpl_->buff[0]; } -void LyXLex::pushTable(keyword_item* tab, int num) +std::istream & LyXLex::getStream() { - pushed_table *tmppu = new pushed_table; - tmppu->next = pushed; - tmppu->table_elem = table; - tmppu->table_siz = no_items; - pushed = tmppu; - table = tab; - no_items = num; + return pimpl_->is; +} + + +void LyXLex::pushTable(keyword_item * tab, int num) +{ + pimpl_->pushTable(tab, num); } void LyXLex::popTable() { - if (pushed == NULL) - lyxerr.print("LyXLex error: nothing to pop!"); - - pushed_table *tmp; - tmp = pushed; - table = tmp->table_elem; - no_items = tmp->table_siz; - tmp->table_elem = NULL; - pushed = tmp->next; - delete tmp; + pimpl_->popTable(); } -void LyXLex::printTable() +void LyXLex::printTable(ostream & os) { - lyxerr.print(LString("\nNumber of tags: ")+no_items); - for(int i=0; iprintTable(os); } -void LyXLex::printError(LString const & message) +void LyXLex::printError(string const & message) const { - LString tmpmsg = message; - tmpmsg.subst("$$Token",GetString()); - lyxerr.print("LyX: "+tmpmsg+" [around line "+lineno+" of file " - +MakeDisplayPath(name)+']'); + pimpl_->printError(message); } -bool LyXLex::setFile(LString const & filename) +bool LyXLex::setFile(string const & filename) { - if (file) - lyxerr.print("Error in LyXLex::setFile: file already set."); - file = fopen(filename.c_str(), "r"); - name = filename; - owns_file = true; - lineno = 0; - return (file ? true : false); + return pimpl_->setFile(filename); } -void LyXLex::setFile(FILE *f) +void LyXLex::setStream(istream & i) { - if (file) - lyxerr.print("Error in LyXLex::setFile: file already set."); - file = f; - owns_file = false; - lineno = 0; // this is bogus if the file already has been read from + pimpl_->setStream(i); } +void LyXLex::setCommentChar(char c) +{ + pimpl_->setCommentChar(c); +} + int LyXLex::lex() { - //NOTE: possible bug. - if (next() && status==LEX_TOKEN) - return search_kw(buff); - else - return status; + return pimpl_->lex(); } -int LyXLex::GetInteger() +int LyXLex::getInteger() const { - if (buff[0]>' ') - return atoi(buff); - else { - printError("Bad integer `$$Token'"); - return -1; - } + if (isStrInt(pimpl_->getString())) + return strToInt(pimpl_->getString()); + else { + pimpl_->printError("Bad integer `$$Token'"); + return -1; + } } -float LyXLex::GetFloat() +float LyXLex::getFloat() const { - if (buff[0]>' ') - return (float)strtod(buff, (char**)NULL); - else { - printError("Bad float `$$Token'"); - return -1; - } + // replace comma with dot in case the file was written with + // the wrong locale (should be rare, but is easy enough to + // avoid). + string str = subst(pimpl_->getString(), ",", "."); + if (isStrDbl(str)) + return strToDbl(str); + else { + pimpl_->printError("Bad float `$$Token'"); + return -1; + } } -LString LyXLex::GetString() const +string const LyXLex::getString() const { - return LString(buff); + return pimpl_->getString(); } // I would prefer to give a tag number instead of an explicit token // here, but it is not possible because Buffer::readLyXformat2 uses // explicit tokens (JMarc) -LString LyXLex::getLongString(LString const &endtoken) +string const LyXLex::getLongString(string const & endtoken) { - LString str, prefix; + string str, prefix; bool firstline = true; - while (IsOK()) { - if (!EatLine()) + while (isOK()) { + if (!eatLine()) // blank line in the file being read continue; - LString const token = GetString().strip().frontStrip(); + string const token = frontStrip(strip(getString()), " \t"); - lyxerr.debug("LongString: `"+GetString()+'\'', Error::LEX_PARSER); + lyxerr[Debug::PARSER] << "LongString: `" + << getString() << '\'' << endl; // We do a case independent comparison, like search_kw // does. - if (strcasecmp(token.c_str(), endtoken.c_str()) != 0) { - LString tmpstr = GetString(); + if (compare_no_case(token, endtoken) != 0) { + string tmpstr = getString(); if (firstline) { - int i = 0; + unsigned int i = 0; while(i < tmpstr.length() && tmpstr[i] == ' ') { - i++; + ++i; prefix += ' '; } firstline = false; - lyxerr.debug("Prefix = `"+prefix+'\'', - Error::LEX_PARSER); + lyxerr[Debug::PARSER] << "Prefix = `" << prefix + << '\'' << endl; } if (!prefix.empty() - && tmpstr.prefixIs(prefix.c_str())) { - tmpstr.substring(prefix.length(), - tmpstr.length()-1); + && prefixIs(tmpstr, prefix)) { + tmpstr.erase(0, prefix.length() - 1); } - str += tmpstr + '\n'; + str += frontStrip(tmpstr, "\t") + '\n'; } else // token == endtoken break; } - if (!IsOK()) + if (!isOK()) printError("Long string not ended by `" + endtoken + '\''); return str; } -bool LyXLex::GetBool() -{ - if (strcmp(buff, "true") == 0) - return true; - else if (strcmp(buff, "false") != 0) - printError("Bad boolean `$$Token'. Use \"false\" or \"true\""); - return false; -} - - -bool LyXLex::EatLine() +bool LyXLex::getBool() const { - int i=0; - int c = '\0'; // getc() returns an int - - while (!feof(file) && c!='\n' && i!=(LEX_MAX_BUFF-1)) { - c = getc(file); - if (c != '\r') - buff[i++] = c; - } - if (i==(LEX_MAX_BUFF-1) && c !='\n') { - printError("Line too long"); - c = '\n'; // Pretend we had an end of line - lineno--; // but don't increase line counter (netto effect) - i++; // and preserve last character read. - } - if (c=='\n') { - lineno++; - buff[--i] = '\0'; // i can never be 0 here, so no danger - status = LEX_DATA; + if (compare(pimpl_->buff, "true") == 0) return true; - } else { - buff[i] = '\0'; - return false; - } + else if (compare(pimpl_->buff, "false") != 0) + pimpl_->printError("Bad boolean `$$Token'. Use \"false\" or \"true\""); + return false; } -int LyXLex::search_kw(char const * const tag) const +bool LyXLex::eatLine() { - int m, k=0 , l= 0, r=no_items; - - while (l < r) { - m = (l+r)/2; - - if (lyxerr.debugging(Error::LEX_PARSER)) { - LString my_l; - my_l+="LyXLex::search_kw: elem " ; - my_l+= m; - my_l+=" tag "; - my_l+=table[m].tag; - my_l+=" search tag "; - my_l+= tag; - lyxerr.print(my_l); - } - - if (table[m].tag) - k = strcasecmp(table[m].tag, tag); - if (k==0) - return table[m].code; - else - if (k<0) l = m+1; else r = m; - } - return -1; + return pimpl_->eatLine(); } bool LyXLex::next(bool esc) { - - if (!esc) { - int c; // getc() returns an int - int i; - - - status = 0; - while (!feof(file) && !status) { - c = getc(file); - if (c=='#') { - // Read rest of line (fast :-) - fgets(buff, sizeof(buff), file); - lineno++; - continue; - } - - if (c=='\"') { - i = -1; - do { - c = getc(file); - if (c != '\r') - buff[++i] = c; - } while (c!='\"' && c!='\n' && !feof(file) && - i!=(LEX_MAX_BUFF-2)); - - if (i==(LEX_MAX_BUFF-2)) { - printError("Line too long"); - c = '\"'; // Pretend we got a " - i++; - } - - if (c!='\"') { - printError("Missing quote"); - if (c=='\n') - lineno++; - } - - buff[i] = '\0'; - status = LEX_DATA; - break; - } - - if (c==',') - continue; /* Skip ','s */ - - if (c > ' ' && !feof(file)) { - i = 0; - do { - buff[i++] = c; - c = getc(file); - } while (c > ' ' && c != ',' && !feof(file) && - (i != LEX_MAX_BUFF-1) ); - if (i == LEX_MAX_BUFF-1) { - printError("Line too long"); - } - buff[i] = '\0'; - status = LEX_TOKEN; - } - - if (c=='\r' && !feof(file)) { - // The Windows support has lead to the - // possibility of "\r\n" at the end of - // a line. This will stop LyX choking - // when it expected to find a '\n' - c = getc(file); - } - - if (c=='\n') - lineno++; - - } - if (status) return true; - - status = (feof(file)) ? LEX_FEOF: LEX_UNDEF; - buff[0] = '\0'; - return false; - } else { - int c; // getc() returns an int - int i; - - - status = 0; - while (!feof(file) && !status) { - c = getc(file); - - // skip ','s - if (c==',') continue; - - if (c=='\\') { - // escape - i = 0; - do { - if (c == '\\') { - // escape the next char - c = getc(file); - } - buff[i++] = c; - c = getc(file); - } while (c > ' ' && c != ',' && !feof(file) && - (i != LEX_MAX_BUFF-1) ); - if (i == LEX_MAX_BUFF-1) { - printError("Line too long"); - } - buff[i] = '\0'; - status = LEX_TOKEN; - continue; - } - - if (c=='#') { - // Read rest of line (fast :-) - fgets(buff, sizeof(buff), file); - lineno++; - continue; - } - - // string - if (c=='\"') { - i = -1; - bool escaped = false; - do { - escaped = false; - c = getc(file); - if (c == '\r') continue; - if (c == '\\') { - // escape the next char - c = getc(file); - escaped = true; - } - buff[++i] = c; - - if (!escaped && c == '\"') break; - } while (c!='\n' && !feof(file) && - i!=(LEX_MAX_BUFF-2)); - - if (i==(LEX_MAX_BUFF-2)) { - printError("Line too long"); - c = '\"'; // Pretend we got a " - i++; - } - - if (c!='\"') { - printError("Missing quote"); - if (c=='\n') - lineno++; - } - - buff[i] = '\0'; - status = LEX_DATA; - break; - } - - if (c > ' ' && !feof(file)) { - i = 0; - do { - if (c == '\\') { - // escape the next char - c = getc(file); - //escaped = true; - } - buff[i++] = c; - c = getc(file); - } while (c > ' ' && c != ',' && !feof(file) && - (i != LEX_MAX_BUFF-1) ); - if (i == LEX_MAX_BUFF-1) { - printError("Line too long"); - } - buff[i] = '\0'; - status = LEX_TOKEN; - } - - // new line - if (c=='\n') - lineno++; - } - - if (status) return true; - - status = (feof(file)) ? LEX_FEOF: LEX_UNDEF; - buff[0] = '\0'; - return false; - } + return pimpl_->next(esc); } bool LyXLex::nextToken() { - int c; // getc() returns an int - int i; - - status = 0; - while (!feof(file) && !status) { - c = getc(file); - - if (c >= ' ' && !feof(file)) { - i = 0; - if (c == '\\') { // first char == '\\' - do { - buff[i++] = c; - c = getc(file); - } while (c > ' ' && c != '\\' && !feof(file) && - i != (LEX_MAX_BUFF-1)); - } else { - do { - buff[i++] = c; - c = getc(file); - } while (c >= ' ' && c != '\\' && !feof(file) - && i != (LEX_MAX_BUFF-1)); - } + return pimpl_->nextToken(); +} - if (i == (LEX_MAX_BUFF-1)) { - printError("Line too long"); - } - if (c == '\\') ungetc(c,file); // put it back - buff[i] = '\0'; - status = LEX_TOKEN; - } - - if (c=='\n') - lineno++; - - } - if (status) return true; - - status = (feof(file)) ? LEX_FEOF: LEX_UNDEF; - buff[0] = '\0'; - return false; +void LyXLex::pushToken(string const & pt) +{ + pimpl_->pushToken(pt); } -int LyXLex::FindToken(char const* string[]) +int LyXLex::findToken(char const * str[]) { int i = -1; if (next()) { - if (strcmp(buff, "default")) { - for (i=0; string[i][0] && strcmp(string[i], buff); i++); - if (!string[i][0]) { - printError("Unknown argument `$$Token'"); + if (compare(pimpl_->buff, "default")) { + for (i = 0; str[i][0] && compare(str[i], pimpl_->buff); ++i); + if (!str[i][0]) { + pimpl_->printError("Unknown argument `$$Token'"); i = -1; } } } else - printError("file ended while scanning string token"); + pimpl_->printError("file ended while scanning string token"); return i; } -int LyXLex::CheckToken(char const* string[], int print_error) +int LyXLex::checkToken(char const * str[], int print_error) { int i = -1; - if (strcmp(buff, "default")) { - for (i=0; string[i][0] && strcmp(string[i], buff); i++); - if (!string[i][0]) { + if (compare(pimpl_->buff, "default")) { + for (i = 0; str[i][0] && compare(str[i], pimpl_->buff); ++i); + if (!str[i][0]) { if (print_error) - printError("Unknown argument `$$Token'"); + pimpl_->printError("Unknown argument `$$Token'"); i = -1; } }