func (l *lex) parseAnds() (*Pred, error) { if l.debug { defer dbg.Trace(dbg.Call("ands")) } args := []*Pred{} a1, err := l.parsePrim() if err != nil { return nil, err } args = append(args, a1) for { op, _, err := l.peek() if err!=nil || op!=tAnd { if err==io.EOF || op==tRpar || op==tOr { err = nil } if len(args) == 1 { return args[0], err } return &Pred{op: oAnd, args: args}, err } l.scan() a, err := l.parsePrim() if err != nil { return nil, err } args = append(args, a) } }
/* prim ::= prune | t | true | f | false | name op name | unop prim | maxmin name | n | ( ors ) but handle ~ str as meaning "name~str" */ func (l *lex) parsePrim() (*Pred, error) { if l.debug { defer dbg.Trace(dbg.Call("prim")) } t, _, err := l.peek() if err != nil { return nil, err } switch { case t == tPrune, t == tTrue, t == tFalse: l.scan() return &Pred{op: op(t)}, nil case t==tMatch || t==tEqs || t==tRexp: // unary usage assumes path op ... l.scan() t2, v2, err := l.scan() if err!=nil || t2.class()!=cName { return nil, errors.New("name expected") } return &Pred{op: op(t), name: "path", value: v2}, nil case t == tName: _, v1, _ := l.scan() if v1 == "d" || v1 == "-" || v1 == "c" { // d/-/c -> type = d/-/c return &Pred{op: oEqs, name: "type", value: v1}, nil } _, err := strconv.Atoi(v1) if err == nil { // n -> depth<=n return &Pred{op: oLe, name: "depth", value: v1}, nil } x, _, err := l.scan() if err!=nil || x.class()!=cOp { return nil, errors.New("op expected") } t2, v2, err := l.scan() if err!=nil || t2.class()!=cName { return nil, errors.New("name expected") } return &Pred{op: op(x), name: v1, value: v2}, nil case t.class() == cUn: l.scan() arg, err := l.parsePrim() if err != nil { return nil, err } return &Pred{op: op(t), args: []*Pred{arg}}, nil case t == tLpar: l.scan() arg, err := l.parseOrs() if err != nil { return nil, err } r, _, err := l.scan() if err!=nil || r!=tRpar { return nil, errors.New("')' expected") } return arg, nil } return nil, errors.New("not a primary expression") }