X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=blockchain%2Fquery%2Ffilter%2Fparser.go;fp=blockchain%2Fquery%2Ffilter%2Fparser.go;h=0000000000000000000000000000000000000000;hp=eb2fc18a30addbd663a379a0b4732c720c14eb9f;hb=b72647ba6580dbedd557fa5b5b99a129438a6fc6;hpb=1005d5aeca37334f61be9ffb3631137eb7d6088d diff --git a/blockchain/query/filter/parser.go b/blockchain/query/filter/parser.go deleted file mode 100644 index eb2fc18a..00000000 --- a/blockchain/query/filter/parser.go +++ /dev/null @@ -1,260 +0,0 @@ -package filter - -import ( - "fmt" - "strconv" - - "github.com/vapor/errors" -) - -// ErrBadFilter is returned from Parse when -// it encounters an invalid filter expression. -var ErrBadFilter = errors.New("invalid query filter") - -// Predicate represents a parsed filter predicate. -type Predicate struct { - expr expr - selectorTypes map[string]Type - Parameters int -} - -// String returns a cleaned, canonical representation of the -// predicate. -func (p Predicate) String() string { - if p.expr == nil { - return "" - } - return p.expr.String() -} - -// MarshalText implements the encoding.TextMarshaler interface and -// returns a cleaned, canonical representation of the predicate. -func (p Predicate) MarshalText() ([]byte, error) { - return []byte(p.expr.String()), nil -} - -// Parse parses a predicate and returns an internal representation of the -// predicate or an error if it fails to parse. -func Parse(predicate string, tbl *Table, vals []interface{}) (p Predicate, err error) { - expr, parser, err := parse(predicate) - if err != nil { - return p, errors.WithDetail(ErrBadFilter, err.Error()) - } - selectorTypes, err := typeCheck(expr, tbl, vals) - if err != nil { - return p, errors.WithDetail(ErrBadFilter, err.Error()) - } - - return Predicate{ - expr: expr, - selectorTypes: selectorTypes, - Parameters: parser.maxPlaceholder, - }, nil -} - -// Field is a type for simple expressions that simply access an attribute of -// the queried object. They're used for GROUP BYs. -type Field struct { - expr expr -} - -func (f Field) String() string { - return f.expr.String() -} - -// ParseField parses a field expression (either an attrExpr or a selectorExpr). -func ParseField(s string) (f Field, err error) { - expr, _, err := parse(s) - if err != nil { - return f, errors.WithDetail(ErrBadFilter, err.Error()) - } - if expr == nil { - return f, errors.WithDetail(ErrBadFilter, "empty field expression") - } - - switch expr.(type) { - case attrExpr, selectorExpr: - return Field{expr: expr}, nil - default: - return f, errors.WithDetailf(ErrBadFilter, "%q is not a valid field expression", s) - } -} - -func parse(exprString string) (expr expr, parser *parser, err error) { - defer func() { - r := recover() - if perr, ok := r.(parseError); ok { - err = perr - } else if r != nil { - panic(r) - } - }() - parser = newParser([]byte(exprString)) - - // An empty expression is a valid predicate. - if parser.tok == tokEOF { - return nil, parser, nil - } - - expr = parseExpr(parser) - parser.parseTok(tokEOF) - return expr, parser, err -} - -func newParser(src []byte) *parser { - p := new(parser) - p.scanner.init(src) - p.next() // advance onto the first input token - return p -} - -// The parser structure holds the parser's internal state. -type parser struct { - scanner scanner - - maxPlaceholder int - - // Current token - pos int // token position - tok token // one token look-ahead - lit string // token literal -} - -func determineBinaryOp(p *parser, minPrecedence int) (op *binaryOp, ok bool) { - op, ok = binaryOps[p.lit] - return op, ok && op.precedence >= minPrecedence -} - -// next advances to the next token. -func (p *parser) next() { - p.pos, p.tok, p.lit = p.scanner.Scan() -} - -func (p *parser) parseLit(lit string) { - if p.lit != lit { - p.errorf("got %s, expected %s", p.lit, lit) - } - p.next() -} - -func (p *parser) parseTok(tok token) { - if p.tok != tok { - p.errorf("got %s, expected %s", p.lit, tok.String()) - } - p.next() -} - -func parseExpr(p *parser) expr { - // Uses the precedence-climbing algorithm: - // https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method - expr := parsePrimaryExpr(p) - return parseExprCont(p, expr, 0) -} - -func parseExprCont(p *parser, lhs expr, minPrecedence int) expr { - for { - op, ok := determineBinaryOp(p, minPrecedence) - if !ok { - break - } - p.next() - - rhs := parsePrimaryExpr(p) - - for { - op2, ok := determineBinaryOp(p, op.precedence+1) - if !ok { - break - } - rhs = parseExprCont(p, rhs, op2.precedence) - } - lhs = binaryExpr{l: lhs, r: rhs, op: op} - } - return lhs -} - -func parsePrimaryExpr(p *parser) expr { - x := parseOperand(p) - for p.lit == "." { - x = parseSelectorExpr(p, x) - } - return x -} - -func parseOperand(p *parser) expr { - switch { - case p.lit == "(": - p.next() - expr := parseExpr(p) - p.parseLit(")") - return parenExpr{inner: expr} - case p.tok == tokString: - v := valueExpr{typ: p.tok, value: p.lit} - p.next() - return v - case p.tok == tokInteger: - // Parse the literal into an integer so that we store the string - // representation of the *decimal* value, never the hex. - integer, err := strconv.ParseInt(p.lit, 0, 64) - if err != nil { - // can't happen; scanner guarantees it - p.errorf("invalid integer: %q", p.lit) - } - v := valueExpr{typ: p.tok, value: strconv.Itoa(int(integer))} - p.next() - return v - case p.tok == tokPlaceholder: - num, err := strconv.Atoi(p.lit[1:]) - if err != nil || num <= 0 { - p.errorf("invalid placeholder: %q", p.lit) - } - v := placeholderExpr{num: num} - p.next() - - if num > p.maxPlaceholder { - p.maxPlaceholder = num - } - return v - default: - return parseEnvironmentExpr(p) - } -} - -func parseSelectorExpr(p *parser, objExpr expr) expr { - p.next() // move past the '.' - - ident := p.lit - p.parseTok(tokIdent) - return selectorExpr{ - ident: ident, - objExpr: objExpr, - } -} - -func parseEnvironmentExpr(p *parser) expr { - name := p.lit - p.parseTok(tokIdent) - if p.lit != "(" { - return attrExpr{attr: name} - } - p.next() - expr := parseExpr(p) - p.parseLit(")") - return envExpr{ - ident: name, - expr: expr, - } -} - -type parseError struct { - pos int - msg string -} - -func (err parseError) Error() string { - return fmt.Sprintf("col %d: %s", err.pos, err.msg) -} - -func (p *parser) errorf(format string, args ...interface{}) { - panic(parseError{pos: p.pos, msg: fmt.Sprintf(format, args...)}) -}