A toy dynamic programming language written in Ruby
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lexer_spec.rb 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. RSpec.describe Lexer do
  2. it 'lexes null' do
  3. expect(Lexer.new('null').scan_all).to eq(
  4. [Token.new(TokenKinds::NULL), Token.new(TokenKinds::EOF)]
  5. )
  6. end
  7. it 'lexes booleans' do
  8. expect(Lexer.new('true false').scan_all).to eq(
  9. [
  10. Token.new(TokenKinds::BOOLEAN, true),
  11. Token.new(TokenKinds::BOOLEAN, false),
  12. Token.new(TokenKinds::EOF)
  13. ]
  14. )
  15. end
  16. it 'lexes numbers' do
  17. expect(Lexer.new('1 2.3').scan_all).to eq(
  18. [
  19. Token.new(TokenKinds::NUMBER, 1.0),
  20. Token.new(TokenKinds::NUMBER, 2.3),
  21. Token.new(TokenKinds::EOF)
  22. ]
  23. )
  24. end
  25. it 'lexes strings' do
  26. expect(Lexer.new('"hello world"').scan_all).to eq(
  27. [Token.new(TokenKinds::STRING, 'hello world'), Token.new(TokenKinds::EOF)]
  28. )
  29. end
  30. it 'lexes operators' do
  31. expect(Lexer.new('+-*/<<=>>===# and or not').scan_all).to eq(
  32. [
  33. Token.new(TokenKinds::OPERATOR, :+),
  34. Token.new(TokenKinds::OPERATOR, :-),
  35. Token.new(TokenKinds::OPERATOR, :*),
  36. Token.new(TokenKinds::OPERATOR, :/),
  37. Token.new(TokenKinds::OPERATOR, :<),
  38. Token.new(TokenKinds::OPERATOR, :<=),
  39. Token.new(TokenKinds::OPERATOR, :>),
  40. Token.new(TokenKinds::OPERATOR, :>=),
  41. Token.new(TokenKinds::OPERATOR, :==),
  42. Token.new(TokenKinds::OPERATOR, :'#'),
  43. Token.new(TokenKinds::OPERATOR, :and),
  44. Token.new(TokenKinds::OPERATOR, :or),
  45. Token.new(TokenKinds::OPERATOR, :not),
  46. Token.new(TokenKinds::EOF)
  47. ]
  48. )
  49. end
  50. it 'lexes punctuation' do
  51. expect(Lexer.new('{}()[];,.').scan_all).to eq(
  52. [
  53. Token.new(TokenKinds::LBRACE),
  54. Token.new(TokenKinds::RBRACE),
  55. Token.new(TokenKinds::LPAREN),
  56. Token.new(TokenKinds::RPAREN),
  57. Token.new(TokenKinds::LBRACKET),
  58. Token.new(TokenKinds::RBRACKET),
  59. Token.new(TokenKinds::SEMICOLON),
  60. Token.new(TokenKinds::COMMA),
  61. Token.new(TokenKinds::DOT),
  62. Token.new(TokenKinds::EOF)
  63. ]
  64. )
  65. end
  66. it 'lexes if elseif else' do
  67. expect(Lexer.new('if elseif else').scan_all).to eq(
  68. [
  69. Token.new(TokenKinds::IF),
  70. Token.new(TokenKinds::ELSEIF),
  71. Token.new(TokenKinds::ELSE),
  72. Token.new(TokenKinds::EOF)
  73. ]
  74. )
  75. end
  76. it 'lexes =' do
  77. expect(Lexer.new('=').scan_all).to eq(
  78. [Token.new(TokenKinds::EQUALS), Token.new(TokenKinds::EOF)]
  79. )
  80. end
  81. it 'lexes let' do
  82. expect(Lexer.new('let').scan_all).to eq(
  83. [Token.new(TokenKinds::LET), Token.new(TokenKinds::EOF)]
  84. )
  85. end
  86. it 'lexes identifiers' do
  87. expect(Lexer.new('x').scan_all).to eq(
  88. [Token.new(TokenKinds::IDENTIFIER, 'x'), Token.new(TokenKinds::EOF)]
  89. )
  90. end
  91. it 'lexes function' do
  92. expect(Lexer.new('function').scan_all).to eq(
  93. [Token.new(TokenKinds::FUNCTION), Token.new(TokenKinds::EOF)]
  94. )
  95. end
  96. it 'lexes class' do
  97. expect(Lexer.new('class').scan_all).to eq(
  98. [Token.new(TokenKinds::CLASS), Token.new(TokenKinds::EOF)]
  99. )
  100. end
  101. it 'lexes class names' do
  102. expect(Lexer.new('Class').scan_all).to eq(
  103. [Token.new(TokenKinds::CLASS_NAME, 'Class'), Token.new(TokenKinds::EOF)]
  104. )
  105. end
  106. it 'lexes public and private' do
  107. expect(Lexer.new('public private').scan_all).to eq(
  108. [
  109. Token.new(TokenKinds::PUBLIC),
  110. Token.new(TokenKinds::PRIVATE),
  111. Token.new(TokenKinds::EOF)
  112. ]
  113. )
  114. end
  115. it 'lexes hash' do
  116. expect(Lexer.new('{ :a => 1 }').scan_all).to eq(
  117. [
  118. Token.new(TokenKinds::LBRACE),
  119. Token.new(TokenKinds::ATOM, :a),
  120. Token.new(TokenKinds::ROCKET),
  121. Token.new(TokenKinds::NUMBER, 1.0),
  122. Token.new(TokenKinds::RBRACE),
  123. Token.new(TokenKinds::EOF)
  124. ]
  125. )
  126. end
  127. it 'lexes for' do
  128. expect(Lexer.new('for in').scan_all).to eq(
  129. [
  130. Token.new(TokenKinds::FOR),
  131. Token.new(TokenKinds::IN),
  132. Token.new(TokenKinds::EOF)
  133. ]
  134. )
  135. end
  136. it 'allows escaping quotes in strings' do
  137. expect(Lexer.new('"hello \"world\""').scan_all).to eq(
  138. [
  139. Token.new(TokenKinds::STRING, 'hello "world"'),
  140. Token.new(TokenKinds::EOF)
  141. ]
  142. )
  143. end
  144. it 'supports newlines and tabs in strings' do
  145. expect(Lexer.new('"hello\nworld" "hello\tworld"').scan_all).to eq(
  146. [
  147. Token.new(TokenKinds::STRING, "hello\nworld"),
  148. Token.new(TokenKinds::STRING, "hello\tworld"),
  149. Token.new(TokenKinds::EOF)
  150. ]
  151. )
  152. end
  153. it 'ignores comments' do
  154. expect(Lexer.new("// prints 5\nprint(5)").scan_all).to eq(
  155. [
  156. Token.new(TokenKinds::IDENTIFIER, 'print'),
  157. Token.new(TokenKinds::LPAREN),
  158. Token.new(TokenKinds::NUMBER, 5),
  159. Token.new(TokenKinds::RPAREN),
  160. Token.new(TokenKinds::EOF)
  161. ]
  162. )
  163. end
  164. end