Chervil is a toy Lisp interpreter written in Ruby
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

parser_spec.rb 2.4KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. [
  20. AST::Boolean.new(true),
  21. AST::Boolean.new(false),
  22. ]
  23. )
  24. end
  25. it 'parses an application' do
  26. expect(parse('(+ 1 2)').first).to eq(
  27. AST::Application.new(
  28. AST::Identifier.new('+'),
  29. [AST::Number.new(1.0), AST::Number.new(2.0)]
  30. )
  31. )
  32. end
  33. it 'parses a definition' do
  34. expect(parse('(define x 5)').first).to eq(
  35. AST::Definition.new(AST::Identifier.new('x'), AST::Number.new(5.0))
  36. )
  37. end
  38. it 'parses a nested expression' do
  39. expect(parse('(+ (+ 1 2) (- 3 4))').first).to eq(
  40. AST::Application.new(
  41. AST::Identifier.new("+"),
  42. [
  43. AST::Application.new(
  44. AST::Identifier.new("+"),
  45. [
  46. AST::Number.new(1.0),
  47. AST::Number.new(2.0),
  48. ]
  49. ),
  50. AST::Application.new(
  51. AST::Identifier.new("-"),
  52. [
  53. AST::Number.new(3.0),
  54. AST::Number.new(4.0),
  55. ]
  56. ),
  57. ]
  58. )
  59. )
  60. end
  61. it 'parses a function definition' do
  62. expect(parse('(define (square x) (* x x))').first).to eq(
  63. AST::Definition.new(
  64. AST::Identifier.new("square"),
  65. AST::Function.new(
  66. AST::Identifier.new("square"),
  67. [
  68. AST::Identifier.new("x")
  69. ],
  70. [
  71. AST::Application.new(
  72. AST::Identifier.new("*"),
  73. [
  74. AST::Identifier.new("x"),
  75. AST::Identifier.new("x"),
  76. ]
  77. )
  78. ]
  79. )
  80. )
  81. )
  82. end
  83. it 'returns a syntax error object instead of raising' do
  84. expect(parse('(+ 1')).to eq(Error.new("Expected rparen but got eof"))
  85. expect(parse('1)')).to eq(Error.new("Unexpected token rparen: )"))
  86. end
  87. end
  88. end