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(margin, 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(margin, 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
  @margin = margin
  @space = margin
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

#marginObject (readonly)

Page margin (Called length in the original paper).



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

def margin
  @margin
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

Instance Method Details

#handle_begin(token, token_length) ⇒ Nil

Handle Begin Token.

Parameters:

  • token (Token)
  • token_length (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_length)
  if token_length > 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_length) ⇒ Nil

Handle Break Token.

Parameters:

  • token (Token)
  • token_length (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
# File 'lib/oppen/print_stack.rb', line 137

def handle_break(token, token_length)
  block = top
  case block.break_type
  in Token::BreakType::FITS
    @space -= token.length
    write token
  in Token::BreakType::CONSISTENT
    @space = block.offset - token.offset
    indent =
      if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
        token.offset
      else
        margin - space
      end
    print_new_line indent
  in Token::BreakType::INCONSISTENT
    if token_length > space
      @space = block.offset - token.offset
      indent =
        if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
          token.offset
        else
          margin - space
        end
      print_new_line indent
    else
      @space -= token.length
      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_length) ⇒ Nil

Handle String Token.

Parameters:

  • token (Token)
  • token_length (Integer)

Returns:

  • (Nil)

See Also:



177
178
179
180
# File 'lib/oppen/print_stack.rb', line 177

def handle_string(token, token_length)
  @space = [0, space - token_length].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)


246
247
248
# File 'lib/oppen/print_stack.rb', line 246

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:



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

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_length (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_length)
  case token
  in Token::Begin
    handle_begin token, token_length
  in Token::End
    handle_end
  in Token::Break
    handle_break token, token_length
  in Token::String
    handle_string token, token_length
  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)


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

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

#push(print_stack_entry) ⇒ Nil

Push a PrintStackEntry into the stack.

Parameters:

Returns:

  • (Nil)


187
188
189
# File 'lib/oppen/print_stack.rb', line 187

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

#topPrintStackEntry

Get the element at the top of the stack.

Returns:



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

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)


235
236
237
# File 'lib/oppen/print_stack.rb', line 235

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