Class: Oppen::PrintStack

Inherits:
Object
  • Object
show all
Defined in:
lib/oppen/print_stack.rb

Overview

Class that represents a stack that builds an output string using the values of the tokens that were pushed into it.

Defined Under Namespace

Classes: PrintStackEntry

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, new_line, config, space, out) ⇒ PrintStack

Returns a new instance of PrintStack.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/oppen/print_stack.rb', line 44

def initialize(width, new_line, config, space, out)
  @buffer = out
  @config = config
  @genspace =
    if space.respond_to?(:call)
      raise ArgumentError, 'space argument must be a Proc of arity 1' \
        if space.to_proc.arity != 1

      space
    else
      ->(n) { space * n }
    end
  @items = []
  @new_line = new_line
  @width = width
  @space = width
end

Instance Attribute Details

#bufferObject (readonly)

IO element that builds the output.



22
23
24
# File 'lib/oppen/print_stack.rb', line 22

def buffer
  @buffer
end

#configObject (readonly)

Config containing customization flags



25
26
27
# File 'lib/oppen/print_stack.rb', line 25

def config
  @config
end

#genspaceObject (readonly)

Callable that generate spaces



28
29
30
# File 'lib/oppen/print_stack.rb', line 28

def genspace
  @genspace
end

#itemsObject (readonly)

Array representing the stack of PrintStackEntries.



31
32
33
# File 'lib/oppen/print_stack.rb', line 31

def items
  @items
end

#new_lineObject (readonly)

Delimiter between lines in output



34
35
36
# File 'lib/oppen/print_stack.rb', line 34

def new_line
  @new_line
end

#spaceInteger (readonly)

Current available space (Called index in the original paper).

Returns:

  • (Integer)

    Current available space (Called index in the original paper).



42
43
44
# File 'lib/oppen/print_stack.rb', line 42

def space
  @space
end

#widthObject (readonly)

Maximum allowed width for printing (Called length in the original paper).



37
38
39
# File 'lib/oppen/print_stack.rb', line 37

def width
  @width
end

Instance Method Details

#handle_begin(token, token_width) ⇒ Nil

Handle Begin Token.

Parameters:

  • token (Token)
  • token_width (Integer)

Returns:

  • (Nil)

See Also:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/oppen/print_stack.rb', line 98

def handle_begin(token, token_width)
  if token_width > space
    type =
      if token.break_type == Token::BreakType::CONSISTENT
        Token::BreakType::CONSISTENT
      else
        Token::BreakType::INCONSISTENT
      end
    if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
      indent = token.offset
      if !items.empty?
        indent += top.offset
      end
    else
      indent = space - token.offset
    end
    push PrintStackEntry.new indent, type
  else
    push PrintStackEntry.new 0, Token::BreakType::FITS
  end
end

#handle_break(token, token_width) ⇒ Nil

Handle Break Token.

Parameters:

  • token (Token)
  • token_width (Integer)

Returns:

  • (Nil)

See Also:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/oppen/print_stack.rb', line 137

def handle_break(token, token_width)
  block = top
  case block.break_type
  in Token::BreakType::FITS
    @space -= token.width
    write token
  in Token::BreakType::CONSISTENT
    @space = block.offset - token.offset
    indent =
      if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
        token.offset
      else
        width - space
      end
    write token.line_continuation
    print_new_line indent
  in Token::BreakType::INCONSISTENT
    if token_width > space
      @space = block.offset - token.offset
      indent =
        if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
          token.offset
        else
          width - space
        end
      write token.line_continuation
      print_new_line indent
    else
      @space -= token.width
      write token
    end
  end
end

#handle_endNil

Handle End Token.

Returns:

  • (Nil)

See Also:



125
126
127
# File 'lib/oppen/print_stack.rb', line 125

def handle_end
  pop
end

#handle_string(token, token_width) ⇒ Nil

Handle String Token.

Parameters:

  • token (Token)
  • token_width (Integer)

Returns:

  • (Nil)

See Also:



179
180
181
182
# File 'lib/oppen/print_stack.rb', line 179

def handle_string(token, token_width)
  @space = [0, space - token_width].max
  write token
end

#indent(amount) ⇒ Nil

Note:

Called Indent as well in the original paper.

Add indentation by amount.

Parameters:

  • amount (Integer)

Returns:

  • (Nil)


248
249
250
# File 'lib/oppen/print_stack.rb', line 248

def indent(amount)
  write genspace.call(amount)
end

#outputString

Returns the output of the print stack

Returns:

  • (String)


65
66
67
# File 'lib/oppen/print_stack.rb', line 65

def output
  buffer.string
end

#popPrintStackEntry

Pop a PrintStackEntry from the stack.

Returns:



196
197
198
199
200
201
202
# File 'lib/oppen/print_stack.rb', line 196

def pop
  if items.empty?
    raise 'Popping empty stack'
  end

  items.pop
end
Note:

Called Print in the original paper.

Core method responsible for building the print stack and the output string.

Parameters:

  • token (Token)
  • token_width (Integer)

Returns:

  • (Nil)


77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/oppen/print_stack.rb', line 77

def print(token, token_width)
  case token
  in Token::Begin
    handle_begin token, token_width
  in Token::End
    handle_end
  in Token::Break
    handle_break token, token_width
  in Token::String
    handle_string token, token_width
  end
end
Note:

Called PrintNewLine as well in the original paper.

Add a new line to the output.

Parameters:

  • amount (Integer)

    indentation amount.

Returns:

  • (Nil)


222
223
224
225
226
227
228
229
230
# File 'lib/oppen/print_stack.rb', line 222

def print_new_line(amount)
  write new_line
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
    @space = width - top.offset - amount
    indent width - space
  else
    indent amount
  end
end

#push(print_stack_entry) ⇒ Nil

Push a PrintStackEntry into the stack.

Parameters:

Returns:

  • (Nil)


189
190
191
# File 'lib/oppen/print_stack.rb', line 189

def push(print_stack_entry)
  items.append(print_stack_entry)
end

#topPrintStackEntry

Get the element at the top of the stack.

Returns:



207
208
209
210
211
212
213
# File 'lib/oppen/print_stack.rb', line 207

def top
  if items.empty?
    raise 'Accessing empty stack'
  end

  items.last
end

#write(obj) ⇒ Nil

Write a string to the output.

Parameters:

  • obj (Object)

Returns:

  • (Nil)


237
238
239
# File 'lib/oppen/print_stack.rb', line 237

def write(obj)
  buffer.write(obj.to_s)
end