context-free.scm 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. ;;; Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
  2. ;;;
  3. ;;; This program is free software. You may run, copy, modify, and
  4. ;;; redistribute it under the terms of the GNU General Purpose License
  5. ;;; (GPL) version 3, or any later version.
  6. ;;; Derived (pun intended) from Matt Might, Dacid Darais, and Daniel
  7. ;;; Spiewak's paper "Parsing with Derivatives, A Functional Pearl" ACM
  8. ;;; 978-1-4503-086-6/11/09
  9. (define-module (derivative language context-free)
  10. #:use-module (ice-9 match)
  11. #:use-module (derivative language)
  12. #:use-module (derivative utils fix)
  13. #:use-module (derivative utils memoize)
  14. #:re-export (<alt> alt?
  15. <cat> cat?
  16. <rep> rep?)
  17. #:export (alt cat rep
  18. δ nullable?
  19. D derivative
  20. recognize?
  21. ;; test/example languages
  22. d-lang
  23. S-lang
  24. N-lang
  25. xyz-lang
  26. rep-lang
  27. parens-lang
  28. ab-lang
  29. aab-lang
  30. palindrome-lang
  31. double-lang))
  32. (define-syntax alt
  33. (syntax-rules ()
  34. ((_) 'empty)
  35. ((_ L) L)
  36. ((_ L L* ...)
  37. ((@@ (derivative language) make-alt) (delay L) (delay (alt L* ...))))))
  38. (define-syntax cat
  39. (syntax-rules ()
  40. ((_) 'eps)
  41. ((_ L) L)
  42. ((_ L L* ...)
  43. ((@@ (derivative language) make-cat) (delay L) (delay (cat L* ...))))))
  44. (define-syntax rep
  45. (syntax-rules ()
  46. ((_) 'empty)
  47. ((_ L) ((@@ (derivative language) make-rep) (delay L)))))
  48. (define δ
  49. (fix* #f (match-lambda
  50. ('empty #f)
  51. ('eps #t)
  52. ((? char?) #f)
  53. (($ <rep> _) #t)
  54. (($ <alt> L L')
  55. (or (δ (force L)) (δ (force L'))))
  56. (($ <cat> L L')
  57. (and (δ (force L)) (δ (force L')))))))
  58. (define nullable? δ)
  59. (define D
  60. (memoize
  61. (lambda (c language)
  62. (match language
  63. ('empty 'empty)
  64. ('eps 'empty)
  65. ((? char? a) (if (eq? a c)
  66. 'eps
  67. 'empty))
  68. (($ <alt> L L')
  69. (alt (D c (force L)) (D c (force L'))))
  70. (($ <cat> (= force (? δ L)) L')
  71. (alt (D c (force L'))
  72. (cat (D c L) (force L'))))
  73. (($ <cat> L L')
  74. (cat (D c (force L)) (force L')))
  75. (($ <rep> L)
  76. (cat (D c (force L)) language))))))
  77. (define derivative D)
  78. (define (recognize? w L)
  79. (match w
  80. ((? string?)
  81. (recognize? (string->list w) L))
  82. (()
  83. (δ L))
  84. ((head tail ...)
  85. (recognize? tail (D head L)))))
  86. ;;; Define some test/example languages
  87. (define d-lang
  88. (alt (cat d-lang #\d)
  89. 'eps))
  90. (define S-lang
  91. (alt (cat S-lang #\x)
  92. 'eps))
  93. (define N-lang
  94. (alt (cat N-lang #\+ N-lang)
  95. #\N)) ;kleene plus
  96. (define xyz-lang
  97. (alt (cat xyz-lang (cat #\x #\y #\z))
  98. (cat #\x #\y #\z)))
  99. (define rep-lang
  100. (rep #\a))
  101. (define parens-lang
  102. (alt (cat parens-lang parens-lang)
  103. (cat #\( parens-lang #\))
  104. 'eps))
  105. (define ab-lang
  106. (alt (cat #\a ab-lang #\b)
  107. (cat #\a #\b)))
  108. (define aab-lang
  109. ;; L = {a^nb^m; n>m}
  110. (letrec ((S' (alt (cat #\a S' #\b) 'eps))
  111. (A (alt (cat #\a A) #\a)))
  112. (cat A S')))
  113. (define palindrome-lang
  114. (alt (cat #\a palindrome-lang #\a)
  115. (cat #\b palindrome-lang #\b)
  116. 'eps))
  117. (define double-lang
  118. (alt (cat #\a double-lang #\b)
  119. (cat double-lang double-lang)
  120. 'eps)) ;e.g. abaabb, aababb, ababab