Chervil is a toy Lisp interpreter written in Ruby
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

parser.rb 1.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. module Chervil
  2. class Parser def initialize(lexer)
  3. @lexer = lexer
  4. @tree = Array.new
  5. @current_token = @lexer.get_next_token
  6. end
  7. def parse
  8. until @current_token.type == :eof
  9. @tree << expr
  10. end
  11. @tree
  12. end
  13. def expr
  14. if [:string, :number, :boolean].include?(@current_token.type)
  15. constant
  16. elsif @current_token.type == :identifier
  17. identifier
  18. elsif @current_token.type == :lparen
  19. application
  20. else
  21. raise "Unexpected token #{@current_token.type}: #{@current_token.value}"
  22. end
  23. end
  24. def application
  25. eat(:lparen)
  26. if @current_token.type == :identifier && @current_token.value == 'define'
  27. eat(:identifier)
  28. name = identifier
  29. value = expr
  30. eat(:rparen)
  31. return AST::Definition.new(name, value)
  32. end
  33. expression = expr
  34. args = Array.new
  35. until @current_token.type == :rparen
  36. args << expr
  37. end
  38. eat(:rparen)
  39. AST::Application.new(expression, args)
  40. end
  41. def identifier
  42. identifier = eat(:identifier)
  43. AST::Identifier.new(identifier.value)
  44. end
  45. def constant
  46. case @current_token.type
  47. when :number
  48. token = eat(:number)
  49. AST::Number.new(token.value.to_f)
  50. when :string
  51. token = eat(:string)
  52. AST::String.new(token.value)
  53. when :boolean
  54. token = eat(:boolean)
  55. AST::Boolean.new(token.value)
  56. end
  57. end
  58. def eat(type)
  59. if @current_token.type == type
  60. token = @current_token
  61. @current_token = @lexer.get_next_token
  62. token
  63. else
  64. raise "Expected #{type} but got #{@current_token.type}"
  65. end
  66. end
  67. end
  68. end