Chervil is a toy Lisp interpreter written in Ruby
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lexer.rb 1.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. module Chervil
  2. class Lexer
  3. def initialize(source)
  4. @source = source
  5. @position = 0
  6. end
  7. def current_char
  8. @source[@position]
  9. end
  10. def advance(step = 1)
  11. @position += step
  12. end
  13. def get_next_token
  14. while @source.slice(@position..-1).match(/^\s/)
  15. advance
  16. end
  17. case current_char
  18. when nil
  19. Token.new(:eof, "eof")
  20. when '('
  21. advance
  22. Token.new(:lparen, "(")
  23. when ')'
  24. advance
  25. Token.new(:rparen, ")")
  26. when '#'
  27. advance
  28. if current_char == 't'
  29. advance
  30. Token.new(:boolean, true)
  31. elsif current_char == 'f'
  32. advance
  33. Token.new(:boolean, false)
  34. else
  35. raise "Unexpected character #{current_char}"
  36. end
  37. when '"', '\''
  38. delimiter = current_char
  39. advance
  40. string = String.new
  41. until current_char == delimiter || current_char.nil?
  42. string << current_char
  43. advance
  44. end
  45. if current_char.nil?
  46. return Error.new("Unterminated string")
  47. end
  48. advance
  49. Token.new(:string, string)
  50. else
  51. source = @source.slice(@position..-1)
  52. if match = source.match(/^[0-9]+(\.[0-9]+)?/)
  53. advance(match[0].size)
  54. Token.new(:number, match[0])
  55. elsif match = source.match(/^[a-z!$%&*\/:<=>?~_^+\-][a-z0-9@!$%&*\/:<=>?~_^+\-]*/)
  56. advance(match[0].size)
  57. Token.new(:identifier, match[0])
  58. else
  59. raise "Unrecognized character #{current_char}"
  60. end
  61. end
  62. end
  63. def tokenize
  64. tokens = Array.new
  65. loop do
  66. token = get_next_token
  67. tokens << token unless token.nil?
  68. break if token.type == :eof
  69. end
  70. tokens
  71. end
  72. end
  73. end