Class: Python::Parser::IndentConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/python/parser/indent_converter.rb

Constant Summary collapse

IndentConversionError =
Class.new(RuntimeError)
INDENT =
"$I"
DEDENT =
"$D"
NEWLINE =
"\n"

Instance Method Summary collapse

Instance Method Details

#convert(str) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/python/parser/indent_converter.rb', line 10

def convert(str)
  stack = [0]
  converted_lines = []
  lines = str.gsub("\r\n", "\n").gsub("\r", "\n").split("\n") + [""]
  lines.each do |line|
    ilevel = indent_level(line)
    if ilevel > stack.last
      stack << ilevel
      converted_lines << convert_line(line, INDENT)
    elsif ilevel < stack.last
      dedent_livel = 0
      while ilevel < stack.last
        dedent_livel += 1
        stack.pop
      end
      unless ilevel == stack.last
        raise IndentConversionError.new
      end
      converted_lines << convert_line(line, DEDENT * dedent_livel)
    else
      converted_lines << convert_line(line, "")
    end
  end
  converted_lines.join(NEWLINE) + NEWLINE
end

#convert_line(line, token) ⇒ Object



47
48
49
# File 'lib/python/parser/indent_converter.rb', line 47

def convert_line(line, token)
  token + line.chars.drop_while{|c| c == "\s" || c == "\t"}.inject("", &:+)
end

#indent_level(line) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/python/parser/indent_converter.rb', line 36

def indent_level(line)
  line.chars.take_while{|c| c == "\s" || c == "\t"}.inject(0) do |acc, c|
    case c
    when "\s"
      acc + 1
    when "\t"
      acc - (acc % 8) + 8
    end
  end
end