THRIFT-153. Proper handling of strings with escapes (in IDL)

- Recognize and parse escape characters in .thrift files.
- Escape strings used as constants in generated source files.


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@758922 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/thriftl.ll b/compiler/cpp/src/thriftl.ll
index 0b4e960..a700ca3 100644
--- a/compiler/cpp/src/thriftl.ll
+++ b/compiler/cpp/src/thriftl.ll
@@ -14,6 +14,7 @@
 
 %{
 
+#include <string>
 #include <errno.h>
 
 #include "main.h"
@@ -58,10 +59,8 @@
 comment       ("//"[^\n]*)
 unixcomment   ("#"[^\n]*)
 symbol        ([:;\,\{\}\(\)\=<>\[\]])
-dliteral      ("\""[^"]*"\"")
-sliteral      ("'"[^']*"'")
 st_identifier ([a-zA-Z-][\.a-zA-Z_0-9-]*)
-
+literal_begin (['\"])
 
 %%
 
@@ -222,17 +221,56 @@
   return tok_st_identifier;
 }
 
-{dliteral} {
-  yylval.id = strdup(yytext+1);
-  yylval.id[strlen(yylval.id)-1] = '\0';
-  return tok_literal;
+{literal_begin} {
+  char mark = yytext[0];
+  std::string result;
+  for(;;)
+  {
+    int ch = yyinput();
+    switch (ch) {
+      case EOF:
+        yyerror("End of file while read string at %d\n", yylineno);
+        exit(1);
+      case '\n':
+        yyerror("End of line while read string at %d\n", yylineno - 1);
+        exit(1);
+      case '\\':
+        ch = yyinput();
+        switch (ch) {
+          case 'r':
+            result.push_back('\r');
+            continue;
+          case 'n':
+            result.push_back('\n');
+            continue;
+          case 't':
+            result.push_back('\t');
+            continue;
+          case '"':
+            result.push_back('"');
+            continue;
+          case '\'':
+            result.push_back('\'');
+            continue;
+          case '\\':
+            result.push_back('\\');
+            continue;
+          default:
+            yyerror("Bad escape character\n");
+            return -1;
+        }
+        break;
+      default:
+        if (ch == mark) {
+          yylval.id = strdup(result.c_str());
+          return tok_literal;
+        } else {
+          result.push_back(ch);
+        }
+    }
+  }
 }
 
-{sliteral} {
-  yylval.id = strdup(yytext+1);
-  yylval.id[strlen(yylval.id)-1] = '\0';
-  return tok_literal;
-}
 
 {doctext} {
  /* This does not show up in the parse tree. */