config-parser.lisp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. ;;;; config-parser.lisp
  2. #+quicklisp (ql:quickload :parse-number)
  3. (defpackage #:config-parser
  4. (:use :esrap
  5. :cl)
  6. (:import-from #:parse-number
  7. #:parse-number)
  8. (:export open-configuration-file))
  9. (in-package #:config-parser)
  10. ;;; "config-parser" goes here. Hacks and glory await!
  11. (defrule space
  12. (+ (or #\Space #\Tab #\Newline))
  13. (:constant nil))
  14. (defrule identifier
  15. (* (or (alphanumericp character) "_" "-" "."))
  16. (:text t)
  17. (:lambda (identifier)
  18. (intern (string-upcase identifier) "KEYWORD")))
  19. (defun not-doublequote (character)
  20. (not (eql #\" character)))
  21. (defrule string-chars
  22. (or (not-doublequote character)
  23. (and #\\ #\")))
  24. (defrule string
  25. (and #\" (* string-chars) #\")
  26. (:destructure (sq string eq)
  27. (declare (ignore sq eq))
  28. (text string)))
  29. (defrule number
  30. (and (? (or "-" "+"))
  31. (+ (or "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))
  32. (? (and "."
  33. (+ (or "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))))
  34. (? (and (or "e" "E")
  35. (? "-")
  36. (+ (or "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")))))
  37. (:text t)
  38. (:lambda (num-string)
  39. (parse-number num-string)))
  40. (defrule block-title
  41. (and (? #\Newline) "[" (? space) identifier (? space) "]" (? #\Newline))
  42. (:destructure (nl1 lb sp1 ident sp2 rb nl)
  43. (declare (ignore nl1 lb sp1 sp2 rb nl))
  44. ident))
  45. (defrule ident-path
  46. (and identifier (? space) "/" (? space) identifier)
  47. (:destructure (identa sp1 sep sp2 identb)
  48. (declare (ignore sp1 sep sp2))
  49. (list identa identb)))
  50. (defrule variable-expression
  51. (and identifier (? space) "=" (? space) (or string number ident-path) (? #\Newline))
  52. (:destructure (identifier sp1 eq sp2 value nl)
  53. (declare (ignore sp1 eq sp2 nl))
  54. (list identifier value)))
  55. (defrule block-contents
  56. (* variable-expression)
  57. (:lambda (expressions)
  58. (loop for expression in expressions
  59. append expression)))
  60. (defrule block
  61. (and block-title block-contents)
  62. (:destructure (title contents)
  63. (list title contents)))
  64. (defrule file
  65. (* block)
  66. (:lambda (blocks)
  67. (loop for block in blocks
  68. append block)))
  69. (defun open-configuration-file (filename)
  70. (parse 'file
  71. (concatenate 'string
  72. (with-open-file (input-file filename)
  73. (loop for char = (read-char input-file nil 'foo)
  74. until (eq char 'foo)
  75. collect char)))))