Chervil is a toy Lisp interpreter written in Ruby
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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