phpdbg_parser.y 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. %require "3.0"
  2. /*
  3. * phpdbg_parser.y
  4. * (from php-src root)
  5. */
  6. %code requires {
  7. #include "phpdbg.h"
  8. #ifndef YY_TYPEDEF_YY_SCANNER_T
  9. #define YY_TYPEDEF_YY_SCANNER_T
  10. typedef void* yyscan_t;
  11. #endif
  12. }
  13. %code {
  14. #include "phpdbg_cmd.h"
  15. #include "phpdbg_utils.h"
  16. #include "phpdbg_cmd.h"
  17. #include "phpdbg_prompt.h"
  18. #include "phpdbg_parser.h"
  19. #include "phpdbg_lexer.h"
  20. #undef yyerror
  21. static int yyerror(const char *msg);
  22. ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  23. #ifdef _MSC_VER
  24. #define YYMALLOC malloc
  25. #define YYFREE free
  26. #endif
  27. }
  28. %define api.prefix {phpdbg_}
  29. %define api.pure full
  30. %define api.value.type {phpdbg_param_t}
  31. %define parse.error verbose
  32. %token END 0 "end of command"
  33. %token T_EVAL "eval"
  34. %token T_RUN "run"
  35. %token T_SHELL "shell"
  36. %token T_IF "if (condition)"
  37. %token T_TRUTHY "truthy (true, on, yes or enabled)"
  38. %token T_FALSY "falsy (false, off, no or disabled)"
  39. %token T_STRING "string (some input, perhaps)"
  40. %token T_COLON ": (colon)"
  41. %token T_DCOLON ":: (double colon)"
  42. %token T_POUND "# (pound sign followed by digits)"
  43. %token T_SEPARATOR "# (pound sign)"
  44. %token T_PROTO "protocol (file://)"
  45. %token T_DIGITS "digits (numbers)"
  46. %token T_LITERAL "literal (string)"
  47. %token T_ADDR "address"
  48. %token T_OPCODE "opcode"
  49. %token T_ID "identifier (command or function name)"
  50. %token T_INPUT "input (input string or data)"
  51. %token T_UNEXPECTED "input"
  52. %token T_REQ_ID "request id (-r %d)"
  53. %% /* Rules */
  54. input
  55. : command { $$ = $1; }
  56. | input T_SEPARATOR command { phpdbg_stack_separate($1.top); $$ = $3; }
  57. | %empty
  58. ;
  59. command
  60. : parameters { $$.top = PHPDBG_G(parser_stack)->top; }
  61. | full_expression { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); $$.top = PHPDBG_G(parser_stack)->top; }
  62. ;
  63. parameters
  64. : parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); $$.top = PHPDBG_G(parser_stack)->top; }
  65. | parameters parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$2); $$.top = PHPDBG_G(parser_stack)->top; }
  66. | parameters T_REQ_ID { $$ = $1; PHPDBG_G(req_id) = $2.num; }
  67. ;
  68. parameter
  69. : T_ID T_COLON T_DIGITS {
  70. $$.type = FILE_PARAM;
  71. $$.file.name = $2.str;
  72. $$.file.line = $3.num;
  73. }
  74. | T_ID T_COLON T_POUND T_DIGITS {
  75. $$.type = NUMERIC_FILE_PARAM;
  76. $$.file.name = $1.str;
  77. $$.file.line = $4.num;
  78. }
  79. | T_PROTO T_ID T_COLON T_DIGITS {
  80. $$.type = FILE_PARAM;
  81. $$.file.name = malloc($1.len + $2.len + 1);
  82. if ($$.file.name) {
  83. memcpy(&$$.file.name[0], $1.str, $1.len);
  84. memcpy(&$$.file.name[$1.len], $2.str, $2.len);
  85. $$.file.name[$1.len + $2.len] = '\0';
  86. }
  87. $$.file.line = $4.num;
  88. }
  89. | T_PROTO T_ID T_COLON T_POUND T_DIGITS {
  90. $$.type = NUMERIC_FILE_PARAM;
  91. $$.file.name = malloc($1.len + $2.len + 1);
  92. if ($$.file.name) {
  93. memcpy(&$$.file.name[0], $1.str, $1.len);
  94. memcpy(&$$.file.name[$1.len], $2.str, $2.len);
  95. $$.file.name[$1.len + $2.len] = '\0';
  96. }
  97. $$.file.line = $5.num;
  98. }
  99. | T_ID T_DCOLON T_ID {
  100. $$.type = METHOD_PARAM;
  101. $$.method.class = $1.str;
  102. $$.method.name = $3.str;
  103. }
  104. | T_ID T_DCOLON T_ID T_POUND T_DIGITS {
  105. $$.type = NUMERIC_METHOD_PARAM;
  106. $$.method.class = $1.str;
  107. $$.method.name = $3.str;
  108. $$.num = $5.num;
  109. }
  110. | T_ID T_POUND T_DIGITS {
  111. $$.type = NUMERIC_FUNCTION_PARAM;
  112. $$.str = $1.str;
  113. $$.len = $1.len;
  114. $$.num = $3.num;
  115. }
  116. | T_IF T_INPUT {
  117. $$.type = COND_PARAM;
  118. $$.str = $2.str;
  119. $$.len = $2.len;
  120. }
  121. | T_OPCODE { $$ = $1; }
  122. | T_ADDR { $$ = $1; }
  123. | T_LITERAL { $$ = $1; }
  124. | T_TRUTHY { $$ = $1; }
  125. | T_FALSY { $$ = $1; }
  126. | T_DIGITS { $$ = $1; }
  127. | T_ID { $$ = $1; }
  128. ;
  129. req_id
  130. : T_REQ_ID { PHPDBG_G(req_id) = $1.num; }
  131. | %empty
  132. ;
  133. full_expression
  134. : T_EVAL req_id T_INPUT {
  135. $$.type = EVAL_PARAM;
  136. $$.str = $3.str;
  137. $$.len = $3.len;
  138. }
  139. | T_SHELL req_id T_INPUT {
  140. $$.type = SHELL_PARAM;
  141. $$.str = $3.str;
  142. $$.len = $3.len;
  143. }
  144. | T_RUN req_id {
  145. $$.type = RUN_PARAM;
  146. $$.len = 0;
  147. }
  148. | T_RUN req_id T_INPUT {
  149. $$.type = RUN_PARAM;
  150. $$.str = $3.str;
  151. $$.len = $3.len;
  152. }
  153. ;
  154. %%
  155. static int yyerror(const char *msg) {
  156. phpdbg_error("Parse Error: %s", msg);
  157. {
  158. const phpdbg_param_t *top = PHPDBG_G(parser_stack);
  159. while (top) {
  160. phpdbg_param_debug(top, "--> ");
  161. top = top->next;
  162. }
  163. }
  164. return 0;
  165. }
  166. int phpdbg_do_parse(phpdbg_param_t *stack, char *input) {
  167. if (!*input) {
  168. return 0;
  169. }
  170. if (PHPDBG_G(cur_command)) {
  171. free(PHPDBG_G(cur_command));
  172. }
  173. PHPDBG_G(cur_command) = strdup(input);
  174. phpdbg_init_lexer(stack, input);
  175. return yyparse();
  176. }