tree.lisp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: TREE; -*-
  2. ;;; Copyright (c) 2013, Mark VandenBrink. All rights reserved.
  3. (in-package #:tree)
  4. (declaim (inline #:first-child #:add-child #:next-sibling #:data))
  5. (defun make-node (data)
  6. "Creates a new node with DATA as contents"
  7. (declare #.utils:*standard-optimize-settings*)
  8. (cons (cons data nil) nil))
  9. (defun add-child (node child)
  10. "Takes two nodes created with MAKE-NODE and adds CHILD"
  11. (declare #.utils:*standard-optimize-settings*)
  12. (nconc (first node) child)
  13. node)
  14. (defun first-child (node)
  15. "Returns a reference to the first child of NODE"
  16. (declare #.utils:*standard-optimize-settings*)
  17. (rest (first node)))
  18. (defun next-sibling (node)
  19. "Returns next SIBLING of NODE"
  20. (declare #.utils:*standard-optimize-settings*)
  21. (rest node))
  22. (defun data (node)
  23. "Returns the information in NODE"
  24. (declare #.utils:*standard-optimize-settings*)
  25. (first (first node)))
  26. (defun traverse (tree func &optional (depth 0))
  27. "Depth-first traversal of TREE calling FUNC for each node"
  28. (declare #.utils:*standard-optimize-settings*)
  29. (when tree
  30. (funcall func tree depth)
  31. (traverse (first-child tree) func (+ 2 depth))
  32. (traverse (next-sibling tree) func depth)))
  33. (defun print-tree (tree)
  34. "Print the nodes of TREE"
  35. (declare #.utils:*standard-optimize-settings*)
  36. (traverse tree (lambda (node depth) (format t "~v@tNode: ~a~%" depth (data node)))))
  37. (defun find-tree (tree test)
  38. "Find all nodes in TREE where TEST returns T"
  39. (declare #.utils:*standard-optimize-settings*)
  40. (let ((results))
  41. (traverse tree (lambda (node depth)
  42. (declare (ignore depth))
  43. (when (funcall test node)
  44. (push node results))))
  45. (nreverse results)))
  46. (defun at-path (tree path cmp)
  47. "Return node from TREE located at PATH"
  48. (declare #.utils:*standard-optimize-settings*)
  49. (when (or (null tree) (null path))
  50. (return-from at-path nil))
  51. (when (funcall cmp tree (first path))
  52. (when (= 1 (length path))
  53. (return-from at-path tree))
  54. (loop for node = (first-child tree) then (next-sibling node)
  55. until (null node) do
  56. (utils:aif (at-path node (rest path) cmp)
  57. (return-from at-path utils:it))))
  58. nil)
  59. (let ((pkg (find-package :tree)))
  60. (do-all-symbols (sym pkg) (when (eql (symbol-package sym) pkg) (export sym pkg))))