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
- #emit_indentation(indent, line_number, line_offset) ⇒ Object
- #recover_indentation(indent, line_number, line_offset) ⇒ Object
Instance Method Details
#emit_indentation(indent, line_number, line_offset) ⇒ Object
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 |