psych 2.0.14-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +18 -0
  3. data/.gemtest +0 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.rdoc +576 -0
  6. data/Manifest.txt +114 -0
  7. data/README.rdoc +71 -0
  8. data/Rakefile +123 -0
  9. data/ext/psych/depend +3 -0
  10. data/ext/psych/extconf.rb +38 -0
  11. data/ext/psych/psych.c +34 -0
  12. data/ext/psych/psych.h +20 -0
  13. data/ext/psych/psych_emitter.c +555 -0
  14. data/ext/psych/psych_emitter.h +8 -0
  15. data/ext/psych/psych_parser.c +597 -0
  16. data/ext/psych/psych_parser.h +6 -0
  17. data/ext/psych/psych_to_ruby.c +43 -0
  18. data/ext/psych/psych_to_ruby.h +8 -0
  19. data/ext/psych/psych_yaml_tree.c +24 -0
  20. data/ext/psych/psych_yaml_tree.h +8 -0
  21. data/ext/psych/yaml/LICENSE +19 -0
  22. data/ext/psych/yaml/api.c +1415 -0
  23. data/ext/psych/yaml/config.h +10 -0
  24. data/ext/psych/yaml/dumper.c +394 -0
  25. data/ext/psych/yaml/emitter.c +2329 -0
  26. data/ext/psych/yaml/loader.c +459 -0
  27. data/ext/psych/yaml/parser.c +1370 -0
  28. data/ext/psych/yaml/reader.c +469 -0
  29. data/ext/psych/yaml/scanner.c +3576 -0
  30. data/ext/psych/yaml/writer.c +141 -0
  31. data/ext/psych/yaml/yaml.h +1971 -0
  32. data/ext/psych/yaml/yaml_private.h +664 -0
  33. data/lib/psych.jar +0 -0
  34. data/lib/psych.rb +504 -0
  35. data/lib/psych/class_loader.rb +101 -0
  36. data/lib/psych/coder.rb +94 -0
  37. data/lib/psych/core_ext.rb +35 -0
  38. data/lib/psych/deprecated.rb +85 -0
  39. data/lib/psych/exception.rb +13 -0
  40. data/lib/psych/handler.rb +249 -0
  41. data/lib/psych/handlers/document_stream.rb +22 -0
  42. data/lib/psych/handlers/recorder.rb +39 -0
  43. data/lib/psych/json/ruby_events.rb +19 -0
  44. data/lib/psych/json/stream.rb +16 -0
  45. data/lib/psych/json/tree_builder.rb +12 -0
  46. data/lib/psych/json/yaml_events.rb +29 -0
  47. data/lib/psych/nodes.rb +77 -0
  48. data/lib/psych/nodes/alias.rb +18 -0
  49. data/lib/psych/nodes/document.rb +60 -0
  50. data/lib/psych/nodes/mapping.rb +56 -0
  51. data/lib/psych/nodes/node.rb +55 -0
  52. data/lib/psych/nodes/scalar.rb +67 -0
  53. data/lib/psych/nodes/sequence.rb +81 -0
  54. data/lib/psych/nodes/stream.rb +37 -0
  55. data/lib/psych/omap.rb +4 -0
  56. data/lib/psych/parser.rb +51 -0
  57. data/lib/psych/scalar_scanner.rb +149 -0
  58. data/lib/psych/set.rb +4 -0
  59. data/lib/psych/stream.rb +37 -0
  60. data/lib/psych/streaming.rb +27 -0
  61. data/lib/psych/syntax_error.rb +21 -0
  62. data/lib/psych/tree_builder.rb +96 -0
  63. data/lib/psych/versions.rb +3 -0
  64. data/lib/psych/visitors.rb +6 -0
  65. data/lib/psych/visitors/depth_first.rb +26 -0
  66. data/lib/psych/visitors/emitter.rb +51 -0
  67. data/lib/psych/visitors/json_tree.rb +24 -0
  68. data/lib/psych/visitors/to_ruby.rb +404 -0
  69. data/lib/psych/visitors/visitor.rb +19 -0
  70. data/lib/psych/visitors/yaml_tree.rb +605 -0
  71. data/lib/psych/y.rb +9 -0
  72. data/lib/psych_jars.rb +5 -0
  73. data/test/psych/handlers/test_recorder.rb +25 -0
  74. data/test/psych/helper.rb +121 -0
  75. data/test/psych/json/test_stream.rb +109 -0
  76. data/test/psych/nodes/test_enumerable.rb +43 -0
  77. data/test/psych/test_alias_and_anchor.rb +96 -0
  78. data/test/psych/test_array.rb +57 -0
  79. data/test/psych/test_boolean.rb +36 -0
  80. data/test/psych/test_class.rb +36 -0
  81. data/test/psych/test_coder.rb +206 -0
  82. data/test/psych/test_date_time.rb +38 -0
  83. data/test/psych/test_deprecated.rb +214 -0
  84. data/test/psych/test_document.rb +46 -0
  85. data/test/psych/test_emitter.rb +93 -0
  86. data/test/psych/test_encoding.rb +259 -0
  87. data/test/psych/test_exception.rb +157 -0
  88. data/test/psych/test_hash.rb +94 -0
  89. data/test/psych/test_json_tree.rb +65 -0
  90. data/test/psych/test_merge_keys.rb +180 -0
  91. data/test/psych/test_nil.rb +18 -0
  92. data/test/psych/test_null.rb +19 -0
  93. data/test/psych/test_numeric.rb +45 -0
  94. data/test/psych/test_object.rb +44 -0
  95. data/test/psych/test_object_references.rb +71 -0
  96. data/test/psych/test_omap.rb +75 -0
  97. data/test/psych/test_parser.rb +339 -0
  98. data/test/psych/test_psych.rb +168 -0
  99. data/test/psych/test_safe_load.rb +97 -0
  100. data/test/psych/test_scalar.rb +11 -0
  101. data/test/psych/test_scalar_scanner.rb +106 -0
  102. data/test/psych/test_serialize_subclasses.rb +38 -0
  103. data/test/psych/test_set.rb +49 -0
  104. data/test/psych/test_stream.rb +93 -0
  105. data/test/psych/test_string.rb +226 -0
  106. data/test/psych/test_struct.rb +49 -0
  107. data/test/psych/test_symbol.rb +25 -0
  108. data/test/psych/test_tainted.rb +130 -0
  109. data/test/psych/test_to_yaml_properties.rb +63 -0
  110. data/test/psych/test_tree_builder.rb +79 -0
  111. data/test/psych/test_yaml.rb +1292 -0
  112. data/test/psych/test_yamldbm.rb +193 -0
  113. data/test/psych/test_yamlstore.rb +85 -0
  114. data/test/psych/visitors/test_depth_first.rb +49 -0
  115. data/test/psych/visitors/test_emitter.rb +144 -0
  116. data/test/psych/visitors/test_to_ruby.rb +333 -0
  117. data/test/psych/visitors/test_yaml_tree.rb +173 -0
  118. metadata +240 -0
@@ -0,0 +1,81 @@
1
+ module Psych
2
+ module Nodes
3
+ ###
4
+ # This class represents a
5
+ # {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
6
+ #
7
+ # A YAML sequence is basically a list, and looks like this:
8
+ #
9
+ # %YAML 1.1
10
+ # ---
11
+ # - I am
12
+ # - a Sequence
13
+ #
14
+ # A YAML sequence may have an anchor like this:
15
+ #
16
+ # %YAML 1.1
17
+ # ---
18
+ # &A [
19
+ # "This sequence",
20
+ # "has an anchor"
21
+ # ]
22
+ #
23
+ # A YAML sequence may also have a tag like this:
24
+ #
25
+ # %YAML 1.1
26
+ # ---
27
+ # !!seq [
28
+ # "This sequence",
29
+ # "has a tag"
30
+ # ]
31
+ #
32
+ # This class represents a sequence in a YAML document. A
33
+ # Psych::Nodes::Sequence node may have 0 or more children. Valid children
34
+ # for this node are:
35
+ #
36
+ # * Psych::Nodes::Sequence
37
+ # * Psych::Nodes::Mapping
38
+ # * Psych::Nodes::Scalar
39
+ # * Psych::Nodes::Alias
40
+ class Sequence < Psych::Nodes::Node
41
+ # Any Styles, emitter chooses
42
+ ANY = 0
43
+
44
+ # Block style sequence
45
+ BLOCK = 1
46
+
47
+ # Flow style sequence
48
+ FLOW = 2
49
+
50
+ # The anchor for this sequence (if any)
51
+ attr_accessor :anchor
52
+
53
+ # The tag name for this sequence (if any)
54
+ attr_accessor :tag
55
+
56
+ # Is this sequence started implicitly?
57
+ attr_accessor :implicit
58
+
59
+ # The sequence style used
60
+ attr_accessor :style
61
+
62
+ ###
63
+ # Create a new object representing a YAML sequence.
64
+ #
65
+ # +anchor+ is the anchor associated with the sequence or nil.
66
+ # +tag+ is the tag associated with the sequence or nil.
67
+ # +implicit+ a boolean indicating whether or not the sequence was
68
+ # implicitly started.
69
+ # +style+ is an integer indicating the list style.
70
+ #
71
+ # See Psych::Handler#start_sequence
72
+ def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
73
+ super()
74
+ @anchor = anchor
75
+ @tag = tag
76
+ @implicit = implicit
77
+ @style = style
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ module Psych
2
+ module Nodes
3
+ ###
4
+ # Represents a YAML stream. This is the root node for any YAML parse
5
+ # tree. This node must have one or more child nodes. The only valid
6
+ # child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
7
+ class Stream < Psych::Nodes::Node
8
+
9
+ # Encodings supported by Psych (and libyaml)
10
+
11
+ # Any encoding
12
+ ANY = Psych::Parser::ANY
13
+
14
+ # UTF-8 encoding
15
+ UTF8 = Psych::Parser::UTF8
16
+
17
+ # UTF-16LE encoding
18
+ UTF16LE = Psych::Parser::UTF16LE
19
+
20
+ # UTF-16BE encoding
21
+ UTF16BE = Psych::Parser::UTF16BE
22
+
23
+ # The encoding used for this stream
24
+ attr_accessor :encoding
25
+
26
+ ###
27
+ # Create a new Psych::Nodes::Stream node with an +encoding+ that
28
+ # defaults to Psych::Nodes::Stream::UTF8.
29
+ #
30
+ # See also Psych::Handler#start_stream
31
+ def initialize encoding = UTF8
32
+ super()
33
+ @encoding = encoding
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/psych/omap.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Psych
2
+ class Omap < ::Hash
3
+ end
4
+ end
@@ -0,0 +1,51 @@
1
+ module Psych
2
+ ###
3
+ # YAML event parser class. This class parses a YAML document and calls
4
+ # events on the handler that is passed to the constructor. The events can
5
+ # be used for things such as constructing a YAML AST or deserializing YAML
6
+ # documents. It can even be fed back to Psych::Emitter to emit the same
7
+ # document that was parsed.
8
+ #
9
+ # See Psych::Handler for documentation on the events that Psych::Parser emits.
10
+ #
11
+ # Here is an example that prints out ever scalar found in a YAML document:
12
+ #
13
+ # # Handler for detecting scalar values
14
+ # class ScalarHandler < Psych::Handler
15
+ # def scalar value, anchor, tag, plain, quoted, style
16
+ # puts value
17
+ # end
18
+ # end
19
+ #
20
+ # parser = Psych::Parser.new(ScalarHandler.new)
21
+ # parser.parse(yaml_document)
22
+ #
23
+ # Here is an example that feeds the parser back in to Psych::Emitter. The
24
+ # YAML document is read from STDIN and written back out to STDERR:
25
+ #
26
+ # parser = Psych::Parser.new(Psych::Emitter.new($stderr))
27
+ # parser.parse($stdin)
28
+ #
29
+ # Psych uses Psych::Parser in combination with Psych::TreeBuilder to
30
+ # construct an AST of the parsed YAML document.
31
+
32
+ class Parser
33
+ class Mark < Struct.new(:index, :line, :column)
34
+ end
35
+
36
+ # The handler on which events will be called
37
+ attr_accessor :handler
38
+
39
+ # Set the encoding for this parser to +encoding+
40
+ attr_writer :external_encoding
41
+
42
+ ###
43
+ # Creates a new Psych::Parser instance with +handler+. YAML events will
44
+ # be called on +handler+. See Psych::Parser for more details.
45
+
46
+ def initialize handler = Handler.new
47
+ @handler = handler
48
+ @external_encoding = ANY
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,149 @@
1
+ require 'strscan'
2
+
3
+ module Psych
4
+ ###
5
+ # Scan scalars for built in types
6
+ class ScalarScanner
7
+ # Taken from http://yaml.org/type/timestamp.html
8
+ TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
9
+
10
+ # Taken from http://yaml.org/type/float.html
11
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
12
+ |[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60)
13
+ |[-+]?\.(inf|Inf|INF)(?# infinity)
14
+ |\.(nan|NaN|NAN)(?# not a number))$/x
15
+
16
+ # Taken from http://yaml.org/type/int.html
17
+ INTEGER = /^(?:[-+]?0b[0-1_]+ (?# base 2)
18
+ |[-+]?0[0-7_]+ (?# base 8)
19
+ |[-+]?(?:0|[1-9][0-9_]*) (?# base 10)
20
+ |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
21
+
22
+ attr_reader :class_loader
23
+
24
+ # Create a new scanner
25
+ def initialize class_loader
26
+ @string_cache = {}
27
+ @symbol_cache = {}
28
+ @class_loader = class_loader
29
+ end
30
+
31
+ # Tokenize +string+ returning the Ruby object
32
+ def tokenize string
33
+ return nil if string.empty?
34
+ return string if @string_cache.key?(string)
35
+ return @symbol_cache[string] if @symbol_cache.key?(string)
36
+
37
+ case string
38
+ # Check for a String type, being careful not to get caught by hash keys, hex values, and
39
+ # special floats (e.g., -.inf).
40
+ when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/, /\n/
41
+ if string.length > 5
42
+ @string_cache[string] = true
43
+ return string
44
+ end
45
+
46
+ case string
47
+ when /^[^ytonf~]/i
48
+ @string_cache[string] = true
49
+ string
50
+ when '~', /^null$/i
51
+ nil
52
+ when /^(yes|true|on)$/i
53
+ true
54
+ when /^(no|false|off)$/i
55
+ false
56
+ else
57
+ @string_cache[string] = true
58
+ string
59
+ end
60
+ when TIME
61
+ begin
62
+ parse_time string
63
+ rescue ArgumentError
64
+ string
65
+ end
66
+ when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
67
+ require 'date'
68
+ begin
69
+ class_loader.date.strptime(string, '%Y-%m-%d')
70
+ rescue ArgumentError
71
+ string
72
+ end
73
+ when /^\.inf$/i
74
+ Float::INFINITY
75
+ when /^-\.inf$/i
76
+ -Float::INFINITY
77
+ when /^\.nan$/i
78
+ Float::NAN
79
+ when /^:./
80
+ if string =~ /^:(["'])(.*)\1/
81
+ @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
82
+ else
83
+ @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
84
+ end
85
+ when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
86
+ i = 0
87
+ string.split(':').each_with_index do |n,e|
88
+ i += (n.to_i * 60 ** (e - 2).abs)
89
+ end
90
+ i
91
+ when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/
92
+ i = 0
93
+ string.split(':').each_with_index do |n,e|
94
+ i += (n.to_f * 60 ** (e - 2).abs)
95
+ end
96
+ i
97
+ when FLOAT
98
+ if string =~ /\A[-+]?\.\Z/
99
+ @string_cache[string] = true
100
+ string
101
+ else
102
+ Float(string.gsub(/[,_]|\.$/, ''))
103
+ end
104
+ else
105
+ int = parse_int string.gsub(/[,_]/, '')
106
+ return int if int
107
+
108
+ @string_cache[string] = true
109
+ string
110
+ end
111
+ end
112
+
113
+ ###
114
+ # Parse and return an int from +string+
115
+ def parse_int string
116
+ return unless INTEGER === string
117
+ Integer(string)
118
+ end
119
+
120
+ ###
121
+ # Parse and return a Time from +string+
122
+ def parse_time string
123
+ klass = class_loader.load 'Time'
124
+
125
+ date, time = *(string.split(/[ tT]/, 2))
126
+ (yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i }
127
+ md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
128
+
129
+ (hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
130
+ us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000
131
+
132
+ time = klass.utc(yy, m, dd, hh, mm, ss, us)
133
+
134
+ return time if 'Z' == md[3]
135
+ return klass.at(time.to_i, us) unless md[3]
136
+
137
+ tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
138
+ offset = tz.first * 3600
139
+
140
+ if offset < 0
141
+ offset -= ((tz[1] || 0) * 60)
142
+ else
143
+ offset += ((tz[1] || 0) * 60)
144
+ end
145
+
146
+ klass.at((time - offset).to_i, us)
147
+ end
148
+ end
149
+ end
data/lib/psych/set.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Psych
2
+ class Set < ::Hash
3
+ end
4
+ end
@@ -0,0 +1,37 @@
1
+ module Psych
2
+ ###
3
+ # Psych::Stream is a streaming YAML emitter. It will not buffer your YAML,
4
+ # but send it straight to an IO.
5
+ #
6
+ # Here is an example use:
7
+ #
8
+ # stream = Psych::Stream.new($stdout)
9
+ # stream.start
10
+ # stream.push({:foo => 'bar'})
11
+ # stream.finish
12
+ #
13
+ # YAML will be immediately emitted to $stdout with no buffering.
14
+ #
15
+ # Psych::Stream#start will take a block and ensure that Psych::Stream#finish
16
+ # is called, so you can do this form:
17
+ #
18
+ # stream = Psych::Stream.new($stdout)
19
+ # stream.start do |em|
20
+ # em.push(:foo => 'bar')
21
+ # end
22
+ #
23
+ class Stream < Psych::Visitors::YAMLTree
24
+ class Emitter < Psych::Emitter # :nodoc:
25
+ def end_document implicit_end = !streaming?
26
+ super
27
+ end
28
+
29
+ def streaming?
30
+ true
31
+ end
32
+ end
33
+
34
+ include Psych::Streaming
35
+ extend Psych::Streaming::ClassMethods
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module Psych
2
+ module Streaming
3
+ module ClassMethods
4
+ ###
5
+ # Create a new streaming emitter. Emitter will print to +io+. See
6
+ # Psych::Stream for an example.
7
+ def new io
8
+ emitter = const_get(:Emitter).new(io)
9
+ class_loader = ClassLoader.new
10
+ ss = ScalarScanner.new class_loader
11
+ super(emitter, ss, {})
12
+ end
13
+ end
14
+
15
+ ###
16
+ # Start streaming using +encoding+
17
+ def start encoding = Nodes::Stream::UTF8
18
+ super.tap { yield self if block_given? }
19
+ ensure
20
+ finish if block_given?
21
+ end
22
+
23
+ private
24
+ def register target, obj
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'psych/exception'
2
+
3
+ module Psych
4
+ class SyntaxError < Psych::Exception
5
+ attr_reader :file, :line, :column, :offset, :problem, :context
6
+
7
+ def initialize file, line, col, offset, problem, context
8
+ err = [problem, context].compact.join ' '
9
+ filename = file || '<unknown>'
10
+ message = "(%s): %s at line %d column %d" % [filename, err, line, col]
11
+
12
+ @file = file
13
+ @line = line
14
+ @column = col
15
+ @offset = offset
16
+ @problem = problem
17
+ @context = context
18
+ super(message)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,96 @@
1
+ require 'psych/handler'
2
+
3
+ module Psych
4
+ ###
5
+ # This class works in conjunction with Psych::Parser to build an in-memory
6
+ # parse tree that represents a YAML document.
7
+ #
8
+ # == Example
9
+ #
10
+ # parser = Psych::Parser.new Psych::TreeBuilder.new
11
+ # parser.parse('--- foo')
12
+ # tree = parser.handler.root
13
+ #
14
+ # See Psych::Handler for documentation on the event methods used in this
15
+ # class.
16
+ class TreeBuilder < Psych::Handler
17
+ # Returns the root node for the built tree
18
+ attr_reader :root
19
+
20
+ # Create a new TreeBuilder instance
21
+ def initialize
22
+ @stack = []
23
+ @last = nil
24
+ @root = nil
25
+ end
26
+
27
+ %w{
28
+ Sequence
29
+ Mapping
30
+ }.each do |node|
31
+ class_eval %{
32
+ def start_#{node.downcase}(anchor, tag, implicit, style)
33
+ n = Nodes::#{node}.new(anchor, tag, implicit, style)
34
+ @last.children << n
35
+ push n
36
+ end
37
+
38
+ def end_#{node.downcase}
39
+ pop
40
+ end
41
+ }
42
+ end
43
+
44
+ ###
45
+ # Handles start_document events with +version+, +tag_directives+,
46
+ # and +implicit+ styling.
47
+ #
48
+ # See Psych::Handler#start_document
49
+ def start_document version, tag_directives, implicit
50
+ n = Nodes::Document.new version, tag_directives, implicit
51
+ @last.children << n
52
+ push n
53
+ end
54
+
55
+ ###
56
+ # Handles end_document events with +version+, +tag_directives+,
57
+ # and +implicit+ styling.
58
+ #
59
+ # See Psych::Handler#start_document
60
+ def end_document implicit_end = !streaming?
61
+ @last.implicit_end = implicit_end
62
+ pop
63
+ end
64
+
65
+ def start_stream encoding
66
+ @root = Nodes::Stream.new(encoding)
67
+ push @root
68
+ end
69
+
70
+ def end_stream
71
+ pop
72
+ end
73
+
74
+ def scalar value, anchor, tag, plain, quoted, style
75
+ s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
76
+ @last.children << s
77
+ s
78
+ end
79
+
80
+ def alias anchor
81
+ @last.children << Nodes::Alias.new(anchor)
82
+ end
83
+
84
+ private
85
+ def push value
86
+ @stack.push value
87
+ @last = value
88
+ end
89
+
90
+ def pop
91
+ x = @stack.pop
92
+ @last = @stack.last
93
+ x
94
+ end
95
+ end
96
+ end