plurimath-parslet 3.0.0

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.
Files changed (148) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY.txt +284 -0
  3. data/LICENSE +23 -0
  4. data/README.adoc +454 -0
  5. data/Rakefile +71 -0
  6. data/lib/parslet/accelerator/application.rb +62 -0
  7. data/lib/parslet/accelerator/engine.rb +112 -0
  8. data/lib/parslet/accelerator.rb +162 -0
  9. data/lib/parslet/atoms/alternative.rb +53 -0
  10. data/lib/parslet/atoms/base.rb +157 -0
  11. data/lib/parslet/atoms/can_flatten.rb +137 -0
  12. data/lib/parslet/atoms/capture.rb +38 -0
  13. data/lib/parslet/atoms/context.rb +103 -0
  14. data/lib/parslet/atoms/dsl.rb +112 -0
  15. data/lib/parslet/atoms/dynamic.rb +32 -0
  16. data/lib/parslet/atoms/entity.rb +45 -0
  17. data/lib/parslet/atoms/ignored.rb +26 -0
  18. data/lib/parslet/atoms/infix.rb +115 -0
  19. data/lib/parslet/atoms/lookahead.rb +52 -0
  20. data/lib/parslet/atoms/named.rb +32 -0
  21. data/lib/parslet/atoms/re.rb +41 -0
  22. data/lib/parslet/atoms/repetition.rb +87 -0
  23. data/lib/parslet/atoms/scope.rb +26 -0
  24. data/lib/parslet/atoms/sequence.rb +48 -0
  25. data/lib/parslet/atoms/str.rb +42 -0
  26. data/lib/parslet/atoms/visitor.rb +89 -0
  27. data/lib/parslet/atoms.rb +34 -0
  28. data/lib/parslet/cause.rb +101 -0
  29. data/lib/parslet/context.rb +21 -0
  30. data/lib/parslet/convenience.rb +33 -0
  31. data/lib/parslet/error_reporter/contextual.rb +120 -0
  32. data/lib/parslet/error_reporter/deepest.rb +100 -0
  33. data/lib/parslet/error_reporter/tree.rb +63 -0
  34. data/lib/parslet/error_reporter.rb +8 -0
  35. data/lib/parslet/export.rb +163 -0
  36. data/lib/parslet/expression/treetop.rb +92 -0
  37. data/lib/parslet/expression.rb +51 -0
  38. data/lib/parslet/graphviz.rb +97 -0
  39. data/lib/parslet/parser.rb +68 -0
  40. data/lib/parslet/pattern/binding.rb +49 -0
  41. data/lib/parslet/pattern.rb +113 -0
  42. data/lib/parslet/position.rb +21 -0
  43. data/lib/parslet/rig/rspec.rb +52 -0
  44. data/lib/parslet/scope.rb +42 -0
  45. data/lib/parslet/slice.rb +105 -0
  46. data/lib/parslet/source/line_cache.rb +99 -0
  47. data/lib/parslet/source.rb +96 -0
  48. data/lib/parslet/transform.rb +265 -0
  49. data/lib/parslet/version.rb +5 -0
  50. data/lib/parslet.rb +314 -0
  51. data/plurimath-parslet.gemspec +42 -0
  52. data/spec/acceptance/infix_parser_spec.rb +145 -0
  53. data/spec/acceptance/mixing_parsers_spec.rb +74 -0
  54. data/spec/acceptance/regression_spec.rb +329 -0
  55. data/spec/acceptance/repetition_and_maybe_spec.rb +44 -0
  56. data/spec/acceptance/unconsumed_input_spec.rb +21 -0
  57. data/spec/examples/boolean_algebra_spec.rb +257 -0
  58. data/spec/examples/calc_spec.rb +278 -0
  59. data/spec/examples/capture_spec.rb +137 -0
  60. data/spec/examples/comments_spec.rb +186 -0
  61. data/spec/examples/deepest_errors_spec.rb +420 -0
  62. data/spec/examples/documentation_spec.rb +205 -0
  63. data/spec/examples/email_parser_spec.rb +275 -0
  64. data/spec/examples/empty_spec.rb +37 -0
  65. data/spec/examples/erb_spec.rb +482 -0
  66. data/spec/examples/ip_address_spec.rb +153 -0
  67. data/spec/examples/json_spec.rb +413 -0
  68. data/spec/examples/local_spec.rb +302 -0
  69. data/spec/examples/mathn_spec.rb +151 -0
  70. data/spec/examples/minilisp_spec.rb +492 -0
  71. data/spec/examples/modularity_spec.rb +340 -0
  72. data/spec/examples/nested_errors_spec.rb +322 -0
  73. data/spec/examples/optimized_erb_spec.rb +299 -0
  74. data/spec/examples/parens_spec.rb +239 -0
  75. data/spec/examples/prec_calc_spec.rb +525 -0
  76. data/spec/examples/readme_spec.rb +228 -0
  77. data/spec/examples/scopes_spec.rb +187 -0
  78. data/spec/examples/seasons_spec.rb +196 -0
  79. data/spec/examples/sentence_spec.rb +119 -0
  80. data/spec/examples/simple_xml_spec.rb +250 -0
  81. data/spec/examples/string_parser_spec.rb +407 -0
  82. data/spec/fixtures/examples/boolean_algebra.rb +62 -0
  83. data/spec/fixtures/examples/calc.rb +86 -0
  84. data/spec/fixtures/examples/capture.rb +36 -0
  85. data/spec/fixtures/examples/comments.rb +22 -0
  86. data/spec/fixtures/examples/deepest_errors.rb +99 -0
  87. data/spec/fixtures/examples/documentation.rb +32 -0
  88. data/spec/fixtures/examples/email_parser.rb +42 -0
  89. data/spec/fixtures/examples/empty.rb +10 -0
  90. data/spec/fixtures/examples/erb.rb +39 -0
  91. data/spec/fixtures/examples/ip_address.rb +103 -0
  92. data/spec/fixtures/examples/json.rb +107 -0
  93. data/spec/fixtures/examples/local.rb +60 -0
  94. data/spec/fixtures/examples/mathn.rb +47 -0
  95. data/spec/fixtures/examples/minilisp.rb +75 -0
  96. data/spec/fixtures/examples/modularity.rb +60 -0
  97. data/spec/fixtures/examples/nested_errors.rb +95 -0
  98. data/spec/fixtures/examples/optimized_erb.rb +105 -0
  99. data/spec/fixtures/examples/parens.rb +25 -0
  100. data/spec/fixtures/examples/prec_calc.rb +71 -0
  101. data/spec/fixtures/examples/readme.rb +59 -0
  102. data/spec/fixtures/examples/scopes.rb +43 -0
  103. data/spec/fixtures/examples/seasons.rb +40 -0
  104. data/spec/fixtures/examples/sentence.rb +18 -0
  105. data/spec/fixtures/examples/simple_xml.rb +51 -0
  106. data/spec/fixtures/examples/string_parser.rb +77 -0
  107. data/spec/parslet/atom_results_spec.rb +39 -0
  108. data/spec/parslet/atoms/alternative_spec.rb +26 -0
  109. data/spec/parslet/atoms/base_spec.rb +127 -0
  110. data/spec/parslet/atoms/capture_spec.rb +21 -0
  111. data/spec/parslet/atoms/combinations_spec.rb +5 -0
  112. data/spec/parslet/atoms/dsl_spec.rb +7 -0
  113. data/spec/parslet/atoms/entity_spec.rb +77 -0
  114. data/spec/parslet/atoms/ignored_spec.rb +15 -0
  115. data/spec/parslet/atoms/infix_spec.rb +5 -0
  116. data/spec/parslet/atoms/lookahead_spec.rb +22 -0
  117. data/spec/parslet/atoms/named_spec.rb +4 -0
  118. data/spec/parslet/atoms/re_spec.rb +14 -0
  119. data/spec/parslet/atoms/repetition_spec.rb +24 -0
  120. data/spec/parslet/atoms/scope_spec.rb +26 -0
  121. data/spec/parslet/atoms/sequence_spec.rb +28 -0
  122. data/spec/parslet/atoms/str_spec.rb +15 -0
  123. data/spec/parslet/atoms/visitor_spec.rb +101 -0
  124. data/spec/parslet/atoms_spec.rb +488 -0
  125. data/spec/parslet/convenience_spec.rb +54 -0
  126. data/spec/parslet/error_reporter/contextual_spec.rb +118 -0
  127. data/spec/parslet/error_reporter/deepest_spec.rb +82 -0
  128. data/spec/parslet/error_reporter/tree_spec.rb +7 -0
  129. data/spec/parslet/export_spec.rb +40 -0
  130. data/spec/parslet/expression/treetop_spec.rb +74 -0
  131. data/spec/parslet/minilisp.citrus +29 -0
  132. data/spec/parslet/minilisp.tt +29 -0
  133. data/spec/parslet/parser_spec.rb +36 -0
  134. data/spec/parslet/parslet_spec.rb +38 -0
  135. data/spec/parslet/pattern_spec.rb +272 -0
  136. data/spec/parslet/position_spec.rb +14 -0
  137. data/spec/parslet/rig/rspec_spec.rb +54 -0
  138. data/spec/parslet/scope_spec.rb +45 -0
  139. data/spec/parslet/slice_spec.rb +186 -0
  140. data/spec/parslet/source/line_cache_spec.rb +74 -0
  141. data/spec/parslet/source_spec.rb +210 -0
  142. data/spec/parslet/transform/context_spec.rb +56 -0
  143. data/spec/parslet/transform_spec.rb +183 -0
  144. data/spec/spec_helper.rb +74 -0
  145. data/spec/support/opal.rb +8 -0
  146. data/spec/support/opal.rb.erb +14 -0
  147. data/spec/support/parslet_matchers.rb +96 -0
  148. metadata +240 -0
@@ -0,0 +1,492 @@
1
+ require 'spec_helper'
2
+ require_relative '../fixtures/examples/minilisp'
3
+
4
+ RSpec.describe 'MiniLisp Parser Example' do
5
+ let(:parser) { MiniLisp::Parser.new }
6
+ let(:transform) { MiniLisp::Transform.new }
7
+
8
+ describe MiniLisp::Parser do
9
+ describe '#space' do
10
+ it 'parses single space' do
11
+ result = parser.space.parse(' ')
12
+ expect(result).to eq(' ')
13
+ end
14
+
15
+ it 'parses multiple spaces' do
16
+ result = parser.space.parse(' ')
17
+ expect(result).to eq(' ')
18
+ end
19
+
20
+ it 'parses tabs and newlines' do
21
+ result = parser.space.parse("\t\n ")
22
+ expect(result).to eq("\t\n ")
23
+ end
24
+
25
+ it 'fails on empty string' do
26
+ expect { parser.space.parse('') }.to raise_error(Parslet::ParseFailed)
27
+ end
28
+ end
29
+
30
+ describe '#space?' do
31
+ it 'parses optional space' do
32
+ result = parser.space?.parse(' ')
33
+ expect(result).to eq(' ')
34
+ end
35
+
36
+ it 'parses empty string' do
37
+ result = parser.space?.parse('')
38
+ expect(result).to eq('')
39
+ end
40
+
41
+ it 'parses multiple spaces' do
42
+ result = parser.space?.parse(' ')
43
+ expect(result).to eq(' ')
44
+ end
45
+ end
46
+
47
+ describe '#identifier' do
48
+ it 'parses simple identifier' do
49
+ result = parser.identifier.parse('test')
50
+ expected = { identifier: 'test' }
51
+ expect(result).to parse_as(expected)
52
+ end
53
+
54
+ it 'parses identifier with underscores' do
55
+ result = parser.identifier.parse('test_var')
56
+ expected = { identifier: 'test_var' }
57
+ expect(result).to parse_as(expected)
58
+ end
59
+
60
+ it 'parses identifier with equals' do
61
+ result = parser.identifier.parse('=')
62
+ expected = { identifier: '=' }
63
+ expect(result).to parse_as(expected)
64
+ end
65
+
66
+ it 'parses identifier with asterisk' do
67
+ result = parser.identifier.parse('*global*')
68
+ expected = { identifier: '*global*' }
69
+ expect(result).to parse_as(expected)
70
+ end
71
+
72
+ it 'parses identifier with trailing space' do
73
+ result = parser.identifier.parse('test ')
74
+ expected = { identifier: 'test' }
75
+ expect(result).to parse_as(expected)
76
+ end
77
+
78
+ it 'parses mixed case identifier' do
79
+ result = parser.identifier.parse('TestVar')
80
+ expected = { identifier: 'TestVar' }
81
+ expect(result).to parse_as(expected)
82
+ end
83
+
84
+ it 'fails on identifier starting with number' do
85
+ expect { parser.identifier.parse('1test') }.to raise_error(Parslet::ParseFailed)
86
+ end
87
+
88
+ it 'fails on empty string' do
89
+ expect { parser.identifier.parse('') }.to raise_error(Parslet::ParseFailed)
90
+ end
91
+ end
92
+
93
+ describe '#integer' do
94
+ it 'parses positive integer' do
95
+ result = parser.integer.parse('123')
96
+ expected = { integer: '123' }
97
+ expect(result).to parse_as(expected)
98
+ end
99
+
100
+ it 'parses negative integer' do
101
+ result = parser.integer.parse('-123')
102
+ expected = { integer: '-123' }
103
+ expect(result).to parse_as(expected)
104
+ end
105
+
106
+ it 'parses integer with plus sign' do
107
+ result = parser.integer.parse('+123')
108
+ expected = { integer: '+123' }
109
+ expect(result).to parse_as(expected)
110
+ end
111
+
112
+ it 'parses single digit' do
113
+ result = parser.integer.parse('5')
114
+ expected = { integer: '5' }
115
+ expect(result).to parse_as(expected)
116
+ end
117
+
118
+ it 'parses zero' do
119
+ result = parser.integer.parse('0')
120
+ expected = { integer: '0' }
121
+ expect(result).to parse_as(expected)
122
+ end
123
+
124
+ it 'parses integer with trailing space' do
125
+ result = parser.integer.parse('123 ')
126
+ expected = { integer: '123' }
127
+ expect(result).to parse_as(expected)
128
+ end
129
+
130
+ it 'fails on empty string' do
131
+ expect { parser.integer.parse('') }.to raise_error(Parslet::ParseFailed)
132
+ end
133
+
134
+ it 'fails on just sign' do
135
+ expect { parser.integer.parse('+') }.to raise_error(Parslet::ParseFailed)
136
+ end
137
+ end
138
+
139
+ describe '#float' do
140
+ it 'parses decimal float' do
141
+ result = parser.float.parse('123.45')
142
+ expected = { float: { integer: '123', e: '.45' } }
143
+ expect(result).to parse_as(expected)
144
+ end
145
+
146
+ it 'parses scientific notation' do
147
+ result = parser.float.parse('123e45')
148
+ expected = { float: { integer: '123', e: 'e45' } }
149
+ expect(result).to parse_as(expected)
150
+ end
151
+
152
+ it 'parses negative float' do
153
+ result = parser.float.parse('-123.45')
154
+ expected = { float: { integer: '-123', e: '.45' } }
155
+ expect(result).to parse_as(expected)
156
+ end
157
+
158
+ it 'parses float with plus sign' do
159
+ result = parser.float.parse('+123.45')
160
+ expected = { float: { integer: '+123', e: '.45' } }
161
+ expect(result).to parse_as(expected)
162
+ end
163
+
164
+ it 'parses float with trailing space' do
165
+ result = parser.float.parse('123.45 ')
166
+ expected = { float: { integer: '123', e: '.45' } }
167
+ expect(result).to parse_as(expected)
168
+ end
169
+
170
+ it 'parses zero float' do
171
+ result = parser.float.parse('0.0')
172
+ expected = { float: { integer: '0', e: '.0' } }
173
+ expect(result).to parse_as(expected)
174
+ end
175
+
176
+ it 'fails on integer without decimal part' do
177
+ expect { parser.float.parse('123') }.to raise_error(Parslet::ParseFailed)
178
+ end
179
+
180
+ it 'fails on decimal point without digits' do
181
+ expect { parser.float.parse('123.') }.to raise_error(Parslet::ParseFailed)
182
+ end
183
+ end
184
+
185
+ describe '#string' do
186
+ it 'parses simple string' do
187
+ result = parser.string.parse('"hello"')
188
+ expected = { string: 'hello' }
189
+ expect(result).to parse_as(expected)
190
+ end
191
+
192
+ it 'parses empty string' do
193
+ result = parser.string.parse('""')
194
+ expected = { string: [] }
195
+ expect(result).to parse_as(expected)
196
+ end
197
+
198
+ it 'parses string with spaces' do
199
+ result = parser.string.parse('"hello world"')
200
+ expected = { string: 'hello world' }
201
+ expect(result).to parse_as(expected)
202
+ end
203
+
204
+ it 'parses string with trailing space' do
205
+ result = parser.string.parse('"hello" ')
206
+ expected = { string: 'hello' }
207
+ expect(result).to parse_as(expected)
208
+ end
209
+
210
+ it 'parses string with numbers' do
211
+ result = parser.string.parse('"test123"')
212
+ expected = { string: 'test123' }
213
+ expect(result).to parse_as(expected)
214
+ end
215
+
216
+ it 'fails on unclosed string' do
217
+ expect { parser.string.parse('"hello') }.to raise_error(Parslet::ParseFailed)
218
+ end
219
+
220
+ it 'fails on string without opening quote' do
221
+ expect { parser.string.parse('hello"') }.to raise_error(Parslet::ParseFailed)
222
+ end
223
+ end
224
+
225
+ describe '#body' do
226
+ it 'parses single identifier' do
227
+ result = parser.body.parse('test')
228
+ expected = { exp: [{ identifier: 'test' }] }
229
+ expect(result).to parse_as(expected)
230
+ end
231
+
232
+ it 'parses multiple identifiers' do
233
+ result = parser.body.parse('test var')
234
+ expected = { exp: [{ identifier: 'test' }, { identifier: 'var' }] }
235
+ expect(result).to parse_as(expected)
236
+ end
237
+
238
+ it 'parses mixed types' do
239
+ result = parser.body.parse('test 123 "hello"')
240
+ expected = {
241
+ exp: [
242
+ { identifier: 'test' },
243
+ { integer: '123' },
244
+ { string: 'hello' }
245
+ ]
246
+ }
247
+ expect(result).to parse_as(expected)
248
+ end
249
+
250
+ it 'parses nested expression' do
251
+ result = parser.body.parse('(test)')
252
+ expected = {
253
+ exp: [
254
+ { exp: [{ identifier: 'test' }] }
255
+ ]
256
+ }
257
+ expect(result).to parse_as(expected)
258
+ end
259
+
260
+ it 'parses empty body' do
261
+ result = parser.body.parse('')
262
+ expected = { exp: [] }
263
+ expect(result).to parse_as(expected)
264
+ end
265
+ end
266
+
267
+ describe '#expression (root)' do
268
+ it 'parses simple expression' do
269
+ result = parser.parse('(test)')
270
+ expected = { exp: [{ identifier: 'test' }] }
271
+ expect(result).to parse_as(expected)
272
+ end
273
+
274
+ it 'parses expression with string' do
275
+ result = parser.parse('(display "hello")')
276
+ expected = {
277
+ exp: [
278
+ { identifier: 'display' },
279
+ { string: 'hello' }
280
+ ]
281
+ }
282
+ expect(result).to parse_as(expected)
283
+ end
284
+
285
+ it 'parses empty expression' do
286
+ result = parser.parse('()')
287
+ expected = { exp: [] }
288
+ expect(result).to parse_as(expected)
289
+ end
290
+
291
+ it 'handles whitespace around expression' do
292
+ result = parser.parse(' ( test ) ')
293
+ expected = { exp: [{ identifier: 'test' }] }
294
+ expect(result).to parse_as(expected)
295
+ end
296
+
297
+ it 'fails on unclosed expression' do
298
+ expect { parser.parse('(test') }.to raise_error(Parslet::ParseFailed)
299
+ end
300
+
301
+ it 'fails on expression without opening paren' do
302
+ expect { parser.parse('test)') }.to raise_error(Parslet::ParseFailed)
303
+ end
304
+
305
+ it 'fails on mismatched parens' do
306
+ expect { parser.parse('(test))') }.to raise_error(Parslet::ParseFailed)
307
+ end
308
+ end
309
+
310
+ describe 'error handling' do
311
+ it 'provides meaningful error for invalid syntax' do
312
+ expect { parser.parse('(test invalid@symbol)') }.to raise_error(Parslet::ParseFailed)
313
+ end
314
+
315
+ it 'handles unclosed strings in expressions' do
316
+ expect { parser.parse('(test "unclosed)') }.to raise_error(Parslet::ParseFailed)
317
+ end
318
+ end
319
+ end
320
+
321
+ describe MiniLisp::Transform do
322
+ describe 'identifier transformation' do
323
+ it 'transforms identifier to symbol' do
324
+ parsed = { identifier: 'test' }
325
+ result = transform.do(parsed)
326
+ expect(result).to eq(:test)
327
+ end
328
+
329
+ it 'transforms special identifiers' do
330
+ parsed = { identifier: '+' }
331
+ result = transform.do(parsed)
332
+ expect(result).to eq(:+)
333
+ end
334
+
335
+ it 'transforms identifier with underscores' do
336
+ parsed = { identifier: 'test_var' }
337
+ result = transform.do(parsed)
338
+ expect(result).to eq(:test_var)
339
+ end
340
+ end
341
+
342
+ describe 'string transformation' do
343
+ it 'transforms string to string' do
344
+ parsed = { string: 'hello' }
345
+ result = transform.do(parsed)
346
+ expect(result).to eq('hello')
347
+ end
348
+
349
+ it 'transforms empty string' do
350
+ parsed = { string: [] }
351
+ result = transform.do(parsed)
352
+ expect(result).to eq({ string: [] })
353
+ end
354
+
355
+ it 'transforms string with spaces' do
356
+ parsed = { string: 'hello world' }
357
+ result = transform.do(parsed)
358
+ expect(result).to eq('hello world')
359
+ end
360
+ end
361
+
362
+ describe 'integer transformation' do
363
+ it 'transforms positive integer' do
364
+ parsed = { integer: '123' }
365
+ result = transform.do(parsed)
366
+ expect(result).to eq(123)
367
+ end
368
+
369
+ it 'transforms negative integer' do
370
+ parsed = { integer: '-123' }
371
+ result = transform.do(parsed)
372
+ expect(result).to eq(-123)
373
+ end
374
+
375
+ it 'transforms zero' do
376
+ parsed = { integer: '0' }
377
+ result = transform.do(parsed)
378
+ expect(result).to eq(0)
379
+ end
380
+
381
+ it 'transforms integer with plus sign' do
382
+ parsed = { integer: '+123' }
383
+ result = transform.do(parsed)
384
+ expect(result).to eq(123)
385
+ end
386
+ end
387
+
388
+ describe 'float transformation' do
389
+ it 'transforms decimal float' do
390
+ parsed = { float: { integer: '123', e: '.45' } }
391
+ result = transform.do(parsed)
392
+ expect(result).to eq(123.45)
393
+ end
394
+
395
+ it 'transforms scientific notation' do
396
+ parsed = { float: { integer: '123', e: 'e45' } }
397
+ result = transform.do(parsed)
398
+ expect(result).to eq(123e45)
399
+ end
400
+
401
+ it 'transforms negative float' do
402
+ parsed = { float: { integer: '-123', e: '.45' } }
403
+ result = transform.do(parsed)
404
+ expect(result).to eq(-123.45)
405
+ end
406
+
407
+ it 'transforms zero float' do
408
+ parsed = { float: { integer: '0', e: '.0' } }
409
+ result = transform.do(parsed)
410
+ expect(result).to eq(0.0)
411
+ end
412
+ end
413
+
414
+ describe 'expression transformation' do
415
+ it 'transforms expression list' do
416
+ parsed = { exp: [{ identifier: 'test' }, { integer: '123' }] }
417
+ result = transform.do(parsed)
418
+ expect(result).to eq([:test, 123])
419
+ end
420
+
421
+ it 'transforms empty expression' do
422
+ parsed = { exp: [] }
423
+ result = transform.do(parsed)
424
+ expect(result).to eq([])
425
+ end
426
+
427
+ it 'transforms nested expressions' do
428
+ parsed = {
429
+ exp: [
430
+ { identifier: 'display' },
431
+ { exp: [{ identifier: 'test' }] }
432
+ ]
433
+ }
434
+ result = transform.do(parsed)
435
+ expect(result).to eq([:display, [:test]])
436
+ end
437
+ end
438
+
439
+ describe 'integration transformation' do
440
+ it 'transforms function call with string' do
441
+ input = '(display "hello world")'
442
+ parsed = parser.parse(input)
443
+ result = transform.do(parsed)
444
+ expect(result).to eq([:display, "hello world"])
445
+ end
446
+
447
+ it 'transforms simple function call' do
448
+ input = '(test)'
449
+ parsed = parser.parse(input)
450
+ result = transform.do(parsed)
451
+ expect(result).to eq([:test])
452
+ end
453
+
454
+ it 'transforms nested function calls' do
455
+ input = '(outer (inner))'
456
+ parsed = parser.parse(input)
457
+ result = transform.do(parsed)
458
+ expect(result).to eq([:outer, [:inner]])
459
+ end
460
+ end
461
+ end
462
+
463
+ describe 'parser and transformer integration' do
464
+ it 'processes simple lisp expression end-to-end' do
465
+ input = '(test)'
466
+ parsed = parser.parse(input)
467
+ result = transform.do(parsed)
468
+ expect(result).to eq([:test])
469
+ end
470
+
471
+ it 'processes function call with string end-to-end' do
472
+ input = '(display "hello")'
473
+ parsed = parser.parse(input)
474
+ result = transform.do(parsed)
475
+ expect(result).to eq([:display, "hello"])
476
+ end
477
+
478
+ it 'processes nested expressions end-to-end' do
479
+ input = '(outer (inner "value"))'
480
+ parsed = parser.parse(input)
481
+ result = transform.do(parsed)
482
+ expect(result).to eq([:outer, [:inner, "value"]])
483
+ end
484
+
485
+ it 'processes empty expression end-to-end' do
486
+ input = '()'
487
+ parsed = parser.parse(input)
488
+ result = transform.do(parsed)
489
+ expect(result).to eq([])
490
+ end
491
+ end
492
+ end