PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ast-parser.ss

https://bitbucket.org/grundik/php-dep-builder
Scheme | 573 lines | 378 code | 59 blank | 136 comment | 1 complexity | 761a8a15b928d6a2c003f0f3324824f6 MD5 | raw file
  1. #lang scheme
  2. ;;; Documentation
  3. ;; Requirements:
  4. ;; 1. AST in XML format should be created by phc
  5. ;; (http://www.phpcompiler.org) tool
  6. ;; 2. PLT Scheme 4.1
  7. ;; 3. it may be required to run ast-parser on php-files several times
  8. ;; for proper functions resolving, see +function-class-name+ related
  9. ;; things for details.
  10. ;; 4. input xml-file should not contain namespaces (i.e. sed -e
  11. ;; 's/AST://' should be executed on the file) because xml-match
  12. ;; raises error. NOTE: it is better not to use xml-match at all :)
  13. ;; Actually now xml-file is preprocessed and xml-match not used :)
  14. ;;
  15. ;; GLOBAL TODO:
  16. ;; 1. see TODO in the code :)
  17. ;;
  18. ;; 3. there are no variables scope:
  19. ;;
  20. ;; 3.1. example: $this->Table ($this^Table) should resolve to some
  21. ;; value for a class (e.g., for DNSZone it should be
  22. ;; DNSZoneTable). As such assignment done in cObject, it is very
  23. ;; difficult to process it automatically. So, there should be
  24. ;; some table (like for function
  25. ;; "resolve-method-invocation") to define
  26. ;; $this->smth for every class; and get-variable-definition should
  27. ;; use this table.
  28. ;;
  29. ;; 4. [partially done] built-in functions should be highlighted (and
  30. ;; there should be ability to hide them)
  31. ;;
  32. ;; 5. [partially done] WizardContext.php.log and many others - unable
  33. ;; to process "Do"
  34. ;;
  35. ;; 6. [done, bugs possible] Tooltip.php.log and many others - unable
  36. ;; to process empty method parameters (method definition)
  37. ;;
  38. ;; 7. There are no extends processing, so:
  39. ;;
  40. ;; 7.1. $this-> wronlgy resolved to the current class. Right
  41. ;; resolve may be done (actually it's a fake, but looks like it's
  42. ;; enough) the following way: if class A extends class B, and B
  43. ;; and A defines method "qwe", we should add special fake call
  44. ;; B::qwe -> A::qwe; the diagram should represent this call
  45. ;; special way (dotted line, for example); if class A extends
  46. ;; class B, and B defines method "qwe" (A has no such definition),
  47. ;; and some method of class A (e.g., A::foo) calls $this->qwe, we
  48. ;; should add special fake call A::qwe -> B::qwe, so, there will
  49. ;; be calls: A::foo -> A::qwe; A::qwe -> B::qwe. Or $this->
  50. ;; resolving should be moved to the Merge stage.
  51. ;;
  52. ;; 8. defines don't processed => some rare things may work wrong
  53. ;;; requires
  54. (require (planet lizorkin/ssax:2:0/ssax))
  55. (require (only-in (planet lizorkin/sxml:2:1/sxml) sxpath))
  56. ;;(require (only-in (planet jim/webit:1:6/xml) xml-match))
  57. (require scheme/pretty)
  58. (require scheme/match)
  59. (require scheme/path)
  60. (require "calls-record.ss")
  61. (require "php-builtin-functions-hash.ss")
  62. ;;; Auxiliary functions
  63. (define (load-xml-as-sxml filename)
  64. (with-input-from-file filename
  65. (lambda () (ssax:xml->sxml (current-input-port) '()))))
  66. (define +ast-xml-file+ (vector-ref (current-command-line-arguments) 0))
  67. (define +output-file+ (vector-ref (current-command-line-arguments) 1))
  68. (define ast-xml-file (load-xml-as-sxml +ast-xml-file+))
  69. (define +function-file-hash+ ".function-file-hash")
  70. (define *function-to-file-relations*
  71. (with-handlers ((exn? (lambda (exn) (make-immutable-hash '())))) (with-input-from-file +function-file-hash+ read)))
  72. (define +processing-php-file+ (cadar ((sxpath '(// (attr 1 (@ (equal? (key "phc.filename")))) string)) ast-xml-file)))
  73. (define (get-processing-php-file)
  74. (path->string (file-name-from-path +processing-php-file+)))
  75. (define (add-method-to-function-file-hash func-name)
  76. (set! *function-to-file-relations* (hash-set *function-to-file-relations* func-name (get-processing-php-file))))
  77. (define +top-class+ (get-processing-php-file))
  78. ;;; pattern processors backend
  79. ;;(define +top-class+ "{main}")
  80. (define +top-method+ "{top}")
  81. (define +function-class-name+ "{phpBuiltInFunctions}")
  82. (define *current-class* +top-class+)
  83. (define *current-method* +top-method+)
  84. (define *current-parent* +top-class+)
  85. (define *defined-variables* (make-hash))
  86. (define (get-current-class) *current-class*)
  87. (define (get-current-method) *current-method*)
  88. (define (set-current-class val) (set! *current-class* val))
  89. (define (set-current-method val)
  90. (display "\nSet current method: ") (display val) (display "\n") ;debug
  91. (set! *current-method* val))
  92. (define (get-current-parent) *current-parent*)
  93. (define (set-current-parent val) (set! *current-parent* val))
  94. (define (get-variable-definition a-variable-name)
  95. (let ((no-def-handler (lambda() (if (equal? a-variable-name "this")
  96. (get-current-class)
  97. (string-append "$" a-variable-name)))))
  98. (hash-ref *defined-variables* a-variable-name no-def-handler)))
  99. (define (add-variable-definition a-variable-name a-definition)
  100. (hash-set! *defined-variables* a-variable-name a-definition)
  101. (display "Variable definition added: ") (display a-variable-name) (display " => ") (display a-definition) (display "\n") ;debug
  102. )
  103. ;; normalize unheaded list to headed sxml
  104. (define (norm-l->sxml a-list)
  105. (append '(start) a-list))
  106. ;; required for xml-match to make error-reporting more useful
  107. (define (errhandler err)
  108. (let ((op (open-output-string)))
  109. (pretty-print err op)
  110. (error (format "Didn't match ~n~a~n" (get-output-string op)))))
  111. ;;;
  112. ;;
  113. (define (action-go-deep a-body)
  114. (map dispatch a-body))
  115. ;;
  116. (define processor-eval-expr action-go-deep)
  117. ;;
  118. (define (processor-class a-body)
  119. (display "\n---- class\n") (pretty-print a-body) ;;debug
  120. (let ((class-name (car ((sxpath '(CLASS_NAME value *text*)) (norm-l->sxml a-body))))
  121. (class-methods ((sxpath '(Member_list Method)) (norm-l->sxml a-body)))
  122. (a-parent ((sxpath '((CLASS_NAME 2) value *text*)) (norm-l->sxml a-body)))
  123. (normalize-parent (lambda(x) (if (null? x) "" (car x))))
  124. (old-current-class (get-current-class))
  125. (old-current-parent (get-current-parent))
  126. )
  127. (display "\n---- class methods\n") (pretty-print class-methods) ;;debug
  128. (set-current-class class-name)
  129. (set-current-parent (normalize-parent a-parent))
  130. (map dispatch class-methods)
  131. (set-current-class old-current-class)
  132. (set-current-parent old-current-parent)
  133. ))
  134. ;;
  135. (define (processor-method a-body)
  136. (display "\n---- method\n") (pretty-print a-body (current-output-port)) ;;debug
  137. (let ((method-name (car ((sxpath '(Signature METHOD_NAME value *text*)) (norm-l->sxml a-body))))
  138. (method-body (car ((sxpath '(Statement_list)) (norm-l->sxml a-body))))
  139. (method-parameters ((sxpath '(Signature Formal_parameter_list Formal_parameter)) (norm-l->sxml a-body)))
  140. (old-current-method (get-current-method))
  141. )
  142. (if (eq? (get-current-class) +top-class+)
  143. (add-method-to-function-file-hash method-name)
  144. #f)
  145. ;; (pretty-print method-body) ;debug
  146. (set-current-method method-name)
  147. ;; process method parameters to set variables to class names if specified
  148. (display "\n---- method parameters\n") (pretty-print method-parameters) ;debug
  149. (for-each
  150. (lambda(x)
  151. (display "\n---- method parameter :: \n") (pretty-print x)
  152. (let ((class-name ((sxpath '(Type CLASS_NAME value *text*)) x))
  153. (variable-name ((sxpath '(// VARIABLE_NAME value *text*)) x)))
  154. (if (and (not (null? class-name))
  155. (not (null? variable-name)))
  156. (add-variable-definition (car variable-name) (car class-name))
  157. #f)
  158. ))
  159. method-parameters)
  160. ;; parse body of the method
  161. (dispatch method-body)
  162. (set-current-method old-current-method)
  163. )
  164. )
  165. ;; bin-op -> string
  166. (define (processor-bin-op a-body)
  167. (let ((res ""))
  168. (for-each
  169. (lambda(a-part)
  170. (set! res
  171. (string-append
  172. res
  173. (let ((fmatch? (lambda(x) (eq? x (car a-part)))))
  174. (cond
  175. ((fmatch? 'attrs) "")
  176. ((fmatch? 'Variable) (get-variable-definition (processor-get-variable-name a-part)))
  177. ((fmatch? 'OP) (if (equal? (car (cdaddr a-part)) ".") "" "##FIXME_OP_processor_bin_op##"))
  178. ((fmatch? 'STRING) (car (cdaddr a-part)))
  179. (#t (error (format "Unknown processor-bin-op a-part: ~a~%" a-part))))))))
  180. a-body)
  181. res))
  182. ;;
  183. (define (generic-processor-reflection a-sxml)
  184. (if (null? a-sxml)
  185. #f
  186. ;; second child is variable name definition structure
  187. (let* ((a-body (caddar a-sxml))
  188. (fmatch? (lambda(x) (eq? x (car a-body)))))
  189. (cond
  190. ((fmatch? 'Bin_op) (processor-bin-op (cdr a-body)))
  191. ((fmatch? 'Variable) (processor-get-variable-name a-body))
  192. (#t (error (format "Unknown reflection operation type: ~a~%" a-sxml)))))))
  193. ;;
  194. (define (processor-reflection/get-variable-name a-sxml)
  195. (display "\n---- reflection get variable name\n") (pretty-print a-sxml (current-output-port)) ;;debug
  196. (generic-processor-reflection a-sxml))
  197. ;; sxml -> string
  198. (define (processor-get-variable-name a-sxml)
  199. ;; second child is variable prefix
  200. (let* ((fmatch? (lambda(x) (eq? x (caaddr a-sxml))))
  201. (variable-name-raw ((sxpath '(VARIABLE_NAME value *text*)) a-sxml))
  202. (variable-name (if (null? variable-name-raw)
  203. (processor-reflection/get-variable-name ((sxpath '(Reflection)) a-sxml))
  204. (car variable-name-raw)))
  205. )
  206. (cond
  207. ((fmatch? 'Variable) (string-append (processor-get-variable-name (caddr a-sxml)) "^" variable-name))
  208. ((fmatch? 'Target) variable-name)
  209. ((fmatch? 'Method_invocation) (resolve-method-invocation (caddr a-sxml)))
  210. ;; TODO: resolve "self" to (get-curent-class)
  211. ((fmatch? 'CLASS_NAME) (string-append (car ((sxpath '(value *text*)) (caddr a-sxml))) "^" variable-name))
  212. (#t (error (format "Unknown variable-prefix type: ~a for ~a~%" (caaddr a-sxml) a-sxml))))))
  213. ;;
  214. (define (resolve-method-invocation a-sxml)
  215. (display "\n---- resolve-method-invocation\n") (pretty-print a-sxml (current-output-port)) ;;debug
  216. (let* ((i-res (processor-method-invocation (cdr a-sxml)))
  217. (c-class (car i-res))
  218. (c-method (cdr i-res))
  219. (c-method? (lambda(x) (equal? x c-method)))
  220. (c-method-length (string-length c-method))
  221. (m? (lambda(x) (equal? x (string-append c-class "::" c-method)))))
  222. (cond
  223. ;; TODO: make the following list dynamically loaded according to
  224. ;; path of processing PHP-file
  225. ;; some special cases
  226. ((c-method? "objectMaker")
  227. ;; return first parameter because it is a class name
  228. (let ((a-class-name ((sxpath '(((Actual_parameter_list Actual_parameter) 1) STRING value *text*)) a-sxml)))
  229. (if (null? a-class-name) "##objectMaker##" (car a-class-name))))
  230. ;; smthMaker resolved to smth in most cases. Exceptions of this rule should be specified above
  231. ((and (> c-method-length 5)
  232. (equal? (substring c-method (- c-method-length 5)) "Maker"))
  233. (substring c-method 0 (- c-method-length 5)))
  234. ;; smth::getInstance resolved to smth in most cases. Exceptions of this rule should be specified above
  235. ((c-method? "getInstance") c-class)
  236. ;; TODO: now it is a hack, so, it should be rewritten to reflect c-class, not c-method only
  237. ((or (c-method? "getItemByClass")
  238. (c-method? "getParent"))
  239. "UIPointer")
  240. ;; just hardcoded class::methods resolving
  241. ((m? "Webgrind_FileHandler::getInstance") "Webgrind_FileHandler")
  242. ((m? "Webgrind_FileHandler::getTraceReader") "Webgrind_Reader")
  243. ;; if euristic doesn't found anything...
  244. (#t (string-append "##METHOD_INVOCATION##::" c-class "::" c-method)))))
  245. ;;
  246. (define (processor-reflection/get-method-name a-sxml)
  247. (display "\n---- reflection get method name\n") (pretty-print a-sxml (current-output-port)) ;;debug
  248. (generic-processor-reflection a-sxml))
  249. ;; WARNING! Performance issues may be here
  250. (define (determine-file-name-for-invoked-func func-name)
  251. (hash-ref *function-to-file-relations* func-name +top-class+))
  252. ;;
  253. (define (processor-method-invocation a-body)
  254. "Process method invocation and returns pair (string:class_name
  255. . string:method_name) which was invoked"
  256. ;; sxml -> string
  257. (local ((define (get-class-name-for-invoked-func supposed-class-name func-name)
  258. (if (equal? supposed-class-name +function-class-name+)
  259. (if (hash-ref +php-builtin-functions+ func-name #f)
  260. +function-class-name+
  261. (determine-file-name-for-invoked-func func-name)
  262. )
  263. supposed-class-name))
  264. (define (processor-get-class-name a-sxml)
  265. (let ((fmatch? (lambda(x) (eq? x (car a-sxml)))))
  266. (cond
  267. ((fmatch? 'Variable) (get-variable-definition (processor-get-variable-name a-sxml)))
  268. ((fmatch? 'Target) +function-class-name+)
  269. ((fmatch? 'CLASS_NAME)
  270. (let ((class-name (car ((sxpath '(value *text*)) a-sxml))))
  271. (cond
  272. ((equal? class-name "parent") (get-current-parent))
  273. (#t class-name))))
  274. ((fmatch? 'Method_invocation)
  275. (resolve-method-invocation a-sxml))
  276. ((fmatch? 'Reflection) ; TODO: check that here unable to be anything except variable name
  277. (processor-reflection/get-variable-name `(,a-sxml)))
  278. (#t (error (format "Unknown class-name type: ~a~%" a-sxml))))))
  279. ;; actual parameters list -> unspecified (side effect: processor-method-invocation calls)
  280. (define (processor-parameters-list a-body)
  281. (display "\n---- processor parameters list\n") (pretty-print a-body) ;;debug
  282. (let ((a-parameters ((sxpath '(Actual_parameter)) (norm-l->sxml a-body))))
  283. (display "\n---- processor parameters list :: parameters \n") (pretty-print a-parameters) ;;debug
  284. (if (null? a-parameters)
  285. #f
  286. (map dispatch a-parameters))))
  287. )
  288. (display "\n---- method invocation\n") (pretty-print a-body) ;;debug
  289. (let* ((method-name-raw ((sxpath '(METHOD_NAME value *text*)) (norm-l->sxml a-body)))
  290. (normalize-method-name car)
  291. (method-name (if (null? method-name-raw)
  292. (processor-reflection/get-method-name ((sxpath '(Reflection)) (norm-l->sxml a-body)))
  293. (normalize-method-name method-name-raw)))
  294. ;; class name of the invoking method described by second
  295. ;; element in method's AST. WARNING: if phc guys changes order
  296. ;; of the AST elements, class name processing algorithm will
  297. ;; fail.
  298. (class-name (get-class-name-for-invoked-func (processor-get-class-name (cadr a-body))
  299. method-name))
  300. )
  301. ;; add call to calls table
  302. (add-call (get-current-class)
  303. (get-current-method)
  304. class-name
  305. method-name)
  306. ;; debug
  307. (display
  308. (format "==[ ~a::~a -> ~a::~a~%"
  309. ;(format "==[ ~a__~a -> ~a__~a~%"
  310. (get-current-class)
  311. (get-current-method)
  312. class-name
  313. method-name))
  314. ;; process calls in parameter list
  315. (let (;;(old-method-name (get-current-method))
  316. ;;(old-class-name (get-current-class))
  317. (a-parameters-list ((sxpath '(Actual_parameter_list)) (norm-l->sxml a-body))))
  318. (if (null? a-parameters-list)
  319. #f
  320. (begin
  321. ;;(set-current-method method-name)
  322. ;;(set-current-class class-name)
  323. (processor-parameters-list (cdar a-parameters-list))
  324. ;;(set-current-class old-class-name)
  325. ;;(set-current-method old-method-name)
  326. )))
  327. ;; return pair class-name method-name
  328. (cons class-name method-name)
  329. )))
  330. ;; TODO: make it more correct way
  331. (define (processor-new a-body-raw)
  332. (display "\n---- processor-new\n") (pretty-print a-body-raw (current-output-port)) ;;debug
  333. (let* ((value-struct (if (list? (car a-body-raw)) (norm-l->sxml a-body-raw) a-body-raw))
  334. (a-body (cdr value-struct))
  335. (class-name-raw ((sxpath '(CLASS_NAME value *text*)) value-struct))
  336. (class-name (if (null? class-name-raw)
  337. (processor-reflection/get-class-name ((sxpath '(Reflection)) value-struct))
  338. (car class-name-raw))))
  339. (processor-method-invocation (append (list (car a-body) (cadr a-body) '(METHOD_NAME (value "__construct"))) (cddr a-body)))
  340. (processor-method-invocation (append (list (car a-body) (cadr a-body) `(METHOD_NAME (value ,class-name))) (cddr a-body)))
  341. class-name))
  342. ;;
  343. (define (processor-reflection/get-class-name a-sxml)
  344. (display "\n---- reflection get class name\n") (pretty-print a-sxml (current-output-port)) ;;debug
  345. (generic-processor-reflection a-sxml))
  346. ;; assign value to variable;
  347. ;; Note: as variables are interesting only for $qwe->asd() cases,
  348. ;; valid assigment makes sense only if value resolves to class name
  349. ;; TODO: make visibility scope
  350. (define (processor-assigment a-body)
  351. ;; sxml -> string
  352. (define (processor-get-variable-value value-struct)
  353. (display "\n---- assignment :: processor get variable value\n") (pretty-print value-struct (current-output-port)) ;;debug
  354. (let ((fmatch? (lambda(x) (eq? x (car value-struct)))))
  355. (cond
  356. ((fmatch? 'Method_invocation) (resolve-method-invocation value-struct))
  357. ((fmatch? 'Variable) (get-variable-definition (processor-get-variable-name value-struct)))
  358. ((fmatch? 'New)
  359. (processor-new value-struct))
  360. ;; other types not interesting
  361. (#t (string-append "##" (symbol->string (car value-struct)) "##")))))
  362. (display "\n---- assignment\n") (pretty-print a-body (current-output-port)) ;;debug
  363. ;; variable to assign is second child. value is last child
  364. (let ((variable-name (processor-get-variable-name (cadr a-body)))
  365. (value-struct (car ((sxpath '((*any* -1))) (norm-l->sxml a-body)))))
  366. (add-variable-definition variable-name (processor-get-variable-value value-struct)))
  367. )
  368. ;; variable to assign is second child. value is last child. so, it
  369. ;; is suitable to use just processor-assignment
  370. (define processor-op-assignment processor-assigment)
  371. ;; TODO
  372. (define (processor-list-assignment a-body)
  373. (display "\n---- list assignment\n") (pretty-print a-body (current-output-port)) ;;debug
  374. )
  375. ;;
  376. (define (processor-switch a-body)
  377. (display "\n---- switch\n") (pretty-print a-body) ;;debug
  378. (let ((list-to-process ((sxpath '(Switch_case_list Switch_case Statement_list)) (norm-l->sxml a-body)))
  379. )
  380. (display "\n---- switch-statement\n") (pretty-print list-to-process) ;;debug
  381. (map dispatch list-to-process)))
  382. ;;
  383. (define (generic-processor-statement a-body)
  384. (let ((list-to-process ((sxpath '(Statement_list)) (norm-l->sxml a-body))))
  385. (map dispatch list-to-process)))
  386. ;;
  387. (define (generic-processor-header a-body)
  388. ;; all childs from second inclusively to Statement_list exclusively
  389. ;; are header; below is dirty code, but it works...
  390. (let* ((add? #t)
  391. ;; first child is always attrs, we reject it via cdr
  392. ;; reverse required because of cons
  393. (headers (cdr (reverse (fold (lambda(x y)
  394. (if (eq? (car x) 'Statement_list) (set! add? #f) '())
  395. (if add? (cons x y) y))
  396. '()
  397. a-body)))))
  398. (map dispatch headers)))
  399. ;; ;; second child is the header
  400. ;; (dispatch (cadr a-body)))
  401. ;;
  402. (define (processor-if a-body)
  403. (display "\n---- if\n") (pretty-print a-body) ;;debug
  404. (generic-processor-header a-body)
  405. (generic-processor-statement a-body))
  406. ;;
  407. (define (processor-foreach a-body)
  408. (display "\n---- foreach\n") (pretty-print a-body) ;;debug
  409. (generic-processor-header a-body)
  410. (generic-processor-statement a-body))
  411. ;;
  412. (define (processor-for a-body)
  413. (display "\n---- for\n") (pretty-print a-body) ;;debug
  414. (generic-processor-header a-body)
  415. (generic-processor-statement a-body))
  416. ;;
  417. (define (processor-while a-body)
  418. (display "\n---- while\n") (pretty-print a-body) ;;debug
  419. (generic-processor-header a-body)
  420. (generic-processor-statement a-body))
  421. ;; TODO: inside do footer can be calls, they should be processed
  422. (define (processor-do a-body)
  423. (display "\n---- do\n") (pretty-print a-body) ;;debug
  424. (generic-processor-statement a-body))
  425. ;;
  426. (define (processor-return a-body)
  427. (display "\n---- return\n") (pretty-print a-body) ;;debug
  428. ;; the second child is the return body, and should be processed as action-go-deep
  429. (action-go-deep a-body))
  430. ;;
  431. (define (processor-try a-body)
  432. (display "\n---- try\n") (pretty-print a-body) ;;debug
  433. (generic-processor-statement a-body)
  434. ;; process catch list because it can contain method invocations
  435. (let ((catch-list (cdar ((sxpath '(Catch_list)) (norm-l->sxml a-body)))))
  436. (display "\n---- catch-list\n") (pretty-print catch-list) ;debug
  437. (map (lambda(x)
  438. (display "\n---- catch-item\n") (pretty-print x) ;debug
  439. (generic-processor-statement (cdr x)))
  440. catch-list)))
  441. ;; symbol -> function
  442. (define (processor-dispatcher fragment-type)
  443. "Determine function to parse sxml fragment according to type"
  444. (let ((fmatch? (lambda(x) (eq? fragment-type x)))
  445. (action-stop (lambda(x) '())))
  446. (cond
  447. ((fmatch? 'PHP_script) action-go-deep)
  448. ((fmatch? 'attrs) action-stop)
  449. ((fmatch? 'bool) action-stop)
  450. ((fmatch? 'Statement_list) action-go-deep)
  451. ((fmatch? 'Static_declaration) action-go-deep)
  452. ((fmatch? 'Eval_expr) processor-eval-expr)
  453. ((fmatch? 'Expr) action-go-deep)
  454. ((fmatch? 'Conditional_expr) action-go-deep)
  455. ((fmatch? 'Method) processor-method)
  456. ((fmatch? 'If) processor-if)
  457. ((fmatch? 'Assignment) processor-assigment)
  458. ((fmatch? 'Op_assignment) processor-op-assignment)
  459. ((fmatch? 'List_assignment) processor-list-assignment)
  460. ((fmatch? 'Method_invocation) processor-method-invocation)
  461. ((fmatch? 'Name_with_default_list) action-stop) ; TODO: processor should be assignment-like
  462. ((fmatch? 'Global) action-stop) ; TODO: processor should be assigment-like
  463. ((fmatch? 'Return) processor-return)
  464. ((fmatch? 'Switch) processor-switch)
  465. ((fmatch? 'Break) action-stop)
  466. ((fmatch? 'Class_def) processor-class)
  467. ((fmatch? 'Foreach) processor-foreach)
  468. ((fmatch? 'Continue) action-stop)
  469. ((fmatch? 'Throw) action-go-deep)
  470. ((fmatch? 'New) processor-new)
  471. ((fmatch? 'Nop) action-stop)
  472. ((fmatch? 'For) processor-for)
  473. ((fmatch? 'While) processor-while)
  474. ((fmatch? 'Do) processor-do)
  475. ((fmatch? 'Try) processor-try)
  476. ((fmatch? 'Ignore_errors) action-go-deep)
  477. ((fmatch? 'Bin_op) action-go-deep)
  478. ((fmatch? 'Post_op) action-stop) ; TODO: check that there unable to be methods invocations
  479. ((fmatch? 'Pre_op) action-stop) ; TODO: check that there unable to be methods invocations
  480. ((fmatch? '@) action-stop) ;TODO: check that there unable to be methods invocations
  481. ((fmatch? 'Interface_def) action-stop)
  482. ((fmatch? 'Actual_parameter) action-go-deep)
  483. ((fmatch? 'Array) action-go-deep)
  484. ((fmatch? 'Array_elem_list) action-go-deep)
  485. ((fmatch? 'Array_elem) action-go-deep)
  486. ((fmatch? 'Cast) action-go-deep)
  487. ((fmatch? 'CAST) action-go-deep) ; TODO: what is the difference between Cast and CAST?
  488. ;; the following types may appear only inside some context
  489. ;; (header is most probably place to meet they)
  490. ((fmatch? 'Variable) action-stop)
  491. ((fmatch? 'INT) action-stop)
  492. ((fmatch? 'REAL) action-stop)
  493. ((fmatch? 'OP) action-stop)
  494. ((fmatch? 'Unary_op) action-go-deep)
  495. ((fmatch? 'STRING) action-stop)
  496. ((fmatch? 'BOOL) action-stop)
  497. ((fmatch? 'Constant) action-stop)
  498. ((fmatch? 'NIL) action-stop)
  499. ((fmatch? 'value) action-stop)
  500. ((fmatch? 'Instanceof) action-stop) ; TODO: check that there unable to be methods invocations
  501. (#t
  502. (lambda(x)
  503. (error (format "Unknown type: ~a~%Body: ~s~%" fragment-type x)))))))
  504. (define (dispatch a-sxml)
  505. ((processor-dispatcher (car a-sxml)) (cdr a-sxml)))
  506. ;;; main
  507. (display (format "Processing ~a~%" +ast-xml-file+)) ;;debug
  508. (dispatch (caddr ast-xml-file))
  509. (local ((define (write-to-output-file) (write *calls*)))
  510. (with-output-to-file +output-file+
  511. write-to-output-file #:exists 'replace))
  512. (local ((define (write-to-output-file) (write *function-to-file-relations*)))
  513. (with-output-to-file +function-file-hash+
  514. write-to-output-file #:exists 'replace))