]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/Parser.cpp
Fix #10778 (issue with CJK and language nesting)
[lyx.git] / src / tex2lyx / Parser.cpp
index 11ecfe12ec410698ec1caa56d4f14ba80ff137a1..69e3460f459de17c1ccc6f15b564eeac8589af69 100644 (file)
@@ -118,24 +118,19 @@ void debugToken(std::ostream & os, Token const & t, unsigned int flags)
 // Wrapper
 //
 
-bool iparserdocstream::setEncoding(std::string const & e)
+void iparserdocstream::setEncoding(std::string const & e)
 {
        is_ << lyx::setEncoding(e);
-       if (s_.empty())
-               return true;
-       cerr << "Setting encoding " << e << " too late. The encoding of `"
-            << to_utf8(s_) << "ยด is wrong." << std::endl;
-       return false;
 }
 
 
 void iparserdocstream::putback(char_type c)
 {
-       s_ += c;
+       s_ = c + s_;
 }
 
 
-void iparserdocstream::put_almost_back(docstring s)
+void iparserdocstream::putback(docstring s)
 {
        s_ = s + s_;
 }
@@ -146,6 +141,7 @@ iparserdocstream & iparserdocstream::get(char_type &c)
        if (s_.empty())
                is_.get(c);
        else {
+               //cerr << "unparsed: " << to_utf8(s_) <<endl;
                c = s_[0];
                s_.erase(0,1);
        }
@@ -158,10 +154,14 @@ iparserdocstream & iparserdocstream::get(char_type &c)
 //
 
 
-Parser::Parser(idocstream & is)
-       : lineno_(0), pos_(0), iss_(0), is_(is), encoding_iconv_("UTF-8"),
-         theCatcodesType_(NORMAL_CATCODES), curr_cat_(UNDECIDED_CATCODES)
+Parser::Parser(idocstream & is, std::string const & fixedenc)
+       : lineno_(0), pos_(0), iss_(0), is_(is),
+         encoding_iconv_(fixedenc.empty() ? "UTF-8" : fixedenc),
+         theCatcodesType_(NORMAL_CATCODES), curr_cat_(UNDECIDED_CATCODES),
+         fixed_enc_(!fixedenc.empty())
 {
+       if (fixed_enc_)
+               is_.setEncoding(fixedenc);
 }
 
 
@@ -169,7 +169,9 @@ Parser::Parser(string const & s)
        : lineno_(0), pos_(0),
          iss_(new idocstringstream(from_utf8(s))), is_(*iss_),
          encoding_iconv_("UTF-8"),
-         theCatcodesType_(NORMAL_CATCODES), curr_cat_(UNDECIDED_CATCODES)
+         theCatcodesType_(NORMAL_CATCODES), curr_cat_(UNDECIDED_CATCODES),
+         // An idocstringstream can not change the encoding
+         fixed_enc_(true)
 {
 }
 
@@ -186,7 +188,7 @@ void Parser::deparse()
        for(size_type i = pos_ ; i < tokens_.size() ; ++i) {
                s += tokens_[i].asInput();
        }
-       is_.put_almost_back(from_utf8(s));
+       is_.putback(from_utf8(s));
        tokens_.erase(tokens_.begin() + pos_, tokens_.end());
        // make sure that next token is read
        tokenize_one();
@@ -265,7 +267,13 @@ bool Parser::setEncoding(std::string const & e)
 {
        //cerr << "setting encoding to " << e << std::endl;
        encoding_iconv_ = e;
-       return is_.setEncoding(e);
+       // If the encoding is fixed, we must not change the stream encoding
+       // (because the whole input uses that encoding, e.g. if it comes from
+       // the clipboard). We still need to track the original encoding in
+       // encoding_iconv_, so that the generated output is correct.
+       if (!fixed_enc_)
+               is_.setEncoding(e);
+       return true;
 }
 
 
@@ -311,11 +319,10 @@ Token const Parser::next_next_token()
                return dummy;
        // If tokenize_one() has not been called after the last get_token() we
        // need to tokenize two more tokens.
-       if (pos_ >= tokens_.size()) {
+       if (pos_ >= tokens_.size())
+               tokenize_one();
+       if (pos_ + 1 >= tokens_.size())
                tokenize_one();
-               if (pos_ + 1 >= tokens_.size())
-                       tokenize_one();
-       }
        return pos_ + 1 < tokens_.size() ? tokens_[pos_ + 1] : dummy;
 }
 
@@ -425,6 +432,13 @@ void Parser::popPosition()
 {
        pos_ = positions_.back();
        positions_.pop_back();
+       deparse();
+}
+
+
+void Parser::dropPosition()
+{
+       positions_.pop_back();
 }
 
 
@@ -623,11 +637,12 @@ string const Parser::plainCommand(char left, char right, string const & name)
 }
 
 
-string const Parser::verbatimStuff(string const & end_string)
+Parser::Arg Parser::verbatimStuff(string const & end_string, bool const allow_linebreak)
 {
        if (!good())
-               return string();
+               return Arg(false, string());
 
+       pushPosition();
        ostringstream oss;
        size_t match_index = 0;
        setCatcodes(VERBATIM_CATCODES);
@@ -638,22 +653,38 @@ string const Parser::verbatimStuff(string const & end_string)
                        match_index += t.asInput().length();
                        if (match_index >= end_string.length())
                                break;
-               } else if (match_index) {
-                       oss << end_string.substr(0, match_index) << t.asInput();
-                       match_index = 0;
-               } else
-                       oss << t.asInput();
+               } else {
+                       if (!allow_linebreak && t.asInput() == "\n") {
+                               cerr << "unexpected end of input" << endl;
+                               popPosition();
+                               setCatcodes(NORMAL_CATCODES);
+                               return Arg(false, string());
+                       }
+                       if (match_index) {
+                               oss << end_string.substr(0, match_index) 
+                                   << t.asInput();
+                               match_index = 0;
+                       } else
+                               oss << t.asInput();
+               }
        }
-       setCatcodes(NORMAL_CATCODES);
-       if (!good())
+
+       if (!good()) {
                cerr << "unexpected end of input" << endl;
-       return oss.str();
+               popPosition();
+               setCatcodes(NORMAL_CATCODES);
+               return Arg(false, string());
+       }
+       setCatcodes(NORMAL_CATCODES);
+       dropPosition();
+       return Arg(true, oss.str());
 }
 
 
 string const Parser::verbatimEnvironment(string const & name)
 {
-       string s = verbatimStuff("\\end{" + name + "}");
+       //FIXME: do something if endstring is not found
+       string s = verbatimStuff("\\end{" + name + "}").second;
        // ignore one newline at beginning or end of string
        if (prefixIs(s, "\n"))
                s.erase(0,1);
@@ -673,7 +704,7 @@ string Parser::verbatimOption()
                                putback();
                                res += '{' + verbatim_item() + '}';
                        } else
-                               res += t.cs();
+                               res += t.asInput();
                }
        }
        return res;