json_parser.y 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. %require "3.0"
  2. %code top {
  3. /*
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Jakub Zelenka <bukka@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "php_json.h"
  20. #include "php_json_parser.h"
  21. #define YYDEBUG 0
  22. #if YYDEBUG
  23. int json_yydebug = 1;
  24. #endif
  25. #ifdef _MSC_VER
  26. #define YYMALLOC malloc
  27. #define YYFREE free
  28. #endif
  29. #define PHP_JSON_DEPTH_DEC --parser->depth
  30. #define PHP_JSON_DEPTH_INC \
  31. if (parser->max_depth && parser->depth >= parser->max_depth) { \
  32. parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
  33. YYERROR; \
  34. } \
  35. ++parser->depth
  36. }
  37. %define api.prefix {php_json_yy}
  38. %define api.pure full
  39. %param { php_json_parser *parser }
  40. %union {
  41. zval value;
  42. }
  43. %token <value> PHP_JSON_T_NUL
  44. %token <value> PHP_JSON_T_TRUE
  45. %token <value> PHP_JSON_T_FALSE
  46. %token <value> PHP_JSON_T_INT
  47. %token <value> PHP_JSON_T_DOUBLE
  48. %token <value> PHP_JSON_T_STRING
  49. %token <value> PHP_JSON_T_ESTRING
  50. %token PHP_JSON_T_EOI
  51. %token PHP_JSON_T_ERROR
  52. %type <value> start object key value array
  53. %type <value> members member elements element
  54. %destructor { zval_ptr_dtor_nogc(&$$); } <value>
  55. %code {
  56. static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
  57. static void php_json_yyerror(php_json_parser *parser, char const *msg);
  58. static int php_json_parser_array_create(php_json_parser *parser, zval *array);
  59. static int php_json_parser_object_create(php_json_parser *parser, zval *array);
  60. }
  61. %% /* Rules */
  62. start:
  63. value PHP_JSON_T_EOI
  64. {
  65. ZVAL_COPY_VALUE(&$$, &$1);
  66. ZVAL_COPY_VALUE(parser->return_value, &$1);
  67. YYACCEPT;
  68. }
  69. ;
  70. object:
  71. '{'
  72. {
  73. PHP_JSON_DEPTH_INC;
  74. if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
  75. YYERROR;
  76. }
  77. }
  78. members object_end
  79. {
  80. ZVAL_COPY_VALUE(&$$, &$3);
  81. PHP_JSON_DEPTH_DEC;
  82. if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &$$)) {
  83. YYERROR;
  84. }
  85. }
  86. ;
  87. object_end:
  88. '}'
  89. | ']'
  90. {
  91. parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
  92. YYERROR;
  93. }
  94. ;
  95. members:
  96. %empty
  97. {
  98. if ((parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) && parser->methods.object_create == php_json_parser_object_create) {
  99. ZVAL_EMPTY_ARRAY(&$$);
  100. } else {
  101. parser->methods.object_create(parser, &$$);
  102. }
  103. }
  104. | member
  105. ;
  106. member:
  107. key ':' value
  108. {
  109. parser->methods.object_create(parser, &$$);
  110. if (parser->methods.object_update(parser, &$$, Z_STR($1), &$3) == FAILURE) {
  111. YYERROR;
  112. }
  113. }
  114. | member ',' key ':' value
  115. {
  116. if (parser->methods.object_update(parser, &$1, Z_STR($3), &$5) == FAILURE) {
  117. YYERROR;
  118. }
  119. ZVAL_COPY_VALUE(&$$, &$1);
  120. }
  121. ;
  122. array:
  123. '['
  124. {
  125. PHP_JSON_DEPTH_INC;
  126. if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
  127. YYERROR;
  128. }
  129. }
  130. elements array_end
  131. {
  132. ZVAL_COPY_VALUE(&$$, &$3);
  133. PHP_JSON_DEPTH_DEC;
  134. if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &$$)) {
  135. YYERROR;
  136. }
  137. }
  138. ;
  139. array_end:
  140. ']'
  141. | '}'
  142. {
  143. parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
  144. YYERROR;
  145. }
  146. ;
  147. elements:
  148. %empty
  149. {
  150. if (parser->methods.array_create == php_json_parser_array_create) {
  151. ZVAL_EMPTY_ARRAY(&$$);
  152. } else {
  153. parser->methods.array_create(parser, &$$);
  154. }
  155. }
  156. | element
  157. ;
  158. element:
  159. value
  160. {
  161. parser->methods.array_create(parser, &$$);
  162. parser->methods.array_append(parser, &$$, &$1);
  163. }
  164. | element ',' value
  165. {
  166. parser->methods.array_append(parser, &$1, &$3);
  167. ZVAL_COPY_VALUE(&$$, &$1);
  168. }
  169. ;
  170. key:
  171. PHP_JSON_T_STRING
  172. | PHP_JSON_T_ESTRING
  173. ;
  174. value:
  175. object
  176. | array
  177. | PHP_JSON_T_STRING
  178. | PHP_JSON_T_ESTRING
  179. | PHP_JSON_T_INT
  180. | PHP_JSON_T_DOUBLE
  181. | PHP_JSON_T_NUL
  182. | PHP_JSON_T_TRUE
  183. | PHP_JSON_T_FALSE
  184. ;
  185. %% /* Functions */
  186. static int php_json_parser_array_create(php_json_parser *parser, zval *array)
  187. {
  188. array_init(array);
  189. return SUCCESS;
  190. }
  191. static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
  192. {
  193. zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
  194. return SUCCESS;
  195. }
  196. static int php_json_parser_object_create(php_json_parser *parser, zval *object)
  197. {
  198. if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
  199. array_init(object);
  200. } else {
  201. object_init(object);
  202. }
  203. return SUCCESS;
  204. }
  205. static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
  206. {
  207. /* if JSON_OBJECT_AS_ARRAY is set */
  208. if (Z_TYPE_P(object) == IS_ARRAY) {
  209. zend_symtable_update(Z_ARRVAL_P(object), key, zvalue);
  210. } else {
  211. if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') {
  212. parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
  213. zend_string_release_ex(key, 0);
  214. zval_ptr_dtor_nogc(zvalue);
  215. zval_ptr_dtor_nogc(object);
  216. return FAILURE;
  217. }
  218. zend_std_write_property(Z_OBJ_P(object), key, zvalue, NULL);
  219. Z_TRY_DELREF_P(zvalue);
  220. }
  221. zend_string_release_ex(key, 0);
  222. return SUCCESS;
  223. }
  224. static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
  225. {
  226. int token = php_json_scan(&parser->scanner);
  227. value->value = parser->scanner.value;
  228. return token;
  229. }
  230. static void php_json_yyerror(php_json_parser *parser, char const *msg)
  231. {
  232. if (!parser->scanner.errcode) {
  233. parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
  234. }
  235. }
  236. PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
  237. {
  238. return parser->scanner.errcode;
  239. }
  240. static const php_json_parser_methods default_parser_methods =
  241. {
  242. php_json_parser_array_create,
  243. php_json_parser_array_append,
  244. NULL,
  245. NULL,
  246. php_json_parser_object_create,
  247. php_json_parser_object_update,
  248. NULL,
  249. NULL,
  250. };
  251. PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
  252. zval *return_value,
  253. const char *str,
  254. size_t str_len,
  255. int options,
  256. int max_depth,
  257. const php_json_parser_methods *parser_methods)
  258. {
  259. memset(parser, 0, sizeof(php_json_parser));
  260. php_json_scanner_init(&parser->scanner, str, str_len, options);
  261. parser->depth = 1;
  262. parser->max_depth = max_depth;
  263. parser->return_value = return_value;
  264. memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
  265. }
  266. PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
  267. zval *return_value,
  268. const char *str,
  269. size_t str_len,
  270. int options,
  271. int max_depth)
  272. {
  273. php_json_parser_init_ex(
  274. parser,
  275. return_value,
  276. str,
  277. str_len,
  278. options,
  279. max_depth,
  280. &default_parser_methods);
  281. }
  282. PHP_JSON_API int php_json_parse(php_json_parser *parser)
  283. {
  284. return php_json_yyparse(parser);
  285. }