]> git.tdb.fi Git - libs/datafile.git/blobdiff - source/textparser.cpp
Fix EOF handling
[libs/datafile.git] / source / textparser.cpp
index 298b7cac363ebd2b75a712b2ea41d18dd17b3801..f7c830d0030ebcf5428c3c0abf06c63ba043ce60 100644 (file)
@@ -6,6 +6,7 @@ Distributed under the LGPL
 */
 
 #include <msp/strings/formatter.h>
+#include <msp/strings/utils.h>
 #include "input.h"
 #include "textparser.h"
 #include "token.h"
@@ -103,10 +104,10 @@ Statement TextParser::parse_statement(const Token *t)
 Token TextParser::parse_token()
 {
        int c=0;
-       unsigned comment=0;
+       int comment=0;
 
        // Skip over comments and whitespace
-       while(in)
+       while(in && comment>=0)
        {
                c=in.get();
                int next=in.peek();
@@ -122,11 +123,13 @@ Token TextParser::parse_token()
                else if(comment==3)   // Skip the second character of block comment end
                        comment=0;
                else if(!isspace(c) && !comment)
-                       break;
+                       comment=-1;
        }
 
-       if(comment)  // Didn't hit any non-whitespace
+       if(comment>0)  // EOF while in comment
                throw ParseError(src+": Unfinished comment at end of input", src, in.get_line_number());
+       else if(comment==0)  // Didn't hit any non-whitespace
+               return Token(Token::SPECIAL, "");
 
        enum ParseState
        {
@@ -166,7 +169,7 @@ Token TextParser::parse_token()
        string     buf;
        bool       escape=false;
 
-       while(in)
+       while(in || state==INIT)
        {
                if(state!=INIT)
                        c=in.get();
@@ -266,7 +269,16 @@ Token TextParser::parse_token()
                        if(c=='\\')
                                escape=!escape;
                        else if(c=='"' && !escape)
-                               return Token(Token::STRING, unescape_string(buf));
+                       {
+                               try
+                               {
+                                       return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
+                               }
+                               catch(const Exception &e)
+                               {
+                                       throw ParseError(format("%s: %s", get_location(), e.what()), src, in.get_line_number());
+                               }
+                       }
                        else
                                escape=false;
                        break;
@@ -297,57 +309,6 @@ bool TextParser::isodigit(int c)
        return (c>='0' && c<='7');
 }
 
-string TextParser::unescape_string(const string &str)
-{
-       string   result;
-       bool     escape=false;
-       unsigned hexcape=0;
-       for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i)
-       {
-               if(escape)
-               {
-                       if(*i=='n')
-                               result+='\n';
-                       else if(*i=='t')
-                               result+='\t';
-                       else if(*i=='\\')
-                               result+='\\';
-                       else if(*i=='"')
-                               result+='"';
-                       else if(*i=='x')
-                               hexcape=0x100;
-                       else
-                               throw ParseError(format("%s: Invalid escape sequence '\\%c'", get_location(), *i), src, in.get_line_number());
-                       escape=false;
-               }
-               else if(hexcape)
-               {
-                       unsigned digit=0;
-                       if(*i>='0' && *i<='9')
-                               digit=*i-'0';
-                       else if(*i>='a' && *i<='f')
-                               digit=*i-'a'+10;
-                       else if(*i>='A' && *i<='F')
-                               digit=*i-'A'+10;
-                       else
-                               throw ParseError(get_location()+": Invalid hex digit", src, in.get_line_number());
-
-                       hexcape=(hexcape<<4)|digit;
-                       if(hexcape&0x10000)
-                       {
-                               result+=hexcape&0xFF;
-                               hexcape=0;
-                       }
-               }
-               else if(*i=='\\')
-                       escape=true;
-               else
-                       result+=*i;
-       }
-
-       return result;
-}
-
 string TextParser::get_location()
 {
        ostringstream ss;