prism 1.4.0 → 1.6.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/Makefile +4 -2
  4. data/README.md +2 -0
  5. data/config.yml +266 -38
  6. data/docs/design.md +2 -2
  7. data/docs/parser_translation.md +8 -23
  8. data/docs/releasing.md +5 -24
  9. data/docs/ripper_translation.md +1 -1
  10. data/ext/prism/api_node.c +2 -0
  11. data/ext/prism/extension.c +25 -3
  12. data/ext/prism/extension.h +1 -1
  13. data/include/prism/ast.h +306 -50
  14. data/include/prism/diagnostic.h +5 -0
  15. data/include/prism/options.h +43 -3
  16. data/include/prism/regexp.h +2 -2
  17. data/include/prism/util/pm_buffer.h +8 -0
  18. data/include/prism/util/pm_integer.h +4 -0
  19. data/include/prism/util/pm_list.h +6 -0
  20. data/include/prism/util/pm_string.h +12 -2
  21. data/include/prism/version.h +2 -2
  22. data/include/prism.h +39 -14
  23. data/lib/prism/compiler.rb +456 -151
  24. data/lib/prism/desugar_compiler.rb +1 -0
  25. data/lib/prism/dispatcher.rb +16 -0
  26. data/lib/prism/dot_visitor.rb +5 -1
  27. data/lib/prism/dsl.rb +3 -0
  28. data/lib/prism/ffi.rb +25 -9
  29. data/lib/prism/inspect_visitor.rb +3 -0
  30. data/lib/prism/lex_compat.rb +1 -0
  31. data/lib/prism/mutation_compiler.rb +3 -0
  32. data/lib/prism/node.rb +507 -336
  33. data/lib/prism/node_ext.rb +4 -1
  34. data/lib/prism/pack.rb +2 -0
  35. data/lib/prism/parse_result/comments.rb +1 -0
  36. data/lib/prism/parse_result/errors.rb +1 -0
  37. data/lib/prism/parse_result/newlines.rb +1 -0
  38. data/lib/prism/parse_result.rb +1 -0
  39. data/lib/prism/pattern.rb +1 -0
  40. data/lib/prism/polyfill/scan_byte.rb +14 -0
  41. data/lib/prism/polyfill/warn.rb +36 -0
  42. data/lib/prism/reflection.rb +3 -0
  43. data/lib/prism/relocation.rb +1 -0
  44. data/lib/prism/serialize.rb +25 -19
  45. data/lib/prism/string_query.rb +1 -0
  46. data/lib/prism/translation/parser/builder.rb +1 -0
  47. data/lib/prism/translation/parser/compiler.rb +47 -25
  48. data/lib/prism/translation/parser/lexer.rb +29 -21
  49. data/lib/prism/translation/parser.rb +21 -2
  50. data/lib/prism/translation/parser33.rb +1 -0
  51. data/lib/prism/translation/parser34.rb +1 -0
  52. data/lib/prism/translation/parser35.rb +1 -0
  53. data/lib/prism/translation/parser_current.rb +24 -0
  54. data/lib/prism/translation/ripper/sexp.rb +1 -0
  55. data/lib/prism/translation/ripper.rb +17 -1
  56. data/lib/prism/translation/ruby_parser.rb +287 -4
  57. data/lib/prism/translation.rb +2 -0
  58. data/lib/prism/visitor.rb +457 -152
  59. data/lib/prism.rb +23 -0
  60. data/prism.gemspec +5 -1
  61. data/rbi/prism/dsl.rbi +3 -3
  62. data/rbi/prism/node.rbi +21 -9
  63. data/sig/prism/dispatcher.rbs +3 -0
  64. data/sig/prism/dsl.rbs +3 -3
  65. data/sig/prism/node.rbs +444 -30
  66. data/sig/prism/node_ext.rbs +84 -17
  67. data/sig/prism/parse_result/comments.rbs +38 -0
  68. data/sig/prism/parse_result.rbs +4 -0
  69. data/sig/prism/reflection.rbs +1 -1
  70. data/sig/prism.rbs +4 -0
  71. data/src/diagnostic.c +9 -1
  72. data/src/node.c +2 -0
  73. data/src/options.c +2 -2
  74. data/src/prettyprint.c +2 -0
  75. data/src/prism.c +324 -147
  76. data/src/serialize.c +2 -0
  77. data/src/token_type.c +36 -34
  78. data/src/util/pm_string.c +6 -8
  79. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0209a58426470fc6afedb5922c9bf9264cb9ccd2debbef68fb1a307a4d1be78
4
- data.tar.gz: 491a11ab3d9d840f4ac228e8b79e85ddb24ae1f82b3cee7cbdb1003bea9f33f2
3
+ metadata.gz: 2ef507799374ba0281ff3d8ab78fc29f673b3fc213f695ae68c65cf0d38b4bcc
4
+ data.tar.gz: 7610a756cffd1aeb517f135446ae25360568cc00e6d78e748470469bd345463c
5
5
  SHA512:
6
- metadata.gz: 30b9cb40262daf924f047034c6314b418c367691eccc188acd08328bd92e6a51d3818a91c3d17fb5dc3f159129186ef6c4bd7bfbe815b9c8f268fa9b938fd1ac
7
- data.tar.gz: a1b9ab207e98c779b0d371f2f14e6c5fb8315273af7518bc8e8135ba3dff4f1385787e169a4e4c146aa1ea7c10f6fce4f82d37958f88e8f68f1e8dabe54115bf
6
+ metadata.gz: 539d064482f82c7fd85c7e8269b1c400fd576b20effbcb857636667ce8818367eea35446bc7ee2decf3cdde7171883e8aeaa154c2bf1b8d7f3c7fa5c12203f08
7
+ data.tar.gz: 59181adcac710bf7697b1dec0556eb306f9cf79d2b7492e0392d9698401dd3abb5a1406fc5d66d1c4d0acbd85d9ebf8e674683e9ec585d765216953f80a75297
data/CHANGELOG.md CHANGED
@@ -6,6 +6,52 @@ 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.6.0] - 2025-10-16
10
+
11
+ ### Added
12
+
13
+ - Add support for passing `"current"` as the version option to `Prism.*` APIs.
14
+
15
+ ### Changed
16
+
17
+ - Remove a compiler warning for a missing unsigned cast for a shift value.
18
+
19
+ ## [1.5.2] - 2025-10-09
20
+
21
+ ### Changed
22
+
23
+ - Fix character literal forced encoding when a unicode escape sequence is used.
24
+ - Reject `1 if foo = bar baz`.
25
+ - Clear static literal flag on interpolated strings.
26
+ - Reject optional argument/endless method definition ambiguity.
27
+
28
+ ## [1.5.1] - 2025-09-13
29
+
30
+ ### Changed
31
+
32
+ - Revert of a bug introduced with static literal flags on interpolated strings.
33
+
34
+ ## [1.5.0] - 2025-09-12
35
+
36
+ ### Added
37
+
38
+ - Add `Prism::Translation::ParserCurrent`.
39
+ - Add `Integer::to_u32_digits` for the Rust API.
40
+ - Add `pm_comment_type_t` field for the Rust API.
41
+ - Support leading logical operators for CRuby 3.5+.
42
+
43
+ ### Changed
44
+
45
+ - Mark Prism as ractor-safe.
46
+ - Enforce a minimum version for the parser translation layer.
47
+ - Many fixes to the parser translation layer.
48
+ - Accept a newline after the `defined?` keyword.
49
+ - Reject `true && not true`.
50
+ - Make `it = it` assign nil to match parse.y behavior [Bug #21139].
51
+ - Some fixes to the ruby parser translation layer.
52
+ - Ensure call nodes have the correct ending location.
53
+ - Reject `foo && return bar`.
54
+
9
55
  ## [1.4.0] - 2025-03-18
10
56
 
11
57
  ### Added
@@ -649,7 +695,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
649
695
 
650
696
  - 🎉 Initial release! 🎉
651
697
 
652
- [unreleased]: https://github.com/ruby/prism/compare/v1.4.0...HEAD
698
+ [unreleased]: https://github.com/ruby/prism/compare/v1.6.0...HEAD
699
+ [1.6.0]: https://github.com/ruby/prism/compare/v1.5.2...v1.6.0
700
+ [1.5.2]: https://github.com/ruby/prism/compare/v1.5.1...v1.5.2
701
+ [1.5.1]: https://github.com/ruby/prism/compare/v1.5.0...v1.5.1
702
+ [1.5.0]: https://github.com/ruby/prism/compare/v1.4.0...v1.5.0
653
703
  [1.4.0]: https://github.com/ruby/prism/compare/v1.3.0...v1.4.0
654
704
  [1.3.0]: https://github.com/ruby/prism/compare/v1.2.0...v1.3.0
655
705
  [1.2.0]: https://github.com/ruby/prism/compare/v1.1.0...v1.2.0
data/Makefile CHANGED
@@ -12,8 +12,10 @@ 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
18
+ ARFLAGS ?= -r$(V0:1=v)
17
19
  WASI_SDK_PATH := /opt/wasi-sdk
18
20
 
19
21
  MAKEDIRS ?= mkdir -p
@@ -37,7 +39,7 @@ build/libprism.$(SOEXT): $(SHARED_OBJECTS)
37
39
 
38
40
  build/libprism.a: $(STATIC_OBJECTS)
39
41
  $(ECHO) "building $@ with $(AR)"
40
- $(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS) $(Q1:0=>/dev/null)
42
+ $(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS)
41
43
 
42
44
  javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS)
43
45
  $(ECHO) "building $@"
@@ -45,7 +47,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS)
45
47
 
46
48
  java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS)
47
49
  $(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)
50
+ $(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
51
 
50
52
  build/shared/%.o: src/%.c Makefile $(HEADERS)
51
53
  $(ECHO) "compiling $@"
data/README.md CHANGED
@@ -135,7 +135,9 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an
135
135
  * [sorbet-eraser](https://github.com/kddnewton/sorbet-eraser/pull/25)
136
136
  * [synvert](https://github.com/xinminlabs/synvert-core-ruby)
137
137
  * [typeprof](https://github.com/ruby/typeprof)
138
+ * [unparser](https://github.com/mbj/unparser) (via parser translator)
138
139
 
139
140
  ### Applications
140
141
 
141
142
  * [gem.sh](https://github.com/marcoroth/gem.sh/pull/96)
143
+ * [Sorbet](https://github.com/sorbet/sorbet)
data/config.yml CHANGED
@@ -60,6 +60,7 @@ errors:
60
60
  - CONDITIONAL_WHILE_PREDICATE
61
61
  - CONSTANT_PATH_COLON_COLON_CONSTANT
62
62
  - DEF_ENDLESS
63
+ - DEF_ENDLESS_PARAMETERS
63
64
  - DEF_ENDLESS_SETTER
64
65
  - DEF_NAME
65
66
  - DEF_PARAMS_TERM
@@ -101,6 +102,8 @@ errors:
101
102
  - EXPECT_FOR_DELIMITER
102
103
  - EXPECT_IDENT_REQ_PARAMETER
103
104
  - EXPECT_IN_DELIMITER
105
+ - EXPECT_LPAREN_AFTER_NOT_LPAREN
106
+ - EXPECT_LPAREN_AFTER_NOT_OTHER
104
107
  - EXPECT_LPAREN_REQ_PARAMETER
105
108
  - EXPECT_MESSAGE
106
109
  - EXPECT_RBRACKET
@@ -320,13 +323,42 @@ warnings:
320
323
  - UNUSED_LOCAL_VARIABLE
321
324
  - VOID_STATEMENT
322
325
  tokens:
326
+ # The order of the tokens at the beginning is important, because we use them
327
+ # for a lookup table.
323
328
  - name: EOF
324
329
  value: 1
325
330
  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"
331
+ - name: BRACE_RIGHT
332
+ comment: "}"
333
+ - name: COMMA
334
+ comment: ","
335
+ - name: EMBEXPR_END
336
+ comment: "}"
337
+ - name: KEYWORD_DO
338
+ comment: "do"
339
+ - name: KEYWORD_ELSE
340
+ comment: "else"
341
+ - name: KEYWORD_ELSIF
342
+ comment: "elsif"
343
+ - name: KEYWORD_END
344
+ comment: "end"
345
+ - name: KEYWORD_ENSURE
346
+ comment: "ensure"
347
+ - name: KEYWORD_IN
348
+ comment: "in"
349
+ - name: KEYWORD_RESCUE
350
+ comment: "rescue"
351
+ - name: KEYWORD_THEN
352
+ comment: "then"
353
+ - name: KEYWORD_WHEN
354
+ comment: "when"
355
+ - name: NEWLINE
356
+ comment: "a newline character outside of other tokens"
357
+ - name: PARENTHESIS_RIGHT
358
+ comment: ")"
359
+ - name: SEMICOLON
360
+ comment: ";"
361
+ # Tokens from here on are not used for lookup, and can be in any order.
330
362
  - name: AMPERSAND
331
363
  comment: "&"
332
364
  - name: AMPERSAND_AMPERSAND
@@ -349,8 +381,6 @@ tokens:
349
381
  comment: "!~"
350
382
  - name: BRACE_LEFT
351
383
  comment: "{"
352
- - name: BRACE_RIGHT
353
- comment: "}"
354
384
  - name: BRACKET_LEFT
355
385
  comment: "["
356
386
  - name: BRACKET_LEFT_ARRAY
@@ -373,8 +403,6 @@ tokens:
373
403
  comment: ":"
374
404
  - name: COLON_COLON
375
405
  comment: "::"
376
- - name: COMMA
377
- comment: ","
378
406
  - name: COMMENT
379
407
  comment: "a comment"
380
408
  - name: CONSTANT
@@ -393,8 +421,6 @@ tokens:
393
421
  comment: "a line inside of embedded documentation"
394
422
  - name: EMBEXPR_BEGIN
395
423
  comment: "#{"
396
- - name: EMBEXPR_END
397
- comment: "}"
398
424
  - name: EMBVAR
399
425
  comment: "#"
400
426
  - name: EQUAL
@@ -461,20 +487,10 @@ tokens:
461
487
  comment: "def"
462
488
  - name: KEYWORD_DEFINED
463
489
  comment: "defined?"
464
- - name: KEYWORD_DO
465
- comment: "do"
466
490
  - name: KEYWORD_DO_LOOP
467
491
  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
492
  - name: KEYWORD_END_UPCASE
475
493
  comment: "END"
476
- - name: KEYWORD_ENSURE
477
- comment: "ensure"
478
494
  - name: KEYWORD_FALSE
479
495
  comment: "false"
480
496
  - name: KEYWORD_FOR
@@ -483,8 +499,6 @@ tokens:
483
499
  comment: "if"
484
500
  - name: KEYWORD_IF_MODIFIER
485
501
  comment: "if in the modifier form"
486
- - name: KEYWORD_IN
487
- comment: "in"
488
502
  - name: KEYWORD_MODULE
489
503
  comment: "module"
490
504
  - name: KEYWORD_NEXT
@@ -497,8 +511,6 @@ tokens:
497
511
  comment: "or"
498
512
  - name: KEYWORD_REDO
499
513
  comment: "redo"
500
- - name: KEYWORD_RESCUE
501
- comment: "rescue"
502
514
  - name: KEYWORD_RESCUE_MODIFIER
503
515
  comment: "rescue in the modifier form"
504
516
  - name: KEYWORD_RETRY
@@ -509,8 +521,6 @@ tokens:
509
521
  comment: "self"
510
522
  - name: KEYWORD_SUPER
511
523
  comment: "super"
512
- - name: KEYWORD_THEN
513
- comment: "then"
514
524
  - name: KEYWORD_TRUE
515
525
  comment: "true"
516
526
  - name: KEYWORD_UNDEF
@@ -523,8 +533,6 @@ tokens:
523
533
  comment: "until"
524
534
  - name: KEYWORD_UNTIL_MODIFIER
525
535
  comment: "until in the modifier form"
526
- - name: KEYWORD_WHEN
527
- comment: "when"
528
536
  - name: KEYWORD_WHILE
529
537
  comment: "while"
530
538
  - name: KEYWORD_WHILE_MODIFIER
@@ -561,16 +569,12 @@ tokens:
561
569
  comment: "-="
562
570
  - name: MINUS_GREATER
563
571
  comment: "->"
564
- - name: NEWLINE
565
- comment: "a newline character outside of other tokens"
566
572
  - name: NUMBERED_REFERENCE
567
573
  comment: "a numbered reference to a capture group in the previous regular expression match"
568
574
  - name: PARENTHESIS_LEFT
569
575
  comment: "("
570
576
  - name: PARENTHESIS_LEFT_PARENTHESES
571
577
  comment: "( for a parentheses node"
572
- - name: PARENTHESIS_RIGHT
573
- comment: ")"
574
578
  - name: PERCENT
575
579
  comment: "%"
576
580
  - name: PERCENT_EQUAL
@@ -603,8 +607,6 @@ tokens:
603
607
  comment: "the beginning of a regular expression"
604
608
  - name: REGEXP_END
605
609
  comment: "the end of a regular expression"
606
- - name: SEMICOLON
607
- comment: ";"
608
610
  - name: SLASH
609
611
  comment: "/"
610
612
  - name: SLASH_EQUAL
@@ -649,6 +651,10 @@ tokens:
649
651
  comment: "a separator between words in a list"
650
652
  - name: __END__
651
653
  comment: "marker for the point in the file at which the parser should stop"
654
+ - name: MISSING
655
+ comment: "a token that was expected but not found"
656
+ - name: NOT_PROVIDED
657
+ comment: "a token that was not present but it is okay"
652
658
  flags:
653
659
  - name: ArgumentsNodeFlags
654
660
  values:
@@ -987,8 +993,19 @@ nodes:
987
993
  - name: constant
988
994
  type: node?
989
995
  kind:
990
- - ConstantReadNode
991
996
  - ConstantPathNode
997
+ - ConstantReadNode
998
+ comment: |
999
+ Represents the optional constant preceding the Array
1000
+
1001
+ foo in Bar[]
1002
+ ^^^
1003
+
1004
+ foo in Bar[1, 2, 3]
1005
+ ^^^
1006
+
1007
+ foo in Bar::Baz[1, 2, 3]
1008
+ ^^^^^^^^
992
1009
  - name: requireds
993
1010
  type: node[]
994
1011
  kind: pattern expression
@@ -1784,7 +1801,7 @@ nodes:
1784
1801
  Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
1785
1802
 
1786
1803
  case true; when false; end
1787
- ^^^^
1804
+ ^^^^
1788
1805
  - name: conditions
1789
1806
  type: node[]
1790
1807
  kind: WhenNode
@@ -1828,6 +1845,11 @@ nodes:
1828
1845
  type: constant[]
1829
1846
  - name: class_keyword_loc
1830
1847
  type: location
1848
+ comment: |
1849
+ Represents the location of the `class` keyword.
1850
+
1851
+ class Foo end
1852
+ ^^^^^
1831
1853
  - name: constant_path
1832
1854
  type: node
1833
1855
  kind:
@@ -1836,18 +1858,43 @@ nodes:
1836
1858
  - on error: CallNode # class 0.X end
1837
1859
  - name: inheritance_operator_loc
1838
1860
  type: location?
1861
+ comment: |
1862
+ Represents the location of the `<` operator.
1863
+
1864
+ class Foo < Bar
1865
+ ^
1839
1866
  - name: superclass
1840
1867
  type: node?
1841
1868
  kind: non-void expression
1869
+ comment: |
1870
+ Represents the superclass of the class.
1871
+
1872
+ class Foo < Bar
1873
+ ^^^
1842
1874
  - name: body
1843
1875
  type: node?
1844
1876
  kind:
1845
1877
  - StatementsNode
1846
1878
  - BeginNode
1879
+ comment: |
1880
+ Represents the body of the class.
1881
+
1882
+ class Foo
1883
+ foo
1884
+ ^^^
1847
1885
  - name: end_keyword_loc
1848
1886
  type: location
1887
+ comment: |
1888
+ Represents the location of the `end` keyword.
1889
+
1890
+ class Foo end
1891
+ ^^^
1849
1892
  - name: name
1850
1893
  type: constant
1894
+ comment: |
1895
+ The name of the class.
1896
+
1897
+ class Foo end # name `:Foo`
1851
1898
  comment: |
1852
1899
  Represents a class declaration involving the `class` keyword.
1853
1900
 
@@ -2374,23 +2421,68 @@ nodes:
2374
2421
  - name: constant
2375
2422
  type: node?
2376
2423
  kind:
2377
- - ConstantReadNode
2378
2424
  - ConstantPathNode
2425
+ - ConstantReadNode
2426
+ comment: |
2427
+ Represents the optional constant preceding the pattern
2428
+
2429
+ foo in Foo(*bar, baz, *qux)
2430
+ ^^^
2379
2431
  - name: left
2380
2432
  type: node
2381
2433
  kind: SplatNode
2434
+ comment: |
2435
+ Represents the first wildcard node in the pattern.
2436
+
2437
+ foo in *bar, baz, *qux
2438
+ ^^^^
2439
+
2440
+ foo in Foo(*bar, baz, *qux)
2441
+ ^^^^
2382
2442
  - name: requireds
2383
2443
  type: node[]
2384
2444
  kind: pattern expression
2445
+ comment: |
2446
+ Represents the nodes in between the wildcards.
2447
+
2448
+ foo in *bar, baz, *qux
2449
+ ^^^
2450
+
2451
+ foo in Foo(*bar, baz, 1, *qux)
2452
+ ^^^^^^
2385
2453
  - name: right
2386
2454
  type: node
2387
2455
  kind:
2388
2456
  - SplatNode
2389
2457
  - on error: MissingNode
2458
+ comment: |
2459
+ Represents the second wildcard node in the pattern.
2460
+
2461
+ foo in *bar, baz, *qux
2462
+ ^^^^
2463
+
2464
+ foo in Foo(*bar, baz, *qux)
2465
+ ^^^^
2390
2466
  - name: opening_loc
2391
2467
  type: location?
2468
+ comment: |
2469
+ The location of the opening brace.
2470
+
2471
+ foo in [*bar, baz, *qux]
2472
+ ^
2473
+
2474
+ foo in Foo(*bar, baz, *qux)
2475
+ ^
2392
2476
  - name: closing_loc
2393
2477
  type: location?
2478
+ comment: |
2479
+ The location of the closing brace.
2480
+
2481
+ foo in [*bar, baz, *qux]
2482
+ ^
2483
+
2484
+ foo in Foo(*bar, baz, *qux)
2485
+ ^
2394
2486
  comment: |
2395
2487
  Represents a find pattern in pattern matching.
2396
2488
 
@@ -2402,6 +2494,9 @@ nodes:
2402
2494
 
2403
2495
  foo in Foo(*bar, baz, *qux)
2404
2496
  ^^^^^^^^^^^^^^^^^^^^
2497
+
2498
+ foo => *bar, baz, *qux
2499
+ ^^^^^^^^^^^^^^^
2405
2500
  - name: FlipFlopNode
2406
2501
  flags: RangeFlags
2407
2502
  fields:
@@ -2679,20 +2774,60 @@ nodes:
2679
2774
  - name: constant
2680
2775
  type: node?
2681
2776
  kind:
2682
- - ConstantReadNode
2683
2777
  - ConstantPathNode
2778
+ - ConstantReadNode
2779
+ comment: |
2780
+ Represents the optional constant preceding the Hash.
2781
+
2782
+ foo => Bar[a: 1, b: 2]
2783
+ ^^^
2784
+
2785
+ foo => Bar::Baz[a: 1, b: 2]
2786
+ ^^^^^^^^
2684
2787
  - name: elements
2685
2788
  type: node[]
2686
2789
  kind: AssocNode
2790
+ comment: |
2791
+ Represents the explicit named hash keys and values.
2792
+
2793
+ foo => { a: 1, b:, ** }
2794
+ ^^^^^^^^
2687
2795
  - name: rest
2688
2796
  type: node?
2689
2797
  kind:
2690
2798
  - AssocSplatNode
2691
2799
  - NoKeywordsParameterNode
2800
+ comment: |
2801
+ 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`.
2802
+
2803
+ foo => { a: 1, b:, **c }
2804
+ ^^^
2805
+
2806
+ foo => { a: 1, b:, ** }
2807
+ ^^
2808
+
2809
+ foo => { a: 1, b:, **nil }
2810
+ ^^^^^
2692
2811
  - name: opening_loc
2693
2812
  type: location?
2813
+ comment: |
2814
+ The location of the opening brace.
2815
+
2816
+ foo => { a: 1 }
2817
+ ^
2818
+
2819
+ foo => Bar[a: 1]
2820
+ ^
2694
2821
  - name: closing_loc
2695
2822
  type: location?
2823
+ comment: |
2824
+ The location of the closing brace.
2825
+
2826
+ foo => { a: 1 }
2827
+ ^
2828
+
2829
+ foo => Bar[a: 1]
2830
+ ^
2696
2831
  comment: |
2697
2832
  Represents a hash pattern in pattern matching.
2698
2833
 
@@ -2701,6 +2836,12 @@ nodes:
2701
2836
 
2702
2837
  foo => { a: 1, b: 2, **c }
2703
2838
  ^^^^^^^^^^^^^^^^^^^
2839
+
2840
+ foo => Bar[a: 1, b: 2]
2841
+ ^^^^^^^^^^^^^^^
2842
+
2843
+ foo in { a: 1, b: 2 }
2844
+ ^^^^^^^^^^^^^^
2704
2845
  - name: IfNode
2705
2846
  fields:
2706
2847
  - name: if_keyword_loc
@@ -3353,6 +3494,9 @@ nodes:
3353
3494
 
3354
3495
  foo, bar = baz
3355
3496
  ^^^ ^^^
3497
+
3498
+ foo => baz
3499
+ ^^^
3356
3500
  - name: LocalVariableWriteNode
3357
3501
  fields:
3358
3502
  - name: name
@@ -3443,11 +3587,65 @@ nodes:
3443
3587
  - name: value
3444
3588
  type: node
3445
3589
  kind: non-void expression
3590
+ comment: |
3591
+ Represents the left-hand side of the operator.
3592
+
3593
+ foo => bar
3594
+ ^^^
3446
3595
  - name: pattern
3447
3596
  type: node
3448
3597
  kind: pattern expression
3598
+ comment: |
3599
+ Represents the right-hand side of the operator. The type of the node depends on the expression.
3600
+
3601
+ Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
3602
+
3603
+ foo => a # This is equivalent to writing `a = foo`
3604
+ ^
3605
+
3606
+ Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
3607
+
3608
+ foo => [a]
3609
+ ^^^
3610
+
3611
+ foo => a, b
3612
+ ^^^^
3613
+
3614
+ foo => Bar[a, b]
3615
+ ^^^^^^^^^
3616
+
3617
+ If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
3618
+
3619
+ foo => *, 1, *a
3620
+ ^^^^^
3621
+
3622
+ Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
3623
+
3624
+ foo => { a: 1, b: }
3625
+
3626
+ foo => Bar[a: 1, b:]
3627
+
3628
+ foo => Bar[**]
3629
+
3630
+ To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
3631
+
3632
+ foo => ^a
3633
+ ^^
3634
+
3635
+ Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
3636
+
3637
+ foo => ^(a + 1)
3638
+
3639
+ Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
3640
+
3641
+ foo => CONST
3449
3642
  - name: operator_loc
3450
3643
  type: location
3644
+ comment: |
3645
+ The location of the operator.
3646
+
3647
+ foo => bar
3648
+ ^^
3451
3649
  comment: |
3452
3650
  Represents the use of the `=>` operator.
3453
3651
 
@@ -3877,12 +4075,32 @@ nodes:
3877
4075
  - name: expression
3878
4076
  type: node
3879
4077
  kind: non-void expression
4078
+ comment: |
4079
+ The expression used in the pinned expression
4080
+
4081
+ foo in ^(bar)
4082
+ ^^^
3880
4083
  - name: operator_loc
3881
4084
  type: location
4085
+ comment: |
4086
+ The location of the `^` operator
4087
+
4088
+ foo in ^(bar)
4089
+ ^
3882
4090
  - name: lparen_loc
3883
4091
  type: location
4092
+ comment: |
4093
+ The location of the opening parenthesis.
4094
+
4095
+ foo in ^(bar)
4096
+ ^
3884
4097
  - name: rparen_loc
3885
4098
  type: location
4099
+ comment: |
4100
+ The location of the closing parenthesis.
4101
+
4102
+ foo in ^(bar)
4103
+ ^
3886
4104
  comment: |
3887
4105
  Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
3888
4106
 
@@ -3901,8 +4119,18 @@ nodes:
3901
4119
  - NumberedReferenceReadNode # foo in ^$1
3902
4120
  - ItLocalVariableReadNode # proc { 1 in ^it }
3903
4121
  - on error: MissingNode # foo in ^Bar
4122
+ comment: |
4123
+ The variable used in the pinned expression
4124
+
4125
+ foo in ^bar
4126
+ ^^^
3904
4127
  - name: operator_loc
3905
4128
  type: location
4129
+ comment: |
4130
+ The location of the `^` operator
4131
+
4132
+ foo in ^bar
4133
+ ^
3906
4134
  comment: |
3907
4135
  Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
3908
4136
 
data/docs/design.md CHANGED
@@ -18,11 +18,11 @@ The templated files contain all of the code required to allocate and initialize
18
18
 
19
19
  In order to provide the best possible error tolerance, the parser is hand-written. It is structured using Pratt parsing, a technique developed by Vaughan Pratt back in the 1970s. Below are a bunch of links to articles and papers that explain Pratt parsing in more detail.
20
20
 
21
- * https://web.archive.org/web/20151223215421/http://hall.org.ua/halls/wizzard/pdf/Vaughan.Pratt.TDOP.pdf
21
+ * https://github.com/tdop/tdop.github.io/raw/master/original.pdf
22
22
  * https://tdop.github.io/
23
23
  * https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
24
24
  * https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
25
- * https://chidiwilliams.com/post/on-recursive-descent-and-pratt-parsing/
25
+ * https://chidiwilliams.com/posts/on-recursive-descent-and-pratt-parsing
26
26
 
27
27
  You can find most of the functions that correspond to constructs in the Pratt parsing algorithm in `prism.c`. As a couple of examples:
28
28