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