class RDoc::Parser::RipperStateLex
def self.end?(token)
def self.end?(token) (token[:state] & EXPR_END) end
def self.parse(code)
def self.parse(code) lex = self.new(code) tokens = [] begin while tk = lex.get_squashed_tk tokens.push tk end rescue StopIteration end tokens end
def get_embdoc_tk(tk)
def get_embdoc_tk(tk) = tk[:text] :on_embdoc_end == (embdoc_tk = get_squashed_tk)[:kind] do ng = string + embdoc_tk[:text] = string + embdoc_tk[:text] new(tk.line_no, tk.char_no, :on_embdoc, string, embdoc_tk.state)
def get_heredoc_tk(heredoc_name, indent)
def get_heredoc_tk(heredoc_name, indent) = '' tk = nil k = nil heredoc_end?(heredoc_name, indent, tk = @tokens.shift) do t_tk = tk unless start_tk prev_tk.nil? or "\n" == prev_tk[:text][-1]) and 0 != tk[:char_no] ring = string + (' ' * tk[:char_no]) ng = string + tk[:text] _tk = tk tk = tk unless start_tk k = tk unless prev_tk nshift tk # closing heredoc c_tk = Token.new(start_tk.line_no, start_tk.char_no, :on_heredoc, string, prev_tk.state) nshift heredoc_tk
def get_op_tk(tk)
def get_op_tk(tk) nable_operators = %w[! != !~ % & * ** + +@ - -@ / < << <= <=> == === =~ > >= >> [] []= ^ ` | ~] efinable_operators.include?(tk[:text]) and tk[:state] == EXPR_ARG then state] = Ripper::Lexer::State.new(EXPR_ARG) kind] = :on_ident tk[:text] =~ /^[-+]$/ then head = get_squashed_tk tk_ahead[:kind] :on_int, :on_float, :on_rational, :on_imaginary then [:text] += tk_ahead[:text] [:kind] = tk_ahead[:kind] [:state] = tk_ahead[:state] :on_heredoc_beg, :on_tstring, :on_dstring # frozen/non-frozen string literal [:text] += tk_ahead[:text] [:kind] = tk_ahead[:kind] [:state] = tk_ahead[:state] uf.unshift tk_ahead
def get_regexp_tk(tk)
def get_regexp_tk(tk) = tk[:text] = nil o r_str_tk = get_squashed_tk nner_str_tk.nil? eak f :on_regexp_end == inner_str_tk[:kind] ring = string + inner_str_tk[:text] ate = inner_str_tk[:state] eak ring = string + inner_str_tk[:text] new(tk.line_no, tk.char_no, :on_regexp, string, state)
def get_squashed_tk
def get_squashed_tk if @buf.empty? tk = @tokens.shift else tk = @buf.shift end return nil if tk.nil? case tk[:kind] when :on_symbeg then tk = get_symbol_tk(tk) when :on_tstring_beg then tk = get_string_tk(tk) when :on_backtick then if (tk[:state] & (EXPR_FNAME | EXPR_ENDFN)) != 0 tk[:kind] = :on_ident tk[:state] = Ripper::Lexer::State.new(EXPR_ARG) else tk = get_string_tk(tk) end when :on_regexp_beg then tk = get_regexp_tk(tk) when :on_embdoc_beg then tk = get_embdoc_tk(tk) when :on_heredoc_beg then @heredoc_queue << retrieve_heredoc_info(tk) when :on_nl, :on_ignored_nl, :on_comment, :on_heredoc_end then if !@heredoc_queue.empty? get_heredoc_tk(*@heredoc_queue.shift) elsif tk[:text].nil? # :on_ignored_nl sometimes gives nil tk[:text] = '' end when :on_words_beg then tk = get_words_tk(tk) when :on_qwords_beg then tk = get_words_tk(tk) when :on_symbols_beg then tk = get_words_tk(tk) when :on_qsymbols_beg then tk = get_words_tk(tk) when :on_op then if '&.' == tk[:text] tk[:kind] = :on_period else tk = get_op_tk(tk) end end tk end
def get_string_tk(tk)
def get_string_tk(tk) = tk[:text] = nil :on_tstring o r_str_tk = get_squashed_tk nner_str_tk.nil? eak f :on_tstring_end == inner_str_tk[:kind] ring = string + inner_str_tk[:text] ate = inner_str_tk[:state] eak f :on_label_end == inner_str_tk[:kind] ring = string + inner_str_tk[:text] ate = inner_str_tk[:state] nd = :on_symbol eak ring = string + inner_str_tk[:text] :on_embexpr_beg == inner_str_tk[:kind] then kind = :on_dstring if :on_tstring == kind d new(tk.line_no, tk.char_no, kind, string, state)
def get_symbol_tk(tk)
def get_symbol_tk(tk) bol = true _tk = Token.new(tk.line_no, tk.char_no, :on_symbol) " == tk[:text] or ':"' == tk[:text] or tk[:text].start_with?('%s') = get_string_tk(tk) ol_tk[:text] = tk1[:text] ol_tk[:state] = tk1[:state] (tk1 = get_squashed_tk)[:kind] :on_ident mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_tstring_content mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = get_squashed_tk[:state] # skip :on_tstring_end :on_tstring_end mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_op mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_ivar mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_cvar mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_gvar mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_const mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] :on_kw mbol_tk[:text] = ":#{tk1[:text]}" mbol_tk[:state] = tk1[:state] _symbol = false = tk1 symbol symbol_tk
def get_words_tk(tk)
def get_words_tk(tk) = '' token = tk[:text] quote = tk[:text].rstrip[-1] o = tk[:line_no] o = tk[:char_no] = tk[:state] ote = start_quote ?( then ?) ?[ then ?] ?{ then ?} ?< then ?> start_quote ken = nil o get_squashed_tk k.nil? d_token = end_quote eak f :on_tstring_content == tk[:kind] then ring += tk[:text] f :on_words_sep == tk[:kind] or :on_tstring_end == tk[:kind] then end_quote == tk[:text].strip then end_token = tk[:text] break se string += tk[:text] d ring += tk[:text] "#{start_token}#{string}#{end_token}" new(line_no, char_no, :on_dstring, text, state)
def heredoc_end?(name, indent, tk)
def heredoc_end?(name, indent, tk) = false _heredoc_end == tk[:kind] then ame = tk[:text].chomp ame.lstrip! if indent ame == tk_name sult = true
def initialize(code)
def initialize(code) @buf = [] @heredoc_queue = [] @inner_lex = InnerStateLex.new(code) @tokens = @inner_lex.parse([]) end
def retrieve_heredoc_info(tk)
def retrieve_heredoc_info(tk) tk[:text].gsub(/\A<<[-~]?(['"`]?)(.+)\1\z/, '\2') = tk[:text] =~ /\A<<[-~]/ indent]