mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-26 11:16:55 +00:00
Fix bug 3293 by Bernhard Roider:
This changes the semantics of isOK() and operator(), comments from Bernhard below: With the old version of lyxlex it was _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. the bug was introduced by the patch that fixed the bug that crashed lyx when "inset-insert ert" was executed from the command buffer. The lexer has the method isOK() which reflects the status of the stream is. The operators void* and ! are not really well defined (they depend on the value of is.bad()). What is missing is a test if the last reading operation was successful and thus the returned value is valid. That's what i implemented in this patch. The new rule for using the lexer: if you want to know if the lexer still has data to read (either from the stream or from the pushed token) then use "lex.isOK()". If you want to test if the last reading operation was successful then use eg. "if (lex) {...}" or unsuccessful then use eg. "if (!lex) {...}" an 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 the reading operation was successful } return param; } git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17569 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
4d2732b1e7
commit
4d5ae916ad
@ -79,12 +79,12 @@ void ToolbarBackend::read(LyXLex & lex)
|
|||||||
Toolbar tb;
|
Toolbar tb;
|
||||||
tb.name = lex.getString();
|
tb.name = lex.getString();
|
||||||
lex.next(true);
|
lex.next(true);
|
||||||
if (!lex.isOK()) {
|
tb.gui_name = lex.getString();
|
||||||
|
if (!lex) {
|
||||||
lyxerr << "ToolbarBackend::read: Malformed toolbar "
|
lyxerr << "ToolbarBackend::read: Malformed toolbar "
|
||||||
"description " << lex.getString() << endl;
|
"description " << lex.getString() << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tb.gui_name = lex.getString();
|
|
||||||
|
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
|
@ -653,7 +653,7 @@ Buffer::ReadStatus Buffer::readFile(LyXLex & lex, FileName const & filename,
|
|||||||
lex.next();
|
lex.next();
|
||||||
string const token(lex.getString());
|
string const token(lex.getString());
|
||||||
|
|
||||||
if (!lex.isOK()) {
|
if (!lex) {
|
||||||
Alert::error(_("Document could not be read"),
|
Alert::error(_("Document could not be read"),
|
||||||
bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
|
bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
|
||||||
return failure;
|
return failure;
|
||||||
|
@ -234,14 +234,14 @@ DocIterator::col_type DocIterator::col() const
|
|||||||
|
|
||||||
MathArray const & DocIterator::cell() const
|
MathArray const & DocIterator::cell() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(inMathed());
|
// BOOST_ASSERT(inMathed());
|
||||||
return top().cell();
|
return top().cell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MathArray & DocIterator::cell()
|
MathArray & DocIterator::cell()
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(inMathed());
|
// BOOST_ASSERT(inMathed());
|
||||||
return top().cell();
|
return top().cell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ bool ControlLog::initialiseParams(string const & data)
|
|||||||
|
|
||||||
string logtype, logfile;
|
string logtype, logfile;
|
||||||
lex >> logtype;
|
lex >> logtype;
|
||||||
if (lex.isOK()) {
|
if (lex) {
|
||||||
lex.next(true);
|
lex.next(true);
|
||||||
logfile = lex.getString();
|
logfile = lex.getString();
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,12 @@ bool ControlParagraph::initialiseParams(string const & data)
|
|||||||
} else if (token == "update") {
|
} else if (token == "update") {
|
||||||
lex.next();
|
lex.next();
|
||||||
bool const accept = lex.getBool();
|
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()) {
|
} else if (!token.empty()) {
|
||||||
// Unrecognised token
|
// Unrecognised token
|
||||||
return false;
|
return false;
|
||||||
|
@ -531,15 +531,17 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
if (!lex.isOK())
|
if (!lex.isOK())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (lex.isOK()) {
|
lex.next();
|
||||||
lex.next();
|
type = lex.getString();
|
||||||
type = lex.getString();
|
|
||||||
}
|
if (!lex)
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lex.next();
|
lex.next();
|
||||||
string token;
|
string token;
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "position") {
|
if (token == "position") {
|
||||||
lex.next();
|
lex.next();
|
||||||
// The [0] is needed. We need the first and only char in
|
// The [0] is needed. We need the first and only char in
|
||||||
@ -549,10 +551,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'position'-tag!" << token << endl;
|
lyxerr << "InsetBox::Read: Missing 'position'-tag!" << token << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "hor_pos") {
|
if (token == "hor_pos") {
|
||||||
lex.next();
|
lex.next();
|
||||||
hor_pos = lex.getString()[0];
|
hor_pos = lex.getString()[0];
|
||||||
@ -560,10 +563,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'hor_pos'-tag!" << token << endl;
|
lyxerr << "InsetBox::Read: Missing 'hor_pos'-tag!" << token << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "has_inner_box") {
|
if (token == "has_inner_box") {
|
||||||
lex.next();
|
lex.next();
|
||||||
inner_box = lex.getInteger();
|
inner_box = lex.getInteger();
|
||||||
@ -572,10 +576,10 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "inner_pos") {
|
if (token == "inner_pos") {
|
||||||
lex.next();
|
lex.next();
|
||||||
inner_pos = lex.getString()[0];
|
inner_pos = lex.getString()[0];
|
||||||
@ -584,10 +588,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
<< token << endl;
|
<< token << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "use_parbox") {
|
if (token == "use_parbox") {
|
||||||
lex.next();
|
lex.next();
|
||||||
use_parbox = lex.getInteger();
|
use_parbox = lex.getInteger();
|
||||||
@ -595,10 +600,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'use_parbox'-tag!" << endl;
|
lyxerr << "InsetBox::Read: Missing 'use_parbox'-tag!" << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "width") {
|
if (token == "width") {
|
||||||
lex.next();
|
lex.next();
|
||||||
width = LyXLength(lex.getString());
|
width = LyXLength(lex.getString());
|
||||||
@ -606,10 +612,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'width'-tag!" << endl;
|
lyxerr << "InsetBox::Read: Missing 'width'-tag!" << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "special") {
|
if (token == "special") {
|
||||||
lex.next();
|
lex.next();
|
||||||
special = lex.getString();
|
special = lex.getString();
|
||||||
@ -617,10 +624,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'special'-tag!" << endl;
|
lyxerr << "InsetBox::Read: Missing 'special'-tag!" << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "height") {
|
if (token == "height") {
|
||||||
lex.next();
|
lex.next();
|
||||||
height = LyXLength(lex.getString());
|
height = LyXLength(lex.getString());
|
||||||
@ -628,10 +636,11 @@ void InsetBoxParams::read(LyXLex & lex)
|
|||||||
lyxerr << "InsetBox::Read: Missing 'height'-tag!" << endl;
|
lyxerr << "InsetBox::Read: Missing 'height'-tag!" << endl;
|
||||||
lex.pushToken(token);
|
lex.pushToken(token);
|
||||||
}
|
}
|
||||||
if (!lex.isOK())
|
|
||||||
return;
|
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
|
if (!lex)
|
||||||
|
return;
|
||||||
if (token == "height_special") {
|
if (token == "height_special") {
|
||||||
lex.next();
|
lex.next();
|
||||||
height_special = lex.getString();
|
height_special = lex.getString();
|
||||||
|
@ -466,7 +466,7 @@ void InsetERTMailer::string2params(string const & in,
|
|||||||
|
|
||||||
int s;
|
int s;
|
||||||
lex >> s;
|
lex >> s;
|
||||||
if (lex.isOK())
|
if (lex)
|
||||||
status = static_cast<InsetCollapsable::CollapseStatus>(s);
|
status = static_cast<InsetCollapsable::CollapseStatus>(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ void InsetNoteParams::read(LyXLex & lex)
|
|||||||
{
|
{
|
||||||
string label;
|
string label;
|
||||||
lex >> label;
|
lex >> label;
|
||||||
if (lex.isOK())
|
if (lex)
|
||||||
type = notetranslator().find(label);
|
type = notetranslator().find(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,11 +231,11 @@ void InsetTabular::read(Buffer const & buf, LyXLex & lex)
|
|||||||
|
|
||||||
lex.next();
|
lex.next();
|
||||||
string token = lex.getString();
|
string token = lex.getString();
|
||||||
while (lex.isOK() && (token != "\\end_inset")) {
|
while (lex && token != "\\end_inset") {
|
||||||
lex.next();
|
lex.next();
|
||||||
token = lex.getString();
|
token = lex.getString();
|
||||||
}
|
}
|
||||||
if (token != "\\end_inset") {
|
if (!lex) {
|
||||||
lex.printError("Missing \\end_inset at this point. "
|
lex.printError("Missing \\end_inset at this point. "
|
||||||
"Read: `$$Token'");
|
"Read: `$$Token'");
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ void InsetVSpace::read(Buffer const &, LyXLex & lex)
|
|||||||
BOOST_ASSERT(lex.isOK());
|
BOOST_ASSERT(lex.isOK());
|
||||||
string vsp;
|
string vsp;
|
||||||
lex >> vsp;
|
lex >> vsp;
|
||||||
if (lex.isOK())
|
if (lex)
|
||||||
space_ = VSpace(vsp);
|
space_ = VSpace(vsp);
|
||||||
|
|
||||||
string end_token;
|
string end_token;
|
||||||
@ -257,7 +257,7 @@ void InsetVSpaceMailer::string2params(string const & in, VSpace & vspace)
|
|||||||
|
|
||||||
string vsp;
|
string vsp;
|
||||||
lex >> vsp;
|
lex >> vsp;
|
||||||
if (lex.isOK())
|
if (lex)
|
||||||
vspace = VSpace(vsp);
|
vspace = VSpace(vsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
53
src/lyxlex.C
53
src/lyxlex.C
@ -53,7 +53,7 @@ LyXLex::~LyXLex()
|
|||||||
|
|
||||||
bool LyXLex::isOK() const
|
bool LyXLex::isOK() const
|
||||||
{
|
{
|
||||||
return pimpl_->is.good();
|
return pimpl_->inputAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,8 +124,16 @@ int LyXLex::lex()
|
|||||||
|
|
||||||
int LyXLex::getInteger() const
|
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()))
|
if (isStrInt(pimpl_->getString()))
|
||||||
return convert<int>(pimpl_->getString());
|
return convert<int>(pimpl_->getString());
|
||||||
|
|
||||||
|
lastReadOk_ = false;
|
||||||
pimpl_->printError("Bad integer `$$Token'");
|
pimpl_->printError("Bad integer `$$Token'");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -136,9 +144,17 @@ double LyXLex::getFloat() const
|
|||||||
// replace comma with dot in case the file was written with
|
// replace comma with dot in case the file was written with
|
||||||
// the wrong locale (should be rare, but is easy enough to
|
// the wrong locale (should be rare, but is easy enough to
|
||||||
// avoid).
|
// 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(), ",", ".");
|
string const str = subst(pimpl_->getString(), ",", ".");
|
||||||
if (isStrDbl(str))
|
if (isStrDbl(str))
|
||||||
return convert<double>(str);
|
return convert<double>(str);
|
||||||
|
|
||||||
|
lastReadOk_ = false;
|
||||||
pimpl_->printError("Bad float `$$Token'");
|
pimpl_->printError("Bad float `$$Token'");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -146,13 +162,23 @@ double LyXLex::getFloat() const
|
|||||||
|
|
||||||
string const LyXLex::getString() const
|
string const LyXLex::getString() const
|
||||||
{
|
{
|
||||||
|
lastReadOk_ = pimpl_->status == LEX_DATA || pimpl_->status == LEX_TOKEN;
|
||||||
|
|
||||||
|
if (lastReadOk_)
|
||||||
return pimpl_->getString();
|
return pimpl_->getString();
|
||||||
|
|
||||||
|
return string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
docstring const LyXLex::getDocString() const
|
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 const LyXLex::getLongString(string const & endtoken)
|
|||||||
string str, prefix;
|
string str, prefix;
|
||||||
bool firstline = true;
|
bool firstline = true;
|
||||||
|
|
||||||
while (isOK()) {
|
while (pimpl_->is) { //< eatLine only reads from is, not from pushTok
|
||||||
if (!eatLine())
|
if (!eatLine())
|
||||||
// blank line in the file being read
|
// blank line in the file being read
|
||||||
continue;
|
continue;
|
||||||
@ -197,7 +223,7 @@ string const LyXLex::getLongString(string const & endtoken)
|
|||||||
str += ltrim(tmpstr, "\t") + '\n';
|
str += ltrim(tmpstr, "\t") + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isOK()) {
|
if (!pimpl_->is) {
|
||||||
printError("Long string not ended by `" + endtoken + '\'');
|
printError("Long string not ended by `" + endtoken + '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +234,14 @@ string const LyXLex::getLongString(string const & endtoken)
|
|||||||
bool LyXLex::getBool() const
|
bool LyXLex::getBool() const
|
||||||
{
|
{
|
||||||
if (pimpl_->getString() == "true") {
|
if (pimpl_->getString() == "true") {
|
||||||
|
lastReadOk_ = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (pimpl_->getString() != "false") {
|
} else if (pimpl_->getString() != "false") {
|
||||||
pimpl_->printError("Bad boolean `$$Token'. "
|
pimpl_->printError("Bad boolean `$$Token'. "
|
||||||
"Use \"false\" or \"true\"");
|
"Use \"false\" or \"true\"");
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
|
lastReadOk_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,13 +275,13 @@ LyXLex::operator void const *() const
|
|||||||
// use fail() here. However, our implementation of getString() et al.
|
// use fail() here. However, our implementation of getString() et al.
|
||||||
// can cause the eof() and fail() bits to be set, even though we
|
// can cause the eof() and fail() bits to be set, even though we
|
||||||
// haven't tried to read 'em.
|
// haven't tried to read 'em.
|
||||||
return pimpl_->is.bad() ? 0 : this;
|
return lastReadOk_? this: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LyXLex::operator!() const
|
bool LyXLex::operator!() const
|
||||||
{
|
{
|
||||||
return pimpl_->is.bad();
|
return !lastReadOk_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,6 +290,8 @@ LyXLex & LyXLex::operator>>(std::string & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getString();
|
s = getString();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -271,6 +302,8 @@ LyXLex & LyXLex::operator>>(docstring & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getDocString();
|
s = getDocString();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -281,6 +314,8 @@ LyXLex & LyXLex::operator>>(double & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getFloat();
|
s = getFloat();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -291,6 +326,8 @@ LyXLex & LyXLex::operator>>(int & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getInteger();
|
s = getInteger();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -301,6 +338,8 @@ LyXLex & LyXLex::operator>>(unsigned int & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getInteger();
|
s = getInteger();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -311,6 +350,8 @@ LyXLex & LyXLex::operator>>(bool & s)
|
|||||||
if (isOK()) {
|
if (isOK()) {
|
||||||
next();
|
next();
|
||||||
s = getBool();
|
s = getBool();
|
||||||
|
} else {
|
||||||
|
lastReadOk_ = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
36
src/lyxlex.h
36
src/lyxlex.h
@ -37,8 +37,22 @@ struct keyword_item {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Generalized simple lexical analizer.
|
/** Generalized simple lexical analizer.
|
||||||
It can be used for simple syntax parsers, like lyxrc,
|
Use the method isOK() to check if there is still data available
|
||||||
texclass and others to come.
|
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.
|
@see lyxrc.C for an example of usage.
|
||||||
*/
|
*/
|
||||||
class LyXLex : boost::noncopyable {
|
class LyXLex : boost::noncopyable {
|
||||||
@ -61,14 +75,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// stream is open and end of stream is not reached
|
/// stream is open and end of stream is not reached
|
||||||
/// FIXME: Rename to good() since this is the name of the
|
/// FIXME: test also if pushTok is not empty
|
||||||
/// corresponding std::stream method.
|
/// FIXME: the method should be renamed to something like
|
||||||
|
/// dataAvailable(), in order to reflect the real behavior
|
||||||
bool isOK() const;
|
bool isOK() const;
|
||||||
/// stream is ok
|
/// FIXME: The next two operators should be replaced by one method
|
||||||
/// FIXME: This does not behave like the std::stream counterpart.
|
/// called e.g. lastReadOk(), in order to reflect the real
|
||||||
|
/// behavior
|
||||||
|
/// last read operation was successful.
|
||||||
operator void const *() const;
|
operator void const *() const;
|
||||||
/// stream is not ok
|
/// last read operation was not successful
|
||||||
/// FIXME: This does not behave like the std::stream counterpart.
|
|
||||||
bool operator!() const;
|
bool operator!() const;
|
||||||
/// return true if able to open file, else false
|
/// return true if able to open file, else false
|
||||||
bool setFile(support::FileName const & filename);
|
bool setFile(support::FileName const & filename);
|
||||||
@ -84,7 +100,7 @@ public:
|
|||||||
/// returns a lex code
|
/// returns a lex code
|
||||||
int lex();
|
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
|
some chars might be escaped: "\ atleast
|
||||||
*/
|
*/
|
||||||
bool next(bool esc = false);
|
bool next(bool esc = false);
|
||||||
@ -162,6 +178,8 @@ private:
|
|||||||
class Pimpl;
|
class Pimpl;
|
||||||
///
|
///
|
||||||
Pimpl * pimpl_;
|
Pimpl * pimpl_;
|
||||||
|
///
|
||||||
|
mutable bool lastReadOk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,15 +204,15 @@ bool LyXLex::Pimpl::next(bool esc /* = false */)
|
|||||||
// There can have been a whole line pushed so
|
// There can have been a whole line pushed so
|
||||||
// we extract the first word and leaves the rest
|
// we extract the first word and leaves the rest
|
||||||
// in pushTok. (Lgb)
|
// in pushTok. (Lgb)
|
||||||
if (pushTok.find(' ') != string::npos && pushTok[0] == '\\') {
|
if (pushTok[0] == '\\' && pushTok.find(' ') != string::npos) {
|
||||||
buff.clear();
|
buff.clear();
|
||||||
pushTok = split(pushTok, buff, ' ');
|
pushTok = split(pushTok, buff, ' ');
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
buff = pushTok;
|
buff = pushTok;
|
||||||
pushTok.clear();
|
pushTok.clear();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
status = LEX_TOKEN;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (!esc) {
|
if (!esc) {
|
||||||
unsigned char c = 0; // getc() returns an int
|
unsigned char c = 0; // getc() returns an int
|
||||||
@ -306,26 +306,8 @@ bool LyXLex::Pimpl::next(bool esc /* = false */)
|
|||||||
c = cc;
|
c = cc;
|
||||||
|
|
||||||
// skip ','s
|
// skip ','s
|
||||||
if (c == ',') continue;
|
if (c == ',')
|
||||||
|
|
||||||
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;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (c == commentChar) {
|
if (c == commentChar) {
|
||||||
// Read rest of line (fast :-)
|
// Read rest of line (fast :-)
|
||||||
@ -457,6 +439,9 @@ bool LyXLex::Pimpl::eatLine()
|
|||||||
buff.resize(buff.size() - 1);
|
buff.resize(buff.size() - 1);
|
||||||
status = LEX_DATA;
|
status = LEX_DATA;
|
||||||
return true;
|
return true;
|
||||||
|
} else if (buff.length() > 0) { // last line
|
||||||
|
status = LEX_DATA;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -469,15 +454,15 @@ bool LyXLex::Pimpl::nextToken()
|
|||||||
// There can have been a whole line pushed so
|
// There can have been a whole line pushed so
|
||||||
// we extract the first word and leaves the rest
|
// we extract the first word and leaves the rest
|
||||||
// in pushTok. (Lgb)
|
// in pushTok. (Lgb)
|
||||||
if (pushTok.find(' ') != string::npos && pushTok[0] == '\\') {
|
if (pushTok[0] == '\\' && pushTok.find(' ') != string::npos) {
|
||||||
buff.clear();
|
buff.clear();
|
||||||
pushTok = split(pushTok, buff, ' ');
|
pushTok = split(pushTok, buff, ' ');
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
buff = pushTok;
|
buff = pushTok;
|
||||||
pushTok.clear();
|
pushTok.clear();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
status = LEX_TOKEN;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
@ -519,6 +504,11 @@ bool LyXLex::Pimpl::nextToken()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LyXLex::Pimpl::inputAvailable() {
|
||||||
|
return is.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LyXLex::Pimpl::pushToken(string const & pt)
|
void LyXLex::Pimpl::pushToken(string const & pt)
|
||||||
{
|
{
|
||||||
pushTok = pt;
|
pushTok = pt;
|
||||||
|
@ -65,6 +65,8 @@ public:
|
|||||||
bool eatLine();
|
bool eatLine();
|
||||||
///
|
///
|
||||||
bool nextToken();
|
bool nextToken();
|
||||||
|
/// test if there is a pushed token or the stream is ok
|
||||||
|
bool inputAvailable();
|
||||||
///
|
///
|
||||||
void pushToken(std::string const &);
|
void pushToken(std::string const &);
|
||||||
/// fb_ is only used to open files, the stream is accessed through is.
|
/// fb_ is only used to open files, the stream is accessed through is.
|
||||||
|
Loading…
Reference in New Issue
Block a user