Class: Oppen::Printer
- Inherits:
-
Object
- Object
- Oppen::Printer
- Extended by:
- Mixins
- Defined in:
- lib/oppen/printer.rb
Overview
Oppen pretty-printer.
Instance Attribute Summary collapse
-
#config ⇒ Config
readonly
The printer's configuration, altering its behavior.
-
#left ⇒ Integer
readonly
Ring buffer's left index.
-
#left_total ⇒ Integer
readonly
Number of spaces needed to print from start of buffer to left.
-
#print_stack ⇒ PrintStack
readonly
A stack of Tokens; builds the the final output.
-
#right ⇒ Integer
readonly
Ring buffer's right index.
-
#right_total ⇒ Integer
readonly
Number of spaces needed to print from start of buffer to right.
-
#scan_stack ⇒ ScanStack
readonly
Potential breaking positions.
-
#size ⇒ Integer
readonly
Size buffer, initially filled with nil.
-
#tokens ⇒ Array<Tokens>
readonly
Token buffer, initially filled with nil.
Instance Method Summary collapse
-
#advance_left(token, token_width) ⇒ Nil
Advances the #left pointer and lets the print stack print some of the tokens it contains.
-
#advance_right ⇒ Nil
Advances the #right pointer.
-
#check_stack(depth) ⇒ Nil
Updates the #size buffer taking into account the length of the current group.
-
#check_stream ⇒ Nil
Flushes the input if possible.
-
#handle_begin(token) ⇒ Nil
Handle Token::Begin.
-
#handle_break(token) ⇒ Nil
Handle Token::Break.
-
#handle_end(token) ⇒ Nil
Handle Token::End.
-
#handle_eof ⇒ Nil
Handle Token::EOF.
-
#handle_string(token) ⇒ Nil
Handle Token::String.
-
#initialize(width, new_line, config = Config.oppen, space = ' ', out = StringIO.new) ⇒ Printer
constructor
A new instance of Printer.
-
#output ⇒ String
The final pretty-printed output.
-
#print(token) ⇒ Nil
Core function of the algorithm responsible for populating the ScanStack and PrintStack.
Methods included from Mixins
Constructor Details
#initialize(width, new_line, config = Config.oppen, space = ' ', out = StringIO.new) ⇒ Printer
Called PrettyPrintInit
in the original paper.
Returns a new instance of Printer.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/oppen/printer.rb', line 84 def initialize(width, new_line, config = Config.oppen, space = ' ', out = StringIO.new) # Maximum size if the stacks n = 3 * width @config = config @last_whitespaces_width = 0 # Accumulates the width of the last Whitespace tokens encountered. @left = 0 @left_total = 1 @print_stack = PrintStack.new width, new_line, config, space, out @right = 0 @right_total = 1 @scan_stack = ScanStack.new n, config @size = Array.new n @tokens = Array.new n end |
Instance Attribute Details
#config ⇒ Config (readonly)
The printer's configuration, altering its behavior.
18 19 20 |
# File 'lib/oppen/printer.rb', line 18 def config @config end |
#left ⇒ Integer (readonly)
Called left
as well in the original paper.
Ring buffer's left index.
24 25 26 |
# File 'lib/oppen/printer.rb', line 24 def left @left end |
#left_total ⇒ Integer (readonly)
Called leftTotal
as well in the original paper.
Number of spaces needed to print from start of buffer to left.
30 31 32 |
# File 'lib/oppen/printer.rb', line 30 def left_total @left_total end |
#print_stack ⇒ PrintStack (readonly)
Called printStack
as well in the original paper.
A stack of Tokens; builds the the final output.
36 37 38 |
# File 'lib/oppen/printer.rb', line 36 def print_stack @print_stack end |
#right ⇒ Integer (readonly)
Called right
as well in the original paper.
Ring buffer's right index.
42 43 44 |
# File 'lib/oppen/printer.rb', line 42 def right @right end |
#right_total ⇒ Integer (readonly)
Called leftTotal
as well in the original paper.
Number of spaces needed to print from start of buffer to right.
48 49 50 |
# File 'lib/oppen/printer.rb', line 48 def right_total @right_total end |
#scan_stack ⇒ ScanStack (readonly)
Called scanStack
as well in the original paper.
Potential breaking positions.
54 55 56 |
# File 'lib/oppen/printer.rb', line 54 def scan_stack @scan_stack end |
#size ⇒ Integer (readonly)
Called size
as well in the original paper.
Size buffer, initially filled with nil.
60 61 62 |
# File 'lib/oppen/printer.rb', line 60 def size @size end |
#tokens ⇒ Array<Tokens> (readonly)
Called token
in the original paper.
Token buffer, initially filled with nil.
66 67 68 |
# File 'lib/oppen/printer.rb', line 66 def tokens @tokens end |
Instance Method Details
#advance_left(token, token_width) ⇒ Nil
Called AdvanceLeft
as well in the original paper.
Advances the #left pointer and lets the print stack print some of the tokens it contains.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/oppen/printer.rb', line 274 def advance_left(token, token_width) return if token_width.negative? trim_on_break = if token.is_a?(Token::Break) # Find the first previous String token. idx = (left - 1) % tokens.length while idx != right && tokens[idx] && !tokens[idx].is_a?(Token::String) \ && !tokens[idx].is_a?(Token::Break) idx = (idx - 1) % tokens.length end # Sum the widths of the last whitespace tokens. total = 0 while tokens[idx].is_a?(Token::Whitespace) total += tokens[idx].width idx = (idx - 1) % tokens.length end @last_whitespaces_width = 0 total end trim_on_break ||= 0 print_stack.print(token, token_width, trim_on_break:) case token when Token::Break @left_total += token.width when Token::String @left_total += token_width end return if left == right @left = (left + 1) % tokens.length advance_left tokens[left], size[left] end |
#advance_right ⇒ Nil
Called AdvanceRight
as well in the original paper.
Advances the #right pointer.
253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/oppen/printer.rb', line 253 def advance_right @right = (right + 1) % @size.length return if right != left raise 'Token queue full' if !config.upsize_stack? @scan_stack.update_indexes(-@left) @size, _left, _right = ScanStack.upsize_circular_array(@size, @left) @tokens, @left, @right = ScanStack.upsize_circular_array(@tokens, @left) end |
#check_stack(depth) ⇒ Nil
Called CheckStack
as well in the original paper.
Updates the #size buffer taking into account the length of the current group.
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/oppen/printer.rb', line 320 def check_stack(depth) return if scan_stack.empty? x = scan_stack.top case tokens[x] in Token::Begin if depth.positive? size[scan_stack.pop] = size[x] + right_total check_stack depth - 1 end in Token::End size[scan_stack.pop] = 1 check_stack depth + 1 else size[scan_stack.pop] = size[x] + right_total if depth.positive? check_stack depth end end end |
#check_stream ⇒ Nil
Called CheckStream
as well in the original paper.
Flushes the input if possible.
236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/oppen/printer.rb', line 236 def check_stream return if right_total - left_total <= print_stack.space if !scan_stack.empty? && left == scan_stack.bottom size[scan_stack.pop_bottom] = Float::INFINITY end advance_left tokens[left], size[left] return if left == right check_stream end |
#handle_begin(token) ⇒ Nil
Handle Token::Begin.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/oppen/printer.rb', line 150 def handle_begin(token) if scan_stack.empty? @left = 0 @left_total = 1 @right = 0 @right_total = 1 # config.trim_trailing_whitespaces. @tokens[-1] = nil else advance_right end tokens[right] = token size[right] = -right_total scan_stack.push right end |
#handle_break(token) ⇒ Nil
Handle Token::Break.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/oppen/printer.rb', line 193 def handle_break(token) if scan_stack.empty? @left = 0 @left_total = 1 @right = 0 @right_total = 1 # config.trim_trailing_whitespaces. tokens[-1] = nil print_stack.erase @last_whitespaces_width @last_whitespaces_width = 0 else advance_right end check_stack 0 scan_stack.push right tokens[right] = token size[right] = -right_total @right_total += token.width end |
#handle_end(token) ⇒ Nil
Handle Token::End.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/oppen/printer.rb', line 172 def handle_end(token) if scan_stack.empty? print_stack.print token, 0 else advance_right tokens[right] = token size[right] = -1 scan_stack.push right if config&.eager_print? && (!scan_stack.empty? && right_total - left_total < print_stack.space) check_stack 0 advance_left tokens[left], size[left] end end end |
#handle_eof ⇒ Nil
Handle Token::EOF.
137 138 139 140 141 142 143 |
# File 'lib/oppen/printer.rb', line 137 def handle_eof if !scan_stack.empty? check_stack 0 advance_left tokens[left], size[left] end print_stack.indent 0 end |
#handle_string(token) ⇒ Nil
Handle Token::String.
219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/oppen/printer.rb', line 219 def handle_string(token) if scan_stack.empty? print_stack.print token, token.width else advance_right tokens[right] = token size[right] = token.width @right_total += token.width check_stream if @last_whitespaces_width.zero? end end |
#output ⇒ String
The final pretty-printed output.
105 |
# File 'lib/oppen/printer.rb', line 105 def output = print_stack.output |
#print(token) ⇒ Nil
Called PrettyPrint
as well in the original paper.
Core function of the algorithm responsible for populating the ScanStack and Oppen::PrintStack.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/oppen/printer.rb', line 115 def print(token) case token in Token::EOF handle_eof in Token::Begin handle_begin token in Token::End handle_end token in Token::Break handle_break token in Token::Whitespace @last_whitespaces_width += token.width handle_string token in Token::String @last_whitespaces_width = 0 handle_string token end end |