1
+ <?php
2
+ /**
3
+ * Enter description here...
4
+ *
5
+ * @package aowp.parser
6
+ */
7
+ //
8
+ // +----------------------------------------------------------------------+
9
+ // | PHP_Parser |
10
+ // +----------------------------------------------------------------------+
11
+ // | Copyright (c) 1997-2004 The PHP Group |
12
+ // +----------------------------------------------------------------------+
13
+ // | This source file is subject to version 3.0 of the PHP license, |
14
+ // | that is bundled with this package in the file LICENSE, and is |
15
+ // | available through the world-wide-web at the following url: |
16
+ // | http://www.php.net/license/3_0.txt. |
17
+ // | If you did not receive a copy of the PHP license and are unable to |
18
+ // | obtain it through the world-wide-web, please send a note to |
19
+ // | [email protected] so we can mail you a copy immediately. |
20
+ // +----------------------------------------------------------------------+
21
+ // | Authors: Greg Beaver <[email protected] > |
22
+ // | Alan Knowles <[email protected] > |
23
+ // +----------------------------------------------------------------------+
24
+ //
25
+ // $Id: Parser.php,v 1.12 2007/02/21 20:41:54 cellog Exp $
26
+ //
27
+
28
+ /*
29
+ * usage :
30
+ * print_r(PHP_Parser::staticParseFile($filename));
31
+ */
32
+
33
+ //require_once 'System.php';
34
+ // this will be used if the package is approved in PEAR
35
+ //require_once 'Error/Stack.php';
36
+ //require_once 'PEAR/ErrorStack.php';
37
+
38
+ define ('PHP_PARSER_ERROR_NODRIVER ' , 1 );
39
+ define ('PHP_PARSER_ERROR_NOTINITIALIZED ' , 2 );
40
+ define ('PHP_PARSER_ERROR_NOINPUT ' , 3 );
41
+
42
+ /**
43
+ * Enter description here...
44
+ *
45
+ * @package aowp.parser.template
46
+ */
47
+
48
+ class PHP_Parser {
49
+ const ERROR_NODRIVER = 1 ;
50
+ const ERROR_NOTINITIALIZED = 2 ;
51
+ const ERROR_NOINPUT = 3 ;
52
+ var $ _parser ;
53
+ var $ _tokenizer ;
54
+
55
+ /**
56
+ * Choose the parser and tokenizer
57
+ * @static
58
+ * @return PHP_Parser
59
+ */
60
+ function factory ($ parser ='Core ' , $ tokenizer ='' )
61
+ {
62
+ $ ret = new PHP_Parser ;
63
+ $ ret ->setParser ($ parser );
64
+ $ ret ->setTokenizer ($ tokenizer );
65
+ return $ ret ;
66
+ }
67
+
68
+ /**
69
+ * @param string|object
70
+ * @return bool
71
+ * @throws PHP_Parser_Exception
72
+ */
73
+ function setParser ($ parser ='Core ' )
74
+ {
75
+ if (is_object ($ parser )) {
76
+ $ this ->_parser = $ parser ;
77
+ return false ;
78
+ }
79
+
80
+
81
+
82
+ if (!class_exists ($ parser )) {
83
+ if ($ this ->isIncludeable ('PHP/Parser/ ' . $ parser . '.php ' )) {
84
+ include_once 'PHP/Parser/ ' . $ parser . '.php ' ;
85
+ }
86
+ if (!class_exists ('PHP_Parser_ ' . $ parser )) {
87
+ throw $ this ->raiseError ("no parser driver \"$ parser \" found " ,
88
+ self ::ERROR_NODRIVER , array ('driver ' => $ parser ,
89
+ 'type ' => 'parse ' ));
90
+ }
91
+ $ parser = "PHP_Parser_ $ parser " ;
92
+ }
93
+ $ this ->_parser = new $ parser ;
94
+ return true ;
95
+ }
96
+
97
+ /**
98
+ * @param string|object
99
+ * @return PEAR_Error|false
100
+ */
101
+ function setTokenizer ($ tokenizer ='' )
102
+ {
103
+ if (is_object ($ tokenizer )) {
104
+ $ this ->_tokenizer = $ tokenizer ;
105
+ return false ;
106
+ }
107
+ if ($ tokenizer =='' ) {
108
+ $ tokenizer = 'PHP_Parser_Tokenizer ' ;
109
+ include_once 'Parser/Tokenizer.php ' ;
110
+ $ this ->_tokenizer = new $ tokenizer ('' ,array ('parser_class ' =>get_class ($ this ->_parser )));
111
+ return false ;
112
+ }
113
+
114
+ if (!class_exists ('PHP_Parser_Tokenizer_ ' .$ tokenizer )) {
115
+ if ($ this ->isIncludeable ('PHP/Parser/Tokenizer/ ' . $ tokenizer . '.php ' )) {
116
+ include_once 'PHP/Parser/Tokenizer/ ' . $ tokenizer . '.php ' ;
117
+ }
118
+ if (!class_exists ('PHP_Parser_Tokenizer_ ' . $ tokenizer )) {
119
+ return $ this ->raiseError ("no tokenizer driver \"$ tokenizer \" found " ,
120
+ self ::ERROR_NODRIVER , array ('driver ' => $ tokenizer ,
121
+ 'type ' => 'tokenize ' ));
122
+ }
123
+ $ tokenizer = "PHP_Parser_Tokenizer_ $ tokenizer " ;
124
+ }
125
+ $ this ->_tokenizer = new $ tokenizer ;
126
+ return false ;
127
+ }
128
+
129
+ /**
130
+ * @param string input to parse
131
+ * @param array options for the tokenizer
132
+ * @return PEAR_Error|false
133
+ */
134
+ function setTokenizerOptions ($ php , $ options = array ())
135
+ {
136
+ if (is_object ($ this ->_tokenizer )) {
137
+ $ this ->_tokenizer ->setOptions ($ php , $ options );
138
+ return false ;
139
+ }
140
+ return $ this ->raiseError ("tokenizer must be initialized before setTokenizerOptions " ,
141
+ PHP_PARSER_ERROR_NOTINITIALIZED );
142
+ }
143
+
144
+ function raiseError ($ msg , $ code , $ params = array ())
145
+ {
146
+ return PEAR_ErrorStack::staticPush ('PHP_Parser ' , $ code ,
147
+ 'exception ' , $ params , $ msg );
148
+ }
149
+
150
+ /**
151
+ * @param string $path relative or absolute include path
152
+ * @return boolean
153
+ * @static
154
+ */
155
+ function isIncludeable ($ path )
156
+ {
157
+ if (file_exists ($ path ) && is_readable ($ path )) {
158
+ return true ;
159
+ }
160
+ $ ipath = explode (DIRECTORY_SEPARATOR , ini_get ('include_path ' ));
161
+ foreach ($ ipath as $ include ) {
162
+ $ test = realpath ($ include . DIRECTORY_SEPARATOR . $ path );
163
+ if (file_exists ($ test ) && is_readable ($ test )) {
164
+ return true ;
165
+ }
166
+ }
167
+ return false ;
168
+ }
169
+
170
+ /**
171
+ * Parse a file with wddx caching options.
172
+ *
173
+ * parses a php file,
174
+ * @param string name of file to parse
175
+ * @param false|string false = no caching, '' = write to same directory, '/some/dir/' - cache directory
176
+ *
177
+ * @return array| object PEAR_Error should return an array of includes and classes.. will grow...
178
+ * @access public
179
+ */
180
+ static function &staticParseFile (
181
+ $ file ,
182
+ $ options = array (),
183
+ $ tokenizeroptions = array (),
184
+ $ tokenizerClass = 'PHP_Parser_Tokenizer ' ,
185
+ $ cacheDir =false
186
+ )
187
+ {
188
+ if ($ cacheDir === false ) {
189
+ return self ::parse (file_get_contents ($ file ), $ options , $ tokenizeroptions , $ tokenizerClass );
190
+ }
191
+ if (!strlen ($ cacheDir )) {
192
+ $ cacheFile = dirname ($ file ).'/.PHP_Parser/ ' . basename ($ file ) . '.wddx ' ;
193
+ } else {
194
+ $ cacheFile = $ cacheDir . $ file . '.wddx ' ;
195
+ }
196
+ if (!file_exists (dirname ($ cacheFile ))) {
197
+ System::mkdir (dirname ($ cacheFile ) ." -p " );
198
+ }
199
+
200
+ //echo "Cache = $cacheFile\n";
201
+ if (file_exists ($ cacheFile ) && (filemtime ($ cacheFile ) > filemtime ($ file ))) {
202
+ //echo "get cache";
203
+ return wddx_deserialize (file_get_contents ($ cacheFile ));
204
+ }
205
+
206
+ // this whole caching needs a much nicer logic to it..
207
+ // but for the time being test the filename as md5 in /tmp/
208
+ $ tmpCacheFile = '/tmp/ ' .md5 ($ file ).'.wddx ' ;
209
+ if (file_exists ($ tmpCacheFile ) && (filemtime ($ tmpCacheFile ) > filemtime ($ file ))) {
210
+ //echo "get cache";
211
+ return wddx_deserialize (file_get_contents ($ tmpCacheFile ));
212
+ }
213
+
214
+ $ result = &PHP_Parser::parse (file_get_contents ($ file ), $ options , $ tokenizeroptions , $ tokenizerClass );
215
+ if (function_exists ('wddx_set_indent ' )) {
216
+ wddx_set_indent (2 );
217
+ }
218
+ //echo "Writing Cache = $cacheFile\n";
219
+ $ fh = @fopen ($ cacheFile ,'w ' );
220
+ if (!$ fh ) {
221
+ $ fh = fopen ($ tmpCacheFile ,'w ' );
222
+ }
223
+ fwrite ($ fh ,wddx_serialize_value ($ result ));
224
+ fclose ($ fh );
225
+ return $ result ;
226
+ }
227
+
228
+
229
+ /**
230
+ * Parse a string
231
+ *
232
+ * parses a php file,
233
+ *
234
+ *
235
+ * @param string name of file to parse
236
+ *
237
+ *
238
+ * @return array| object PEAR_Error should return an array of includes and classes.. will grow...
239
+ * @access public
240
+ */
241
+
242
+
243
+ static function &parse (
244
+ $ string ,
245
+ $ options = array (),
246
+ $ tokenizeroptions = array (),
247
+ $ tokenizerClass = 'PHP_Parser_Tokenizer ' )
248
+ {
249
+ /*
250
+ if (!trim($string)) {
251
+ throw new Exception('Nothing to parse');
252
+ }
253
+ */
254
+
255
+ if (($ tokenizerClass == 'PHP_Parser_Tokenizer ' ) && !class_exists ($ tokenizerClass )) {
256
+ require_once 'Parser/Tokenizer.php ' ;
257
+ }
258
+
259
+ $ yyInput = new $ tokenizerClass ($ string , $ tokenizeroptions );
260
+ //$yyInput->setOptions($string, $tokenizeroptions);
261
+ //xdebug_start_profiling();
262
+ $ t = new PHP_Parser_Core ($ yyInput );
263
+ while ($ yyInput ->advance ()) {
264
+ $ t ->doParse ($ yyInput ->token , $ yyInput ->getValue (), $ yyInput );
265
+ }
266
+ $ t ->doParse (0 , 0 );
267
+
268
+ return $ t ;
269
+ }
270
+
271
+ function parseString ($ php , $ tokenoptions = array ())
272
+ {
273
+ $ string = $ php ;
274
+ if (!trim ($ string )) {
275
+ throw new Exception ('Nothing to parse ' );
276
+ }
277
+ $ this ->setTokenizerOptions ($ php , $ tokenoptions );
278
+ $ err = $ this ->_parser ->yyparse ($ this ->_tokenizer );
279
+ // some parser do not set stuff like this..
280
+ if ($ err ) {
281
+ return $ err ;
282
+ }
283
+ if (!isset ($ this ->_parser ->classes )) {
284
+ return ;
285
+ }
286
+
287
+ return array (
288
+ 'classes ' => $ this ->_parser ->classes ,
289
+ 'interfaces ' => $ this ->_parser ->interfaces ,
290
+ 'includes ' => $ this ->_parser ->includes ,
291
+ 'functions ' => $ this ->_parser ->functions ,
292
+ 'constants ' => $ this ->_parser ->constants ,
293
+ 'globals ' => $ this ->_parser ->globals
294
+ );
295
+ }
296
+ }
297
+
298
+ ?>
0 commit comments