Advertisement
Guest User

Untitled

a guest
Feb 20th, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 0.95 KB | None | 0 0
  1. # Wrote this in the bathtub just as a curiousity to see how hard it'd be :shrug:
  2. require 'strscan'
  3.  
  4. def scan(str)
  5. tokens = []
  6. scanner = StringScanner.new str
  7. loop do
  8. next if scanner.scan /\s+/
  9. token = scanner.scan /[()]/
  10. next tokens << token if token
  11. token = scanner.scan /[^\s()"']+/
  12. next tokens << token if token
  13. break
  14. end
  15. tokens# scanner.pos
  16. end
  17.  
  18. def parse(str)
  19. tokens = scan str
  20. stack = [[]]
  21. until tokens.empty?
  22. current = stack.last
  23. token = tokens.shift
  24. case token
  25. when '('
  26. stack.push []
  27. when ')'
  28. current = stack.pop
  29. stack.last.push current
  30. when /\A\d+\z/
  31. stack.last.push token.to_f
  32. else
  33. stack.last.push token.intern
  34. end
  35. end
  36. raise unless stack.one?
  37. stack.pop
  38. end
  39.  
  40. parse <<~LISP
  41. (=(+(* a (square x))
  42. (* b x)
  43. c)
  44. 0)
  45. (= (f (x))
  46. (square x))
  47. LISP
  48. # => [[:"=", [:+, [:*, :a, [:square, :x]], [:*, :b, :x], :c], 0.0],
  49. # [:"=", [:f, [:x]], [:square, :x]]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement