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 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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, :and),
  43. Token.new(TokenKinds::OPERATOR, :or),
  44. Token.new(TokenKinds::OPERATOR, :not),
  45. Token.new(TokenKinds::EOF)
  46. ]
  47. )
  48. end
  49. it 'lexes punctuation' do
  50. expect(Lexer.new('{}()[];,.').scan_all).to eq(
  51. [
  52. Token.new(TokenKinds::LBRACE),
  53. Token.new(TokenKinds::RBRACE),
  54. Token.new(TokenKinds::LPAREN),
  55. Token.new(TokenKinds::RPAREN),
  56. Token.new(TokenKinds::LBRACKET),
  57. Token.new(TokenKinds::RBRACKET),
  58. Token.new(TokenKinds::SEMICOLON),
  59. Token.new(TokenKinds::COMMA),
  60. Token.new(TokenKinds::DOT),
  61. Token.new(TokenKinds::EOF)
  62. ]
  63. )
  64. end
  65. it 'lexes if elseif else' do
  66. expect(Lexer.new('if elseif else').scan_all).to eq(
  67. [
  68. Token.new(TokenKinds::IF),
  69. Token.new(TokenKinds::ELSEIF),
  70. Token.new(TokenKinds::ELSE),
  71. Token.new(TokenKinds::EOF)
  72. ]
  73. )
  74. end
  75. it 'lexes =' do
  76. expect(Lexer.new('=').scan_all).to eq(
  77. [Token.new(TokenKinds::EQUALS), Token.new(TokenKinds::EOF)]
  78. )
  79. end
  80. it 'lexes let' do
  81. expect(Lexer.new('let').scan_all).to eq(
  82. [Token.new(TokenKinds::LET), Token.new(TokenKinds::EOF)]
  83. )
  84. end
  85. it 'lexes identifiers' do
  86. expect(Lexer.new('x').scan_all).to eq(
  87. [Token.new(TokenKinds::IDENTIFIER, 'x'), Token.new(TokenKinds::EOF)]
  88. )
  89. end
  90. it 'lexes function' do
  91. expect(Lexer.new('function').scan_all).to eq(
  92. [Token.new(TokenKinds::FUNCTION), Token.new(TokenKinds::EOF)]
  93. )
  94. end
  95. it 'lexes class' do
  96. expect(Lexer.new('class').scan_all).to eq(
  97. [Token.new(TokenKinds::CLASS), Token.new(TokenKinds::EOF)]
  98. )
  99. end
  100. it 'lexes class names' do
  101. expect(Lexer.new('Class').scan_all).to eq(
  102. [Token.new(TokenKinds::CLASS_NAME, 'Class'), Token.new(TokenKinds::EOF)]
  103. )
  104. end
  105. it 'lexes public and private' do
  106. expect(Lexer.new('public private').scan_all).to eq(
  107. [
  108. Token.new(TokenKinds::PUBLIC),
  109. Token.new(TokenKinds::PRIVATE),
  110. Token.new(TokenKinds::EOF)
  111. ]
  112. )
  113. end
  114. it 'lexes hash' do
  115. expect(Lexer.new('{ :a => 1 }').scan_all).to eq(
  116. [
  117. Token.new(TokenKinds::LBRACE),
  118. Token.new(TokenKinds::ATOM, :a),
  119. Token.new(TokenKinds::ROCKET),
  120. Token.new(TokenKinds::NUMBER, 1.0),
  121. Token.new(TokenKinds::RBRACE),
  122. Token.new(TokenKinds::EOF)
  123. ]
  124. )
  125. end
  126. it 'lexes for' do
  127. expect(Lexer.new('for in').scan_all).to eq(
  128. [
  129. Token.new(TokenKinds::FOR),
  130. Token.new(TokenKinds::IN),
  131. Token.new(TokenKinds::EOF)
  132. ]
  133. )
  134. end
  135. it 'allows escaping quotes in strings' do
  136. expect(Lexer.new('"hello \"world\""').scan_all).to eq(
  137. [
  138. Token.new(TokenKinds::STRING, 'hello "world"'),
  139. Token.new(TokenKinds::EOF)
  140. ]
  141. )
  142. end
  143. it 'supports newlines and tabs in strings' do
  144. expect(Lexer.new('"hello\nworld" "hello\tworld"').scan_all).to eq(
  145. [
  146. Token.new(TokenKinds::STRING, "hello\nworld"),
  147. Token.new(TokenKinds::STRING, "hello\tworld"),
  148. Token.new(TokenKinds::EOF)
  149. ]
  150. )
  151. end
  152. it 'ignores comments' do
  153. expect(Lexer.new("// prints 5\nprint(5)").scan_all).to eq(
  154. [
  155. Token.new(TokenKinds::IDENTIFIER, 'print'),
  156. Token.new(TokenKinds::LPAREN),
  157. Token.new(TokenKinds::NUMBER, 5),
  158. Token.new(TokenKinds::RPAREN),
  159. Token.new(TokenKinds::EOF)
  160. ]
  161. )
  162. end
  163. it 'lexes hashes' do
  164. expect(Lexer.new('#').scan_all).to eq(
  165. [Token.new(TokenKinds::HASH), Token.new(TokenKinds::EOF)]
  166. )
  167. end
  168. it 'lexes method and classmethod' do
  169. expect(Lexer.new('method classmethod').scan_all).to eq(
  170. [
  171. Token.new(TokenKinds::METHOD),
  172. Token.new(TokenKinds::CLASSMETHOD),
  173. Token.new(TokenKinds::EOF)
  174. ]
  175. )
  176. end
  177. end