# HG changeset patch # User Thinker K.F. Li # Date 1308182630 -28800 # Node ID aa05cc7ccd0d7431946cbafa4285511db7b94914 # Parent 0766bd54c9d3ec37f3f52e84e98f25998a316ca7 Serious implementation for parsing predicates in structpath.py diff -r 0766bd54c9d3 -r aa05cc7ccd0d paraspace/structpath.py --- a/paraspace/structpath.py Wed Jun 15 22:16:00 2011 +0800 +++ b/paraspace/structpath.py Thu Jun 16 08:03:50 2011 +0800 @@ -53,6 +53,7 @@ STATE_STR_SQ = 2 STATE_STR_DQ = 3 STATE_BKSP = 4 +STATE_STOP = 5 def _path_split(path): stk = [] @@ -128,6 +129,91 @@ return parts +def _path_parse_preds(path): + stk = [] + idx = 0 + state = STATE_START + name = None + preds = [] + while True: + mo = _reo_nest_chars.search(path, idx) + + if mo == None: + break + + ch = mo.group() + idx = mo.end() + if state in (STATE_START, STATE_STOP): + if ch == '[': + name = path[:idx - 1] + left = idx + stk.append(STATE_STOP) + state = STATE_PRED + elif ch == '\'': + stk.append(state) + state = STATE_STR_SQ + elif ch == '"': + stk.append(state) + state = STATE_STR_DQ + pass + else: + raise ValueError, 'invalid structpath string' + pass + elif state == STATE_STR_SQ: + if ch == '\'': + state = stk.pop() + pass + elif ch == '\\': + stk.append(state) + state = STATE_BKSP + bksp_idx = idx + pass + pass + elif state == STATE_STR_DQ: + if ch == '"': + state = stk.pop() + elif ch == '\\': + stk.append(state) + state = STATE_BKSP + bksp_idx = idx + pass + pass + elif state == STATE_PRED: + if ch == '[': + stk.append(state) + state = STATE_PRED + elif ch == '\'': + stk.append(state) + state = STATE_STR_SQ + elif ch == '"': + stk.append(state) + state = STATE_STR_DQ + elif ch == ']': + state = stk.pop() + if state == STATE_STOP: + preds.append(path[left:idx - 1]) + pass + pass + pass + elif state == STATE_BKSP: + if idx != (bksp_idx + 1): + idx = mo.start() + pass + state = stk.pop() + pass + pass + + if state not in (STATE_START, STATE_STOP): + raise ValueError, 'invalid structpath string' + if state == STATE_STOP and idx != len(path): + raise ValueError, 'invalid structpath string' + if state == STATE_START: + name = path + pass + + return name, preds + + def _is_abs(path_parts): if len(path_parts) == 0: return False @@ -150,15 +236,7 @@ return part == '..' -def _split_attr_pred(part): - try: - lq_idx = part.index('[') - except: - return part, '' - return part[:lq_idx].strip(), part[lq_idx:].strip() - - -def _eval_obj_sub_pred(ctx, obj, sub_pred): +def _eval_obj_pred(ctx, obj, pred): ns_global = {} for attr in dir(obj): if attr.startswith('_'): @@ -167,24 +245,16 @@ ns_global[attr] = v pass - truth_v = eval(sub_pred, ns_global) + truth_v = eval(pred, ns_global) return truth_v -def _split_pred_into_subs(pred): - striped_pred = pred.strip(' []\n\r') - subs = striped_pred.split('][') - return subs - - -def _eval_obj_pred(ctx, obj, pred): - subs = _split_pred_into_subs(pred) - - for sub in subs: - if not sub: +def _eval_obj_preds(ctx, obj, preds): + for pred in preds: + if not pred: continue - if not _eval_obj_sub_pred(ctx, obj, sub): + if not _eval_obj_pred(ctx, obj, pred): return False pass return True @@ -213,7 +283,7 @@ def _handle_path_part_obj(ctx, part, obj): - attr, pred = _split_attr_pred(part) + attr, preds = _path_parse_preds(part) if _is_parent_name(attr): new_objs = [ctx.get_parent(obj)] @@ -227,7 +297,7 @@ return [] pass - new_objs = filter((lambda x: _eval_obj_pred(ctx, x, pred)), new_objs) + new_objs = filter((lambda x: _eval_obj_preds(ctx, x, preds)), new_objs) return new_objs