# frozen_string_literal: true # Oppen. module Oppen # Token. class Token # Default token width. # # @return [Integer] def width = 0 # String Token. class String < Token # @return [String] attr_reader :value # @return [Integer] attr_reader :width def initialize(value, width: value.length) @value = value @width = width super() end # @return [String] def to_s = value end # This token is not part of Oppen's original work. We introduced it to # handle trailing whitespaces. # # When the config flag `trim_trailing_whitespaces == true`, and a new line # is needed, all the {Token::Whitespace} figuring after the last {Token::String} # will be be skipped. class Whitespace < ::Oppen::Token::String end # Break Token. class Break < Token # @return [String] # If a new line is needed, display this string before the new line. # # @see Wadler#break example on `line_continuation`. attr_reader :line_continuation # @return [Integer] Indentation. attr_reader :offset # @return [String] Break strings. attr_reader :str # @return [Integer] attr_reader :width def initialize(str = ' ', line_continuation: '', offset: 0, width: str.length) raise ArgumentError, 'line_continuation cannot be nil' if line_continuation.nil? @line_continuation = line_continuation @offset = offset @str = str @width = width super() end # Convert token to String. # # @return [String] def to_s = str end # Distinguished instance of Break which forces a line break. class LineBreak < Break # Mock string that represents an infinite string to force new line. class LineBreakString # @return [Integer] def length = 999_999 end def initialize(line_continuation: '', offset: 0) super(LineBreakString.new, line_continuation:, offset:) end end # Begin Token. class Begin < Token # @return [BreakType] attr_reader :break_type # @return [Integer] attr_reader :offset def initialize(break_type: :inconsistent, offset: 2) @offset = offset @break_type = break_type super() end end # End Token. class End < Token nil end # The EOF token can be interpreted as an output flush operation. # # @note Multiple {Token::EOF} tokens can be present in the same list of tokens. # # @example # tokens = [ # Oppen::Token::Begin.new, # Oppen::Token::String.new('XXXXXXXXXX'), # Oppen::Token::End.new, # Oppen::Token::EOF.new, # Oppen::Token::Begin.new, # Oppen::Token::String.new('YYYYYYYYYY'), # Oppen::Token::End.new, # ] # Oppen.print tokens: # # # => # # XXXXXXXXXX # # tokens = [ # Oppen::Token::Begin.new, # Oppen::Token::String.new('XXXXXXXXXX'), # Oppen::Token::End.new, # Oppen::Token::Begin.new, # Oppen::Token::String.new('YYYYYYYYYY'), # Oppen::Token::End.new, # Oppen::Token::EOF.new, # ] # Oppen.print tokens: # # # => # # XXXXXXXXXXYYYYYYYYYY class EOF < Token nil end end end