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
data/lib/oppen/printer.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'stringio'
|
4
4
|
|
5
|
-
require_relative 'scan_stack'
|
6
|
-
require_relative 'print_stack'
|
7
5
|
require_relative 'mixins'
|
6
|
+
require_relative 'print_stack'
|
7
|
+
require_relative 'scan_stack'
|
8
8
|
|
9
9
|
# Oppen.
|
10
10
|
module Oppen
|
@@ -12,73 +12,82 @@ module Oppen
|
|
12
12
|
class Printer
|
13
13
|
extend Mixins
|
14
14
|
|
15
|
+
# The printer's configuration, altering its behavior.
|
16
|
+
#
|
17
|
+
# @return [Config]
|
15
18
|
attr_reader :config
|
16
|
-
# Ring buffer left index.
|
19
|
+
# Ring buffer's left index.
|
17
20
|
#
|
18
|
-
# @note Called left as well in the original paper.
|
21
|
+
# @note Called `left` as well in the original paper.
|
22
|
+
#
|
23
|
+
# @return [Integer]
|
19
24
|
attr_reader :left
|
20
|
-
|
21
|
-
# Total number of spaces needed to print from start of buffer to the left.
|
25
|
+
# Number of spaces needed to print from start of buffer to left.
|
22
26
|
#
|
23
|
-
# @note Called leftTotal as well in the original paper.
|
27
|
+
# @note Called `leftTotal` as well in the original paper.
|
28
|
+
#
|
29
|
+
# @return [Integer]
|
24
30
|
attr_reader :left_total
|
25
|
-
|
26
|
-
#
|
31
|
+
# A stack of {Token}s; builds the the final output.
|
32
|
+
#
|
33
|
+
# @note Called `printStack` as well in the original paper.
|
34
|
+
#
|
35
|
+
# @return [PrintStack]
|
27
36
|
attr_reader :print_stack
|
28
|
-
|
29
|
-
# Ring buffer right index.
|
37
|
+
# Ring buffer's right index.
|
30
38
|
#
|
31
|
-
# @note Called right as well in the original paper.
|
39
|
+
# @note Called `right` as well in the original paper.
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
32
42
|
attr_reader :right
|
33
|
-
|
34
|
-
# Total number of spaces needed to print from start of buffer to the right.
|
43
|
+
# Number of spaces needed to print from start of buffer to right.
|
35
44
|
#
|
36
|
-
# @note Called leftTotal as well in the original paper.
|
45
|
+
# @note Called `leftTotal` as well in the original paper.
|
46
|
+
#
|
47
|
+
# @return [Integer]
|
37
48
|
attr_reader :right_total
|
38
|
-
|
39
49
|
# Potential breaking positions.
|
40
50
|
#
|
41
|
-
# @note Called scanStack as well in the original paper.
|
51
|
+
# @note Called `scanStack` as well in the original paper.
|
52
|
+
#
|
53
|
+
# @return [ScanStack]
|
42
54
|
attr_reader :scan_stack
|
43
|
-
|
44
55
|
# Size buffer, initially filled with nil.
|
45
56
|
#
|
46
|
-
# @note Called size as well in the original paper.
|
57
|
+
# @note Called `size` as well in the original paper.
|
58
|
+
#
|
59
|
+
# @return [Integer]
|
47
60
|
attr_reader :size
|
48
|
-
|
49
61
|
# Token buffer, initially filled with nil.
|
50
62
|
#
|
51
|
-
# @note Called token in the original paper.
|
63
|
+
# @note Called `token` in the original paper.
|
64
|
+
#
|
65
|
+
# @return [Array<Tokens>]
|
52
66
|
attr_reader :tokens
|
53
67
|
|
54
|
-
#
|
55
|
-
#
|
56
|
-
# @
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# @param width
|
66
|
-
#
|
67
|
-
# @param
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# lambda `->(n){ n * space }`, where `n` is the number of columns
|
71
|
-
# to indent.
|
72
|
-
# If it's a callable, it will receive `n` and it needs to return
|
73
|
-
# a string.
|
74
|
-
# @param out [Object] should have a write and string method
|
68
|
+
# @note Called `PrettyPrintInit` in the original paper.
|
69
|
+
#
|
70
|
+
# @param config [Config]
|
71
|
+
# to customize the printer's behavior.
|
72
|
+
# @param new_line [String]
|
73
|
+
# the delimiter between lines.
|
74
|
+
# @param space [String, Proc]
|
75
|
+
# indentation string or a string generator.
|
76
|
+
# - If a `String`, spaces will be generated with the the lambda
|
77
|
+
# `->(n){ space * n }`, where `n` is the number of columns to indent.
|
78
|
+
# - If a `Proc`, it will receive `n` and it needs to return a `String`.
|
79
|
+
# @param width [Integer]
|
80
|
+
# maximum line width desired.
|
81
|
+
# @param out [Object]
|
82
|
+
# the output string buffer. It should have both `write` and `string`
|
83
|
+
# methods.
|
75
84
|
def initialize(width, new_line, config = Config.oppen,
|
76
85
|
space = ' ', out = StringIO.new)
|
77
86
|
# Maximum size if the stacks
|
78
87
|
n = 3 * width
|
79
88
|
|
80
89
|
@config = config
|
81
|
-
@last_whitespaces_width = 0
|
90
|
+
@last_whitespaces_width = 0 # Accumulates the width of the last Whitespace tokens encountered.
|
82
91
|
@left = 0
|
83
92
|
@left_total = 1
|
84
93
|
@print_stack = PrintStack.new width, new_line, config, space, out
|
@@ -89,14 +98,16 @@ module Oppen
|
|
89
98
|
@tokens = Array.new n
|
90
99
|
end
|
91
100
|
|
101
|
+
# The final pretty-printed output.
|
102
|
+
#
|
92
103
|
# @return [String]
|
93
|
-
|
94
|
-
|
95
|
-
end
|
104
|
+
# the output of the print stack.
|
105
|
+
def output = print_stack.output
|
96
106
|
|
97
|
-
# Core function of the algorithm responsible for populating the
|
107
|
+
# Core function of the algorithm responsible for populating the {ScanStack}
|
108
|
+
# and {PrintStack}.
|
98
109
|
#
|
99
|
-
# @note Called PrettyPrint as well in the original paper.
|
110
|
+
# @note Called `PrettyPrint` as well in the original paper.
|
100
111
|
#
|
101
112
|
# @param token [Token]
|
102
113
|
#
|
@@ -120,11 +131,9 @@ module Oppen
|
|
120
131
|
end
|
121
132
|
end
|
122
133
|
|
123
|
-
# Handle EOF
|
134
|
+
# Handle {Token::EOF}.
|
124
135
|
#
|
125
136
|
# @return [Nil]
|
126
|
-
#
|
127
|
-
# @see Token::EOF
|
128
137
|
def handle_eof
|
129
138
|
if !scan_stack.empty?
|
130
139
|
check_stack 0
|
@@ -133,11 +142,11 @@ module Oppen
|
|
133
142
|
print_stack.indent 0
|
134
143
|
end
|
135
144
|
|
136
|
-
# Handle Begin
|
145
|
+
# Handle {Token::Begin}.
|
137
146
|
#
|
138
|
-
# @
|
147
|
+
# @param token [Token::Begin]
|
139
148
|
#
|
140
|
-
# @
|
149
|
+
# @return [Nil]
|
141
150
|
def handle_begin(token)
|
142
151
|
if scan_stack.empty?
|
143
152
|
@left = 0
|
@@ -145,7 +154,7 @@ module Oppen
|
|
145
154
|
@right = 0
|
146
155
|
@right_total = 1
|
147
156
|
|
148
|
-
# config.trim_trailing_whitespaces
|
157
|
+
# config.trim_trailing_whitespaces.
|
149
158
|
@tokens[-1] = nil
|
150
159
|
else
|
151
160
|
advance_right
|
@@ -155,11 +164,11 @@ module Oppen
|
|
155
164
|
scan_stack.push right
|
156
165
|
end
|
157
166
|
|
158
|
-
# Handle End
|
167
|
+
# Handle {Token::End}.
|
159
168
|
#
|
160
|
-
# @
|
169
|
+
# @param token [Token::End]
|
161
170
|
#
|
162
|
-
# @
|
171
|
+
# @return [Nil]
|
163
172
|
def handle_end(token)
|
164
173
|
if scan_stack.empty?
|
165
174
|
print_stack.print token, 0
|
@@ -176,11 +185,11 @@ module Oppen
|
|
176
185
|
end
|
177
186
|
end
|
178
187
|
|
179
|
-
# Handle Break
|
188
|
+
# Handle {Token::Break}.
|
180
189
|
#
|
181
|
-
# @
|
190
|
+
# @param token [Token::Break]
|
182
191
|
#
|
183
|
-
# @
|
192
|
+
# @return [Nil]
|
184
193
|
def handle_break(token)
|
185
194
|
if scan_stack.empty?
|
186
195
|
@left = 0
|
@@ -188,7 +197,7 @@ module Oppen
|
|
188
197
|
@right = 0
|
189
198
|
@right_total = 1
|
190
199
|
|
191
|
-
# config.trim_trailing_whitespaces
|
200
|
+
# config.trim_trailing_whitespaces.
|
192
201
|
tokens[-1] = nil
|
193
202
|
print_stack.erase @last_whitespaces_width
|
194
203
|
@last_whitespaces_width = 0
|
@@ -202,11 +211,11 @@ module Oppen
|
|
202
211
|
@right_total += token.width
|
203
212
|
end
|
204
213
|
|
205
|
-
# Handle String
|
214
|
+
# Handle {Token::String}.
|
206
215
|
#
|
207
|
-
# @
|
216
|
+
# @param token [Token::String]
|
208
217
|
#
|
209
|
-
# @
|
218
|
+
# @return [Nil]
|
210
219
|
def handle_string(token)
|
211
220
|
if scan_stack.empty?
|
212
221
|
print_stack.print token, token.width
|
@@ -221,7 +230,7 @@ module Oppen
|
|
221
230
|
|
222
231
|
# Flushes the input if possible.
|
223
232
|
#
|
224
|
-
# @note Called CheckStream as well in the original paper.
|
233
|
+
# @note Called `CheckStream` as well in the original paper.
|
225
234
|
#
|
226
235
|
# @return [Nil]
|
227
236
|
def check_stream
|
@@ -236,9 +245,9 @@ module Oppen
|
|
236
245
|
check_stream
|
237
246
|
end
|
238
247
|
|
239
|
-
# Advances the
|
248
|
+
# Advances the {#right} pointer.
|
240
249
|
#
|
241
|
-
# @note Called AdvanceRight as well in the original paper.
|
250
|
+
# @note Called `AdvanceRight` as well in the original paper.
|
242
251
|
#
|
243
252
|
# @return [Nil]
|
244
253
|
def advance_right
|
@@ -253,10 +262,13 @@ module Oppen
|
|
253
262
|
@tokens, @left, @right = ScanStack.upsize_circular_array(@tokens, @left)
|
254
263
|
end
|
255
264
|
|
256
|
-
# Advances the
|
257
|
-
#
|
265
|
+
# Advances the {#left} pointer and lets the print stack print some of the
|
266
|
+
# tokens it contains.
|
267
|
+
#
|
268
|
+
# @note Called `AdvanceLeft` as well in the original paper.
|
258
269
|
#
|
259
|
-
# @
|
270
|
+
# @param token [Token]
|
271
|
+
# @param token_width [Integer]
|
260
272
|
#
|
261
273
|
# @return [Nil]
|
262
274
|
def advance_left(token, token_width)
|
@@ -281,7 +293,7 @@ module Oppen
|
|
281
293
|
end
|
282
294
|
trim_on_break ||= 0
|
283
295
|
|
284
|
-
print_stack.print(token, token_width, trim_on_break:)
|
296
|
+
print_stack.print(token, token_width, trim_on_break: trim_on_break)
|
285
297
|
|
286
298
|
case token
|
287
299
|
when Token::Break
|
@@ -296,12 +308,13 @@ module Oppen
|
|
296
308
|
advance_left tokens[left], size[left]
|
297
309
|
end
|
298
310
|
|
299
|
-
# Updates the size buffer taking into
|
300
|
-
#
|
311
|
+
# Updates the {#size} buffer taking into account the length of the current
|
312
|
+
# group.
|
301
313
|
#
|
302
|
-
# @note Called CheckStack as well in the original paper.
|
314
|
+
# @note Called `CheckStack` as well in the original paper.
|
303
315
|
#
|
304
|
-
# @param depth [Integer]
|
316
|
+
# @param depth [Integer]
|
317
|
+
# depth of the group.
|
305
318
|
#
|
306
319
|
# @return [Nil]
|
307
320
|
def check_stack(depth)
|
@@ -309,12 +322,12 @@ module Oppen
|
|
309
322
|
|
310
323
|
x = scan_stack.top
|
311
324
|
case tokens[x]
|
312
|
-
|
325
|
+
in Token::Begin
|
313
326
|
if depth.positive?
|
314
327
|
size[scan_stack.pop] = size[x] + right_total
|
315
328
|
check_stack depth - 1
|
316
329
|
end
|
317
|
-
|
330
|
+
in Token::End
|
318
331
|
size[scan_stack.pop] = 1
|
319
332
|
check_stack depth + 1
|
320
333
|
else
|
data/lib/oppen/scan_stack.rb
CHANGED
@@ -9,23 +9,28 @@ module Oppen
|
|
9
9
|
extend Mixins
|
10
10
|
|
11
11
|
def initialize(size, config)
|
12
|
-
@bottom = 0
|
13
|
-
@config = config
|
14
|
-
@empty = true
|
15
|
-
@stack = Array.new
|
16
|
-
@top = 0
|
12
|
+
@bottom = 0 # Points to the bottom of the stack.
|
13
|
+
@config = config # Printing config.
|
14
|
+
@empty = true # Emptiness flag.
|
15
|
+
@stack = Array.new size # The fixed sized stack.
|
16
|
+
@top = 0 # Points to the top of the stack.
|
17
17
|
end
|
18
18
|
|
19
|
+
# Whether the stack is empty.
|
20
|
+
#
|
19
21
|
# @return [Boolean]
|
20
|
-
def empty?
|
21
|
-
@empty
|
22
|
-
end
|
22
|
+
def empty? = @empty
|
23
23
|
|
24
|
+
# The current length of the stack.
|
25
|
+
#
|
24
26
|
# @return [Integer]
|
25
|
-
def length
|
26
|
-
@stack.length
|
27
|
-
end
|
27
|
+
def length = @stack.length
|
28
28
|
|
29
|
+
# The top element of the stack.
|
30
|
+
#
|
31
|
+
# @raise [RuntimeError]
|
32
|
+
# when accessing empty stack.
|
33
|
+
#
|
29
34
|
# @return [Object]
|
30
35
|
def top
|
31
36
|
if empty?
|
@@ -35,6 +40,11 @@ module Oppen
|
|
35
40
|
@stack[@top]
|
36
41
|
end
|
37
42
|
|
43
|
+
# The bottom element of the stack.
|
44
|
+
#
|
45
|
+
# @raise [RuntimeError]
|
46
|
+
# when accessing empty stack.
|
47
|
+
#
|
38
48
|
# @return [Object]
|
39
49
|
def bottom
|
40
50
|
if empty?
|
@@ -66,16 +76,20 @@ module Oppen
|
|
66
76
|
#
|
67
77
|
# @param value [Object]
|
68
78
|
#
|
79
|
+
# @raise [RuntimeError]
|
80
|
+
# when the stack is full and the `upsize_stack` flag is not activated in
|
81
|
+
# {Config}.
|
82
|
+
#
|
69
83
|
# @return [Nil]
|
70
84
|
def push(value)
|
71
85
|
if empty?
|
72
86
|
@empty = false
|
73
87
|
else
|
74
|
-
@top = increment
|
88
|
+
@top = increment @top
|
75
89
|
if @top == @bottom
|
76
90
|
raise 'Stack full' if !@config.upsize_stack?
|
77
91
|
|
78
|
-
@stack, @bottom, @top = ScanStack.upsize_circular_array
|
92
|
+
@stack, @bottom, @top = ScanStack.upsize_circular_array @stack, @bottom
|
79
93
|
end
|
80
94
|
end
|
81
95
|
@stack[@top] = value
|
@@ -83,6 +97,9 @@ module Oppen
|
|
83
97
|
|
84
98
|
# Pop a value from the top.
|
85
99
|
#
|
100
|
+
# @raise [RuntimeError]
|
101
|
+
# when accessing empty stack.
|
102
|
+
#
|
86
103
|
# @return [Nil]
|
87
104
|
def pop
|
88
105
|
if empty?
|
@@ -93,13 +110,16 @@ module Oppen
|
|
93
110
|
if @top == @bottom
|
94
111
|
@empty = true
|
95
112
|
else
|
96
|
-
@top = decrement
|
113
|
+
@top = decrement @top
|
97
114
|
end
|
98
115
|
res
|
99
116
|
end
|
100
117
|
|
101
118
|
# Pop a value from the bottom.
|
102
119
|
#
|
120
|
+
# @raise [RuntimeError]
|
121
|
+
# when accessing empty stack.
|
122
|
+
#
|
103
123
|
# @return [Nil]
|
104
124
|
def pop_bottom
|
105
125
|
if empty?
|
@@ -110,7 +130,7 @@ module Oppen
|
|
110
130
|
if @top == @bottom
|
111
131
|
@empty = true
|
112
132
|
else
|
113
|
-
@bottom = increment
|
133
|
+
@bottom = increment @bottom
|
114
134
|
end
|
115
135
|
res
|
116
136
|
end
|
@@ -119,7 +139,7 @@ module Oppen
|
|
119
139
|
#
|
120
140
|
# @param offset [Integer]
|
121
141
|
#
|
122
|
-
# @return [Array
|
142
|
+
# @return [Array<Integer>]
|
123
143
|
def update_indexes(offset)
|
124
144
|
@stack = @stack.map { |val|
|
125
145
|
(val + offset) % length if val
|
data/lib/oppen/token.rb
CHANGED
@@ -4,27 +4,14 @@
|
|
4
4
|
module Oppen
|
5
5
|
# Token.
|
6
6
|
class Token
|
7
|
-
#
|
7
|
+
# Default token width.
|
8
8
|
#
|
9
|
-
# FITS => No break is needed (the block fits on the line).
|
10
|
-
# INCONSISTENT => New line will be forced only if necessary.
|
11
|
-
# CONSISTENT => Each subblock of the block will be placed on a new line.
|
12
|
-
module BreakType
|
13
|
-
# @return [Integer]
|
14
|
-
FITS = 0
|
15
|
-
# @return [Integer]
|
16
|
-
INCONSISTENT = 1
|
17
|
-
# @return [Integer]
|
18
|
-
CONSISTENT = 2
|
19
|
-
end
|
20
|
-
|
21
|
-
# Default token width
|
22
9
|
# @return [Integer]
|
23
10
|
def width = 0
|
24
11
|
|
25
12
|
# String Token.
|
26
13
|
class String < Token
|
27
|
-
# @return [String]
|
14
|
+
# @return [String]
|
28
15
|
attr_reader :value
|
29
16
|
# @return [Integer]
|
30
17
|
attr_reader :width
|
@@ -39,15 +26,21 @@ module Oppen
|
|
39
26
|
def to_s = value
|
40
27
|
end
|
41
28
|
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
29
|
+
# This token is not part of Oppen's original work. We introduced it to
|
30
|
+
# handle trailing whitespaces.
|
31
|
+
#
|
32
|
+
# When the config flag `trim_trailing_whitespaces == true`, and a new line
|
33
|
+
# is needed, all the {Token::Whitespace} figuring after the last {Token::String}
|
34
|
+
# will be be skipped.
|
45
35
|
class Whitespace < ::Oppen::Token::String
|
46
36
|
end
|
47
37
|
|
48
38
|
# Break Token.
|
49
39
|
class Break < Token
|
50
|
-
# @return [String]
|
40
|
+
# @return [String]
|
41
|
+
# If a new line is needed, display this string before the new line.
|
42
|
+
#
|
43
|
+
# @see Wadler#break example on `line_continuation`.
|
51
44
|
attr_reader :line_continuation
|
52
45
|
# @return [Integer] Indentation.
|
53
46
|
attr_reader :offset
|
@@ -56,7 +49,7 @@ module Oppen
|
|
56
49
|
# @return [Integer]
|
57
50
|
attr_reader :width
|
58
51
|
|
59
|
-
def initialize(str = ' ',
|
52
|
+
def initialize(str = ' ', line_continuation: '', offset: 0, width: str.length)
|
60
53
|
raise ArgumentError, 'line_continuation cannot be nil' if line_continuation.nil?
|
61
54
|
|
62
55
|
@line_continuation = line_continuation
|
@@ -66,6 +59,8 @@ module Oppen
|
|
66
59
|
super()
|
67
60
|
end
|
68
61
|
|
62
|
+
# Convert token to String.
|
63
|
+
#
|
69
64
|
# @return [String]
|
70
65
|
def to_s = str
|
71
66
|
end
|
@@ -79,7 +74,7 @@ module Oppen
|
|
79
74
|
end
|
80
75
|
|
81
76
|
def initialize(line_continuation: '', offset: 0)
|
82
|
-
super(LineBreakString.new, line_continuation
|
77
|
+
super(LineBreakString.new, line_continuation: line_continuation, offset: offset)
|
83
78
|
end
|
84
79
|
end
|
85
80
|
|
@@ -87,33 +82,53 @@ module Oppen
|
|
87
82
|
class Begin < Token
|
88
83
|
# @return [BreakType]
|
89
84
|
attr_reader :break_type
|
90
|
-
# @return [Integer]
|
85
|
+
# @return [Integer]
|
91
86
|
attr_reader :offset
|
92
87
|
|
93
|
-
def initialize(break_type:
|
88
|
+
def initialize(break_type: :inconsistent, offset: 2)
|
94
89
|
@offset = offset
|
95
90
|
@break_type = break_type
|
96
91
|
super()
|
97
92
|
end
|
98
|
-
|
99
|
-
# The break_type name as a String.
|
100
|
-
#
|
101
|
-
# @return [String]
|
102
|
-
def break_type_name
|
103
|
-
case @break_type
|
104
|
-
in BreakType::FITS then 'Oppen::Token::BreakType::FITS'
|
105
|
-
in BreakType::INCONSISTENT then 'Oppen::Token::BreakType::INCONSISTENT'
|
106
|
-
in BreakType::CONSISTENT then 'Oppen::Token::BreakType::CONSISTENT'
|
107
|
-
end
|
108
|
-
end
|
109
93
|
end
|
110
94
|
|
111
|
-
# End Token
|
95
|
+
# End Token.
|
112
96
|
class End < Token
|
113
97
|
nil
|
114
98
|
end
|
115
99
|
|
116
|
-
# EOF
|
100
|
+
# The EOF token can be interpreted as an output flush operation.
|
101
|
+
#
|
102
|
+
# @note Multiple {Token::EOF} tokens can be present in the same list of tokens.
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# tokens = [
|
106
|
+
# Oppen::Token::Begin.new,
|
107
|
+
# Oppen::Token::String.new('XXXXXXXXXX'),
|
108
|
+
# Oppen::Token::End.new,
|
109
|
+
# Oppen::Token::EOF.new,
|
110
|
+
# Oppen::Token::Begin.new,
|
111
|
+
# Oppen::Token::String.new('YYYYYYYYYY'),
|
112
|
+
# Oppen::Token::End.new,
|
113
|
+
# ]
|
114
|
+
# Oppen.print tokens:
|
115
|
+
#
|
116
|
+
# # =>
|
117
|
+
# # XXXXXXXXXX
|
118
|
+
#
|
119
|
+
# tokens = [
|
120
|
+
# Oppen::Token::Begin.new,
|
121
|
+
# Oppen::Token::String.new('XXXXXXXXXX'),
|
122
|
+
# Oppen::Token::End.new,
|
123
|
+
# Oppen::Token::Begin.new,
|
124
|
+
# Oppen::Token::String.new('YYYYYYYYYY'),
|
125
|
+
# Oppen::Token::End.new,
|
126
|
+
# Oppen::Token::EOF.new,
|
127
|
+
# ]
|
128
|
+
# Oppen.print tokens:
|
129
|
+
#
|
130
|
+
# # =>
|
131
|
+
# # XXXXXXXXXXYYYYYYYYYY
|
117
132
|
class EOF < Token
|
118
133
|
nil
|
119
134
|
end
|