prism 1.4.0 → 1.5.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -1
  3. data/Makefile +2 -1
  4. data/README.md +1 -0
  5. data/config.yml +264 -37
  6. data/docs/parser_translation.md +8 -23
  7. data/docs/ripper_translation.md +1 -1
  8. data/ext/prism/api_node.c +2 -0
  9. data/ext/prism/extension.c +14 -1
  10. data/ext/prism/extension.h +1 -1
  11. data/include/prism/ast.h +275 -49
  12. data/include/prism/diagnostic.h +4 -0
  13. data/include/prism/options.h +43 -3
  14. data/include/prism/regexp.h +2 -2
  15. data/include/prism/util/pm_buffer.h +8 -0
  16. data/include/prism/util/pm_integer.h +4 -0
  17. data/include/prism/util/pm_list.h +6 -0
  18. data/include/prism/util/pm_string.h +12 -2
  19. data/include/prism/version.h +2 -2
  20. data/include/prism.h +39 -14
  21. data/lib/prism/compiler.rb +456 -151
  22. data/lib/prism/desugar_compiler.rb +1 -0
  23. data/lib/prism/dispatcher.rb +16 -0
  24. data/lib/prism/dot_visitor.rb +5 -1
  25. data/lib/prism/dsl.rb +3 -0
  26. data/lib/prism/ffi.rb +17 -7
  27. data/lib/prism/inspect_visitor.rb +3 -0
  28. data/lib/prism/lex_compat.rb +1 -0
  29. data/lib/prism/mutation_compiler.rb +3 -0
  30. data/lib/prism/node.rb +506 -335
  31. data/lib/prism/node_ext.rb +4 -1
  32. data/lib/prism/pack.rb +2 -0
  33. data/lib/prism/parse_result/comments.rb +1 -0
  34. data/lib/prism/parse_result/errors.rb +1 -0
  35. data/lib/prism/parse_result/newlines.rb +1 -0
  36. data/lib/prism/parse_result.rb +1 -0
  37. data/lib/prism/pattern.rb +1 -0
  38. data/lib/prism/polyfill/scan_byte.rb +14 -0
  39. data/lib/prism/polyfill/warn.rb +42 -0
  40. data/lib/prism/reflection.rb +3 -0
  41. data/lib/prism/relocation.rb +1 -0
  42. data/lib/prism/serialize.rb +24 -19
  43. data/lib/prism/string_query.rb +1 -0
  44. data/lib/prism/translation/parser/builder.rb +1 -0
  45. data/lib/prism/translation/parser/compiler.rb +47 -25
  46. data/lib/prism/translation/parser/lexer.rb +29 -21
  47. data/lib/prism/translation/parser.rb +13 -1
  48. data/lib/prism/translation/parser33.rb +1 -0
  49. data/lib/prism/translation/parser34.rb +1 -0
  50. data/lib/prism/translation/parser35.rb +1 -0
  51. data/lib/prism/translation/parser_current.rb +24 -0
  52. data/lib/prism/translation/ripper/sexp.rb +1 -0
  53. data/lib/prism/translation/ripper.rb +17 -1
  54. data/lib/prism/translation/ruby_parser.rb +286 -3
  55. data/lib/prism/translation.rb +2 -0
  56. data/lib/prism/visitor.rb +457 -152
  57. data/lib/prism.rb +2 -0
  58. data/prism.gemspec +5 -1
  59. data/rbi/prism/dsl.rbi +3 -3
  60. data/rbi/prism/node.rbi +21 -9
  61. data/sig/prism/dispatcher.rbs +3 -0
  62. data/sig/prism/dsl.rbs +3 -3
  63. data/sig/prism/node.rbs +444 -30
  64. data/sig/prism/node_ext.rbs +84 -17
  65. data/sig/prism/parse_result/comments.rbs +38 -0
  66. data/sig/prism/parse_result.rbs +4 -0
  67. data/sig/prism/reflection.rbs +1 -1
  68. data/src/diagnostic.c +7 -1
  69. data/src/node.c +2 -0
  70. data/src/options.c +2 -2
  71. data/src/prettyprint.c +2 -0
  72. data/src/prism.c +252 -130
  73. data/src/serialize.c +2 -0
  74. data/src/token_type.c +36 -34
  75. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0209a58426470fc6afedb5922c9bf9264cb9ccd2debbef68fb1a307a4d1be78
4
- data.tar.gz: 491a11ab3d9d840f4ac228e8b79e85ddb24ae1f82b3cee7cbdb1003bea9f33f2
3
+ metadata.gz: 6d76af31baae33e36fc11994b9b755ce67a0795cdcd5e6dca245b9476991b161
4
+ data.tar.gz: 1505e09c2ed0e902ea7cb769531c1c4ce0b398fca78b8714fe1113204e9d348c
5
5
  SHA512:
6
- metadata.gz: 30b9cb40262daf924f047034c6314b418c367691eccc188acd08328bd92e6a51d3818a91c3d17fb5dc3f159129186ef6c4bd7bfbe815b9c8f268fa9b938fd1ac
7
- data.tar.gz: a1b9ab207e98c779b0d371f2f14e6c5fb8315273af7518bc8e8135ba3dff4f1385787e169a4e4c146aa1ea7c10f6fce4f82d37958f88e8f68f1e8dabe54115bf
6
+ metadata.gz: 0df2dc7057692897f48ad99cdfe5f9d72a0ba6625dc0da1dc141ebadf36cf62405b1704997ffaa93318472b50a4919f4b3253708faf4f3bfcc093814f4f1a198
7
+ data.tar.gz: 2b3a959b7cf5b6103c15de81aeb99226045b27e090acc29a15247fe14b7492c97b6dc1b52c3ba584bfc4eb9fc18ba1744b78e6cf3b836c1e23b3025f5bdb960c
data/CHANGELOG.md CHANGED
@@ -6,6 +6,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.5.0] - 2025-09-12
10
+
11
+ ### Added
12
+
13
+ - Add `Prism::Translation::ParserCurrent`.
14
+ - Add `Integer::to_u32_digits` for the Rust API.
15
+ - Add `pm_comment_type_t` field for the Rust API.
16
+ - Support leading logical operators for CRuby 3.5+.
17
+
18
+ ### Changed
19
+
20
+ - Mark Prism as ractor-safe.
21
+ - Enforce a minimum version for the parser translation layer.
22
+ - Many fixes to the parser translation layer.
23
+ - Accept a newline after the `defined?` keyword.
24
+ - Reject `true && not true`.
25
+ - Make `it = it` assign nil to match parse.y behavior [Bug #21139].
26
+ - Some fixes to the ruby parser translation layer.
27
+ - Ensure call nodes have the correct ending location.
28
+ - Reject `foo && return bar`.
29
+
9
30
  ## [1.4.0] - 2025-03-18
10
31
 
11
32
  ### Added
@@ -649,7 +670,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
649
670
 
650
671
  - 🎉 Initial release! 🎉
651
672
 
652
- [unreleased]: https://github.com/ruby/prism/compare/v1.4.0...HEAD
673
+ [unreleased]: https://github.com/ruby/prism/compare/v1.5.0...HEAD
674
+ [1.5.0]: https://github.com/ruby/prism/compare/v1.4.0...v1.5.0
653
675
  [1.4.0]: https://github.com/ruby/prism/compare/v1.3.0...v1.4.0
654
676
  [1.3.0]: https://github.com/ruby/prism/compare/v1.2.0...v1.3.0
655
677
  [1.2.0]: https://github.com/ruby/prism/compare/v1.1.0...v1.2.0
data/Makefile CHANGED
@@ -12,6 +12,7 @@ SOEXT ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')
12
12
 
13
13
  CPPFLAGS := -Iinclude $(CPPFLAGS)
14
14
  CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(CFLAGS)
15
+ JAVA_WASM_CFLAGS := -g -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS)
15
16
  CC ?= cc
16
17
  AR ?= ar
17
18
  WASI_SDK_PATH := /opt/wasi-sdk
@@ -45,7 +46,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS)
45
46
 
46
47
  java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS)
47
48
  $(ECHO) "building $@"
48
- $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES)
49
+ $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES)
49
50
 
50
51
  build/shared/%.o: src/%.c Makefile $(HEADERS)
51
52
  $(ECHO) "compiling $@"
data/README.md CHANGED
@@ -139,3 +139,4 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an
139
139
  ### Applications
140
140
 
141
141
  * [gem.sh](https://github.com/marcoroth/gem.sh/pull/96)
142
+ * [Sorbet](https://github.com/sorbet/sorbet)
data/config.yml CHANGED
@@ -101,6 +101,8 @@ errors:
101
101
  - EXPECT_FOR_DELIMITER
102
102
  - EXPECT_IDENT_REQ_PARAMETER
103
103
  - EXPECT_IN_DELIMITER
104
+ - EXPECT_LPAREN_AFTER_NOT_LPAREN
105
+ - EXPECT_LPAREN_AFTER_NOT_OTHER
104
106
  - EXPECT_LPAREN_REQ_PARAMETER
105
107
  - EXPECT_MESSAGE
106
108
  - EXPECT_RBRACKET
@@ -320,13 +322,42 @@ warnings:
320
322
  - UNUSED_LOCAL_VARIABLE
321
323
  - VOID_STATEMENT
322
324
  tokens:
325
+ # The order of the tokens at the beginning is important, because we use them
326
+ # for a lookup table.
323
327
  - name: EOF
324
328
  value: 1
325
329
  comment: final token in the file
326
- - name: MISSING
327
- comment: "a token that was expected but not found"
328
- - name: NOT_PROVIDED
329
- comment: "a token that was not present but it is okay"
330
+ - name: BRACE_RIGHT
331
+ comment: "}"
332
+ - name: COMMA
333
+ comment: ","
334
+ - name: EMBEXPR_END
335
+ comment: "}"
336
+ - name: KEYWORD_DO
337
+ comment: "do"
338
+ - name: KEYWORD_ELSE
339
+ comment: "else"
340
+ - name: KEYWORD_ELSIF
341
+ comment: "elsif"
342
+ - name: KEYWORD_END
343
+ comment: "end"
344
+ - name: KEYWORD_ENSURE
345
+ comment: "ensure"
346
+ - name: KEYWORD_IN
347
+ comment: "in"
348
+ - name: KEYWORD_RESCUE
349
+ comment: "rescue"
350
+ - name: KEYWORD_THEN
351
+ comment: "then"
352
+ - name: KEYWORD_WHEN
353
+ comment: "when"
354
+ - name: NEWLINE
355
+ comment: "a newline character outside of other tokens"
356
+ - name: PARENTHESIS_RIGHT
357
+ comment: ")"
358
+ - name: SEMICOLON
359
+ comment: ";"
360
+ # Tokens from here on are not used for lookup, and can be in any order.
330
361
  - name: AMPERSAND
331
362
  comment: "&"
332
363
  - name: AMPERSAND_AMPERSAND
@@ -349,8 +380,6 @@ tokens:
349
380
  comment: "!~"
350
381
  - name: BRACE_LEFT
351
382
  comment: "{"
352
- - name: BRACE_RIGHT
353
- comment: "}"
354
383
  - name: BRACKET_LEFT
355
384
  comment: "["
356
385
  - name: BRACKET_LEFT_ARRAY
@@ -373,8 +402,6 @@ tokens:
373
402
  comment: ":"
374
403
  - name: COLON_COLON
375
404
  comment: "::"
376
- - name: COMMA
377
- comment: ","
378
405
  - name: COMMENT
379
406
  comment: "a comment"
380
407
  - name: CONSTANT
@@ -393,8 +420,6 @@ tokens:
393
420
  comment: "a line inside of embedded documentation"
394
421
  - name: EMBEXPR_BEGIN
395
422
  comment: "#{"
396
- - name: EMBEXPR_END
397
- comment: "}"
398
423
  - name: EMBVAR
399
424
  comment: "#"
400
425
  - name: EQUAL
@@ -461,20 +486,10 @@ tokens:
461
486
  comment: "def"
462
487
  - name: KEYWORD_DEFINED
463
488
  comment: "defined?"
464
- - name: KEYWORD_DO
465
- comment: "do"
466
489
  - name: KEYWORD_DO_LOOP
467
490
  comment: "do keyword for a predicate in a while, until, or for loop"
468
- - name: KEYWORD_ELSE
469
- comment: "else"
470
- - name: KEYWORD_ELSIF
471
- comment: "elsif"
472
- - name: KEYWORD_END
473
- comment: "end"
474
491
  - name: KEYWORD_END_UPCASE
475
492
  comment: "END"
476
- - name: KEYWORD_ENSURE
477
- comment: "ensure"
478
493
  - name: KEYWORD_FALSE
479
494
  comment: "false"
480
495
  - name: KEYWORD_FOR
@@ -483,8 +498,6 @@ tokens:
483
498
  comment: "if"
484
499
  - name: KEYWORD_IF_MODIFIER
485
500
  comment: "if in the modifier form"
486
- - name: KEYWORD_IN
487
- comment: "in"
488
501
  - name: KEYWORD_MODULE
489
502
  comment: "module"
490
503
  - name: KEYWORD_NEXT
@@ -497,8 +510,6 @@ tokens:
497
510
  comment: "or"
498
511
  - name: KEYWORD_REDO
499
512
  comment: "redo"
500
- - name: KEYWORD_RESCUE
501
- comment: "rescue"
502
513
  - name: KEYWORD_RESCUE_MODIFIER
503
514
  comment: "rescue in the modifier form"
504
515
  - name: KEYWORD_RETRY
@@ -509,8 +520,6 @@ tokens:
509
520
  comment: "self"
510
521
  - name: KEYWORD_SUPER
511
522
  comment: "super"
512
- - name: KEYWORD_THEN
513
- comment: "then"
514
523
  - name: KEYWORD_TRUE
515
524
  comment: "true"
516
525
  - name: KEYWORD_UNDEF
@@ -523,8 +532,6 @@ tokens:
523
532
  comment: "until"
524
533
  - name: KEYWORD_UNTIL_MODIFIER
525
534
  comment: "until in the modifier form"
526
- - name: KEYWORD_WHEN
527
- comment: "when"
528
535
  - name: KEYWORD_WHILE
529
536
  comment: "while"
530
537
  - name: KEYWORD_WHILE_MODIFIER
@@ -561,16 +568,12 @@ tokens:
561
568
  comment: "-="
562
569
  - name: MINUS_GREATER
563
570
  comment: "->"
564
- - name: NEWLINE
565
- comment: "a newline character outside of other tokens"
566
571
  - name: NUMBERED_REFERENCE
567
572
  comment: "a numbered reference to a capture group in the previous regular expression match"
568
573
  - name: PARENTHESIS_LEFT
569
574
  comment: "("
570
575
  - name: PARENTHESIS_LEFT_PARENTHESES
571
576
  comment: "( for a parentheses node"
572
- - name: PARENTHESIS_RIGHT
573
- comment: ")"
574
577
  - name: PERCENT
575
578
  comment: "%"
576
579
  - name: PERCENT_EQUAL
@@ -603,8 +606,6 @@ tokens:
603
606
  comment: "the beginning of a regular expression"
604
607
  - name: REGEXP_END
605
608
  comment: "the end of a regular expression"
606
- - name: SEMICOLON
607
- comment: ";"
608
609
  - name: SLASH
609
610
  comment: "/"
610
611
  - name: SLASH_EQUAL
@@ -649,6 +650,10 @@ tokens:
649
650
  comment: "a separator between words in a list"
650
651
  - name: __END__
651
652
  comment: "marker for the point in the file at which the parser should stop"
653
+ - name: MISSING
654
+ comment: "a token that was expected but not found"
655
+ - name: NOT_PROVIDED
656
+ comment: "a token that was not present but it is okay"
652
657
  flags:
653
658
  - name: ArgumentsNodeFlags
654
659
  values:
@@ -987,8 +992,19 @@ nodes:
987
992
  - name: constant
988
993
  type: node?
989
994
  kind:
990
- - ConstantReadNode
991
995
  - ConstantPathNode
996
+ - ConstantReadNode
997
+ comment: |
998
+ Represents the optional constant preceding the Array
999
+
1000
+ foo in Bar[]
1001
+ ^^^
1002
+
1003
+ foo in Bar[1, 2, 3]
1004
+ ^^^
1005
+
1006
+ foo in Bar::Baz[1, 2, 3]
1007
+ ^^^^^^^^
992
1008
  - name: requireds
993
1009
  type: node[]
994
1010
  kind: pattern expression
@@ -1828,6 +1844,11 @@ nodes:
1828
1844
  type: constant[]
1829
1845
  - name: class_keyword_loc
1830
1846
  type: location
1847
+ comment: |
1848
+ Represents the location of the `class` keyword.
1849
+
1850
+ class Foo end
1851
+ ^^^^^
1831
1852
  - name: constant_path
1832
1853
  type: node
1833
1854
  kind:
@@ -1836,18 +1857,43 @@ nodes:
1836
1857
  - on error: CallNode # class 0.X end
1837
1858
  - name: inheritance_operator_loc
1838
1859
  type: location?
1860
+ comment: |
1861
+ Represents the location of the `<` operator.
1862
+
1863
+ class Foo < Bar
1864
+ ^
1839
1865
  - name: superclass
1840
1866
  type: node?
1841
1867
  kind: non-void expression
1868
+ comment: |
1869
+ Represents the superclass of the class.
1870
+
1871
+ class Foo < Bar
1872
+ ^^^
1842
1873
  - name: body
1843
1874
  type: node?
1844
1875
  kind:
1845
1876
  - StatementsNode
1846
1877
  - BeginNode
1878
+ comment: |
1879
+ Represents the body of the class.
1880
+
1881
+ class Foo
1882
+ foo
1883
+ ^^^
1847
1884
  - name: end_keyword_loc
1848
1885
  type: location
1886
+ comment: |
1887
+ Represents the location of the `end` keyword.
1888
+
1889
+ class Foo end
1890
+ ^^^
1849
1891
  - name: name
1850
1892
  type: constant
1893
+ comment: |
1894
+ The name of the class.
1895
+
1896
+ class Foo end # name `:Foo`
1851
1897
  comment: |
1852
1898
  Represents a class declaration involving the `class` keyword.
1853
1899
 
@@ -2374,23 +2420,68 @@ nodes:
2374
2420
  - name: constant
2375
2421
  type: node?
2376
2422
  kind:
2377
- - ConstantReadNode
2378
2423
  - ConstantPathNode
2424
+ - ConstantReadNode
2425
+ comment: |
2426
+ Represents the optional constant preceding the pattern
2427
+
2428
+ foo in Foo(*bar, baz, *qux)
2429
+ ^^^
2379
2430
  - name: left
2380
2431
  type: node
2381
2432
  kind: SplatNode
2433
+ comment: |
2434
+ Represents the first wildcard node in the pattern.
2435
+
2436
+ foo in *bar, baz, *qux
2437
+ ^^^^
2438
+
2439
+ foo in Foo(*bar, baz, *qux)
2440
+ ^^^^
2382
2441
  - name: requireds
2383
2442
  type: node[]
2384
2443
  kind: pattern expression
2444
+ comment: |
2445
+ Represents the nodes in between the wildcards.
2446
+
2447
+ foo in *bar, baz, *qux
2448
+ ^^^
2449
+
2450
+ foo in Foo(*bar, baz, 1, *qux)
2451
+ ^^^^^^
2385
2452
  - name: right
2386
2453
  type: node
2387
2454
  kind:
2388
2455
  - SplatNode
2389
2456
  - on error: MissingNode
2457
+ comment: |
2458
+ Represents the second wildcard node in the pattern.
2459
+
2460
+ foo in *bar, baz, *qux
2461
+ ^^^^
2462
+
2463
+ foo in Foo(*bar, baz, *qux)
2464
+ ^^^^
2390
2465
  - name: opening_loc
2391
2466
  type: location?
2467
+ comment: |
2468
+ The location of the opening brace.
2469
+
2470
+ foo in [*bar, baz, *qux]
2471
+ ^
2472
+
2473
+ foo in Foo(*bar, baz, *qux)
2474
+ ^
2392
2475
  - name: closing_loc
2393
2476
  type: location?
2477
+ comment: |
2478
+ The location of the closing brace.
2479
+
2480
+ foo in [*bar, baz, *qux]
2481
+ ^
2482
+
2483
+ foo in Foo(*bar, baz, *qux)
2484
+ ^
2394
2485
  comment: |
2395
2486
  Represents a find pattern in pattern matching.
2396
2487
 
@@ -2402,6 +2493,9 @@ nodes:
2402
2493
 
2403
2494
  foo in Foo(*bar, baz, *qux)
2404
2495
  ^^^^^^^^^^^^^^^^^^^^
2496
+
2497
+ foo => *bar, baz, *qux
2498
+ ^^^^^^^^^^^^^^^
2405
2499
  - name: FlipFlopNode
2406
2500
  flags: RangeFlags
2407
2501
  fields:
@@ -2679,20 +2773,60 @@ nodes:
2679
2773
  - name: constant
2680
2774
  type: node?
2681
2775
  kind:
2682
- - ConstantReadNode
2683
2776
  - ConstantPathNode
2777
+ - ConstantReadNode
2778
+ comment: |
2779
+ Represents the optional constant preceding the Hash.
2780
+
2781
+ foo => Bar[a: 1, b: 2]
2782
+ ^^^
2783
+
2784
+ foo => Bar::Baz[a: 1, b: 2]
2785
+ ^^^^^^^^
2684
2786
  - name: elements
2685
2787
  type: node[]
2686
2788
  kind: AssocNode
2789
+ comment: |
2790
+ Represents the explicit named hash keys and values.
2791
+
2792
+ foo => { a: 1, b:, ** }
2793
+ ^^^^^^^^
2687
2794
  - name: rest
2688
2795
  type: node?
2689
2796
  kind:
2690
2797
  - AssocSplatNode
2691
2798
  - NoKeywordsParameterNode
2799
+ comment: |
2800
+ Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`.
2801
+
2802
+ foo => { a: 1, b:, **c }
2803
+ ^^^
2804
+
2805
+ foo => { a: 1, b:, ** }
2806
+ ^^
2807
+
2808
+ foo => { a: 1, b:, **nil }
2809
+ ^^^^^
2692
2810
  - name: opening_loc
2693
2811
  type: location?
2812
+ comment: |
2813
+ The location of the opening brace.
2814
+
2815
+ foo => { a: 1 }
2816
+ ^
2817
+
2818
+ foo => Bar[a: 1]
2819
+ ^
2694
2820
  - name: closing_loc
2695
2821
  type: location?
2822
+ comment: |
2823
+ The location of the closing brace.
2824
+
2825
+ foo => { a: 1 }
2826
+ ^
2827
+
2828
+ foo => Bar[a: 1]
2829
+ ^
2696
2830
  comment: |
2697
2831
  Represents a hash pattern in pattern matching.
2698
2832
 
@@ -2701,6 +2835,12 @@ nodes:
2701
2835
 
2702
2836
  foo => { a: 1, b: 2, **c }
2703
2837
  ^^^^^^^^^^^^^^^^^^^
2838
+
2839
+ foo => Bar[a: 1, b: 2]
2840
+ ^^^^^^^^^^^^^^^
2841
+
2842
+ foo in { a: 1, b: 2 }
2843
+ ^^^^^^^^^^^^^^
2704
2844
  - name: IfNode
2705
2845
  fields:
2706
2846
  - name: if_keyword_loc
@@ -3353,6 +3493,9 @@ nodes:
3353
3493
 
3354
3494
  foo, bar = baz
3355
3495
  ^^^ ^^^
3496
+
3497
+ foo => baz
3498
+ ^^^
3356
3499
  - name: LocalVariableWriteNode
3357
3500
  fields:
3358
3501
  - name: name
@@ -3443,11 +3586,65 @@ nodes:
3443
3586
  - name: value
3444
3587
  type: node
3445
3588
  kind: non-void expression
3589
+ comment: |
3590
+ Represents the left-hand side of the operator.
3591
+
3592
+ foo => bar
3593
+ ^^^
3446
3594
  - name: pattern
3447
3595
  type: node
3448
3596
  kind: pattern expression
3597
+ comment: |
3598
+ Represents the right-hand side of the operator. The type of the node depends on the expression.
3599
+
3600
+ Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
3601
+
3602
+ foo => a # This is equivalent to writing `a = foo`
3603
+ ^
3604
+
3605
+ Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
3606
+
3607
+ foo => [a]
3608
+ ^^^
3609
+
3610
+ foo => a, b
3611
+ ^^^^
3612
+
3613
+ foo => Bar[a, b]
3614
+ ^^^^^^^^^
3615
+
3616
+ If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
3617
+
3618
+ foo => *, 1, *a
3619
+ ^^^^^
3620
+
3621
+ Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
3622
+
3623
+ foo => { a: 1, b: }
3624
+
3625
+ foo => Bar[a: 1, b:]
3626
+
3627
+ foo => Bar[**]
3628
+
3629
+ To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
3630
+
3631
+ foo => ^a
3632
+ ^^
3633
+
3634
+ Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
3635
+
3636
+ foo => ^(a + 1)
3637
+
3638
+ Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
3639
+
3640
+ foo => CONST
3449
3641
  - name: operator_loc
3450
3642
  type: location
3643
+ comment: |
3644
+ The location of the operator.
3645
+
3646
+ foo => bar
3647
+ ^^
3451
3648
  comment: |
3452
3649
  Represents the use of the `=>` operator.
3453
3650
 
@@ -3877,12 +4074,32 @@ nodes:
3877
4074
  - name: expression
3878
4075
  type: node
3879
4076
  kind: non-void expression
4077
+ comment: |
4078
+ The expression used in the pinned expression
4079
+
4080
+ foo in ^(bar)
4081
+ ^^^
3880
4082
  - name: operator_loc
3881
4083
  type: location
4084
+ comment: |
4085
+ The location of the `^` operator
4086
+
4087
+ foo in ^(bar)
4088
+ ^
3882
4089
  - name: lparen_loc
3883
4090
  type: location
4091
+ comment: |
4092
+ The location of the opening parenthesis.
4093
+
4094
+ foo in ^(bar)
4095
+ ^
3884
4096
  - name: rparen_loc
3885
4097
  type: location
4098
+ comment: |
4099
+ The location of the closing parenthesis.
4100
+
4101
+ foo in ^(bar)
4102
+ ^
3886
4103
  comment: |
3887
4104
  Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
3888
4105
 
@@ -3901,8 +4118,18 @@ nodes:
3901
4118
  - NumberedReferenceReadNode # foo in ^$1
3902
4119
  - ItLocalVariableReadNode # proc { 1 in ^it }
3903
4120
  - on error: MissingNode # foo in ^Bar
4121
+ comment: |
4122
+ The variable used in the pinned expression
4123
+
4124
+ foo in ^bar
4125
+ ^^^
3904
4126
  - name: operator_loc
3905
4127
  type: location
4128
+ comment: |
4129
+ The location of the `^` operator
4130
+
4131
+ foo in ^bar
4132
+ ^
3906
4133
  comment: |
3907
4134
  Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
3908
4135
 
@@ -6,34 +6,19 @@ Prism ships with the ability to translate its syntax tree into the syntax tree u
6
6
 
7
7
  The `parser` gem provides multiple parsers to support different versions of the Ruby grammar. This includes all of the Ruby versions going back to 1.8, as well as third-party parsers like MacRuby and RubyMotion. The `prism` gem provides another parser that uses the `prism` parser to build the syntax tree.
8
8
 
9
- You can use the `prism` parser like you would any other. After requiring the parser, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
9
+ You can use the `prism` parser like you would any other. After requiring `prism`, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
10
10
 
11
11
  ```ruby
12
12
  require "prism"
13
13
 
14
- Prism::Translation::Parser.parse_file("path/to/file.rb")
15
- ```
16
-
17
- ### RuboCop
18
-
19
- Prism as a parser engine is directly supported since RuboCop 1.62. The class used for parsing is `Prism::Translation::Parser`.
20
-
21
- First, specify `prism` in your Gemfile:
22
-
23
- ```ruby
24
- gem "prism"
25
- ```
26
-
27
- To use Prism with RuboCop, specify `ParserEngine` and `TargetRubyVersion` in your RuboCop configuration file:
14
+ # Same as `Parser::Ruby34`
15
+ Prism::Translation::Parser34.parse_file("path/to/file.rb")
28
16
 
29
- ```yaml
30
- AllCops:
31
- ParserEngine: parser_prism
32
- TargetRubyVersion: 3.3
17
+ # Same as `Parser::CurrentRuby`
18
+ Prism::Translation::ParserCurrent.parse("puts 'Hello World!'")
33
19
  ```
34
20
 
35
- The default value for `ParserEngine` is `parser_whitequark`, which indicates the Parser gem. You need to explicitly switch it to `parser_prism` to indicate Prism. Additionally, the value for `TargetRubyVersion` must be specified as `3.3` or higher, as Prism supports parsing versions of Ruby 3.3 and higher.
36
- The parser class is determined by the combination of values for `ParserEngine` and `TargetRubyVersion`. For example, if `TargetRubyVersion: 3.3`, parsing is performed by `Prism::Translation::Parser33`, and for `TargetRubyVersion 3.4`, parsing is performed by `Prism::Translation::Parser34`.
21
+ All the parsers are autoloaded, so you don't have to worry about requiring them yourself.
37
22
 
38
- For further information, please refer to the RuboCop documentation:
39
- https://docs.rubocop.org/rubocop/configuration.html#setting-the-parser-engine
23
+ If you also need to parse Ruby versions below 3.3 (which `prism` has no support for), check out
24
+ [this guide](https://github.com/whitequark/parser/blob/master/doc/PRISM_TRANSLATION.md) from the `parser` gem on how to use both in conjunction.
@@ -55,7 +55,7 @@ It is helpful to understand the differences between the `Ripper` library and the
55
55
 
56
56
  ### Design
57
57
 
58
- `Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to your the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later).
58
+ `Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to you the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later).
59
59
 
60
60
  ### Fields
61
61
 
data/ext/prism/api_node.c CHANGED
@@ -1,3 +1,5 @@
1
+ /* :markup: markdown */
2
+
1
3
  /*----------------------------------------------------------------------------*/
2
4
  /* This file is generated by the templates/template.rb script and should not */
3
5
  /* be modified manually. See */
@@ -994,6 +994,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
994
994
  return Qnil;
995
995
  }
996
996
 
997
+ static int
998
+ parse_stream_eof(void *stream) {
999
+ if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
1000
+ return 1;
1001
+ }
1002
+ return 0;
1003
+ }
1004
+
997
1005
  /**
998
1006
  * An implementation of fgets that is suitable for use with Ruby IO objects.
999
1007
  */
@@ -1034,7 +1042,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
1034
1042
  pm_parser_t parser;
1035
1043
  pm_buffer_t buffer;
1036
1044
 
1037
- pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
1045
+ pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
1038
1046
  rb_encoding *encoding = rb_enc_find(parser.encoding->name);
1039
1047
 
1040
1048
  VALUE source = pm_source_new(&parser, encoding, options.freeze);
@@ -1331,6 +1339,11 @@ Init_prism(void) {
1331
1339
  );
1332
1340
  }
1333
1341
 
1342
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1343
+ // Mark this extension as Ractor-safe.
1344
+ rb_ext_ractor_safe(true);
1345
+ #endif
1346
+
1334
1347
  // Grab up references to all of the constants that we're going to need to
1335
1348
  // reference throughout this extension.
1336
1349
  rb_cPrism = rb_define_module("Prism");