Chervil is a toy Lisp interpreter written in Ruby
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

parser_spec.rb 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. module Chervil
  2. RSpec.describe Parser do
  3. def parse(source)
  4. lexer = Lexer.new(source)
  5. parser = Parser.new(lexer)
  6. parser.parse
  7. end
  8. it 'parses a number' do
  9. expect(parse('1').first).to eq(AST::Number.new(1.0))
  10. end
  11. it 'parses a string' do
  12. expect(parse('"hello world"').first).to eq(AST::String.new('hello world'))
  13. end
  14. it 'parses an identifier' do
  15. expect(parse('+').first).to eq(AST::Identifier.new('+'))
  16. end
  17. it 'parses booleans' do
  18. expect(parse('#t #f')).to eq(
  19. [AST::Boolean.new(true), AST::Boolean.new(false)]
  20. )
  21. end
  22. it 'parses an application' do
  23. expect(parse('(+ 1 2)').first).to eq(
  24. AST::Application.new(
  25. AST::Identifier.new('+'),
  26. [AST::Number.new(1.0), AST::Number.new(2.0)]
  27. )
  28. )
  29. end
  30. it 'parses a definition' do
  31. expect(parse('(define x 5)').first).to eq(
  32. AST::Definition.new(AST::Identifier.new('x'), AST::Number.new(5.0))
  33. )
  34. end
  35. it 'parses a nested expression' do
  36. expect(parse('(+ (+ 1 2) (- 3 4))').first).to eq(
  37. AST::Application.new(
  38. AST::Identifier.new('+'),
  39. [
  40. AST::Application.new(
  41. AST::Identifier.new('+'),
  42. [AST::Number.new(1.0), AST::Number.new(2.0)]
  43. ),
  44. AST::Application.new(
  45. AST::Identifier.new('-'),
  46. [AST::Number.new(3.0), AST::Number.new(4.0)]
  47. )
  48. ]
  49. )
  50. )
  51. end
  52. it 'parses a function definition' do
  53. expect(parse('(define (square x) (* x x))').first).to eq(
  54. AST::Definition.new(
  55. AST::Identifier.new('square'),
  56. AST::Function.new(
  57. AST::Identifier.new('square'),
  58. [AST::Identifier.new('x')],
  59. [
  60. AST::Application.new(
  61. AST::Identifier.new('*'),
  62. [AST::Identifier.new('x'), AST::Identifier.new('x')]
  63. )
  64. ]
  65. )
  66. )
  67. )
  68. end
  69. it 'returns a syntax error object instead of raising' do
  70. expect(parse('(+ 1')).to eq(Error.new('Expected rparen but got eof'))
  71. expect(parse('1)')).to eq(Error.new('Unexpected token rparen: )'))
  72. end
  73. it 'parses a conditional' do
  74. expect(parse('(if #t 1 0)').first).to eq(
  75. AST::Conditional.new(
  76. AST::Boolean.new(true),
  77. AST::Number.new(1.0),
  78. AST::Number.new(0.0)
  79. )
  80. )
  81. end
  82. end
  83. end