loxxy 0.4.09 → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,26 +23,27 @@ module Loxxy
23
23
  end
24
24
 
25
25
  let(:sample_text) { 'print "Hello, world";' }
26
- subject { Scanner.new }
26
+
27
+ subject(:scanner) { described_class.new }
27
28
 
28
29
  context 'Initialization:' do
29
30
  it 'could be initialized with a text to tokenize or...' do
30
- expect { Scanner.new(sample_text) }.not_to raise_error
31
+ expect { described_class.new(sample_text) }.not_to raise_error
31
32
  end
32
33
 
33
34
  it 'could be initialized without argument...' do
34
- expect { Scanner.new }.not_to raise_error
35
+ expect { described_class.new }.not_to raise_error
35
36
  end
36
37
 
37
- it 'should have its scanner initialized' do
38
- expect(subject.scanner).to be_kind_of(StringScanner)
38
+ it 'has its scanner initialized' do
39
+ expect(scanner.scanner).to be_a(StringScanner)
39
40
  end
40
41
  end # context
41
42
 
42
43
  context 'Input tokenization:' do
43
- it 'should recognize single special character token' do
44
+ it 'recognizes single special character token' do
44
45
  input = '(){},.-+;*/'
45
- subject.start_with(input)
46
+ scanner.start_with(input)
46
47
  expectations = [
47
48
  # [token lexeme]
48
49
  %w[LEFT_PAREN (],
@@ -57,12 +58,12 @@ module Loxxy
57
58
  %w[STAR *],
58
59
  %w[SLASH /]
59
60
  ]
60
- match_expectations(subject, expectations)
61
+ match_expectations(scanner, expectations)
61
62
  end
62
63
 
63
- it 'should recognize one or two special character tokens' do
64
+ it 'recognizes one or two special character tokens' do
64
65
  input = '! != = == > >= < <='
65
- subject.start_with(input)
66
+ scanner.start_with(input)
66
67
  expectations = [
67
68
  # [token lexeme]
68
69
  %w[BANG !],
@@ -74,15 +75,15 @@ module Loxxy
74
75
  %w[LESS <],
75
76
  %w[LESS_EQUAL <=]
76
77
  ]
77
- match_expectations(subject, expectations)
78
+ match_expectations(scanner, expectations)
78
79
  end
79
80
 
80
- it 'should recognize non-datatype keywords' do
81
+ it 'recognizes non-datatype keywords' do
81
82
  keywords = <<-LOX_END
82
83
  and class else fun for if or
83
84
  print return super this var while
84
85
  LOX_END
85
- subject.start_with(keywords)
86
+ scanner.start_with(keywords)
86
87
  expectations = [
87
88
  # [token lexeme]
88
89
  %w[AND and],
@@ -99,30 +100,30 @@ LOX_END
99
100
  %w[VAR var],
100
101
  %w[WHILE while]
101
102
  ]
102
- match_expectations(subject, expectations)
103
+ match_expectations(scanner, expectations)
103
104
  end
104
105
 
105
- it 'should recognize a false boolean token' do
106
- subject.start_with('false')
107
- token_false = subject.tokens[0]
108
- expect(token_false).to be_kind_of(Rley::Lexical::Literal)
106
+ it 'recognizes a false boolean token' do
107
+ scanner.start_with('false')
108
+ token_false = scanner.tokens[0]
109
+ expect(token_false).to be_a(Rley::Lexical::Literal)
109
110
  expect(token_false.terminal).to eq('FALSE')
110
111
  expect(token_false.lexeme).to eq('false')
111
- expect(token_false.value).to be_kind_of(Datatype::False)
112
+ expect(token_false.value).to be_a(Datatype::False)
112
113
  expect(token_false.value.value).to be_falsy
113
114
  end
114
115
 
115
- it 'should recognize a true boolean token' do
116
- subject.start_with('true')
117
- token_true = subject.tokens[0]
118
- expect(token_true).to be_kind_of(Rley::Lexical::Literal)
116
+ it 'recognizes a true boolean token' do
117
+ scanner.start_with('true')
118
+ token_true = scanner.tokens[0]
119
+ expect(token_true).to be_a(Rley::Lexical::Literal)
119
120
  expect(token_true.terminal).to eq('TRUE')
120
121
  expect(token_true.lexeme).to eq('true')
121
- expect(token_true.value).to be_kind_of(Datatype::True)
122
+ expect(token_true.value).to be_a(Datatype::True)
122
123
  expect(token_true.value.value).to be_truthy
123
124
  end
124
125
 
125
- it 'should recognize number values' do
126
+ it 'recognizes number values' do
126
127
  input = <<-LOX_END
127
128
  123 987654
128
129
  0 123.456
@@ -135,18 +136,18 @@ LOX_END
135
136
  ['123.456', 123.456]
136
137
  ]
137
138
 
138
- subject.start_with(input)
139
- subject.tokens[0..-2].each_with_index do |tok, i|
140
- expect(tok).to be_kind_of(Rley::Lexical::Literal)
139
+ scanner.start_with(input)
140
+ scanner.tokens[0..-2].each_with_index do |tok, i|
141
+ expect(tok).to be_a(Rley::Lexical::Literal)
141
142
  expect(tok.terminal).to eq('NUMBER')
142
143
  (lexeme, val) = expectations[i]
143
144
  expect(tok.lexeme).to eq(lexeme)
144
- expect(tok.value).to be_kind_of(Datatype::Number)
145
+ expect(tok.value).to be_a(Datatype::Number)
145
146
  expect(tok.value.value).to eq(val)
146
147
  end
147
148
  end
148
149
 
149
- it 'should recognize negative number values' do
150
+ it 'recognizes negative number values' do
150
151
  input = <<-LOX_END
151
152
  -0
152
153
  -0.001
@@ -157,8 +158,8 @@ LOX_END
157
158
  ['-', '0.001']
158
159
  ].flatten
159
160
 
160
- subject.start_with(input)
161
- tokens = subject.tokens
161
+ scanner.start_with(input)
162
+ tokens = scanner.tokens
162
163
  tokens.pop
163
164
  i = 0
164
165
  tokens.each_slice(2) do |(sign, lit)|
@@ -170,24 +171,24 @@ LOX_END
170
171
  end
171
172
  end
172
173
 
173
- it 'should recognize leading and trailing dots as distinct tokens' do
174
+ it 'recognizes leading and trailing dots as distinct tokens' do
174
175
  input = '.456 123.'
175
176
 
176
- subject.start_with(input)
177
- tokens = subject.tokens[0..-2]
178
- expect(tokens[0]).to be_kind_of(Rley::Lexical::Token)
177
+ scanner.start_with(input)
178
+ tokens = scanner.tokens[0..-2]
179
+ expect(tokens[0]).to be_a(Rley::Lexical::Token)
179
180
  expect(tokens[0].terminal).to eq('DOT')
180
- expect(tokens[1]).to be_kind_of(Rley::Lexical::Literal)
181
+ expect(tokens[1]).to be_a(Rley::Lexical::Literal)
181
182
  expect(tokens[1].terminal).to eq('NUMBER')
182
183
  expect(tokens[1].value.value).to eq(456)
183
- expect(tokens[2]).to be_kind_of(Rley::Lexical::Literal)
184
+ expect(tokens[2]).to be_a(Rley::Lexical::Literal)
184
185
  expect(tokens[2].terminal).to eq('NUMBER')
185
186
  expect(tokens[2].value.value).to eq(123)
186
- expect(tokens[3]).to be_kind_of(Rley::Lexical::Token)
187
+ expect(tokens[3]).to be_a(Rley::Lexical::Token)
187
188
  expect(tokens[3].terminal).to eq('DOT')
188
189
  end
189
190
 
190
- it 'should recognize string values' do
191
+ it 'recognizes string values' do
191
192
  input = <<-LOX_END
192
193
  ""
193
194
  "string"
@@ -200,85 +201,85 @@ LOX_END
200
201
  '123'
201
202
  ]
202
203
 
203
- subject.start_with(input)
204
- subject.tokens[0..-2].each_with_index do |str, i|
205
- expect(str).to be_kind_of(Rley::Lexical::Literal)
204
+ scanner.start_with(input)
205
+ scanner.tokens[0..-2].each_with_index do |str, i|
206
+ expect(str).to be_a(Rley::Lexical::Literal)
206
207
  expect(str.terminal).to eq('STRING')
207
208
  val = expectations[i]
208
- expect(str.value).to be_kind_of(Datatype::LXString)
209
+ expect(str.value).to be_a(Datatype::LXString)
209
210
  expect(str.value.value).to eq(val)
210
211
  end
211
212
  end
212
213
 
213
- it 'should recognize escaped quotes' do
214
+ it 'recognizes escaped quotes' do
214
215
  embedded_quotes = %q{"she said: \"Hello\""}
215
- subject.start_with(embedded_quotes)
216
- result = subject.tokens[0]
216
+ scanner.start_with(embedded_quotes)
217
+ result = scanner.tokens[0]
217
218
  expect(result.value).to eq('she said: "Hello"')
218
219
  end
219
220
 
220
- it 'should recognize escaped backslash' do
221
+ it 'recognizes escaped backslash' do
221
222
  embedded_backslash = '"backslash>\\\\"'
222
- subject.start_with(embedded_backslash)
223
- result = subject.tokens[0]
223
+ scanner.start_with(embedded_backslash)
224
+ result = scanner.tokens[0]
224
225
  expect(result.value).to eq('backslash>\\')
225
226
  end
226
227
 
227
228
  # rubocop: disable Style/StringConcatenation
228
- it 'should recognize newline escape sequence' do
229
+ it 'recognizes newline escape sequence' do
229
230
  embedded_newline = '"line1\\nline2"'
230
- subject.start_with(embedded_newline)
231
- result = subject.tokens[0]
231
+ scanner.start_with(embedded_newline)
232
+ result = scanner.tokens[0]
232
233
  expect(result.value).to eq('line1' + "\n" + 'line2')
233
234
  end
234
235
  # rubocop: enable Style/StringConcatenation
235
236
 
236
- it 'should recognize a nil token' do
237
- subject.start_with('nil')
238
- token_nil = subject.tokens[0]
239
- expect(token_nil).to be_kind_of(Rley::Lexical::Literal)
237
+ it 'recognizes a nil token' do
238
+ scanner.start_with('nil')
239
+ token_nil = scanner.tokens[0]
240
+ expect(token_nil).to be_a(Rley::Lexical::Literal)
240
241
  expect(token_nil.terminal).to eq('NIL')
241
242
  expect(token_nil.lexeme).to eq('nil')
242
- expect(token_nil.value).to be_kind_of(Datatype::Nil)
243
+ expect(token_nil.value).to be_a(Datatype::Nil)
243
244
  end
244
245
 
245
- it 'should differentiate nil from variable spelled same' do
246
- subject.start_with('Nil')
247
- similar = subject.tokens[0]
246
+ it 'differentiates nil from variable spelled same' do
247
+ scanner.start_with('Nil')
248
+ similar = scanner.tokens[0]
248
249
  expect(similar.terminal).to eq('IDENTIFIER')
249
250
  expect(similar.lexeme).to eq('Nil')
250
251
  end
251
252
  end # context
252
253
 
253
254
  context 'Handling comments:' do
254
- it 'should cope with one line comment only' do
255
- subject.start_with('// comment')
255
+ it 'copes with one line comment only' do
256
+ scanner.start_with('// comment')
256
257
 
257
258
  # No token found, except eof marker
258
- eof_token = subject.tokens[0]
259
+ eof_token = scanner.tokens[0]
259
260
  expect(eof_token.terminal).to eq('EOF')
260
261
  end
261
262
 
262
263
  # rubocop: disable Lint/PercentStringArray
263
- it 'should skip end of line comments' do
264
+ it 'skips end of line comments' do
264
265
  input = <<-LOX_END
265
266
  // first comment
266
267
  print "ok"; // second comment
267
268
  // third comment
268
269
  LOX_END
269
- subject.start_with(input)
270
+ scanner.start_with(input)
270
271
  expectations = [
271
272
  # [token lexeme]
272
273
  %w[PRINT print],
273
274
  %w[STRING "ok"],
274
275
  %w[SEMICOLON ;]
275
276
  ]
276
- match_expectations(subject, expectations)
277
+ match_expectations(scanner, expectations)
277
278
  end
278
279
  # rubocop: enable Lint/PercentStringArray
279
280
 
280
- it 'should cope with single slash (divide) expression' do
281
- subject.start_with('8 / 2')
281
+ it 'copes with single slash (divide) expression' do
282
+ scanner.start_with('8 / 2')
282
283
 
283
284
  expectations = [
284
285
  # [token lexeme]
@@ -286,21 +287,21 @@ LOX_END
286
287
  %w[SLASH /],
287
288
  %w[NUMBER 2]
288
289
  ]
289
- match_expectations(subject, expectations)
290
+ match_expectations(scanner, expectations)
290
291
  end
291
292
 
292
- it 'should complain if it finds an unterminated string' do
293
- subject.start_with('var a = "Unfinished;')
293
+ it 'complains if it finds an unterminated string' do
294
+ scanner.start_with('var a = "Unfinished;')
294
295
  err = Loxxy::ScanError
295
296
  err_msg = 'Error: [line 1:9]: Unterminated string.'
296
- expect { subject.tokens }.to raise_error(err, err_msg)
297
+ expect { scanner.tokens }.to raise_error(err, err_msg)
297
298
  end
298
299
 
299
- it 'should complain if it finds an unexpected character' do
300
- subject.start_with('var a = ?1?;')
300
+ it 'complains if it finds an unexpected character' do
301
+ scanner.start_with('var a = ?1?;')
301
302
  err = Loxxy::ScanError
302
303
  err_msg = 'Error: [line 1:9]: Unexpected character.'
303
- expect { subject.tokens }.to raise_error(err, err_msg)
304
+ expect { scanner.tokens }.to raise_error(err, err_msg)
304
305
  end
305
306
  end # context
306
307
  end # describe