class SyntaxTree::Translation::Parser
This visitor is responsible for converting the syntax tree produced by Syntax Tree into the syntax tree produced by the whitequark/parser gem.
Attributes
Public Class Methods
# File lib/syntax_tree/translation/parser.rb, line 77 def initialize(buffer) @buffer = buffer @stack = [] end
Public Instance Methods
For
each node that we visit, we keep track of it in a stack as we descend into its children. We do this so that child nodes can reflect on their parents if they need additional information about their context.
SyntaxTree::BasicVisitor#visit
# File lib/syntax_tree/translation/parser.rb, line 85 def visit(node) stack << node result = super stack.pop result end
Visit a BEGINBlock
node.
# File lib/syntax_tree/translation/parser.rb, line 432 def visit_BEGIN(node) s( :preexe, [visit(node.statements)], smap_keyword( srange_length(node.start_char, 5), srange_find(node.start_char + 5, node.statements.start_char, "{"), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit a CHAR
node.
# File lib/syntax_tree/translation/parser.rb, line 698 def visit_CHAR(node) s( :str, [node.value[1..]], smap_collection( srange_length(node.start_char, 1), nil, srange_node(node) ) ) end
Visit an ENDBlock
node.
# File lib/syntax_tree/translation/parser.rb, line 1085 def visit_END(node) s( :postexe, [visit(node.statements)], smap_keyword( srange_length(node.start_char, 3), srange_find(node.start_char + 3, node.statements.start_char, "{"), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit an AliasNode
node.
# File lib/syntax_tree/translation/parser.rb, line 94 def visit_alias(node) s( :alias, [visit(node.left), visit(node.right)], smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) end
Visit an ARefNode.
# File lib/syntax_tree/translation/parser.rb, line 106 def visit_aref(node) if ::Parser::Builders::Default.emit_index if node.index.nil? s( :index, [visit(node.collection)], smap_index( srange_find(node.collection.end_char, node.end_char, "["), srange_length(node.end_char, -1), srange_node(node) ) ) else s( :index, [visit(node.collection)].concat(visit_all(node.index.parts)), smap_index( srange_find_between(node.collection, node.index, "["), srange_length(node.end_char, -1), srange_node(node) ) ) end else if node.index.nil? s( :send, [visit(node.collection), :[]], smap_send_bare( srange_find(node.collection.end_char, node.end_char, "[]"), srange_node(node) ) ) else s( :send, [visit(node.collection), :[], *visit_all(node.index.parts)], smap_send_bare( srange( srange_find_between( node.collection, node.index, "[" ).begin_pos, node.end_char ), srange_node(node) ) ) end end end
Visit an ARefField
node.
# File lib/syntax_tree/translation/parser.rb, line 160 def visit_aref_field(node) if ::Parser::Builders::Default.emit_index if node.index.nil? s( :indexasgn, [visit(node.collection)], smap_index( srange_find(node.collection.end_char, node.end_char, "["), srange_length(node.end_char, -1), srange_node(node) ) ) else s( :indexasgn, [visit(node.collection)].concat(visit_all(node.index.parts)), smap_index( srange_find_between(node.collection, node.index, "["), srange_length(node.end_char, -1), srange_node(node) ) ) end else if node.index.nil? s( :send, [visit(node.collection), :[]=], smap_send_bare( srange_find(node.collection.end_char, node.end_char, "[]"), srange_node(node) ) ) else s( :send, [visit(node.collection), :[]=].concat( visit_all(node.index.parts) ), smap_send_bare( srange( srange_find_between( node.collection, node.index, "[" ).begin_pos, node.end_char ), srange_node(node) ) ) end end end
Visit an ArgBlock
node.
# File lib/syntax_tree/translation/parser.rb, line 216 def visit_arg_block(node) s( :block_pass, [visit(node.value)], smap_operator(srange_length(node.start_char, 1), srange_node(node)) ) end
Visit an ArgStar
node.
# File lib/syntax_tree/translation/parser.rb, line 225 def visit_arg_star(node) if stack[-3].is_a?(MLHSParen) && stack[-3].contents.is_a?(MLHS) if node.value.nil? s(:restarg, [], smap_variable(nil, srange_node(node))) else s( :restarg, [node.value.value.to_sym], smap_variable(srange_node(node.value), srange_node(node)) ) end else s( :splat, node.value.nil? ? [] : [visit(node.value)], smap_operator( srange_length(node.start_char, 1), srange_node(node) ) ) end end
Visit an ArgsForward
node.
# File lib/syntax_tree/translation/parser.rb, line 249 def visit_args_forward(node) s(:forwarded_args, [], smap(srange_node(node))) end
Visit an ArrayLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 254 def visit_array(node) s( :array, node.contents ? visit_all(node.contents.parts) : [], if node.lbracket.nil? smap_collection_bare(srange_node(node)) else smap_collection( srange_node(node.lbracket), srange_length(node.end_char, -1), srange_node(node) ) end ) end
Visit an AryPtn
node.
# File lib/syntax_tree/translation/parser.rb, line 271 def visit_aryptn(node) type = :array_pattern children = visit_all(node.requireds) if node.rest.is_a?(VarField) if !node.rest.value.nil? children << s(:match_rest, [visit(node.rest)], nil) elsif node.posts.empty? && node.rest.start_char == node.rest.end_char # Here we have an implicit rest, as in [foo,]. parser has a # specific type for these patterns. type = :array_pattern_with_tail else children << s(:match_rest, [], nil) end end if node.constant s( :const_pattern, [ visit(node.constant), s( type, children + visit_all(node.posts), smap_collection_bare( srange(node.constant.end_char + 1, node.end_char - 1) ) ) ], smap_collection( srange_length(node.constant.end_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) else s( type, children + visit_all(node.posts), if buffer.source[node.start_char] == "[" smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) else smap_collection_bare(srange_node(node)) end ) end end
Visit an Assign
node.
# File lib/syntax_tree/translation/parser.rb, line 325 def visit_assign(node) target = visit(node.target) location = target .location .with_operator(srange_find_between(node.target, node.value, "=")) .with_expression(srange_node(node)) s(target.type, target.children + [visit(node.value)], location) end
Visit an Assoc
node.
# File lib/syntax_tree/translation/parser.rb, line 337 def visit_assoc(node) if node.value.nil? # { foo: } expression = srange(node.start_char, node.end_char - 1) type, location = if node.key.value.start_with?(/[A-Z]/) [:const, smap_constant(nil, expression, expression)] else [:send, smap_send_bare(expression, expression)] end s( :pair, [ visit(node.key), s(type, [nil, node.key.value.chomp(":").to_sym], location) ], smap_operator( srange_length(node.key.end_char, -1), srange_node(node) ) ) elsif node.key.is_a?(Label) # { foo: 1 } s( :pair, [visit(node.key), visit(node.value)], smap_operator( srange_length(node.key.end_char, -1), srange_node(node) ) ) elsif (operator = srange_search_between(node.key, node.value, "=>")) # { :foo => 1 } s( :pair, [visit(node.key), visit(node.value)], smap_operator(operator, srange_node(node)) ) else # { "foo": 1 } key = visit(node.key) key_location = smap_collection( key.location.begin, srange_length(node.key.end_char - 2, 1), srange(node.key.start_char, node.key.end_char - 1) ) s( :pair, [s(key.type, key.children, key_location), visit(node.value)], smap_operator( srange_length(node.key.end_char, -1), srange_node(node) ) ) end end
Visit an AssocSplat
node.
# File lib/syntax_tree/translation/parser.rb, line 398 def visit_assoc_splat(node) s( :kwsplat, [visit(node.value)], smap_operator(srange_length(node.start_char, 2), srange_node(node)) ) end
Visit a Backref
node.
# File lib/syntax_tree/translation/parser.rb, line 407 def visit_backref(node) location = smap(srange_node(node)) if node.value.match?(/^\$\d+$/) s(:nth_ref, [node.value[1..].to_i], location) else s(:back_ref, [node.value.to_sym], location) end end
Visit a BareAssocHash
node.
# File lib/syntax_tree/translation/parser.rb, line 418 def visit_bare_assoc_hash(node) s( if ::Parser::Builders::Default.emit_kwargs && !stack[-2].is_a?(ArrayLiteral) :kwargs else :hash end, visit_all(node.assocs), smap_collection_bare(srange_node(node)) ) end
Visit a Begin
node.
# File lib/syntax_tree/translation/parser.rb, line 446 def visit_begin(node) location = smap_collection( srange_length(node.start_char, 5), srange_length(node.end_char, -3), srange_node(node) ) if node.bodystmt.empty? s(:kwbegin, [], location) elsif node.bodystmt.rescue_clause.nil? && node.bodystmt.ensure_clause.nil? && node.bodystmt.else_clause.nil? child = visit(node.bodystmt.statements) s( :kwbegin, child.type == :begin ? child.children : [child], location ) else s(:kwbegin, [visit(node.bodystmt)], location) end end
Visit a Binary
node.
# File lib/syntax_tree/translation/parser.rb, line 472 def visit_binary(node) case node.operator when :| current = -2 while stack[current].is_a?(Binary) && stack[current].operator == :| current -= 1 end if stack[current].is_a?(In) s(:match_alt, [visit(node.left), visit(node.right)], nil) else visit(canonical_binary(node)) end when :"=>", :"&&", :and, :"||", :or s( { "=>": :match_as, "&&": :and, "||": :or }.fetch( node.operator, node.operator ), [visit(node.left), visit(node.right)], smap_operator( srange_find_between(node.left, node.right, node.operator.to_s), srange_node(node) ) ) when :=~ # When you use a regular expression on the left hand side of a =~ # operator and it doesn't have interpolatoin, then its named capture # groups introduce local variables into the scope. In this case the # parser gem has a different node (match_with_lvasgn) instead of the # regular send. if node.left.is_a?(RegexpLiteral) && node.left.parts.length == 1 && node.left.parts.first.is_a?(TStringContent) s( :match_with_lvasgn, [visit(node.left), visit(node.right)], smap_operator( srange_find_between( node.left, node.right, node.operator.to_s ), srange_node(node) ) ) else visit(canonical_binary(node)) end else visit(canonical_binary(node)) end end
Visit a BlockVar
node.
# File lib/syntax_tree/translation/parser.rb, line 539 def visit_block_var(node) shadowargs = node.locals.map do |local| s( :shadowarg, [local.value.to_sym], smap_variable(srange_node(local), srange_node(local)) ) end params = node.params children = if ::Parser::Builders::Default.emit_procarg0 && node.arg0? # There is a special node type in the parser gem for when a single # required parameter to a block would potentially be expanded # automatically. We handle that case here. required = params.requireds.first procarg0 = if ::Parser::Builders::Default.emit_arg_inside_procarg0 && required.is_a?(Ident) s( :procarg0, [ s( :arg, [required.value.to_sym], smap_variable( srange_node(required), srange_node(required) ) ) ], smap_collection_bare(srange_node(required)) ) else child = visit(required) s(:procarg0, child, child.location) end [procarg0] else visit(params).children end s( :args, children + shadowargs, smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit a BlockArg
node.
# File lib/syntax_tree/translation/parser.rb, line 526 def visit_blockarg(node) if node.name.nil? s(:blockarg, [nil], smap_variable(nil, srange_node(node))) else s( :blockarg, [node.name.value.to_sym], smap_variable(srange_node(node.name), srange_node(node)) ) end end
Visit a BodyStmt
node.
# File lib/syntax_tree/translation/parser.rb, line 595 def visit_bodystmt(node) result = visit(node.statements) if node.rescue_clause rescue_node = visit(node.rescue_clause) children = [result] + rescue_node.children location = rescue_node.location if node.else_clause children.pop children << visit(node.else_clause) location = smap_condition( nil, nil, srange_length(node.else_clause.start_char - 3, -4), nil, srange( location.expression.begin_pos, node.else_clause.end_char ) ) end result = s(rescue_node.type, children, location) end if node.ensure_clause ensure_node = visit(node.ensure_clause) expression = ( if result result.location.expression.join( ensure_node.location.expression ) else ensure_node.location.expression end ) location = ensure_node.location.with_expression(expression) result = s(ensure_node.type, [result] + ensure_node.children, location) end result end
Visit a Break
node.
# File lib/syntax_tree/translation/parser.rb, line 647 def visit_break(node) s( :break, visit_all(node.arguments.parts), smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) end
Visit a CallNode
node.
# File lib/syntax_tree/translation/parser.rb, line 659 def visit_call(node) visit_command_call( CommandCall.new( receiver: node.receiver, operator: node.operator, message: node.message, arguments: node.arguments, block: nil, location: node.location ) ) end
Visit a Case
node.
# File lib/syntax_tree/translation/parser.rb, line 673 def visit_case(node) clauses = [node.consequent] while clauses.last && !clauses.last.is_a?(Else) clauses << clauses.last.consequent end else_token = if clauses.last.is_a?(Else) srange_length(clauses.last.start_char, 4) end s( node.consequent.is_a?(In) ? :case_match : :case, [visit(node.value)] + clauses.map { |clause| visit(clause) }, smap_condition( srange_length(node.start_char, 4), nil, else_token, srange_length(node.end_char, -3), srange_node(node) ) ) end
Visit a ClassDeclaration
node.
# File lib/syntax_tree/translation/parser.rb, line 711 def visit_class(node) operator = if node.superclass srange_find_between(node.constant, node.superclass, "<") end s( :class, [ visit(node.constant), visit(node.superclass), visit(node.bodystmt) ], smap_definition( srange_length(node.start_char, 5), operator, srange_node(node.constant), srange_length(node.end_char, -3) ).with_expression(srange_node(node)) ) end
Visit a Command
node.
# File lib/syntax_tree/translation/parser.rb, line 734 def visit_command(node) visit_command_call( CommandCall.new( receiver: nil, operator: nil, message: node.message, arguments: node.arguments, block: node.block, location: node.location ) ) end
Visit a CommandCall
node.
# File lib/syntax_tree/translation/parser.rb, line 748 def visit_command_call(node) children = [ visit(node.receiver), node.message == :call ? :call : node.message.value.to_sym ] begin_token = nil end_token = nil case node.arguments when Args children += visit_all(node.arguments.parts) when ArgParen case node.arguments.arguments when nil # skip when ArgsForward children << visit(node.arguments.arguments) else children += visit_all(node.arguments.arguments.parts) end begin_token = srange_length(node.arguments.start_char, 1) end_token = srange_length(node.arguments.end_char, -1) end dot_bound = if node.arguments node.arguments.start_char elsif node.block node.block.start_char else node.end_char end expression = if node.arguments.is_a?(ArgParen) srange(node.start_char, node.arguments.end_char) elsif node.arguments.is_a?(Args) && node.arguments.parts.any? last_part = node.arguments.parts.last end_char = if last_part.is_a?(Heredoc) last_part.beginning.end_char else last_part.end_char end srange(node.start_char, end_char) elsif node.block if node.receiver srange(node.receiver.start_char, node.message.end_char) else srange_node(node.message) end else srange_node(node) end call = s( if node.operator.is_a?(Op) && node.operator.value == "&." :csend else :send end, children, smap_send( if node.operator == :"::" srange_find( node.receiver.end_char, if node.message == :call dot_bound else node.message.start_char end, "::" ) elsif node.operator srange_node(node.operator) end, node.message == :call ? nil : srange_node(node.message), begin_token, end_token, expression ) ) if node.block type, arguments = block_children(node.block) s( type, [call, arguments, visit(node.block.bodystmt)], smap_collection( srange_node(node.block.opening), srange_length( node.end_char, node.block.opening.is_a?(Kw) ? -3 : -1 ), srange_node(node) ) ) else call end end
Visit a Const
node.
# File lib/syntax_tree/translation/parser.rb, line 856 def visit_const(node) s( :const, [nil, node.value.to_sym], smap_constant(nil, srange_node(node), srange_node(node)) ) end
Visit a ConstPathField
node.
# File lib/syntax_tree/translation/parser.rb, line 865 def visit_const_path_field(node) if node.parent.is_a?(VarRef) && node.parent.value.is_a?(Kw) && node.parent.value.value == "self" && node.constant.is_a?(Ident) s(:send, [visit(node.parent), :"#{node.constant.value}="], nil) else s( :casgn, [visit(node.parent), node.constant.value.to_sym], smap_constant( srange_find_between(node.parent, node.constant, "::"), srange_node(node.constant), srange_node(node) ) ) end end
Visit a ConstPathRef
node.
# File lib/syntax_tree/translation/parser.rb, line 883 def visit_const_path_ref(node) s( :const, [visit(node.parent), node.constant.value.to_sym], smap_constant( srange_find_between(node.parent, node.constant, "::"), srange_node(node.constant), srange_node(node) ) ) end
Visit a ConstRef
node.
# File lib/syntax_tree/translation/parser.rb, line 896 def visit_const_ref(node) s( :const, [nil, node.constant.value.to_sym], smap_constant(nil, srange_node(node.constant), srange_node(node)) ) end
Visit a CVar
node.
# File lib/syntax_tree/translation/parser.rb, line 905 def visit_cvar(node) s( :cvar, [node.value.to_sym], smap_variable(srange_node(node), srange_node(node)) ) end
Visit a DefNode
node.
# File lib/syntax_tree/translation/parser.rb, line 914 def visit_def(node) name = node.name.value.to_sym args = case node.params when Params child = visit(node.params) s( child.type, child.children, smap_collection_bare(child.location&.expression) ) when Paren child = visit(node.params.contents) s( child.type, child.children, smap_collection( srange_length(node.params.start_char, 1), srange_length(node.params.end_char, -1), srange_node(node.params) ) ) else s(:args, [], smap_collection_bare(nil)) end location = if node.endless? smap_method_definition( srange_length(node.start_char, 3), nil, srange_node(node.name), nil, srange_find_between( (node.params || node.name), node.bodystmt, "=" ), srange_node(node) ) else smap_method_definition( srange_length(node.start_char, 3), nil, srange_node(node.name), srange_length(node.end_char, -3), nil, srange_node(node) ) end if node.target target = node.target.is_a?(Paren) ? node.target.contents : node.target s( :defs, [visit(target), name, args, visit(node.bodystmt)], smap_method_definition( location.keyword, srange_node(node.operator), location.name, location.end, location.assignment, location.expression ) ) else s(:def, [name, args, visit(node.bodystmt)], location) end end
Visit a Defined
node.
# File lib/syntax_tree/translation/parser.rb, line 989 def visit_defined(node) paren_range = (node.start_char + 8)...node.end_char begin_token, end_token = if buffer.source[paren_range].include?("(") [ srange_find(paren_range.begin, paren_range.end, "("), srange_length(node.end_char, -1) ] end s( :defined?, [visit(node.value)], smap_keyword( srange_length(node.start_char, 8), begin_token, end_token, srange_node(node) ) ) end
Visit a DynaSymbol
node.
# File lib/syntax_tree/translation/parser.rb, line 1012 def visit_dyna_symbol(node) location = if node.quote smap_collection( srange_length(node.start_char, node.quote.length), srange_length(node.end_char, -1), srange_node(node) ) else smap_collection_bare(srange_node(node)) end if node.parts.length == 1 && node.parts.first.is_a?(TStringContent) s(:sym, ["\"#{node.parts.first.value}\"".undump.to_sym], location) else s(:dsym, visit_all(node.parts), location) end end
Visit an Else
node.
# File lib/syntax_tree/translation/parser.rb, line 1032 def visit_else(node) if node.statements.empty? && stack[-2].is_a?(Case) s(:empty_else, [], nil) else visit(node.statements) end end
Visit an Elsif
node.
# File lib/syntax_tree/translation/parser.rb, line 1041 def visit_elsif(node) begin_start = node.predicate.end_char begin_end = if node.statements.empty? node.statements.end_char else node.statements.body.first.start_char end begin_token = if buffer.source[begin_start...begin_end].include?("then") srange_find(begin_start, begin_end, "then") elsif buffer.source[begin_start...begin_end].include?(";") srange_find(begin_start, begin_end, ";") end else_token = case node.consequent when Elsif srange_length(node.consequent.start_char, 5) when Else srange_length(node.consequent.start_char, 4) end expression = srange(node.start_char, node.statements.end_char - 1) s( :if, [ visit(node.predicate), visit(node.statements), visit(node.consequent) ], smap_condition( srange_length(node.start_char, 5), begin_token, else_token, nil, expression ) ) end
Visit an Ensure
node.
# File lib/syntax_tree/translation/parser.rb, line 1099 def visit_ensure(node) start_char = node.start_char end_char = if node.statements.empty? start_char + 6 else node.statements.body.last.end_char end s( :ensure, [visit(node.statements)], smap_condition( srange_length(start_char, 6), nil, nil, nil, srange(start_char, end_char) ) ) end
Visit a Field
node.
# File lib/syntax_tree/translation/parser.rb, line 1122 def visit_field(node) message = case stack[-2] when Assign, MLHS Ident.new( value: "#{node.name.value}=", location: node.name.location ) else node.name end visit_command_call( CommandCall.new( receiver: node.parent, operator: node.operator, message: message, arguments: nil, block: nil, location: node.location ) ) end
Visit a FloatLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 1147 def visit_float(node) operator = if %w[+ -].include?(buffer.source[node.start_char]) srange_length(node.start_char, 1) end s( :float, [node.value.to_f], smap_operator(operator, srange_node(node)) ) end
Visit a FndPtn
node.
# File lib/syntax_tree/translation/parser.rb, line 1161 def visit_fndptn(node) left, right = [node.left, node.right].map do |child| location = smap_operator( srange_length(child.start_char, 1), srange_node(child) ) if child.is_a?(VarField) && child.value.nil? s(:match_rest, [], location) else s(:match_rest, [visit(child)], location) end end inner = s( :find_pattern, [left, *visit_all(node.values), right], smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) if node.constant s(:const_pattern, [visit(node.constant), inner], nil) else inner end end
Visit a For
node.
# File lib/syntax_tree/translation/parser.rb, line 1196 def visit_for(node) s( :for, [visit(node.index), visit(node.collection), visit(node.statements)], smap_for( srange_length(node.start_char, 3), srange_find_between(node.index, node.collection, "in"), srange_search_between(node.collection, node.statements, "do") || srange_search_between(node.collection, node.statements, ";"), srange_length(node.end_char, -3), srange_node(node) ) ) end
Visit a GVar
node.
# File lib/syntax_tree/translation/parser.rb, line 1212 def visit_gvar(node) s( :gvar, [node.value.to_sym], smap_variable(srange_node(node), srange_node(node)) ) end
Visit a HashLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 1221 def visit_hash(node) s( :hash, visit_all(node.assocs), smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit a Heredoc
node.
# File lib/syntax_tree/translation/parser.rb, line 1234 def visit_heredoc(node) heredoc = HeredocBuilder.new(node) # For each part of the heredoc, if it's a string content node, split # it into multiple string content nodes, one for each line. Otherwise, # visit the node as normal. node.parts.each do |part| if part.is_a?(TStringContent) && part.value.count("\n") > 1 index = part.start_char lines = part.value.split("\n") lines.each do |line| length = line.length + 1 location = smap_collection_bare(srange_length(index, length)) heredoc << s(:str, ["#{line}\n"], location) index += length end else heredoc << visit(part) end end # Now that we have all of the pieces on the heredoc, we can trim it if # it is a heredoc that supports trimming (i.e., it has a ~ on the # declaration). heredoc.trim! # Generate the location for the heredoc, which goes from the # declaration to the ending delimiter. location = smap_heredoc( srange_node(node.beginning), srange( if node.parts.empty? node.beginning.end_char + 1 else node.parts.first.start_char end, node.ending.start_char ), srange(node.ending.start_char, node.ending.end_char - 1) ) # Finally, decide which kind of heredoc node to generate based on its # declaration and contents. if node.beginning.value.match?(/`\w+`\z/) s(:xstr, heredoc.segments, location) elsif heredoc.segments.length == 1 segment = heredoc.segments.first s(segment.type, segment.children, location) else s(:dstr, heredoc.segments, location) end end
Visit a HshPtn
node.
# File lib/syntax_tree/translation/parser.rb, line 1291 def visit_hshptn(node) children = node.keywords.map do |(keyword, value)| next s(:pair, [visit(keyword), visit(value)], nil) if value case keyword when DynaSymbol raise if keyword.parts.length > 1 s(:match_var, [keyword.parts.first.value.to_sym], nil) when Label s(:match_var, [keyword.value.chomp(":").to_sym], nil) end end if node.keyword_rest.is_a?(VarField) children << if node.keyword_rest.value.nil? s(:match_rest, [], nil) elsif node.keyword_rest.value == :nil s(:match_nil_pattern, [], nil) else s(:match_rest, [visit(node.keyword_rest)], nil) end end inner = s(:hash_pattern, children, nil) if node.constant s(:const_pattern, [visit(node.constant), inner], nil) else inner end end
Visit an Ident
node.
# File lib/syntax_tree/translation/parser.rb, line 1324 def visit_ident(node) s( :lvar, [node.value.to_sym], smap_variable(srange_node(node), srange_node(node)) ) end
Visit an IfNode
node.
# File lib/syntax_tree/translation/parser.rb, line 1333 def visit_if(node) s( :if, [ visit_predicate(node.predicate), visit(node.statements), visit(node.consequent) ], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "if"), srange_node(node) ) else begin_start = node.predicate.end_char begin_end = if node.statements.empty? node.statements.end_char else node.statements.body.first.start_char end begin_token = if buffer.source[begin_start...begin_end].include?("then") srange_find(begin_start, begin_end, "then") elsif buffer.source[begin_start...begin_end].include?(";") srange_find(begin_start, begin_end, ";") end else_token = case node.consequent when Elsif srange_length(node.consequent.start_char, 5) when Else srange_length(node.consequent.start_char, 4) end smap_condition( srange_length(node.start_char, 2), begin_token, else_token, srange_length(node.end_char, -3), srange_node(node) ) end ) end
Visit an IfOp
node.
# File lib/syntax_tree/translation/parser.rb, line 1382 def visit_if_op(node) s( :if, [visit(node.predicate), visit(node.truthy), visit(node.falsy)], smap_ternary( srange_find_between(node.predicate, node.truthy, "?"), srange_find_between(node.truthy, node.falsy, ":"), srange_node(node) ) ) end
Visit an Imaginary
node.
# File lib/syntax_tree/translation/parser.rb, line 1395 def visit_imaginary(node) s( :complex, [ # We have to do an eval here in order to get the value in case # it's something like 42ri. to_c will not give the right value in # that case. Maybe there's an API for this but I can't find it. eval(node.value) ], smap_operator(nil, srange_node(node)) ) end
Visit an In
node.
# File lib/syntax_tree/translation/parser.rb, line 1409 def visit_in(node) case node.pattern when IfNode s( :in_pattern, [ visit(node.pattern.statements), s(:if_guard, [visit(node.pattern.predicate)], nil), visit(node.statements) ], nil ) when UnlessNode s( :in_pattern, [ visit(node.pattern.statements), s(:unless_guard, [visit(node.pattern.predicate)], nil), visit(node.statements) ], nil ) else begin_token = srange_search_between(node.pattern, node.statements, "then") end_char = if begin_token || node.statements.empty? node.statements.end_char - 1 else node.statements.body.last.start_char end s( :in_pattern, [visit(node.pattern), nil, visit(node.statements)], smap_keyword( srange_length(node.start_char, 2), begin_token, nil, srange(node.start_char, end_char) ) ) end end
Visit an Int
node.
# File lib/syntax_tree/translation/parser.rb, line 1456 def visit_int(node) operator = if %w[+ -].include?(buffer.source[node.start_char]) srange_length(node.start_char, 1) end s(:int, [node.value.to_i], smap_operator(operator, srange_node(node))) end
Visit an IVar
node.
# File lib/syntax_tree/translation/parser.rb, line 1466 def visit_ivar(node) s( :ivar, [node.value.to_sym], smap_variable(srange_node(node), srange_node(node)) ) end
Visit a Kw
node.
# File lib/syntax_tree/translation/parser.rb, line 1475 def visit_kw(node) location = smap(srange_node(node)) case node.value when "__FILE__" s(:str, [buffer.name], location) when "__LINE__" s( :int, [node.location.start_line + buffer.first_line - 1], location ) when "__ENCODING__" if ::Parser::Builders::Default.emit_encoding s(:__ENCODING__, [], location) else s(:const, [s(:const, [nil, :Encoding], nil), :UTF_8], location) end else s(node.value.to_sym, [], location) end end
Visit a KwRestParam
node.
# File lib/syntax_tree/translation/parser.rb, line 1499 def visit_kwrest_param(node) if node.name.nil? s(:kwrestarg, [], smap_variable(nil, srange_node(node))) else s( :kwrestarg, [node.name.value.to_sym], smap_variable(srange_node(node.name), srange_node(node)) ) end end
Visit a Label
node.
# File lib/syntax_tree/translation/parser.rb, line 1512 def visit_label(node) s( :sym, [node.value.chomp(":").to_sym], smap_collection_bare(srange(node.start_char, node.end_char - 1)) ) end
Visit a Lambda
node.
# File lib/syntax_tree/translation/parser.rb, line 1521 def visit_lambda(node) args = node.params.is_a?(LambdaVar) ? node.params : node.params.contents args_node = visit(args) type = :block if args.empty? && (maximum = num_block_type(node.statements)) type = :numblock args_node = maximum end begin_token, end_token = if ( srange = srange_search_between(node.params, node.statements, "{") ) [srange, srange_length(node.end_char, -1)] else [ srange_find_between(node.params, node.statements, "do"), srange_length(node.end_char, -3) ] end selector = srange_length(node.start_char, 2) s( type, [ if ::Parser::Builders::Default.emit_lambda s(:lambda, [], smap(selector)) else s(:send, [nil, :lambda], smap_send_bare(selector, selector)) end, args_node, visit(node.statements) ], smap_collection(begin_token, end_token, srange_node(node)) ) end
Visit a LambdaVar
node.
# File lib/syntax_tree/translation/parser.rb, line 1563 def visit_lambda_var(node) shadowargs = node.locals.map do |local| s( :shadowarg, [local.value.to_sym], smap_variable(srange_node(local), srange_node(local)) ) end location = if node.start_char == node.end_char smap_collection_bare(nil) elsif buffer.source[node.start_char - 1] == "(" smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) else smap_collection_bare(srange_node(node)) end s(:args, visit(node.params).children + shadowargs, location) end
Visit an MAssign
node.
# File lib/syntax_tree/translation/parser.rb, line 1590 def visit_massign(node) s( :masgn, [visit(node.target), visit(node.value)], smap_operator( srange_find_between(node.target, node.value, "="), srange_node(node) ) ) end
Visit a MethodAddBlock
node.
# File lib/syntax_tree/translation/parser.rb, line 1602 def visit_method_add_block(node) case node.call when ARef, Super, ZSuper type, arguments = block_children(node.block) s( type, [visit(node.call), arguments, visit(node.block.bodystmt)], smap_collection( srange_node(node.block.opening), srange_length( node.block.end_char, node.block.keywords? ? -3 : -1 ), srange_node(node) ) ) else visit_command_call( CommandCall.new( receiver: node.call.receiver, operator: node.call.operator, message: node.call.message, arguments: node.call.arguments, block: node.block, location: node.location ) ) end end
Visit an MLHS
node.
# File lib/syntax_tree/translation/parser.rb, line 1634 def visit_mlhs(node) s( :mlhs, node.parts.map do |part| if part.is_a?(Ident) s( :arg, [part.value.to_sym], smap_variable(srange_node(part), srange_node(part)) ) else visit(part) end end, smap_collection_bare(srange_node(node)) ) end
Visit an MLHSParen
node.
# File lib/syntax_tree/translation/parser.rb, line 1653 def visit_mlhs_paren(node) child = visit(node.contents) s( child.type, child.children, smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit a ModuleDeclaration
node.
# File lib/syntax_tree/translation/parser.rb, line 1668 def visit_module(node) s( :module, [visit(node.constant), visit(node.bodystmt)], smap_definition( srange_length(node.start_char, 6), nil, srange_node(node.constant), srange_length(node.end_char, -3) ).with_expression(srange_node(node)) ) end
Visit an MRHS
node.
# File lib/syntax_tree/translation/parser.rb, line 1682 def visit_mrhs(node) visit_array( ArrayLiteral.new( lbracket: nil, contents: Args.new(parts: node.parts, location: node.location), location: node.location ) ) end
Visit a Next
node.
# File lib/syntax_tree/translation/parser.rb, line 1693 def visit_next(node) s( :next, visit_all(node.arguments.parts), smap_keyword_bare( srange_length(node.start_char, 4), srange_node(node) ) ) end
Visit a Not
node.
# File lib/syntax_tree/translation/parser.rb, line 1705 def visit_not(node) if node.statement.nil? begin_token = srange_find(node.start_char, nil, "(") end_token = srange_find(node.start_char, nil, ")") s( :send, [ s( :begin, [], smap_collection( begin_token, end_token, begin_token.join(end_token) ) ), :! ], smap_send_bare( srange_length(node.start_char, 3), srange_node(node) ) ) else begin_token, end_token = if node.parentheses? [ srange_find( node.start_char + 3, node.statement.start_char, "(" ), srange_length(node.end_char, -1) ] end s( :send, [visit(node.statement), :!], smap_send( nil, srange_length(node.start_char, 3), begin_token, end_token, srange_node(node) ) ) end end
Visit an OpAssign
node.
# File lib/syntax_tree/translation/parser.rb, line 1757 def visit_opassign(node) target = visit(node.target) location = target .location .with_expression(srange_node(node)) .with_operator(srange_node(node.operator)) case node.operator.value when "||=" s(:or_asgn, [target, visit(node.value)], location) when "&&=" s(:and_asgn, [target, visit(node.value)], location) else s( :op_asgn, [ target, node.operator.value.chomp("=").to_sym, visit(node.value) ], location ) end end
Visit a Params
node.
# File lib/syntax_tree/translation/parser.rb, line 1784 def visit_params(node) children = [] children += node.requireds.map do |required| case required when MLHSParen visit(required) else s( :arg, [required.value.to_sym], smap_variable(srange_node(required), srange_node(required)) ) end end children += node.optionals.map do |(name, value)| s( :optarg, [name.value.to_sym, visit(value)], smap_variable( srange_node(name), srange_node(name).join(srange_node(value)) ).with_operator(srange_find_between(name, value, "=")) ) end if node.rest && !node.rest.is_a?(ExcessedComma) children << visit(node.rest) end children += node.posts.map do |post| s( :arg, [post.value.to_sym], smap_variable(srange_node(post), srange_node(post)) ) end children += node.keywords.map do |(name, value)| key = name.value.chomp(":").to_sym if value s( :kwoptarg, [key, visit(value)], smap_variable( srange(name.start_char, name.end_char - 1), srange_node(name).join(srange_node(value)) ) ) else s( :kwarg, [key], smap_variable( srange(name.start_char, name.end_char - 1), srange_node(name) ) ) end end case node.keyword_rest when nil, ArgsForward # do nothing when :nil children << s( :kwnilarg, [], smap_variable(srange_length(node.end_char, -3), srange_node(node)) ) else children << visit(node.keyword_rest) end children << visit(node.block) if node.block if node.keyword_rest.is_a?(ArgsForward) location = smap(srange_node(node.keyword_rest)) # If there are no other arguments and we have the emit_forward_arg # option enabled, then the entire argument list is represented by a # single forward_args node. if children.empty? && !::Parser::Builders::Default.emit_forward_arg return s(:forward_args, [], location) end # Otherwise, we need to insert a forward_arg node into the list of # parameters before any keyword rest or block parameters. index = node.requireds.length + node.optionals.length + node.keywords.length children.insert(index, s(:forward_arg, [], location)) end location = unless children.empty? first = children.first.location.expression last = children.last.location.expression smap_collection_bare(first.join(last)) end s(:args, children, location) end
Visit a Paren
node.
# File lib/syntax_tree/translation/parser.rb, line 1895 def visit_paren(node) location = smap_collection( srange_length(node.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) if node.contents.nil? || (node.contents.is_a?(Statements) && node.contents.empty?) s(:begin, [], location) else child = visit(node.contents) child.type == :begin ? child : s(:begin, [child], location) end end
Visit a PinnedBegin
node.
# File lib/syntax_tree/translation/parser.rb, line 1913 def visit_pinned_begin(node) s( :pin, [ s( :begin, [visit(node.statement)], smap_collection( srange_length(node.start_char + 1, 1), srange_length(node.end_char, -1), srange(node.start_char + 1, node.end_char) ) ) ], smap_send_bare(srange_length(node.start_char, 1), srange_node(node)) ) end
Visit a PinnedVarRef
node.
# File lib/syntax_tree/translation/parser.rb, line 1932 def visit_pinned_var_ref(node) s( :pin, [visit(node.value)], smap_send_bare(srange_length(node.start_char, 1), srange_node(node)) ) end
Visit a Program
node.
# File lib/syntax_tree/translation/parser.rb, line 1941 def visit_program(node) visit(node.statements) end
Visit a QSymbols
node.
# File lib/syntax_tree/translation/parser.rb, line 1946 def visit_qsymbols(node) parts = node.elements.map do |element| SymbolLiteral.new(value: element, location: element.location) end visit_array( ArrayLiteral.new( lbracket: node.beginning, contents: Args.new(parts: parts, location: node.location), location: node.location ) ) end
Visit a QWords
node.
# File lib/syntax_tree/translation/parser.rb, line 1962 def visit_qwords(node) visit_array( ArrayLiteral.new( lbracket: node.beginning, contents: Args.new(parts: node.elements, location: node.location), location: node.location ) ) end
Visit a RangeNode
node.
# File lib/syntax_tree/translation/parser.rb, line 1973 def visit_range(node) s( node.operator.value == ".." ? :irange : :erange, [visit(node.left), visit(node.right)], smap_operator(srange_node(node.operator), srange_node(node)) ) end
Visit an RAssign
node.
# File lib/syntax_tree/translation/parser.rb, line 1982 def visit_rassign(node) s( node.operator.value == "=>" ? :match_pattern : :match_pattern_p, [visit(node.value), visit(node.pattern)], smap_operator(srange_node(node.operator), srange_node(node)) ) end
Visit a Rational node.
# File lib/syntax_tree/translation/parser.rb, line 1991 def visit_rational(node) s(:rational, [node.value.to_r], smap_operator(nil, srange_node(node))) end
Visit a Redo
node.
# File lib/syntax_tree/translation/parser.rb, line 1996 def visit_redo(node) s(:redo, [], smap_keyword_bare(srange_node(node), srange_node(node))) end
Visit a RegexpLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 2001 def visit_regexp_literal(node) s( :regexp, visit_all(node.parts).push( s( :regopt, node.ending.scan(/[a-z]/).sort.map(&:to_sym), smap(srange_length(node.end_char, -(node.ending.length - 1))) ) ), smap_collection( srange_length(node.start_char, node.beginning.length), srange_length(node.end_char - node.ending.length, 1), srange_node(node) ) ) end
Visit a Rescue
node.
# File lib/syntax_tree/translation/parser.rb, line 2020 def visit_rescue(node) # In the parser gem, there is a separation between the rescue node and # the rescue body. They have different bounds, so we have to calculate # those here. start_char = node.start_char body_end_char = if node.statements.empty? start_char + 6 else node.statements.body.last.end_char end end_char = if node.consequent end_node = node.consequent end_node = end_node.consequent while end_node.consequent if end_node.statements.empty? start_char + 6 else end_node.statements.body.last.end_char end else body_end_char end # These locations are reused for multiple children. keyword = srange_length(start_char, 6) body_expression = srange(start_char, body_end_char) expression = srange(start_char, end_char) exceptions = case node.exception&.exceptions when nil nil when MRHS visit_array( ArrayLiteral.new( lbracket: nil, contents: Args.new( parts: node.exception.exceptions.parts, location: node.exception.exceptions.location ), location: node.exception.exceptions.location ) ) else visit_array( ArrayLiteral.new( lbracket: nil, contents: Args.new( parts: [node.exception.exceptions], location: node.exception.exceptions.location ), location: node.exception.exceptions.location ) ) end resbody = if node.exception.nil? s( :resbody, [nil, nil, visit(node.statements)], smap_rescue_body(keyword, nil, nil, body_expression) ) elsif node.exception.variable.nil? s( :resbody, [exceptions, nil, visit(node.statements)], smap_rescue_body(keyword, nil, nil, body_expression) ) else s( :resbody, [ exceptions, visit(node.exception.variable), visit(node.statements) ], smap_rescue_body( keyword, srange_find( node.start_char + 6, node.exception.variable.start_char, "=>" ), nil, body_expression ) ) end children = [resbody] if node.consequent children += visit(node.consequent).children else children << nil end s(:rescue, children, smap_condition_bare(expression)) end
Visit a RescueMod
node.
# File lib/syntax_tree/translation/parser.rb, line 2127 def visit_rescue_mod(node) keyword = srange_find_between(node.statement, node.value, "rescue") s( :rescue, [ visit(node.statement), s( :resbody, [nil, nil, visit(node.value)], smap_rescue_body( keyword, nil, nil, keyword.join(srange_node(node.value)) ) ), nil ], smap_condition_bare(srange_node(node)) ) end
Visit a RestParam
node.
# File lib/syntax_tree/translation/parser.rb, line 2151 def visit_rest_param(node) if node.name s( :restarg, [node.name.value.to_sym], smap_variable(srange_node(node.name), srange_node(node)) ) else s(:restarg, [], smap_variable(nil, srange_node(node))) end end
Visit a Retry
node.
# File lib/syntax_tree/translation/parser.rb, line 2164 def visit_retry(node) s(:retry, [], smap_keyword_bare(srange_node(node), srange_node(node))) end
Visit a ReturnNode
node.
# File lib/syntax_tree/translation/parser.rb, line 2169 def visit_return(node) s( :return, node.arguments ? visit_all(node.arguments.parts) : [], smap_keyword_bare( srange_length(node.start_char, 6), srange_node(node) ) ) end
Visit an SClass
node.
# File lib/syntax_tree/translation/parser.rb, line 2181 def visit_sclass(node) s( :sclass, [visit(node.target), visit(node.bodystmt)], smap_definition( srange_length(node.start_char, 5), srange_find(node.start_char + 5, node.target.start_char, "<<"), nil, srange_length(node.end_char, -3) ).with_expression(srange_node(node)) ) end
Visit a Statements
node.
# File lib/syntax_tree/translation/parser.rb, line 2195 def visit_statements(node) children = node.body.reject do |child| child.is_a?(Comment) || child.is_a?(EmbDoc) || child.is_a?(EndContent) || child.is_a?(VoidStmt) end case children.length when 0 nil when 1 visit(children.first) else s( :begin, visit_all(children), smap_collection_bare( srange(children.first.start_char, children.last.end_char) ) ) end end
Visit a StringConcat
node.
# File lib/syntax_tree/translation/parser.rb, line 2219 def visit_string_concat(node) s( :dstr, [visit(node.left), visit(node.right)], smap_collection_bare(srange_node(node)) ) end
Visit a StringDVar
node.
# File lib/syntax_tree/translation/parser.rb, line 2228 def visit_string_dvar(node) visit(node.variable) end
Visit a StringEmbExpr
node.
# File lib/syntax_tree/translation/parser.rb, line 2233 def visit_string_embexpr(node) s( :begin, visit(node.statements).then { |child| child ? [child] : [] }, smap_collection( srange_length(node.start_char, 2), srange_length(node.end_char, -1), srange_node(node) ) ) end
Visit a StringLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 2246 def visit_string_literal(node) location = if node.quote smap_collection( srange_length(node.start_char, node.quote.length), srange_length(node.end_char, -1), srange_node(node) ) else smap_collection_bare(srange_node(node)) end if node.parts.empty? s(:str, [""], location) elsif node.parts.length == 1 && node.parts.first.is_a?(TStringContent) child = visit(node.parts.first) s(child.type, child.children, location) else s(:dstr, visit_all(node.parts), location) end end
Visit a Super
node.
# File lib/syntax_tree/translation/parser.rb, line 2269 def visit_super(node) if node.arguments.is_a?(Args) s( :super, visit_all(node.arguments.parts), smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) else case node.arguments.arguments when nil s( :super, [], smap_keyword( srange_length(node.start_char, 5), srange_find(node.start_char + 5, node.end_char, "("), srange_length(node.end_char, -1), srange_node(node) ) ) when ArgsForward s( :super, [visit(node.arguments.arguments)], smap_keyword( srange_length(node.start_char, 5), srange_find(node.start_char + 5, node.end_char, "("), srange_length(node.end_char, -1), srange_node(node) ) ) else s( :super, visit_all(node.arguments.arguments.parts), smap_keyword( srange_length(node.start_char, 5), srange_find(node.start_char + 5, node.end_char, "("), srange_length(node.end_char, -1), srange_node(node) ) ) end end end
Visit a SymbolLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 2319 def visit_symbol_literal(node) begin_token = if buffer.source[node.start_char] == ":" srange_length(node.start_char, 1) end s( :sym, [node.value.value.to_sym], smap_collection(begin_token, nil, srange_node(node)) ) end
Visit a Symbols
node.
# File lib/syntax_tree/translation/parser.rb, line 2333 def visit_symbols(node) parts = node.elements.map do |element| part = element.parts.first if element.parts.length == 1 && part.is_a?(TStringContent) SymbolLiteral.new(value: part, location: part.location) else DynaSymbol.new( parts: element.parts, quote: nil, location: element.location ) end end visit_array( ArrayLiteral.new( lbracket: node.beginning, contents: Args.new(parts: parts, location: node.location), location: node.location ) ) end
Visit a TopConstField
node.
# File lib/syntax_tree/translation/parser.rb, line 2359 def visit_top_const_field(node) s( :casgn, [ s(:cbase, [], smap(srange_length(node.start_char, 2))), node.constant.value.to_sym ], smap_constant( srange_length(node.start_char, 2), srange_node(node.constant), srange_node(node) ) ) end
Visit a TopConstRef
node.
# File lib/syntax_tree/translation/parser.rb, line 2375 def visit_top_const_ref(node) s( :const, [ s(:cbase, [], smap(srange_length(node.start_char, 2))), node.constant.value.to_sym ], smap_constant( srange_length(node.start_char, 2), srange_node(node.constant), srange_node(node) ) ) end
Visit a TStringContent
node.
# File lib/syntax_tree/translation/parser.rb, line 2391 def visit_tstring_content(node) dumped = node.value.gsub(/([^[:ascii:]])/) { $1.dump[1...-1] } s( :str, ["\"#{dumped}\"".undump], smap_collection_bare(srange_node(node)) ) end
Visit a Unary
node.
# File lib/syntax_tree/translation/parser.rb, line 2402 def visit_unary(node) # Special handling here for flipflops if (paren = node.statement).is_a?(Paren) && paren.contents.is_a?(Statements) && paren.contents.body.length == 1 && (range = paren.contents.body.first).is_a?(RangeNode) && node.operator == "!" s( :send, [ s( :begin, [ s( range.operator.value == ".." ? :iflipflop : :eflipflop, visit(range).children, smap_operator( srange_node(range.operator), srange_node(range) ) ) ], smap_collection( srange_length(paren.start_char, 1), srange_length(paren.end_char, -1), srange_node(paren) ) ), :! ], smap_send_bare( srange_length(node.start_char, 1), srange_node(node) ) ) elsif node.operator == "!" && node.statement.is_a?(RegexpLiteral) s( :send, [ s( :match_current_line, [visit(node.statement)], smap(srange_node(node.statement)) ), :! ], smap_send_bare( srange_length(node.start_char, 1), srange_node(node) ) ) else visit(canonical_unary(node)) end end
Visit an Undef
node.
# File lib/syntax_tree/translation/parser.rb, line 2459 def visit_undef(node) s( :undef, visit_all(node.symbols), smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) end
Visit an UnlessNode
node.
# File lib/syntax_tree/translation/parser.rb, line 2471 def visit_unless(node) s( :if, [ visit_predicate(node.predicate), visit(node.consequent), visit(node.statements) ], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "unless"), srange_node(node) ) else begin_start = node.predicate.end_char begin_end = if node.statements.empty? node.statements.end_char else node.statements.body.first.start_char end begin_token = if buffer.source[begin_start...begin_end].include?("then") srange_find(begin_start, begin_end, "then") elsif buffer.source[begin_start...begin_end].include?(";") srange_find(begin_start, begin_end, ";") end else_token = if node.consequent srange_length(node.consequent.start_char, 4) end smap_condition( srange_length(node.start_char, 6), begin_token, else_token, srange_length(node.end_char, -3), srange_node(node) ) end ) end
Visit an UntilNode
node.
# File lib/syntax_tree/translation/parser.rb, line 2517 def visit_until(node) s( loop_post?(node) ? :until_post : :until, [visit(node.predicate), visit(node.statements)], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "until"), srange_node(node) ) else smap_keyword( srange_length(node.start_char, 5), srange_search_between(node.predicate, node.statements, "do") || srange_search_between(node.predicate, node.statements, ";"), srange_length(node.end_char, -3), srange_node(node) ) end ) end
Visit a VarField
node.
# File lib/syntax_tree/translation/parser.rb, line 2539 def visit_var_field(node) name = node.value.value.to_sym match_var = [stack[-3], stack[-2]].any? do |parent| case parent when AryPtn, FndPtn, HshPtn, In, RAssign true when Binary parent.operator == :"=>" else false end end if match_var s( :match_var, [name], smap_variable(srange_node(node.value), srange_node(node.value)) ) elsif node.value.is_a?(Const) s( :casgn, [nil, name], smap_constant(nil, srange_node(node.value), srange_node(node)) ) else location = smap_variable(srange_node(node), srange_node(node)) case node.value when CVar s(:cvasgn, [name], location) when GVar s(:gvasgn, [name], location) when Ident s(:lvasgn, [name], location) when IVar s(:ivasgn, [name], location) when VarRef s(:lvasgn, [name], location) else s(:match_rest, [], nil) end end end
Visit a VarRef
node.
# File lib/syntax_tree/translation/parser.rb, line 2586 def visit_var_ref(node) visit(node.value) end
Visit a VCall
node.
# File lib/syntax_tree/translation/parser.rb, line 2591 def visit_vcall(node) visit_command_call( CommandCall.new( receiver: nil, operator: nil, message: node.value, arguments: nil, block: nil, location: node.location ) ) end
Visit a When
node.
# File lib/syntax_tree/translation/parser.rb, line 2605 def visit_when(node) keyword = srange_length(node.start_char, 4) begin_token = if buffer.source[node.statements.start_char] == ";" srange_length(node.statements.start_char, 1) end end_char = if node.statements.body.empty? node.statements.end_char else node.statements.body.last.end_char end s( :when, visit_all(node.arguments.parts) + [visit(node.statements)], smap_keyword( keyword, begin_token, nil, srange(keyword.begin_pos, end_char) ) ) end
Visit a WhileNode
node.
# File lib/syntax_tree/translation/parser.rb, line 2632 def visit_while(node) s( loop_post?(node) ? :while_post : :while, [visit(node.predicate), visit(node.statements)], if node.modifier? smap_keyword_bare( srange_find_between(node.statements, node.predicate, "while"), srange_node(node) ) else smap_keyword( srange_length(node.start_char, 5), srange_search_between(node.predicate, node.statements, "do") || srange_search_between(node.predicate, node.statements, ";"), srange_length(node.end_char, -3), srange_node(node) ) end ) end
Visit a Word
node.
# File lib/syntax_tree/translation/parser.rb, line 2654 def visit_word(node) visit_string_literal( StringLiteral.new( parts: node.parts, quote: nil, location: node.location ) ) end
Visit a Words
node.
# File lib/syntax_tree/translation/parser.rb, line 2665 def visit_words(node) visit_array( ArrayLiteral.new( lbracket: node.beginning, contents: Args.new(parts: node.elements, location: node.location), location: node.location ) ) end
Visit an XStringLiteral
node.
# File lib/syntax_tree/translation/parser.rb, line 2676 def visit_xstring_literal(node) s( :xstr, visit_all(node.parts), smap_collection( srange_length( node.start_char, buffer.source[node.start_char] == "%" ? 3 : 1 ), srange_length(node.end_char, -1), srange_node(node) ) ) end
# File lib/syntax_tree/translation/parser.rb, line 2691 def visit_yield(node) case node.arguments when nil s( :yield, [], smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) when Args s( :yield, visit_all(node.arguments.parts), smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) else s( :yield, visit_all(node.arguments.contents.parts), smap_keyword( srange_length(node.start_char, 5), srange_length(node.arguments.start_char, 1), srange_length(node.end_char, -1), srange_node(node) ) ) end end
Visit a ZSuper
node.
# File lib/syntax_tree/translation/parser.rb, line 2726 def visit_zsuper(node) s( :zsuper, [], smap_keyword_bare( srange_length(node.start_char, 5), srange_node(node) ) ) end