用了3小时写的:
<?php
class ReadMYDict {
private $str;
private $read_offset;
private $keywords;
private $acceptable_integer_chars;
function __construct($input_str) {
$this->str = $input_str;
$this->read_offset = 0;
$this->keywords = array(',', '"', '\'', '(', ')', '[', ']', '{', '}');
$this->acceptable_integer_chars = explode(' ', '1 2 3 4 5 6 7 8 9 0');
$this->len = strlen($input_str);
}
public function parse() {
switch ($this->str[0]) {
case '[':
return $this->read_dict();
case '(':
return $this->read_list();
default:
throw new Exception('Not a valid PythonDict.');
return NULL;
}
}
private function read_integer() {
$ret_val = '';
while ($this->read_offset < $this->len) {
$char = $this->str[$this->read_offset];
if (in_array($char, $this->acceptable_integer_chars)) $ret_val .= $char;
else break;
$this->read_offset++;
}
if (!strlen($ret_val)) {
throw new Exception('Cannot parse integer on char.'.$this->read_offset);
return NULL;
}
return intval($ret_val);
}
private function read_string() {
$ret_val = '';
$read_end_char = $this->str[$this->read_offset];
if (!in_array($read_end_char, array('"', '\''))) {
throw new Exception('Unexcepted char.'.$this->read_offset);
return NULL;
}
while ($this->read_offset < $this->len - 1) {
$this->read_offset++;
$char = $this->str[$this->read_offset];
if ($char === $read_end_char) {
$this->read_offset++;
break;
}
$ret_val .= $char;
}
return $ret_val;
}
private function read_list() {
$ret_val = array();
if (!in_array($this->str[$this->read_offset], array('(', '{'))) {
throw new Exception('Unexcepted char.'.$this->read_offset);
return NULL;
}
$this->read_offset++;
while ($this->read_offset < $this->len) {
$next_char = $this->str[$this->read_offset];
if (trim($next_char) === '') {
$this->read_offset++;
continue;
}
if (in_array($next_char, $this->acceptable_integer_chars)) {
$next = $this->read_integer();
if ($next === NULL) return;
$ret_val[] = $next;
} elseif (in_array($next_char, array('"', '\''))) {
$next = $this->read_string();
if ($next === NULL) return;
$ret_val[] = $next;
} elseif (in_array($next_char, array('(', '{'))) {
$next = $this->read_list();
if ($next === NULL) return;
$ret_val[] = $next;
} elseif ($next_char === '[') {
$next = $this->read_dict();
if ($next === NULL) return;
$ret_val[] = $next;
} elseif ($next_char === ',') {
$this->read_offset++;
} elseif (in_array($next_char, array(')', '}'))) {
$this->read_offset++;
break;
} else {
throw new Exception('Unexcepted char.'.$this->read_offset);
return NULL;
}
}
return $ret_val;
}
private function read_dict() {
$ret_val = array();
if ($this->str[$this->read_offset] !== '[') {
throw new Exception('Unexcepted char.'.$this->read_offset);
return NULL;
}
$reading_title = TRUE;
$this->read_offset++;
$title = '';
while ($this->read_offset < $this->len) {
$next_char = $this->str[$this->read_offset];
if (trim($next_char) === '') {
$this->read_offset++;
continue;
}
if (in_array($next_char, $this->acceptable_integer_chars)) {
$next = $this->read_integer();
if ($next === NULL) return;
if ($reading_title) $title = $next;
else $ret_val[$title] = $next;
$reading_title = !$reading_title;
} elseif (in_array($next_char, array('"', '\''))) {
$next = $this->read_string();
if ($next === NULL) return;
if ($reading_title) $title = $next;
else $ret_val[$title] = $next;
$reading_title = !$reading_title;
} elseif (in_array($next_char, array('(', '{'))) {
$next = $this->read_list();
if ($next === NULL) return;
if ($reading_title) $title = $next;
else $ret_val[$title] = $next;
$reading_title = !$reading_title;
} elseif ($next_char === '[') {
$next = $this->read_dict();
if ($next === NULL) return;
if ($reading_title) $title = $next;
else $ret_val[$title] = $next;
$reading_title = !$reading_title;
} elseif ($next_char === ',') {
$this->read_offset++;
$reading_title = TRUE;
} elseif ($next_char === ']') {
$this->read_offset++;
break;
} elseif ($next_char === ':') {
$this->read_offset++;
$reading_title = FALSE;
} else {
throw new Exception('Unexcepted char.'.$this->read_offset);
return NULL;
}
}
return $ret_val;
}
}
$a = '(([90102:(["time":1511122453,"progress":79,]),90103:(["time":1509633774,"progress":2,]),60413:(["time":1511122445,"progress":0,]),60414:(["time":1511122445,"progress":0,]),60415:(["time":1511122445,"progress":0,]),90104:(["time":1510312173,"progress":1,]),"ver":1,20406:(["time":1507992271,"finished":1,]),20407:(["para":(["ti":594,]),"time":1511025692,"progress":64,]),51101:(["para":(["ti":906,]),"time":1511032636,"progress":238,]),51102:(["time":1507137233,"progress":0,]),51103:(["time":1507137233,"progress":0,]),51011:(["time":1510312173,"progress":1,]),51010:(["time":1510312173,"finished":1,]),20218:(["time":1509467678,"finished":1,]),20219:(["time":1509467965,"finished":1,]),20221:(["time":1509468024,"finished":1,]),20222:(["time":1509468030,"finished":1,]),20210:(["time":1511023570,"finished":1,]),20211:(["time":1511023578,"finished":1,]),20207:(["time":1511023538,"finished":1,]),50912:(["time":1511022575,"progress":1,]),80609:(["time":1510150701,"finished":1,]),80622:(["time":1510150622,"progress":1,]),80608:(["time":1510150622,"finished":1,]),50911:(["time":1509635493,"finished":1,]),50910:(["time":1508151042,"finished":1,]),50909:(["time":1508151042,"finished":1,]),50906:(["time":1507890831,"finished":1,]),"traces":({}),20109:(["time":1510402286,"progress":0,]),20108:(["time":1510402286,"progress":0,]),80513:(["time":1508849461,"finished":1,]),80514:(["time":1508849461,"progress":1,]),20111:(["time":1509227248,"finished":1,]),"lastest":({50403,20211,20210,}),80406:(["time":1511122445,"progress":1,]),80405:(["time":1511122445,"progress":1,]),80404:(["time":1511122445,"progress":1,]),30211:(["para":2,"time":1509021407,"progress":1,]),30213:(["time":1509226792,"finished":1,]),30201:(["time":1509021407,"finished":1,]),30207:(["time":1509467600,"finished":1,]),70113:(["failed":1,"time":1508150640,]),"update_ti":1511122445,90602:(["time":1509227628,"finished":1,]),70110:(["failed":1,"time":1508150640,]),80325:(["time":1508689999,"finished":1,]),30154:(["time":1508357218,"finished":1,]),30144:(["time":1508357214,"finished":1,]),30147:(["time":1509399083,"finished":1,]),30139:(["time":1508357214,"finished":1,]),80317:(["time":1507829680,"finished":1,]),80318:(["time":1507829680,"finished":1,]),30134:(["time":1508776731,"finished":1,]),30135:(["time":1508776731,"finished":1,]),30136:(["time":1508776731,"finished":1,]),30137:(["time":1508776731,"finished":1,]),30138:(["time":1508776731,"finished":1,]),30132:(["time":1509399083,"finished":1,]),30140:(["time":1509399083,"finished":1,]),30114:(["time":1507902017,"finished":1,]),30115:(["time":1508776919,"finished":1,]),30107:(["time":1507902017,"finished":1,]),30101:(["time":1507902017,"finished":1,]),30111:(["time":1508357214,"finished":1,]),30103:(["time":1508357218,"finished":1,]),30102:(["time":1508357390,"finished":1,]),51504:(["time":1510651636,"finished":1,]),51505:(["time":1510651636,"finished":1,]),"total":5183,51503:(["time":1507893961,"finished":1,]),51502:(["time":1507893961,"finished":1,]),51501:(["time":1507893961,"finished":1,]),10505:(["time":1511122445,"progress":0,]),10506:(["time":1511122445,"progress":0,]),40206:(["para":([]),"time":1511122445,"progress":0,]),90336:(["time":1507829631,"finished":1,]),90348:(["time":1508151043,"finished":1,]),50403:(["time":1511024177,"finished":1,]),90322:(["time":1509209473,"finished":1,]),90331:(["time":1508150640,"finished":1,]),90333:(["time":1510652404,"finished":1,]),90315:(["time":1508149428,"finished":1,]),90316:(["time":1510650252,"progress":14,]),90313:(["time":1509227002,"finished":1,]),90314:(["time":1510402299,"progress":2,]),90301:(["time":1510650154,"finished":1,]),40105:(["time":1511122445,"progress":0,]),40106:(["time":1511122445,"progress":0,]),90228:(["time":1509021201,"progress":1,]),90215:(["time":1507890889,"finished":1,]),90217:(["time":1507890889,"finished":1,]),90216:(["time":1507890890,"finished":1,]),90218:(["time":1507890891,"finished":1,]),]))';
$b = new ReadMYDict($a);
print_r($b->parse());
好久没碰PHP了,都不太熟悉了。
输出示例: