Georg Baum wrote:
Bernhard Roider wrote:
Hello!
Here i again attached the patch for lyxlex i sent nearly two weeks ago
(and one for a superfluous space in the code). In my opinion you should
really consider to put it in because with the current version of lyxlex it
is _impossible_ to check whether reading an integer, float, ... succeeded
or not. The current solution to check for is.bad() in some cases and in
other cases use is.good() does not give the desired information. Moreover
the result of is.bad() depends on the stl implementation and behaves
different for linux and windows.
Please check the documentation in src/lyxlex.h (especially the FIXMEs) and
update it where needed. Without proper documentation your changes might fix
the current problems, but similar ones will be reintroduced because people
do not know how to use LyXLex.
That's true. What about this one?
Bernhard
Index: src/buffer.C
===================================================================
--- src/buffer.C (revision 17394)
+++ src/buffer.C (working copy)
@@ -649,7 +649,7 @@
lex.next();
string const token(lex.getString());
- if (!lex.isOK()) {
+ if (!lex) {
Alert::error(_("Document could not be read"),
bformat(_("%1$s could not be read."),
from_utf8(filename.absFilename())));
return failure;
Index: src/frontends/controllers/ControlLog.C
===================================================================
--- src/frontends/controllers/ControlLog.C (revision 17394)
+++ src/frontends/controllers/ControlLog.C (working copy)
@@ -43,7 +43,7 @@
string logtype, logfile;
lex >> logtype;
- if (lex.isOK()) {
+ if (lex) {
lex.next(true);
logfile = lex.getString();
}
Index: src/frontends/controllers/ControlParagraph.C
===================================================================
--- src/frontends/controllers/ControlParagraph.C (revision 17394)
+++ src/frontends/controllers/ControlParagraph.C (working copy)
@@ -53,7 +53,12 @@
} else if (token == "update") {
lex.next();
bool const accept = lex.getBool();
- action = accept ? 1 : 2;
+ if (lex) {
+ action = accept ? 1 : 2;
+ } else {
+ // Unrecognised update option
+ return false;
+ }
} else if (!token.empty()) {
// Unrecognised token
return false;
Index: src/insets/insetbox.C
===================================================================
--- src/insets/insetbox.C (revision 17394)
+++ src/insets/insetbox.C (working copy)
@@ -531,15 +531,17 @@
if (!lex.isOK())
return;
- if (lex.isOK()) {
- lex.next();
- type = lex.getString();
- }
- if (!lex.isOK())
+ lex.next();
+ type = lex.getString();
+
+ if (!lex)
return;
+
lex.next();
string token;
token = lex.getString();
+ if (!lex)
+ return;
if (token == "position") {
lex.next();
// The [0] is needed. We need the first and only char in
@@ -549,10 +551,11 @@
lyxerr << "InsetBox::Read: Missing 'position'-tag!" << token <<
endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "hor_pos") {
lex.next();
hor_pos = lex.getString()[0];
@@ -560,10 +563,11 @@
lyxerr << "InsetBox::Read: Missing 'hor_pos'-tag!" << token <<
endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "has_inner_box") {
lex.next();
inner_box = lex.getInteger();
@@ -572,10 +576,10 @@
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "inner_pos") {
lex.next();
inner_pos = lex.getString()[0];
@@ -584,10 +588,11 @@
<< token << endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "use_parbox") {
lex.next();
use_parbox = lex.getInteger();
@@ -595,10 +600,11 @@
lyxerr << "InsetBox::Read: Missing 'use_parbox'-tag!" << endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "width") {
lex.next();
width = LyXLength(lex.getString());
@@ -606,10 +612,11 @@
lyxerr << "InsetBox::Read: Missing 'width'-tag!" << endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "special") {
lex.next();
special = lex.getString();
@@ -617,10 +624,11 @@
lyxerr << "InsetBox::Read: Missing 'special'-tag!" << endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "height") {
lex.next();
height = LyXLength(lex.getString());
@@ -628,10 +636,11 @@
lyxerr << "InsetBox::Read: Missing 'height'-tag!" << endl;
lex.pushToken(token);
}
- if (!lex.isOK())
- return;
+
lex.next();
token = lex.getString();
+ if (!lex)
+ return;
if (token == "height_special") {
lex.next();
height_special = lex.getString();
Index: src/insets/insetert.C
===================================================================
--- src/insets/insetert.C (revision 17394)
+++ src/insets/insetert.C (working copy)
@@ -466,7 +466,7 @@
int s;
lex >> s;
- if (lex.isOK())
+ if (lex)
status = static_cast<InsetCollapsable::CollapseStatus>(s);
}
Index: src/insets/insetnote.C
===================================================================
--- src/insets/insetnote.C (revision 17394)
+++ src/insets/insetnote.C (working copy)
@@ -105,7 +105,7 @@
{
string label;
lex >> label;
- if (lex.isOK())
+ if (lex)
type = notetranslator().find(label);
}
Index: src/insets/insettabular.C
===================================================================
--- src/insets/insettabular.C (revision 17394)
+++ src/insets/insettabular.C (working copy)
@@ -230,11 +230,11 @@
lex.next();
string token = lex.getString();
- while (lex.isOK() && (token != "\\end_inset")) {
+ while (lex && token != "\\end_inset") {
lex.next();
token = lex.getString();
}
- if (token != "\\end_inset") {
+ if (!lex) {
lex.printError("Missing \\end_inset at this point. "
"Read: `$$Token'");
}
Index: src/insets/insetvspace.C
===================================================================
--- src/insets/insetvspace.C (revision 17394)
+++ src/insets/insetvspace.C (working copy)
@@ -88,7 +88,7 @@
BOOST_ASSERT(lex.isOK());
string vsp;
lex >> vsp;
- if (lex.isOK())
+ if (lex)
space_ = VSpace(vsp);
string end_token;
@@ -257,7 +257,7 @@
string vsp;
lex >> vsp;
- if (lex.isOK())
+ if (lex)
vspace = VSpace(vsp);
}
Index: src/lyxlex.C
===================================================================
--- src/lyxlex.C (revision 17394)
+++ src/lyxlex.C (working copy)
@@ -53,7 +53,7 @@
bool LyXLex::isOK() const
{
- return pimpl_->is.good();
+ return pimpl_->inputAvailable();
}
@@ -124,8 +124,16 @@
int LyXLex::getInteger() const
{
+ lastReadOk_ = pimpl_->status == LEX_DATA || pimpl_->status == LEX_TOKEN;
+ if (!lastReadOk_) {
+ pimpl_->printError("integer token missing");
+ return -1;
+ }
+
if (isStrInt(pimpl_->getString()))
return convert<int>(pimpl_->getString());
+
+ lastReadOk_ = false;
pimpl_->printError("Bad integer `$$Token'");
return -1;
}
@@ -136,9 +144,17 @@
// replace comma with dot in case the file was written with
// the wrong locale (should be rare, but is easy enough to
// avoid).
+ lastReadOk_ = pimpl_->status == LEX_DATA || pimpl_->status == LEX_TOKEN;
+ if (!lastReadOk_) {
+ pimpl_->printError("float token missing");
+ return -1;
+ }
+
string const str = subst(pimpl_->getString(), ",", ".");
if (isStrDbl(str))
return convert<double>(str);
+
+ lastReadOk_ = false;
pimpl_->printError("Bad float `$$Token'");
return -1;
}
@@ -146,13 +162,23 @@
string const LyXLex::getString() const
{
+ lastReadOk_ = pimpl_->status == LEX_DATA || pimpl_->status == LEX_TOKEN;
+
+ if (lastReadOk_)
return pimpl_->getString();
+
+ return string();
}
docstring const LyXLex::getDocString() const
{
- return pimpl_->getDocString();
+ lastReadOk_ = pimpl_->status == LEX_DATA || pimpl_->status == LEX_TOKEN;
+
+ if (lastReadOk_)
+ return pimpl_->getDocString();
+
+ return docstring();
}
@@ -164,7 +190,7 @@
string str, prefix;
bool firstline = true;
- while (isOK()) {
+ while (pimpl_->is) { //< eatLine only reads from is, not from pushTok
if (!eatLine())
// blank line in the file being read
continue;
@@ -197,7 +223,7 @@
str += ltrim(tmpstr, "\t") + '\n';
}
- if (!isOK()) {
+ if (!pimpl_->is) {
printError("Long string not ended by `" + endtoken + '\'');
}
@@ -208,11 +234,14 @@
bool LyXLex::getBool() const
{
if (pimpl_->getString() == "true") {
+ lastReadOk_ = true;
return true;
} else if (pimpl_->getString() != "false") {
pimpl_->printError("Bad boolean `$$Token'. "
"Use \"false\" or \"true\"");
+ lastReadOk_ = false;
}
+ lastReadOk_ = true;
return false;
}
@@ -246,13 +275,13 @@
// use fail() here. However, our implementation of getString() et al.
// can cause the eof() and fail() bits to be set, even though we
// haven't tried to read 'em.
- return pimpl_->is.bad() ? 0 : this;
+ return lastReadOk_? this: 0;
}
bool LyXLex::operator!() const
{
- return pimpl_->is.bad();
+ return !lastReadOk_;
}
@@ -261,6 +290,8 @@
if (isOK()) {
next();
s = getString();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
@@ -271,6 +302,8 @@
if (isOK()) {
next();
s = getDocString();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
@@ -281,6 +314,8 @@
if (isOK()) {
next();
s = getFloat();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
@@ -291,6 +326,8 @@
if (isOK()) {
next();
s = getInteger();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
@@ -301,6 +338,8 @@
if (isOK()) {
next();
s = getInteger();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
@@ -311,6 +350,8 @@
if (isOK()) {
next();
s = getBool();
+ } else {
+ lastReadOk_ = false;
}
return *this;
}
Index: src/lyxlex.h
===================================================================
--- src/lyxlex.h (revision 17434)
+++ src/lyxlex.h (working copy)
@@ -37,8 +37,22 @@
};
/** Generalized simple lexical analizer.
- It can be used for simple syntax parsers, like lyxrc,
- texclass and others to come.
+ Use the method isOK() to check if there is still data available
+ for lexing. Use one of the the operators void* or ! to test if
+ the last reading operation was successful.
+
+ Example:
+
+ int readParam(LyxLex &lex) {
+ int param = 1; // default value
+ if (lex.isOK()) { // the lexer has data to read
+ int p; // temporary variable
+ lex >> p;
+ if (lex) param = p; // only use the input if reading
was successful
+ }
+ return param;
+ }
+
@see lyxrc.C for an example of usage.
*/
class LyXLex : boost::noncopyable {
@@ -61,14 +75,16 @@
};
/// stream is open and end of stream is not reached
- /// FIXME: Rename to good() since this is the name of the
- /// corresponding std::stream method.
+ /// FIXME: test also if pushTok is not empty
+ /// FIXME: the method should be renamed to something like
+ /// dataAvailable(), in order to reflect the real behavior
bool isOK() const;
- /// stream is ok
- /// FIXME: This does not behave like the std::stream counterpart.
+ /// FIXME: The next two operators should be replaced by one method
+ /// called e.g. lastReadOk(), in order to reflect the real
+ /// behavior
+ /// last read operation was successful.
operator void const *() const;
- /// stream is not ok
- /// FIXME: This does not behave like the std::stream counterpart.
+ /// last read operation was not successful
bool operator!() const;
/// return true if able to open file, else false
bool setFile(support::FileName const & filename);
@@ -84,7 +100,7 @@
/// returns a lex code
int lex();
- /** Just read athe next word. If esc is true remember that
+ /** Just read the next word. If esc is true remember that
some chars might be escaped: "\ atleast
*/
bool next(bool esc = false);
@@ -162,6 +178,8 @@
class Pimpl;
///
Pimpl * pimpl_;
+ ///
+ mutable bool lastReadOk_;
};
Index: src/lyxlex_pimpl.C
===================================================================
--- src/lyxlex_pimpl.C (revision 17434)
+++ src/lyxlex_pimpl.C (working copy)
@@ -204,15 +204,15 @@
// There can have been a whole line pushed so
// we extract the first word and leaves the rest
// in pushTok. (Lgb)
- if (pushTok.find(' ') != string::npos && pushTok[0] == '\\') {
+ if (pushTok[0] == '\\' && pushTok.find(' ') != string::npos) {
buff.clear();
pushTok = split(pushTok, buff, ' ');
- return true;
} else {
buff = pushTok;
pushTok.clear();
- return true;
}
+ status = LEX_TOKEN;
+ return true;
}
if (!esc) {
unsigned char c = 0; // getc() returns an int
@@ -306,26 +306,8 @@
c = cc;
// skip ','s
- if (c == ',') continue;
-
- if (c == '\\') {
- // escape
- buff.clear();
-
- do {
- if (c == '\\') {
- // escape the next char
- is.get(cc);
- c = cc;
- }
- buff.push_back(c);
- is.get(cc);
- c = cc;
- } while (c > ' ' && c != ',' && is);
-
- status = LEX_TOKEN;
+ if (c == ',')
continue;
- }
if (c == commentChar) {
// Read rest of line (fast :-)
@@ -457,6 +439,9 @@
buff.resize(buff.size() - 1);
status = LEX_DATA;
return true;
+ } else if (buff.length() > 0) { // last line
+ status = LEX_DATA;
+ return true;
} else {
return false;
}
@@ -469,15 +454,15 @@
// There can have been a whole line pushed so
// we extract the first word and leaves the rest
// in pushTok. (Lgb)
- if (pushTok.find(' ') != string::npos && pushTok[0] == '\\') {
+ if (pushTok[0] == '\\' && pushTok.find(' ') != string::npos) {
buff.clear();
pushTok = split(pushTok, buff, ' ');
- return true;
} else {
buff = pushTok;
pushTok.clear();
- return true;
}
+ status = LEX_TOKEN;
+ return true;
}
status = 0;
@@ -519,6 +504,11 @@
}
+bool LyXLex::Pimpl::inputAvailable() {
+ return is.good();
+}
+
+
void LyXLex::Pimpl::pushToken(string const & pt)
{
pushTok = pt;
Index: src/lyxlex_pimpl.h
===================================================================
--- src/lyxlex_pimpl.h (revision 17394)
+++ src/lyxlex_pimpl.h (working copy)
@@ -65,6 +65,8 @@
bool eatLine();
///
bool nextToken();
+ /// test if there is a pushed token or the stream is ok
+ bool inputAvailable();
///
void pushToken(std::string const &);
/// fb_ is only used to open files, the stream is accessed through is.
Index: src/ToolbarBackend.C
===================================================================
--- src/ToolbarBackend.C (revision 17394)
+++ src/ToolbarBackend.C (working copy)
@@ -79,12 +79,12 @@
Toolbar tb;
tb.name = lex.getString();
lex.next(true);
- if (!lex.isOK()) {
+ tb.gui_name = lex.getString();
+ if (!lex) {
lyxerr << "ToolbarBackend::read: Malformed toolbar "
"description " << lex.getString() << endl;
return;
}
- tb.gui_name = lex.getString();
bool quit = false;