Module: MilkTea::Lexer::Indentation

Included in:
MilkTea::Lexer
Defined in:
lib/milk_tea/core/lexer/indentation.rb

Overview

Indentation-to-INDENT/DEDENT token conversion and error recovery.

Instance Method Summary collapse

Instance Method Details

#emit_indentation(indent, line_number, line_offset) ⇒ Object

Raises:



7
8
9
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
35
# File 'lib/milk_tea/core/lexer/indentation.rb', line 7

def emit_indentation(indent, line_number, line_offset)
  if (indent % 4) != 0
    raise LexError.new("indentation must use multiples of 4 spaces", line: line_number, column: indent + 1, path: @path)
  end

  current_indent = @indent_stack.last
  if indent == current_indent
    return
  end

  if indent > current_indent
    if indent != current_indent + 4
      raise LexError.new("indentation may only increase by 4 spaces at a time", line: line_number, column: 1, path: @path)
    end

    @indent_stack << indent
    @tokens << token(:indent, "", nil, line_number, 1, start_offset: line_offset, end_offset: line_offset)
    return
  end

  while @indent_stack.last > indent
    @indent_stack.pop
    @tokens << token(:dedent, "", nil, line_number, 1, start_offset: line_offset, end_offset: line_offset)
  end

  return if @indent_stack.last == indent

  raise LexError.new("indentation does not match any open block", line: line_number, column: 1, path: @path)
end

#recover_indentation(indent, line_number, line_offset) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/milk_tea/core/lexer/indentation.rb', line 37

def recover_indentation(indent, line_number, line_offset)
  recovered_indent = indent - (indent % 4)
  current_indent = @indent_stack.last

  if recovered_indent > current_indent + 4
    recovered_indent = current_indent + 4
  end

  if recovered_indent > current_indent
    @indent_stack << recovered_indent
    @tokens << token(:indent, "", nil, line_number, 1, start_offset: line_offset, end_offset: line_offset)
    return
  end

  while @indent_stack.last > recovered_indent
    @indent_stack.pop
    @tokens << token(:dedent, "", nil, line_number, 1, start_offset: line_offset, end_offset: line_offset)
  end

  return if @indent_stack.last == recovered_indent
end