variant_construct_string.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #include "variant.h"
  2. class VariantConstruct {
  3. enum TokenType {
  4. TK_CURLY_BRACKET_OPEN,
  5. TK_CURLY_BRACKET_CLOSE,
  6. TK_BRACKET_OPEN,
  7. TK_BRACKET_CLOSE,
  8. TK_IDENTIFIER,
  9. TK_STRING,
  10. TK_NUMBER,
  11. TK_COLON,
  12. TK_COMMA,
  13. TK_EOF,
  14. TK_MAX
  15. };
  16. enum Expecting {
  17. EXPECT_OBJECT,
  18. EXPECT_OBJECT_KEY,
  19. EXPECT_COLON,
  20. EXPECT_OBJECT_VALUE,
  21. };
  22. struct Token {
  23. TokenType type;
  24. Variant value;
  25. };
  26. static const char * tk_name[TK_MAX];
  27. static String _print_var(const Variant& p_var);
  28. static Error _get_token(const CharType *p_str,int &index, int p_len,Token& r_token,int &line,String &r_err_str);
  29. static Error _parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
  30. static Error _parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
  31. static Error _parse_dict(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
  32. public:
  33. static Error parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud);
  34. };
  35. const char * VariantConstruct::tk_name[TK_MAX] = {
  36. "'{'",
  37. "'}'",
  38. "'['",
  39. "']'",
  40. "identifier",
  41. "string",
  42. "number",
  43. "':'",
  44. "','",
  45. "EOF",
  46. };
  47. Error VariantConstruct::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_token,int &line,String &r_err_str) {
  48. while (true) {
  49. switch(p_str[idx]) {
  50. case '\n': {
  51. line++;
  52. idx++;
  53. break;
  54. };
  55. case 0: {
  56. r_token.type=TK_EOF;
  57. return OK;
  58. } break;
  59. case '{': {
  60. r_token.type=TK_CURLY_BRACKET_OPEN;
  61. idx++;
  62. return OK;
  63. };
  64. case '}': {
  65. r_token.type=TK_CURLY_BRACKET_CLOSE;
  66. idx++;
  67. return OK;
  68. };
  69. case '[': {
  70. r_token.type=TK_BRACKET_OPEN;
  71. idx++;
  72. return OK;
  73. };
  74. case ']': {
  75. r_token.type=TK_BRACKET_CLOSE;
  76. idx++;
  77. return OK;
  78. };
  79. case ':': {
  80. r_token.type=TK_COLON;
  81. idx++;
  82. return OK;
  83. };
  84. case ',': {
  85. r_token.type=TK_COMMA;
  86. idx++;
  87. return OK;
  88. };
  89. case '"': {
  90. idx++;
  91. String str;
  92. while(true) {
  93. if (p_str[idx]==0) {
  94. r_err_str="Unterminated String";
  95. return ERR_PARSE_ERROR;
  96. } else if (p_str[idx]=='"') {
  97. idx++;
  98. break;
  99. } else if (p_str[idx]=='\\') {
  100. //escaped characters...
  101. idx++;
  102. CharType next = p_str[idx];
  103. if (next==0) {
  104. r_err_str="Unterminated String";
  105. return ERR_PARSE_ERROR;
  106. }
  107. CharType res=0;
  108. switch(next) {
  109. case 'b': res=8; break;
  110. case 't': res=9; break;
  111. case 'n': res=10; break;
  112. case 'f': res=12; break;
  113. case 'r': res=13; break;
  114. case '\"': res='\"'; break;
  115. case '\\': res='\\'; break;
  116. case '/': res='/'; break; //wtf
  117. case 'u': {
  118. //hexnumbarh - oct is deprecated
  119. for(int j=0;j<4;j++) {
  120. CharType c = p_str[idx+j+1];
  121. if (c==0) {
  122. r_err_str="Unterminated String";
  123. return ERR_PARSE_ERROR;
  124. }
  125. if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
  126. r_err_str="Malformed hex constant in string";
  127. return ERR_PARSE_ERROR;
  128. }
  129. CharType v;
  130. if (c>='0' && c<='9') {
  131. v=c-'0';
  132. } else if (c>='a' && c<='f') {
  133. v=c-'a';
  134. v+=10;
  135. } else if (c>='A' && c<='F') {
  136. v=c-'A';
  137. v+=10;
  138. } else {
  139. ERR_PRINT("BUG");
  140. v=0;
  141. }
  142. res<<=4;
  143. res|=v;
  144. }
  145. idx+=4; //will add at the end anyway
  146. } break;
  147. default: {
  148. r_err_str="Invalid escape sequence";
  149. return ERR_PARSE_ERROR;
  150. } break;
  151. }
  152. str+=res;
  153. } else {
  154. if (p_str[idx]=='\n')
  155. line++;
  156. str+=p_str[idx];
  157. }
  158. idx++;
  159. }
  160. r_token.type=TK_STRING;
  161. r_token.value=str;
  162. return OK;
  163. } break;
  164. default: {
  165. if (p_str[idx]<=32) {
  166. idx++;
  167. break;
  168. }
  169. if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
  170. //a number
  171. const CharType *rptr;
  172. double number = String::to_double(&p_str[idx],&rptr);
  173. idx+=(rptr - &p_str[idx]);
  174. r_token.type=TK_NUMBER;
  175. r_token.value=number;
  176. return OK;
  177. } else if ((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
  178. String id;
  179. while((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
  180. id+=p_str[idx];
  181. idx++;
  182. }
  183. r_token.type=TK_IDENTIFIER;
  184. r_token.value=id;
  185. return OK;
  186. } else {
  187. r_err_str="Unexpected character.";
  188. return ERR_PARSE_ERROR;
  189. }
  190. }
  191. }
  192. }
  193. return ERR_PARSE_ERROR;
  194. }
  195. Error VariantConstruct::_parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
  196. if (token.type==TK_CURLY_BRACKET_OPEN) {
  197. Dictionary d;
  198. Error err = _parse_dict(d,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
  199. if (err)
  200. return err;
  201. value=d;
  202. return OK;
  203. } else if (token.type==TK_BRACKET_OPEN) {
  204. Array a;
  205. Error err = _parse_array(a,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
  206. if (err)
  207. return err;
  208. value=a;
  209. return OK;
  210. } else if (token.type==TK_IDENTIFIER) {
  211. String id = token.value;
  212. if (id=="true")
  213. value=true;
  214. else if (id=="false")
  215. value=false;
  216. else if (id=="null")
  217. value=Variant();
  218. else {
  219. r_err_str="Expected 'true','false' or 'null', got '"+id+"'.";
  220. return ERR_PARSE_ERROR;
  221. }
  222. return OK;
  223. } else if (token.type==TK_NUMBER) {
  224. value=token.value;
  225. return OK;
  226. } else if (token.type==TK_STRING) {
  227. value=token.value;
  228. return OK;
  229. } else {
  230. r_err_str="Expected value, got "+String(tk_name[token.type])+".";
  231. return ERR_PARSE_ERROR;
  232. }
  233. return ERR_PARSE_ERROR;
  234. }
  235. Error VariantConstruct::_parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
  236. Token token;
  237. bool need_comma=false;
  238. while(index<p_len) {
  239. Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
  240. if (err!=OK)
  241. return err;
  242. if (token.type==TK_BRACKET_CLOSE) {
  243. return OK;
  244. }
  245. if (need_comma) {
  246. if (token.type!=TK_COMMA) {
  247. r_err_str="Expected ','";
  248. return ERR_PARSE_ERROR;
  249. } else {
  250. need_comma=false;
  251. continue;
  252. }
  253. }
  254. Variant v;
  255. err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
  256. if (err)
  257. return err;
  258. array.push_back(v);
  259. need_comma=true;
  260. }
  261. return OK;
  262. }
  263. Error VariantConstruct::_parse_dict(Dictionary &dict,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
  264. bool at_key=true;
  265. Variant key;
  266. Token token;
  267. bool need_comma=false;
  268. while(index<p_len) {
  269. if (at_key) {
  270. Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
  271. if (err!=OK)
  272. return err;
  273. if (token.type==TK_CURLY_BRACKET_CLOSE) {
  274. return OK;
  275. }
  276. if (need_comma) {
  277. if (token.type!=TK_COMMA) {
  278. r_err_str="Expected '}' or ','";
  279. return ERR_PARSE_ERROR;
  280. } else {
  281. need_comma=false;
  282. continue;
  283. }
  284. }
  285. err = _parse_value(key,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
  286. if (err!=OK)
  287. return err;
  288. err = _get_token(p_str,index,p_len,token,line,r_err_str);
  289. if (err!=OK)
  290. return err;
  291. if (token.type!=TK_COLON) {
  292. r_err_str="Expected ':'";
  293. return ERR_PARSE_ERROR;
  294. }
  295. at_key=false;
  296. } else {
  297. Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
  298. if (err!=OK)
  299. return err;
  300. Variant v;
  301. err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
  302. if (err)
  303. return err;
  304. dict[key]=v;
  305. need_comma=true;
  306. at_key=true;
  307. }
  308. }
  309. return OK;
  310. }
  311. Error VariantConstruct::parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud) {
  312. const CharType *str = p_string.ptr();
  313. int idx = 0;
  314. int len = p_string.length();
  315. Token token;
  316. r_err_line=0;
  317. String aux_key;
  318. Error err = _get_token(str,idx,len,token,r_err_line,r_err_str);
  319. if (err)
  320. return err;
  321. return _parse_value(r_ret,token,str,idx,len,r_err_line,r_err_str,p_construct,p_ud);
  322. }