@@ -247,6 +247,11 @@ def visit_call_node(node)
247
247
248
248
if node . call_operator_loc . nil?
249
249
case name
250
+ when :-@
251
+ case ( receiver = node . receiver ) . type
252
+ when :integer_node , :float_node , :rational_node , :imaginary_node
253
+ return visit ( numeric_negate ( node . message_loc , receiver ) )
254
+ end
250
255
when :!
251
256
return visit_block ( builder . not_op ( token ( node . message_loc ) , token ( node . opening_loc ) , visit ( node . receiver ) , token ( node . closing_loc ) ) , block )
252
257
when :[]
@@ -792,7 +797,7 @@ def visit_if_node(node)
792
797
793
798
# 1i
794
799
def visit_imaginary_node ( node )
795
- visit_numeric ( node , builder . complex ( [ node . value , srange ( node . location ) ] ) )
800
+ visit_numeric ( node , builder . complex ( [ imaginary_value ( node ) , srange ( node . location ) ] ) )
796
801
end
797
802
798
803
# { foo: }
@@ -1325,7 +1330,7 @@ def visit_range_node(node)
1325
1330
# 1r
1326
1331
# ^^
1327
1332
def visit_rational_node ( node )
1328
- visit_numeric ( node , builder . rational ( [ node . value , srange ( node . location ) ] ) )
1333
+ visit_numeric ( node , builder . rational ( [ rational_value ( node ) , srange ( node . location ) ] ) )
1329
1334
end
1330
1335
1331
1336
# redo
@@ -1690,6 +1695,26 @@ def find_forwarding(node)
1690
1695
forwarding
1691
1696
end
1692
1697
1698
+ # Because we have mutated the AST to allow for newlines in the middle of
1699
+ # a rational, we need to manually handle the value here.
1700
+ def imaginary_value ( node )
1701
+ Complex ( 0 , node . numeric . is_a? ( RationalNode ) ? rational_value ( node . numeric ) : node . numeric . value )
1702
+ end
1703
+
1704
+ # Negate the value of a numeric node. This is a special case where you
1705
+ # have a negative sign on one line and then a number on the next line.
1706
+ # In normal Ruby, this will always be a method call. The parser gem,
1707
+ # however, marks this as a numeric literal. We have to massage the tree
1708
+ # here to get it into the correct form.
1709
+ def numeric_negate ( message_loc , receiver )
1710
+ case receiver . type
1711
+ when :integer_node , :float_node
1712
+ receiver . copy ( value : -receiver . value , location : message_loc . join ( receiver . location ) )
1713
+ when :rational_node , :imaginary_node
1714
+ receiver . copy ( numeric : numeric_negate ( message_loc , receiver . numeric ) , location : message_loc . join ( receiver . location ) )
1715
+ end
1716
+ end
1717
+
1693
1718
# Blocks can have a special set of parameters that automatically expand
1694
1719
# when given arrays if they have a single required parameter and no
1695
1720
# other parameters.
@@ -1704,6 +1729,16 @@ def procarg0?(parameters)
1704
1729
parameters . block . nil?
1705
1730
end
1706
1731
1732
+ # Because we have mutated the AST to allow for newlines in the middle of
1733
+ # a rational, we need to manually handle the value here.
1734
+ def rational_value ( node )
1735
+ if node . numeric . is_a? ( IntegerNode )
1736
+ Rational ( node . numeric . value )
1737
+ else
1738
+ Rational ( node . slice . gsub ( /\s / , "" ) . chomp ( "r" ) )
1739
+ end
1740
+ end
1741
+
1707
1742
# Locations in the parser gem AST are generated using this class. We
1708
1743
# store a reference to its constant to make it slightly faster to look
1709
1744
# up.
0 commit comments