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