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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. advance
  39. Token.new(:quote, '\'')
  40. when '"'
  41. delimiter = current_char
  42. advance
  43. string = String.new
  44. until current_char == delimiter || current_char.nil?
  45. string << current_char
  46. advance
  47. end
  48. if current_char.nil?
  49. return Error.new("Unterminated string")
  50. end
  51. advance
  52. Token.new(:string, string)
  53. else
  54. source = @source.slice(@position..-1)
  55. if match = source.match(/^[0-9]+(\.[0-9]+)?/)
  56. advance(match[0].size)
  57. Token.new(:number, match[0])
  58. elsif match = source.match(/^[a-z!$%&*\/:<=>?~_^+\-][a-z0-9@!$%&*\/:<=>?~_^+\-]*/)
  59. advance(match[0].size)
  60. Token.new(:identifier, match[0])
  61. else
  62. raise "Unrecognized character #{current_char}"
  63. end
  64. end
  65. end
  66. def tokenize
  67. tokens = Array.new
  68. loop do
  69. token = get_next_token
  70. tokens << token unless token.nil?
  71. break if token.type == :eof
  72. end
  73. tokens
  74. end
  75. end
  76. end