parser 2.6.5.0 → 2.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +7 -0
- data/doc/AST_FORMAT.md +346 -20
- data/lib/parser.rb +3 -1
- data/lib/parser/ast/processor.rb +15 -0
- data/lib/parser/base.rb +19 -0
- data/lib/parser/builders/default.rb +245 -12
- data/lib/parser/context.rb +4 -0
- data/lib/parser/current.rb +4 -4
- data/lib/parser/current_arg_stack.rb +43 -0
- data/lib/parser/lexer.rl +93 -94
- data/lib/parser/lexer/dedenter.rb +48 -49
- data/lib/parser/{lexer/max_numparam_stack.rb → max_numparam_stack.rb} +10 -4
- data/lib/parser/messages.rb +34 -29
- data/lib/parser/meta.rb +6 -2
- data/lib/parser/ruby27.y +488 -35
- data/lib/parser/static_environment.rb +10 -0
- data/lib/parser/variables_stack.rb +32 -0
- data/lib/parser/version.rb +1 -1
- data/test/helper.rb +1 -0
- data/test/test_lexer.rb +7 -66
- data/test/test_parser.rb +1776 -123
- metadata +5 -3
    
        data/lib/parser.rb
    CHANGED
    
    | @@ -67,13 +67,15 @@ module Parser | |
| 67 67 | 
             
              require 'parser/lexer/literal'
         | 
| 68 68 | 
             
              require 'parser/lexer/stack_state'
         | 
| 69 69 | 
             
              require 'parser/lexer/dedenter'
         | 
| 70 | 
            -
              require 'parser/lexer/max_numparam_stack'
         | 
| 71 70 |  | 
| 72 71 | 
             
              module Builders
         | 
| 73 72 | 
             
                require 'parser/builders/default'
         | 
| 74 73 | 
             
              end
         | 
| 75 74 |  | 
| 76 75 | 
             
              require 'parser/context'
         | 
| 76 | 
            +
              require 'parser/max_numparam_stack'
         | 
| 77 | 
            +
              require 'parser/current_arg_stack'
         | 
| 78 | 
            +
              require 'parser/variables_stack'
         | 
| 77 79 |  | 
| 78 80 | 
             
              require 'parser/base'
         | 
| 79 81 |  | 
    
        data/lib/parser/ast/processor.rb
    CHANGED
    
    | @@ -236,6 +236,21 @@ module Parser | |
| 236 236 | 
             
                  alias on_preexe   process_regular_node
         | 
| 237 237 | 
             
                  alias on_postexe  process_regular_node
         | 
| 238 238 |  | 
| 239 | 
            +
                  alias on_case_match              process_regular_node
         | 
| 240 | 
            +
                  alias on_in_match                process_regular_node
         | 
| 241 | 
            +
                  alias on_in_pattern              process_regular_node
         | 
| 242 | 
            +
                  alias on_if_guard                process_regular_node
         | 
| 243 | 
            +
                  alias on_unless_guard            process_regular_node
         | 
| 244 | 
            +
                  alias on_match_var               process_variable_node
         | 
| 245 | 
            +
                  alias on_match_rest              process_regular_node
         | 
| 246 | 
            +
                  alias on_pin                     process_regular_node
         | 
| 247 | 
            +
                  alias on_match_alt               process_regular_node
         | 
| 248 | 
            +
                  alias on_match_as                process_regular_node
         | 
| 249 | 
            +
                  alias on_array_pattern           process_regular_node
         | 
| 250 | 
            +
                  alias on_array_pattern_with_tail process_regular_node
         | 
| 251 | 
            +
                  alias on_hash_pattern            process_regular_node
         | 
| 252 | 
            +
                  alias on_const_pattern           process_regular_node
         | 
| 253 | 
            +
             | 
| 239 254 | 
             
                  # @private
         | 
| 240 255 | 
             
                  def process_variable_node(node)
         | 
| 241 256 | 
             
                    warn 'Parser::AST::Processor#process_variable_node is deprecated as a' \
         | 
    
        data/lib/parser/base.rb
    CHANGED
    
    | @@ -114,6 +114,10 @@ module Parser | |
| 114 114 | 
             
                attr_reader :static_env
         | 
| 115 115 | 
             
                attr_reader :source_buffer
         | 
| 116 116 | 
             
                attr_reader :context
         | 
| 117 | 
            +
                attr_reader :max_numparam_stack
         | 
| 118 | 
            +
                attr_reader :current_arg_stack
         | 
| 119 | 
            +
                attr_reader :pattern_variables
         | 
| 120 | 
            +
                attr_reader :pattern_hash_keys
         | 
| 117 121 |  | 
| 118 122 | 
             
                ##
         | 
| 119 123 | 
             
                # @param [Parser::Builders::Default] builder The AST builder to use.
         | 
| @@ -126,6 +130,18 @@ module Parser | |
| 126 130 | 
             
                  # Stack that holds current parsing context
         | 
| 127 131 | 
             
                  @context = Context.new
         | 
| 128 132 |  | 
| 133 | 
            +
                  # Maximum numbered parameters stack
         | 
| 134 | 
            +
                  @max_numparam_stack = MaxNumparamStack.new
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  # Current argument names stack
         | 
| 137 | 
            +
                  @current_arg_stack = CurrentArgStack.new
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                  # Stack of set of variables used in the current pattern
         | 
| 140 | 
            +
                  @pattern_variables = VariablesStack.new
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  # Stack of set of keys used in the current hash in pattern matchinig
         | 
| 143 | 
            +
                  @pattern_hash_keys = VariablesStack.new
         | 
| 144 | 
            +
             | 
| 129 145 | 
             
                  @lexer = Lexer.new(version)
         | 
| 130 146 | 
             
                  @lexer.diagnostics = @diagnostics
         | 
| 131 147 | 
             
                  @lexer.static_env  = @static_env
         | 
| @@ -153,6 +169,9 @@ module Parser | |
| 153 169 | 
             
                  @lexer.reset
         | 
| 154 170 | 
             
                  @static_env.reset
         | 
| 155 171 | 
             
                  @context.reset
         | 
| 172 | 
            +
                  @current_arg_stack.reset
         | 
| 173 | 
            +
                  @pattern_variables.reset
         | 
| 174 | 
            +
                  @pattern_hash_keys.reset
         | 
| 156 175 |  | 
| 157 176 | 
             
                  self
         | 
| 158 177 | 
             
                end
         | 
| @@ -453,11 +453,6 @@ module Parser | |
| 453 453 | 
             
                    variable_map(token))
         | 
| 454 454 | 
             
                end
         | 
| 455 455 |  | 
| 456 | 
            -
                def numparam(token)
         | 
| 457 | 
            -
                  n(:numparam, [ value(token).to_i ],
         | 
| 458 | 
            -
                    variable_map(token))
         | 
| 459 | 
            -
                end
         | 
| 460 | 
            -
             | 
| 461 456 | 
             
                def back_ref(token)
         | 
| 462 457 | 
             
                  n(:back_ref, [ value(token).to_sym ],
         | 
| 463 458 | 
             
                    token_map(token))
         | 
| @@ -498,6 +493,11 @@ module Parser | |
| 498 493 | 
             
                    name, = *node
         | 
| 499 494 |  | 
| 500 495 | 
             
                    if @parser.static_env.declared?(name)
         | 
| 496 | 
            +
                      if name.to_s == parser.current_arg_stack.top
         | 
| 497 | 
            +
                        diagnostic :error, :circular_argument_reference,
         | 
| 498 | 
            +
                                   { :var_name => name.to_s }, node.loc.expression
         | 
| 499 | 
            +
                      end
         | 
| 500 | 
            +
             | 
| 501 501 | 
             
                      node.updated(:lvar)
         | 
| 502 502 | 
             
                    else
         | 
| 503 503 | 
             
                      name, = *node
         | 
| @@ -556,6 +556,9 @@ module Parser | |
| 556 556 |  | 
| 557 557 | 
             
                  when :ident
         | 
| 558 558 | 
             
                    name, = *node
         | 
| 559 | 
            +
             | 
| 560 | 
            +
                    check_assignment_to_numparam(node)
         | 
| 561 | 
            +
             | 
| 559 562 | 
             
                    @parser.static_env.declare(name)
         | 
| 560 563 |  | 
| 561 564 | 
             
                    node.updated(:lvasgn)
         | 
| @@ -688,6 +691,10 @@ module Parser | |
| 688 691 | 
             
                  n(:numargs, [ max_numparam ], nil)
         | 
| 689 692 | 
             
                end
         | 
| 690 693 |  | 
| 694 | 
            +
                def forward_args(begin_t, dots_t, end_t)
         | 
| 695 | 
            +
                  n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
         | 
| 696 | 
            +
                end
         | 
| 697 | 
            +
             | 
| 691 698 | 
             
                def arg(name_t)
         | 
| 692 699 | 
             
                  n(:arg, [ value(name_t).to_sym ],
         | 
| 693 700 | 
             
                    variable_map(name_t))
         | 
| @@ -837,6 +844,10 @@ module Parser | |
| 837 844 | 
             
                  end
         | 
| 838 845 | 
             
                end
         | 
| 839 846 |  | 
| 847 | 
            +
                def forwarded_args(dots_t)
         | 
| 848 | 
            +
                  n(:forwarded_args, [], token_map(dots_t))
         | 
| 849 | 
            +
                end
         | 
| 850 | 
            +
             | 
| 840 851 | 
             
                def call_method(receiver, dot_t, selector_t,
         | 
| 841 852 | 
             
                                lparen_t=nil, args=[], rparen_t=nil)
         | 
| 842 853 | 
             
                  type = call_type_for_dot(dot_t)
         | 
| @@ -866,11 +877,10 @@ module Parser | |
| 866 877 | 
             
                  end
         | 
| 867 878 |  | 
| 868 879 | 
             
                  last_arg = call_args.last
         | 
| 869 | 
            -
                  if last_arg && last_arg.type == :block_pass
         | 
| 880 | 
            +
                  if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args)
         | 
| 870 881 | 
             
                    diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
         | 
| 871 882 | 
             
                  end
         | 
| 872 883 |  | 
| 873 | 
            -
             | 
| 874 884 | 
             
                  if args.type == :numargs
         | 
| 875 885 | 
             
                    block_type = :numblock
         | 
| 876 886 | 
             
                    args = args.children[0]
         | 
| @@ -1006,11 +1016,6 @@ module Parser | |
| 1006 1016 | 
             
                  end
         | 
| 1007 1017 | 
             
                end
         | 
| 1008 1018 |  | 
| 1009 | 
            -
                def method_ref(receiver, dot_t, selector_t)
         | 
| 1010 | 
            -
                  n(:meth_ref, [ receiver, value(selector_t).to_sym ],
         | 
| 1011 | 
            -
                      send_map(receiver, dot_t, selector_t, nil, [], nil))
         | 
| 1012 | 
            -
                end
         | 
| 1013 | 
            -
             | 
| 1014 1019 | 
             
                #
         | 
| 1015 1020 | 
             
                # Control flow
         | 
| 1016 1021 | 
             
                #
         | 
| @@ -1203,6 +1208,188 @@ module Parser | |
| 1203 1208 | 
             
                  end
         | 
| 1204 1209 | 
             
                end
         | 
| 1205 1210 |  | 
| 1211 | 
            +
                #
         | 
| 1212 | 
            +
                # PATTERN MATCHING
         | 
| 1213 | 
            +
                #
         | 
| 1214 | 
            +
             | 
| 1215 | 
            +
                def case_match(case_t, expr, in_bodies, else_t, else_body, end_t)
         | 
| 1216 | 
            +
                  n(:case_match, [ expr, *(in_bodies << else_body)],
         | 
| 1217 | 
            +
                    condition_map(case_t, expr, nil, nil, else_t, else_body, end_t))
         | 
| 1218 | 
            +
                end
         | 
| 1219 | 
            +
             | 
| 1220 | 
            +
                def in_match(lhs, in_t, rhs)
         | 
| 1221 | 
            +
                  n(:in_match, [lhs, rhs],
         | 
| 1222 | 
            +
                    binary_op_map(lhs, in_t, rhs))
         | 
| 1223 | 
            +
                end
         | 
| 1224 | 
            +
             | 
| 1225 | 
            +
                def in_pattern(in_t, pattern, guard, then_t, body)
         | 
| 1226 | 
            +
                  children = [pattern, guard, body]
         | 
| 1227 | 
            +
                  n(:in_pattern, children,
         | 
| 1228 | 
            +
                    keyword_map(in_t, then_t, children.compact, nil))
         | 
| 1229 | 
            +
                end
         | 
| 1230 | 
            +
             | 
| 1231 | 
            +
                def if_guard(if_t, if_body)
         | 
| 1232 | 
            +
                  n(:if_guard, [if_body], guard_map(if_t, if_body))
         | 
| 1233 | 
            +
                end
         | 
| 1234 | 
            +
             | 
| 1235 | 
            +
                def unless_guard(unless_t, unless_body)
         | 
| 1236 | 
            +
                  n(:unless_guard, [unless_body], guard_map(unless_t, unless_body))
         | 
| 1237 | 
            +
                end
         | 
| 1238 | 
            +
             | 
| 1239 | 
            +
                def match_var(name_t)
         | 
| 1240 | 
            +
                  name = value(name_t).to_sym
         | 
| 1241 | 
            +
             | 
| 1242 | 
            +
                  check_duplicate_pattern_variable(name, loc(name_t))
         | 
| 1243 | 
            +
                  @parser.static_env.declare(name)
         | 
| 1244 | 
            +
             | 
| 1245 | 
            +
                  n(:match_var, [ name ],
         | 
| 1246 | 
            +
                    variable_map(name_t))
         | 
| 1247 | 
            +
                end
         | 
| 1248 | 
            +
             | 
| 1249 | 
            +
                def match_hash_var(name_t)
         | 
| 1250 | 
            +
                  name = value(name_t).to_sym
         | 
| 1251 | 
            +
             | 
| 1252 | 
            +
                  expr_l = loc(name_t)
         | 
| 1253 | 
            +
                  name_l = expr_l.adjust(end_pos: -1)
         | 
| 1254 | 
            +
             | 
| 1255 | 
            +
                  check_duplicate_pattern_variable(name, name_l)
         | 
| 1256 | 
            +
                  @parser.static_env.declare(name)
         | 
| 1257 | 
            +
             | 
| 1258 | 
            +
                  n(:match_var, [ name ],
         | 
| 1259 | 
            +
                    Source::Map::Variable.new(name_l, expr_l))
         | 
| 1260 | 
            +
                end
         | 
| 1261 | 
            +
             | 
| 1262 | 
            +
                def match_hash_var_from_str(begin_t, strings, end_t)
         | 
| 1263 | 
            +
                  if strings.length > 1
         | 
| 1264 | 
            +
                    diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
         | 
| 1265 | 
            +
                  end
         | 
| 1266 | 
            +
             | 
| 1267 | 
            +
                  string = strings[0]
         | 
| 1268 | 
            +
             | 
| 1269 | 
            +
                  case string.type
         | 
| 1270 | 
            +
                  when :str
         | 
| 1271 | 
            +
                    # MRI supports plain strings in hash pattern matching
         | 
| 1272 | 
            +
                    name, = *string
         | 
| 1273 | 
            +
                    name_l = string.loc.expression
         | 
| 1274 | 
            +
             | 
| 1275 | 
            +
                    check_lvar_name(name, name_l)
         | 
| 1276 | 
            +
                    check_duplicate_pattern_variable(name, name_l)
         | 
| 1277 | 
            +
             | 
| 1278 | 
            +
                    @parser.static_env.declare(name)
         | 
| 1279 | 
            +
             | 
| 1280 | 
            +
                    if (begin_l = string.loc.begin)
         | 
| 1281 | 
            +
                      # exclude beginning of the string from the location of the variable
         | 
| 1282 | 
            +
                      name_l = name_l.adjust(begin_pos: begin_l.length)
         | 
| 1283 | 
            +
                    end
         | 
| 1284 | 
            +
             | 
| 1285 | 
            +
                    if (end_l = string.loc.end)
         | 
| 1286 | 
            +
                      # exclude end of the string from the location of the variable
         | 
| 1287 | 
            +
                      name_l = name_l.adjust(end_pos: -end_l.length)
         | 
| 1288 | 
            +
                    end
         | 
| 1289 | 
            +
             | 
| 1290 | 
            +
                    expr_l = loc(begin_t).join(string.loc.expression).join(loc(end_t))
         | 
| 1291 | 
            +
                    n(:match_var, [ name.to_sym ],
         | 
| 1292 | 
            +
                      Source::Map::Variable.new(name_l, expr_l))
         | 
| 1293 | 
            +
                  when :begin
         | 
| 1294 | 
            +
                    match_hash_var_from_str(begin_t, string.children, end_t)
         | 
| 1295 | 
            +
                  end
         | 
| 1296 | 
            +
                end
         | 
| 1297 | 
            +
             | 
| 1298 | 
            +
                def match_rest(star_t, name_t = nil)
         | 
| 1299 | 
            +
                  if name_t.nil?
         | 
| 1300 | 
            +
                    n0(:match_rest,
         | 
| 1301 | 
            +
                      unary_op_map(star_t))
         | 
| 1302 | 
            +
                  else
         | 
| 1303 | 
            +
                    name = match_var(name_t)
         | 
| 1304 | 
            +
                    n(:match_rest, [ name ],
         | 
| 1305 | 
            +
                      unary_op_map(star_t, name))
         | 
| 1306 | 
            +
                  end
         | 
| 1307 | 
            +
                end
         | 
| 1308 | 
            +
             | 
| 1309 | 
            +
                def hash_pattern(lbrace_t, kwargs, rbrace_t)
         | 
| 1310 | 
            +
                  args = check_duplicate_args(kwargs)
         | 
| 1311 | 
            +
                  n(:hash_pattern, args,
         | 
| 1312 | 
            +
                    collection_map(lbrace_t, args, rbrace_t))
         | 
| 1313 | 
            +
                end
         | 
| 1314 | 
            +
             | 
| 1315 | 
            +
                def array_pattern(lbrack_t, elements, rbrack_t)
         | 
| 1316 | 
            +
                  trailing_comma = false
         | 
| 1317 | 
            +
             | 
| 1318 | 
            +
                  elements = elements.map do |element|
         | 
| 1319 | 
            +
                    if element.type == :match_with_trailing_comma
         | 
| 1320 | 
            +
                      trailing_comma = true
         | 
| 1321 | 
            +
                      element.children.first
         | 
| 1322 | 
            +
                    else
         | 
| 1323 | 
            +
                      trailing_comma = false
         | 
| 1324 | 
            +
                      element
         | 
| 1325 | 
            +
                    end
         | 
| 1326 | 
            +
                  end
         | 
| 1327 | 
            +
             | 
| 1328 | 
            +
                  node_type = trailing_comma ? :array_pattern_with_tail : :array_pattern
         | 
| 1329 | 
            +
                  n(node_type, elements,
         | 
| 1330 | 
            +
                    collection_map(lbrack_t, elements, rbrack_t))
         | 
| 1331 | 
            +
                end
         | 
| 1332 | 
            +
             | 
| 1333 | 
            +
                def match_with_trailing_comma(match)
         | 
| 1334 | 
            +
                  n(:match_with_trailing_comma, [ match ], nil)
         | 
| 1335 | 
            +
                end
         | 
| 1336 | 
            +
             | 
| 1337 | 
            +
                def const_pattern(const, ldelim_t, pattern, rdelim_t)
         | 
| 1338 | 
            +
                  n(:const_pattern, [const, pattern],
         | 
| 1339 | 
            +
                    collection_map(ldelim_t, [pattern], rdelim_t))
         | 
| 1340 | 
            +
                end
         | 
| 1341 | 
            +
             | 
| 1342 | 
            +
                def pin(pin_t, var)
         | 
| 1343 | 
            +
                  n(:pin, [ var ],
         | 
| 1344 | 
            +
                    send_unary_op_map(pin_t, var))
         | 
| 1345 | 
            +
                end
         | 
| 1346 | 
            +
             | 
| 1347 | 
            +
                def match_alt(left, pipe_t, right)
         | 
| 1348 | 
            +
                  source_map = binary_op_map(left, pipe_t, right)
         | 
| 1349 | 
            +
             | 
| 1350 | 
            +
                  n(:match_alt, [ left, right ],
         | 
| 1351 | 
            +
                    source_map)
         | 
| 1352 | 
            +
                end
         | 
| 1353 | 
            +
             | 
| 1354 | 
            +
                def match_as(value, assoc_t, as)
         | 
| 1355 | 
            +
                  source_map = binary_op_map(value, assoc_t, as)
         | 
| 1356 | 
            +
             | 
| 1357 | 
            +
                  n(:match_as, [ value, as ],
         | 
| 1358 | 
            +
                    source_map)
         | 
| 1359 | 
            +
                end
         | 
| 1360 | 
            +
             | 
| 1361 | 
            +
                def match_nil_pattern(dstar_t, nil_t)
         | 
| 1362 | 
            +
                  n0(:match_nil_pattern,
         | 
| 1363 | 
            +
                    arg_prefix_map(dstar_t, nil_t))
         | 
| 1364 | 
            +
                end
         | 
| 1365 | 
            +
             | 
| 1366 | 
            +
                def match_pair(label_type, label, value)
         | 
| 1367 | 
            +
                  if label_type == :label
         | 
| 1368 | 
            +
                    check_duplicate_pattern_key(label[0], label[1])
         | 
| 1369 | 
            +
                    pair_keyword(label, value)
         | 
| 1370 | 
            +
                  else
         | 
| 1371 | 
            +
                    begin_t, parts, end_t = label
         | 
| 1372 | 
            +
             | 
| 1373 | 
            +
                    # quoted label like "label": value
         | 
| 1374 | 
            +
                    if (var_name = static_string(parts))
         | 
| 1375 | 
            +
                      loc = loc(begin_t).join(loc(end_t))
         | 
| 1376 | 
            +
                      check_duplicate_pattern_key(var_name, loc)
         | 
| 1377 | 
            +
                    end
         | 
| 1378 | 
            +
             | 
| 1379 | 
            +
                    pair_quoted(begin_t, parts, end_t, value)
         | 
| 1380 | 
            +
                  end
         | 
| 1381 | 
            +
                end
         | 
| 1382 | 
            +
             | 
| 1383 | 
            +
                def match_label(label_type, label)
         | 
| 1384 | 
            +
                  if label_type == :label
         | 
| 1385 | 
            +
                    match_hash_var(label)
         | 
| 1386 | 
            +
                  else
         | 
| 1387 | 
            +
                    # quoted label like "label": value
         | 
| 1388 | 
            +
                    begin_t, strings, end_t = label
         | 
| 1389 | 
            +
                    match_hash_var_from_str(begin_t, strings, end_t)
         | 
| 1390 | 
            +
                  end
         | 
| 1391 | 
            +
                end
         | 
| 1392 | 
            +
             | 
| 1206 1393 | 
             
                private
         | 
| 1207 1394 |  | 
| 1208 1395 | 
             
                #
         | 
| @@ -1292,6 +1479,19 @@ module Parser | |
| 1292 1479 | 
             
                  end
         | 
| 1293 1480 | 
             
                end
         | 
| 1294 1481 |  | 
| 1482 | 
            +
                def check_assignment_to_numparam(node)
         | 
| 1483 | 
            +
                  name = node.children[0].to_s
         | 
| 1484 | 
            +
             | 
| 1485 | 
            +
                  assigning_to_numparam =
         | 
| 1486 | 
            +
                    @parser.context.in_dynamic_block? &&
         | 
| 1487 | 
            +
                    name =~ /\A_([1-9])\z/ &&
         | 
| 1488 | 
            +
                    @parser.max_numparam_stack.has_numparams?
         | 
| 1489 | 
            +
             | 
| 1490 | 
            +
                  if assigning_to_numparam
         | 
| 1491 | 
            +
                    diagnostic :error, :cant_assign_to_numparam, { :name => name }, node.loc.expression
         | 
| 1492 | 
            +
                  end
         | 
| 1493 | 
            +
                end
         | 
| 1494 | 
            +
             | 
| 1295 1495 | 
             
                def arg_name_collides?(this_name, that_name)
         | 
| 1296 1496 | 
             
                  case @parser.version
         | 
| 1297 1497 | 
             
                  when 18
         | 
| @@ -1307,6 +1507,32 @@ module Parser | |
| 1307 1507 | 
             
                  end
         | 
| 1308 1508 | 
             
                end
         | 
| 1309 1509 |  | 
| 1510 | 
            +
                def check_lvar_name(name, loc)
         | 
| 1511 | 
            +
                  if name =~ /\A[[[:lower:]]|_][[[:alnum:]]_]*\z/
         | 
| 1512 | 
            +
                    # OK
         | 
| 1513 | 
            +
                  else
         | 
| 1514 | 
            +
                    diagnostic :error, :lvar_name, { name: name }, loc
         | 
| 1515 | 
            +
                  end
         | 
| 1516 | 
            +
                end
         | 
| 1517 | 
            +
             | 
| 1518 | 
            +
                def check_duplicate_pattern_variable(name, loc)
         | 
| 1519 | 
            +
                  return if name.to_s.start_with?('_')
         | 
| 1520 | 
            +
             | 
| 1521 | 
            +
                  if @parser.pattern_variables.declared?(name)
         | 
| 1522 | 
            +
                    diagnostic :error, :duplicate_variable_name, { name: name.to_s }, loc
         | 
| 1523 | 
            +
                  end
         | 
| 1524 | 
            +
             | 
| 1525 | 
            +
                  @parser.pattern_variables.declare(name)
         | 
| 1526 | 
            +
                end
         | 
| 1527 | 
            +
             | 
| 1528 | 
            +
                def check_duplicate_pattern_key(name, loc)
         | 
| 1529 | 
            +
                  if @parser.pattern_hash_keys.declared?(name)
         | 
| 1530 | 
            +
                    diagnostic :error, :duplicate_pattern_key, { name: name.to_s }, loc
         | 
| 1531 | 
            +
                  end
         | 
| 1532 | 
            +
             | 
| 1533 | 
            +
                  @parser.pattern_hash_keys.declare(name)
         | 
| 1534 | 
            +
                end
         | 
| 1535 | 
            +
             | 
| 1310 1536 | 
             
                #
         | 
| 1311 1537 | 
             
                # SOURCE MAPS
         | 
| 1312 1538 | 
             
                #
         | 
| @@ -1655,6 +1881,13 @@ module Parser | |
| 1655 1881 | 
             
                                             begin_l.join(end_l))
         | 
| 1656 1882 | 
             
                end
         | 
| 1657 1883 |  | 
| 1884 | 
            +
                def guard_map(keyword_t, guard_body_e)
         | 
| 1885 | 
            +
                  keyword_l = loc(keyword_t)
         | 
| 1886 | 
            +
                  guard_body_l = guard_body_e.loc.expression
         | 
| 1887 | 
            +
             | 
| 1888 | 
            +
                  Source::Map::Keyword.new(keyword_l, nil, nil, keyword_l.join(guard_body_l))
         | 
| 1889 | 
            +
                end
         | 
| 1890 | 
            +
             | 
| 1658 1891 | 
             
                #
         | 
| 1659 1892 | 
             
                # HELPERS
         | 
| 1660 1893 | 
             
                #
         | 
    
        data/lib/parser/context.rb
    CHANGED
    
    
    
        data/lib/parser/current.rb
    CHANGED
    
    | @@ -75,7 +75,7 @@ module Parser | |
| 75 75 | 
             
                CurrentRuby = Ruby26
         | 
| 76 76 |  | 
| 77 77 | 
             
              when /^2\.7\./
         | 
| 78 | 
            -
                current_version = '2.7.0 | 
| 78 | 
            +
                current_version = '2.7.0'
         | 
| 79 79 | 
             
                if RUBY_VERSION != current_version
         | 
| 80 80 | 
             
                  warn_syntax_deviation 'parser/ruby27', current_version
         | 
| 81 81 | 
             
                end
         | 
| @@ -85,8 +85,8 @@ module Parser | |
| 85 85 |  | 
| 86 86 | 
             
              else # :nocov:
         | 
| 87 87 | 
             
                # Keep this in sync with released Ruby.
         | 
| 88 | 
            -
                warn_syntax_deviation 'parser/ | 
| 89 | 
            -
                require 'parser/ | 
| 90 | 
            -
                CurrentRuby =  | 
| 88 | 
            +
                warn_syntax_deviation 'parser/ruby27', '2.7.x'
         | 
| 89 | 
            +
                require 'parser/ruby27'
         | 
| 90 | 
            +
                CurrentRuby = Ruby27
         | 
| 91 91 | 
             
              end
         | 
| 92 92 | 
             
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Parser
         | 
| 4 | 
            +
              # Stack that holds names of current arguments,
         | 
| 5 | 
            +
              # i.e. while parsing
         | 
| 6 | 
            +
              #   def m1(a = (def m2(b = def m3(c = 1); end); end)); end
         | 
| 7 | 
            +
              #                                   ^
         | 
| 8 | 
            +
              # stack is [:a, :b, :c]
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              # Emulates `p->cur_arg` in MRI's parse.y
         | 
| 11 | 
            +
              #
         | 
| 12 | 
            +
              # @api private
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              class CurrentArgStack
         | 
| 15 | 
            +
                attr_reader :stack
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def initialize
         | 
| 18 | 
            +
                  @stack = []
         | 
| 19 | 
            +
                  freeze
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def push(value)
         | 
| 23 | 
            +
                  @stack << value
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def set(value)
         | 
| 27 | 
            +
                  pop
         | 
| 28 | 
            +
                  push(value)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def pop
         | 
| 32 | 
            +
                  @stack.pop
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def reset
         | 
| 36 | 
            +
                  @stack.clear
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def top
         | 
| 40 | 
            +
                  @stack.last
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         |