mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
99 lines
3.2 KiB
Text
99 lines
3.2 KiB
Text
|
# MIT License
|
||
|
# See https://github.com/divoxx/ruby-php-serialization/blob/master/LICENSE.txt
|
||
|
|
||
|
class PhpSerialization::Unserializer
|
||
|
rule
|
||
|
|
||
|
data : null ';' { @object = val[0] }
|
||
|
| bool ';' { @object = val[0] }
|
||
|
| integer ';' { @object = val[0] }
|
||
|
| double ';' { @object = val[0] }
|
||
|
| string ';' { @object = val[0] }
|
||
|
| assoc_array { @object = val[0] }
|
||
|
| object { @object = val[0] }
|
||
|
;
|
||
|
|
||
|
null : 'N' { result = nil }
|
||
|
;
|
||
|
|
||
|
bool : 'b' ':' NUMBER { result = Integer(val[2]) > 0 }
|
||
|
;
|
||
|
|
||
|
integer : 'i' ':' NUMBER { result = Integer(val[2]) }
|
||
|
;
|
||
|
|
||
|
double : 'd' ':' NUMBER { result = Float(val[2]) }
|
||
|
;
|
||
|
|
||
|
string : 's' ':' NUMBER ':' STRING { result = val[4] }
|
||
|
;
|
||
|
|
||
|
object : 'O' ':' NUMBER ':' STRING ':' NUMBER ':' '{' attribute_list '}'
|
||
|
{
|
||
|
if eval("defined?(#{val[4]})")
|
||
|
result = Object.const_get(val[4]).new
|
||
|
|
||
|
val[9].each do |(attr_name, value)|
|
||
|
# Protected and private attributes will have a \0..\0 prefix
|
||
|
attr_name = attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
||
|
result.instance_variable_set("@#{attr_name}", value)
|
||
|
end
|
||
|
else
|
||
|
klass_name = val[4].gsub(/^Struct::/, '')
|
||
|
attr_names, values = [], []
|
||
|
|
||
|
val[9].each do |(attr_name, value)|
|
||
|
# Protected and private attributes will have a \0..\0 prefix
|
||
|
attr_names << attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
||
|
values << value
|
||
|
end
|
||
|
|
||
|
result = Struct.new(klass_name, *attr_names).new(*values)
|
||
|
result.instance_variable_set("@_php_class", klass_name)
|
||
|
end
|
||
|
}
|
||
|
;
|
||
|
|
||
|
attribute_list : attribute_list attribute { result = val[0] << val[1] }
|
||
|
| { result = [] }
|
||
|
;
|
||
|
|
||
|
attribute : data data { result = val }
|
||
|
;
|
||
|
|
||
|
assoc_array : 'a' ':' NUMBER ':' '{' attribute_list '}'
|
||
|
{
|
||
|
# Checks if the keys are a sequence of integers
|
||
|
idx = -1
|
||
|
arr = val[5].all? { |(k,v)| k == (idx += 1) }
|
||
|
|
||
|
if arr
|
||
|
result = val[5].map { |(k,v)| v }
|
||
|
else
|
||
|
result = Hash[val[5]]
|
||
|
end
|
||
|
}
|
||
|
;
|
||
|
|
||
|
end
|
||
|
|
||
|
---- header ----
|
||
|
require 'php_serialization/tokenizer'
|
||
|
|
||
|
---- inner ----
|
||
|
def initialize(tokenizer_klass = Tokenizer)
|
||
|
@tokenizer_klass = tokenizer_klass
|
||
|
end
|
||
|
|
||
|
def run(string)
|
||
|
@tokenizer = @tokenizer_klass.new(string)
|
||
|
yyparse(@tokenizer, :each)
|
||
|
return @object
|
||
|
ensure
|
||
|
@tokenizer = nil
|
||
|
end
|
||
|
|
||
|
def next_token
|
||
|
@tokenizer.next_token
|
||
|
end
|