oppen 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/lib/oppen/mixins.rb +42 -39
- data/lib/oppen/print_stack.rb +62 -69
- data/lib/oppen/printer.rb +91 -78
- data/lib/oppen/scan_stack.rb +36 -16
- data/lib/oppen/token.rb +51 -36
- data/lib/oppen/version.rb +3 -2
- data/lib/oppen.rb +177 -77
- data/lib/wadler/print.rb +221 -46
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '008545ae6d86a7415e434ef51a19872fbf5b768db232d70bbac025667e002604'
|
4
|
+
data.tar.gz: a989a6e8d422c363e7ebca36fc10dac4ad030f145afc2b4bc152c9cff5bdfe49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a3e32d3a05c638bd26a9e170d737186c9635eeb3c54844869b108c8252fdafa942a05a76a1e3d3d25d5e93a47d076c280f7346c1c313b5c7159a8f3d1166ef6
|
7
|
+
data.tar.gz: 1f3c076ea8b298f5a772d9c209c4bc64087f6093576e41e2ffb6289b5d0aba08c1b3ed9d3022ebb14b7d7fe4c083804e60219735bce5c00f96785e9dede2bb69
|
data/README.md
CHANGED
data/lib/oppen/mixins.rb
CHANGED
@@ -4,70 +4,73 @@ module Oppen
|
|
4
4
|
# Mixins.
|
5
5
|
module Mixins
|
6
6
|
# Rotates circular array and triples its size.
|
7
|
-
# This method is not for public use.
|
8
7
|
#
|
9
|
-
#
|
10
|
-
# @
|
8
|
+
# @!visibility private
|
9
|
+
# @note This method is not for public use.
|
11
10
|
#
|
12
|
-
# @
|
11
|
+
# @param arr [Array]
|
12
|
+
# the circular array.
|
13
|
+
# @param offset [Integer]
|
14
|
+
# rotation amount.
|
15
|
+
#
|
16
|
+
# @return [Array<Array, Integer, Integer>]
|
17
|
+
# upsized array, lhs, rhs.
|
13
18
|
def upsize_circular_array(arr, offset)
|
14
19
|
size = arr.size
|
15
|
-
arr = arr.rotate
|
16
|
-
arr.fill
|
20
|
+
arr = arr.rotate offset
|
21
|
+
arr.fill nil, size, 2 * size
|
17
22
|
[arr, 0, size]
|
18
23
|
end
|
19
24
|
|
20
|
-
# Convert a list of tokens to its wadler representation.
|
21
|
-
#
|
22
|
-
# @param tokens [Array[Token]]
|
23
|
-
# @param base_indent [Integer]
|
24
|
-
# @param printer_name [String]
|
25
|
-
#
|
26
25
|
# @return [String]
|
27
|
-
def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out')
|
28
|
-
|
29
|
-
|
26
|
+
def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out', width: tokens.length * 3)
|
27
|
+
printer = Oppen::Wadler.new(width: width)
|
28
|
+
printer.base_indent(base_indent)
|
29
|
+
indent = 2
|
30
30
|
|
31
|
-
|
32
|
-
out << (' ' * nb_spaces) << txt << "\n"
|
33
|
-
}
|
34
|
-
display_break_token = ->(token) {
|
31
|
+
handle_break_token = ->(token) {
|
35
32
|
if token.offset.positive?
|
36
|
-
|
37
|
-
|
33
|
+
printer.text "#{printer_name}.nest(#{token.offset}, '', '') {"
|
34
|
+
printer.nest_open indent
|
35
|
+
printer.break
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
printer.text(
|
39
|
+
case token
|
40
|
+
in Token::LineBreak
|
41
|
+
"#{printer_name}.break(line_continuation: #{token.line_continuation.inspect})"
|
42
|
+
in Token::Break
|
43
|
+
"#{printer_name}.breakable(#{token.str.inspect}, width: #{token.width}, " \
|
44
|
+
"line_continuation: #{token.line_continuation.inspect})"
|
45
|
+
end,
|
46
|
+
)
|
47
47
|
|
48
48
|
if token.offset.positive?
|
49
|
-
|
50
|
-
|
49
|
+
printer.nest_close indent
|
50
|
+
printer.break
|
51
|
+
printer.text '}'
|
51
52
|
end
|
52
53
|
}
|
53
54
|
|
54
|
-
tokens.
|
55
|
+
tokens.each_with_index do |token, idx|
|
55
56
|
case token
|
56
57
|
in Token::String
|
57
|
-
|
58
|
+
printer.text "#{printer_name}.text(#{token.value.inspect}, width: #{token.width})"
|
58
59
|
in Token::Break
|
59
|
-
|
60
|
+
handle_break_token.(token)
|
60
61
|
in Token::Begin
|
61
|
-
|
62
|
-
|
62
|
+
printer.text "#{printer_name}.group(#{token.offset}, '', '', #{token.break_type.inspect}) {"
|
63
|
+
printer.nest_open indent
|
63
64
|
in Token::End
|
64
|
-
|
65
|
-
|
65
|
+
printer.nest_close indent
|
66
|
+
printer.break
|
67
|
+
printer.text '}'
|
66
68
|
in Token::EOF
|
67
|
-
|
69
|
+
nil
|
68
70
|
end
|
71
|
+
printer.break if !tokens[idx + 1].is_a?(Token::End)
|
69
72
|
end
|
70
|
-
|
73
|
+
printer.output
|
71
74
|
end
|
72
75
|
end
|
73
76
|
end
|
data/lib/oppen/print_stack.rb
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
# Oppen.
|
4
4
|
module Oppen
|
5
|
-
#
|
6
|
-
# using the values of the tokens that were pushed into it.
|
5
|
+
# A stack of {Token}s.
|
7
6
|
class PrintStack
|
8
|
-
#
|
7
|
+
# An item in the print stack.
|
9
8
|
class PrintStackEntry
|
10
|
-
# @return [
|
11
|
-
|
12
|
-
# @return [Token::BreakType] (Called break in the original paper).
|
9
|
+
# @return [Token::BreakType]
|
10
|
+
# Called `break` in the original paper.
|
13
11
|
attr_reader :break_type
|
12
|
+
# @return [Integer]
|
13
|
+
# Indentation level.
|
14
|
+
attr_reader :offset
|
14
15
|
|
15
16
|
def initialize(offset, break_type)
|
16
17
|
@offset = offset
|
@@ -18,34 +19,26 @@ module Oppen
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
# IO
|
22
|
+
# IO sink for the output.
|
22
23
|
attr_reader :buffer
|
23
|
-
|
24
|
-
# Config containing customization flags
|
24
|
+
# The printer's configuration, altering its behavior.
|
25
25
|
attr_reader :config
|
26
|
-
|
27
|
-
# Callable that generate spaces
|
26
|
+
# Space generator, a callable.
|
28
27
|
attr_reader :genspace
|
29
|
-
|
30
|
-
# Array representing the stack of PrintStackEntries.
|
28
|
+
# The stack of PrintStackEntries.
|
31
29
|
attr_reader :items
|
32
|
-
|
33
|
-
# Delimiter between lines in output
|
30
|
+
# Delimiter between lines.
|
34
31
|
attr_reader :new_line
|
35
|
-
|
36
|
-
# Maximum allowed width for printing (Called length in the original paper).
|
37
|
-
attr_reader :width
|
38
|
-
|
39
|
-
# Current available space (Called index in the original paper).
|
40
|
-
#
|
41
|
-
# @return [Integer] Current available space (Called index in the original paper).
|
32
|
+
# Current available space (`index` in the original paper).
|
42
33
|
attr_reader :space
|
34
|
+
# Maximum allowed width for printing (`length` in the original paper).
|
35
|
+
attr_reader :width
|
43
36
|
|
44
37
|
def initialize(width, new_line, config, space, out)
|
45
38
|
@buffer = out
|
46
39
|
@config = config
|
47
40
|
@genspace =
|
48
|
-
if space.respond_to?
|
41
|
+
if space.respond_to? :call
|
49
42
|
raise ArgumentError, 'space argument must be a Proc of arity 1' \
|
50
43
|
if space.to_proc.arity != 1
|
51
44
|
|
@@ -53,28 +46,32 @@ module Oppen
|
|
53
46
|
else
|
54
47
|
->(n) { space * n }
|
55
48
|
end
|
56
|
-
@indent = 0
|
49
|
+
@indent = 0 # the amount of indentation to display on the next non empty new line.
|
57
50
|
@items = []
|
58
51
|
@new_line = new_line
|
59
52
|
@width = width
|
60
53
|
@space = width
|
61
54
|
end
|
62
55
|
|
63
|
-
#
|
56
|
+
# The final pretty-printed output.
|
64
57
|
#
|
65
58
|
# @return [String]
|
59
|
+
# The output of the print stack.
|
66
60
|
def output
|
67
|
-
buffer.truncate
|
61
|
+
buffer.truncate buffer.pos
|
68
62
|
buffer.string
|
69
63
|
end
|
70
64
|
|
71
|
-
# Core method responsible for building the print stack and the output
|
65
|
+
# Core method responsible for building the print stack and the output
|
66
|
+
# string.
|
72
67
|
#
|
73
|
-
# @note Called Print in the original paper.
|
68
|
+
# @note Called `Print` in the original paper.
|
74
69
|
#
|
75
|
-
# @param token
|
76
|
-
# @param token_width
|
77
|
-
# @param trim_on_break [Integer]
|
70
|
+
# @param token [Token]
|
71
|
+
# @param token_width [Integer]
|
72
|
+
# @param trim_on_break [Integer]
|
73
|
+
# number of trailing whitespace characters to trim. If zero, no
|
74
|
+
# character will be trimmed.
|
78
75
|
#
|
79
76
|
# @return [Nil]
|
80
77
|
def print(token, token_width, trim_on_break: 0)
|
@@ -84,29 +81,27 @@ module Oppen
|
|
84
81
|
in Token::End
|
85
82
|
handle_end
|
86
83
|
in Token::Break
|
87
|
-
handle_break token, token_width, trim_on_break:
|
84
|
+
handle_break token, token_width, trim_on_break: trim_on_break
|
88
85
|
in Token::String
|
89
86
|
handle_string token, token_width
|
90
87
|
end
|
91
88
|
end
|
92
89
|
|
93
|
-
# Handle Begin
|
90
|
+
# Handle {Token::Begin}.
|
94
91
|
#
|
95
|
-
# @param token
|
92
|
+
# @param token [Token]
|
96
93
|
# @param token_width [Integer]
|
97
94
|
#
|
98
95
|
# @return [Nil]
|
99
|
-
#
|
100
|
-
# @see Token::Begin
|
101
96
|
def handle_begin(token, token_width)
|
102
97
|
if token_width > space
|
103
98
|
type =
|
104
|
-
if token.break_type ==
|
105
|
-
|
99
|
+
if token.break_type == :consistent
|
100
|
+
:consistent
|
106
101
|
else
|
107
|
-
|
102
|
+
:inconsistent
|
108
103
|
end
|
109
|
-
if config&.indent_anchor ==
|
104
|
+
if config&.indent_anchor == :current_offset
|
110
105
|
indent = token.offset
|
111
106
|
if !items.empty?
|
112
107
|
indent += top.offset
|
@@ -116,55 +111,54 @@ module Oppen
|
|
116
111
|
end
|
117
112
|
push PrintStackEntry.new indent, type
|
118
113
|
else
|
119
|
-
push PrintStackEntry.new 0,
|
114
|
+
push PrintStackEntry.new 0, :fits
|
120
115
|
end
|
121
116
|
end
|
122
117
|
|
123
|
-
# Handle End
|
118
|
+
# Handle {Token::End}.
|
124
119
|
#
|
125
120
|
# @return [Nil]
|
126
|
-
#
|
127
|
-
# @see Token::End
|
128
121
|
def handle_end
|
129
122
|
pop
|
130
123
|
end
|
131
124
|
|
132
|
-
# Handle Break
|
125
|
+
# Handle {Token::Break}.
|
133
126
|
#
|
134
|
-
# @param token
|
135
|
-
# @param token_width
|
136
|
-
# @param trim_on_break [Integer]
|
127
|
+
# @param token [Token::Break]
|
128
|
+
# @param token_width [Integer]
|
129
|
+
# @param trim_on_break [Integer]
|
130
|
+
# number of trailing whitespace characters to trim.
|
131
|
+
# 0 = none.
|
137
132
|
#
|
138
133
|
# @return [Nil]
|
139
|
-
#
|
140
|
-
# @see Token::Break
|
141
134
|
def handle_break(token, token_width, trim_on_break: 0)
|
142
135
|
block = top
|
143
136
|
case block.break_type
|
144
|
-
in
|
137
|
+
in :fits
|
138
|
+
# No new line is needed (the block fits on the line).
|
145
139
|
@space -= token.width
|
146
140
|
write token
|
147
|
-
in
|
141
|
+
in :consistent
|
148
142
|
@space = block.offset - token.offset
|
149
143
|
indent =
|
150
|
-
if config&.indent_anchor ==
|
144
|
+
if config&.indent_anchor == :current_offset
|
151
145
|
token.offset
|
152
146
|
else
|
153
147
|
width - space
|
154
148
|
end
|
155
|
-
erase
|
149
|
+
erase trim_on_break
|
156
150
|
write token.line_continuation
|
157
151
|
print_new_line indent
|
158
|
-
in
|
152
|
+
in :inconsistent
|
159
153
|
if token_width > space
|
160
154
|
@space = block.offset - token.offset
|
161
155
|
indent =
|
162
|
-
if config&.indent_anchor ==
|
156
|
+
if config&.indent_anchor == :current_offset
|
163
157
|
token.offset
|
164
158
|
else
|
165
159
|
width - space
|
166
160
|
end
|
167
|
-
erase
|
161
|
+
erase trim_on_break
|
168
162
|
write token.line_continuation
|
169
163
|
print_new_line indent
|
170
164
|
else
|
@@ -174,14 +168,12 @@ module Oppen
|
|
174
168
|
end
|
175
169
|
end
|
176
170
|
|
177
|
-
# Handle String
|
171
|
+
# Handle {Token::String}.
|
178
172
|
#
|
179
|
-
# @param token
|
173
|
+
# @param token [Token::String]
|
180
174
|
# @param token_width [Integer]
|
181
175
|
#
|
182
176
|
# @return [Nil]
|
183
|
-
#
|
184
|
-
# @see Token::String
|
185
177
|
def handle_string(token, token_width)
|
186
178
|
return if token.value.empty?
|
187
179
|
|
@@ -193,16 +185,16 @@ module Oppen
|
|
193
185
|
write token
|
194
186
|
end
|
195
187
|
|
196
|
-
# Push a PrintStackEntry into the stack.
|
188
|
+
# Push a {PrintStackEntry} into the stack.
|
197
189
|
#
|
198
190
|
# @param print_stack_entry [PrintStackEntry]
|
199
191
|
#
|
200
192
|
# @return [Nil]
|
201
193
|
def push(print_stack_entry)
|
202
|
-
items.append
|
194
|
+
items.append print_stack_entry
|
203
195
|
end
|
204
196
|
|
205
|
-
# Pop a PrintStackEntry from the stack.
|
197
|
+
# Pop a {PrintStackEntry} from the stack.
|
206
198
|
#
|
207
199
|
# @return [PrintStackEntry]
|
208
200
|
def pop
|
@@ -226,14 +218,15 @@ module Oppen
|
|
226
218
|
|
227
219
|
# Add a new line to the output.
|
228
220
|
#
|
229
|
-
# @note Called PrintNewLine as well in the original paper.
|
221
|
+
# @note Called `PrintNewLine` as well in the original paper.
|
230
222
|
#
|
231
|
-
# @param amount [Integer]
|
223
|
+
# @param amount [Integer]
|
224
|
+
# indentation amount.
|
232
225
|
#
|
233
226
|
# @return [Nil]
|
234
227
|
def print_new_line(amount)
|
235
228
|
write new_line
|
236
|
-
if config&.indent_anchor ==
|
229
|
+
if config&.indent_anchor == :current_offset
|
237
230
|
@space = width - top.offset - amount
|
238
231
|
@indent = width - space
|
239
232
|
else
|
@@ -247,7 +240,7 @@ module Oppen
|
|
247
240
|
#
|
248
241
|
# @return [Nil]
|
249
242
|
def write(obj)
|
250
|
-
buffer.write
|
243
|
+
buffer.write obj.to_s
|
251
244
|
end
|
252
245
|
|
253
246
|
# Erase the last `count` characters.
|
@@ -264,7 +257,7 @@ module Oppen
|
|
264
257
|
|
265
258
|
# Add indentation by `amount`.
|
266
259
|
#
|
267
|
-
# @note Called Indent as well in the original paper.
|
260
|
+
# @note Called `Indent` as well in the original paper.
|
268
261
|
#
|
269
262
|
# @param amount [Integer]
|
270
263
|
#
|