diff --git a/filter/eval.go b/filter/eval.go index 11e9e8e..c6c2bac 100644 --- a/filter/eval.go +++ b/filter/eval.go @@ -23,80 +23,80 @@ func Eval(basenode *TreeNode, context map[string]string, queryGame string) (valu } }() - this := &expression{basenode, context, queryGame} - return this.eval(basenode), nil + e := &expression{basenode, context, queryGame} + return e.eval(basenode), nil } -func (this *expression) eval(basenode *TreeNode) int64 { +func (e *expression) eval(basenode *TreeNode) int64 { for _, node := range basenode.items { switch node.Value.Category() { case CatFunction: - return this.switchFunction(node) + return e.switchFunction(node) case CatValue: - return this.getNumber(node) + return e.getNumber(node) case CatOther: - return this.switchOther(node) + return e.switchOther(node) } } panic("eval failed") } -func (this *expression) switchOther(node *TreeNode) int64 { +func (e *expression) switchOther(node *TreeNode) int64 { switch v1 := node.Value.(type) { case *GroupToken: if v1.GroupType == "()" { - return this.eval(node) + return e.eval(node) } } panic("invalid node " + node.String()) } -func (this *expression) switchFunction(node *TreeNode) int64 { +func (e *expression) switchFunction(node *TreeNode) int64 { val1 := node.Value.(*OperatorToken) switch strings.ToLower(val1.Operator) { case "=": - return this.evalEquals(node.Items()) + return e.evalEquals(node.Items()) case "==": - return this.evalEquals(node.Items()) + return e.evalEquals(node.Items()) case "!=": - return this.evalNotEquals(node.Items()) + return e.evalNotEquals(node.Items()) case ">": - return this.evalMathOperator(this.evalMathGreater, node.Items()) + return e.evalMathOperator(e.evalMathGreater, node.Items()) case "<": - return this.evalMathOperator(this.evalMathLess, node.Items()) + return e.evalMathOperator(e.evalMathLess, node.Items()) case ">=": - return this.evalMathOperator(this.evalMathGreaterOrEqual, node.Items()) + return e.evalMathOperator(e.evalMathGreaterOrEqual, node.Items()) case "<=": - return this.evalMathOperator(this.evalMathLessOrEqual, node.Items()) + return e.evalMathOperator(e.evalMathLessOrEqual, node.Items()) case "+": - return this.evalMathOperator(this.evalMathPlus, node.Items()) + return e.evalMathOperator(e.evalMathPlus, node.Items()) case "-": - return this.evalMathOperator(this.evalMathMinus, node.Items()) + return e.evalMathOperator(e.evalMathMinus, node.Items()) case "&": - return this.evalMathOperator(this.evalMathAnd, node.Items()) + return e.evalMathOperator(e.evalMathAnd, node.Items()) case "|": - return this.evalMathOperator(this.evalMathOr, node.Items()) + return e.evalMathOperator(e.evalMathOr, node.Items()) case "^": - return this.evalMathOperator(this.evalMathXor, node.Items()) + return e.evalMathOperator(e.evalMathXor, node.Items()) case "<<": - return this.evalMathOperator(this.evalMathLShift, node.Items()) + return e.evalMathOperator(e.evalMathLShift, node.Items()) case ">>": - return this.evalMathOperator(this.evalMathRShift, node.Items()) + return e.evalMathOperator(e.evalMathRShift, node.Items()) case "and": - return this.evalAnd(node.Items()) + return e.evalAnd(node.Items()) case "or": - return this.evalOr(node.Items()) + return e.evalOr(node.Items()) case "&&": - return this.evalAnd(node.Items()) + return e.evalAnd(node.Items()) case "||": - return this.evalOr(node.Items()) + return e.evalOr(node.Items()) case "like": - return this.evalLike(node.Items()) + return e.evalLike(node.Items()) default: panic("function not supported: " + val1.Operator) @@ -104,17 +104,17 @@ func (this *expression) switchFunction(node *TreeNode) int64 { } -func (this *expression) getString(node *TreeNode) string { +func (e *expression) getString(node *TreeNode) string { switch v := node.Value.(type) { case *NumberToken: return strconv.FormatInt(v.Value, 10) case *IdentityToken: - return this.getValue(v) + return e.getValue(v) case *OperatorToken: - return strconv.FormatInt(this.switchFunction(node), 10) + return strconv.FormatInt(e.switchFunction(node), 10) case *GroupToken: if v.GroupType == "()" { - return strconv.FormatInt(this.eval(node), 10) + return strconv.FormatInt(e.eval(node), 10) } panic("unexpected grouping type: " + node.String()) case *TextToken: @@ -125,26 +125,26 @@ func (this *expression) getString(node *TreeNode) string { } } -func (this *expression) evalEquals(args []*TreeNode) int64 { +func (e *expression) evalEquals(args []*TreeNode) int64 { cnt := len(args) switch { case cnt < 2: panic("operator missing arguments") case cnt == 2: if n, ok := args[0].Value.(*IdentityToken); ok { - if n.Name == "rk" && this.queryGame == "mariokartwii" { - return this.evalEqualsRK(this.getString(args[1])) + if n.Name == "rk" && e.queryGame == "mariokartwii" { + return e.evalEqualsRK(e.getString(args[1])) } } - if this.getString(args[0]) == this.getString(args[1]) { + if e.getString(args[0]) == e.getString(args[1]) { return 1 } return 0 default: - arg := this.getString(args[0]) + arg := e.getString(args[0]) for i := 1; i < cnt; i++ { - if arg != this.getString(args[i]) { + if arg != e.getString(args[i]) { return 0 } } @@ -153,8 +153,8 @@ func (this *expression) evalEquals(args []*TreeNode) int64 { } // Operator override -func (this *expression) evalEqualsRK(value string) int64 { - rk := this.context["rk"] +func (e *expression) evalEqualsRK(value string) int64 { + rk := e.context["rk"] // Check and remove regional searches due to the limited player count // China (ID 6) gets a pass because it was never released if len(rk) == 4 && (strings.HasPrefix(rk, "vs_") || strings.HasPrefix(rk, "bt_")) && rk[3] >= '0' && rk[3] < '6' { @@ -171,20 +171,20 @@ func (this *expression) evalEqualsRK(value string) int64 { return 0 } -func (this *expression) evalNotEquals(args []*TreeNode) int64 { +func (e *expression) evalNotEquals(args []*TreeNode) int64 { cnt := len(args) switch { case cnt < 2: panic("operator missing arguments") case cnt == 2: - if this.getString(args[0]) != this.getString(args[1]) { + if e.getString(args[0]) != e.getString(args[1]) { return 1 } return 0 default: - arg := this.getString(args[0]) + arg := e.getString(args[0]) for i := 1; i < cnt; i++ { - if arg == this.getString(args[i]) { + if arg == e.getString(args[i]) { return 0 } } @@ -192,57 +192,57 @@ func (this *expression) evalNotEquals(args []*TreeNode) int64 { } } -func (this *expression) evalAnd(args []*TreeNode) int64 { +func (e *expression) evalAnd(args []*TreeNode) int64 { cnt := len(args) if cnt < 2 { panic("operator missing arguments") } for i := 0; i < cnt; i++ { - if this.getString(args[i]) == "0" { + if e.getString(args[i]) == "0" { return 0 } } return 1 } -func (this *expression) evalOr(args []*TreeNode) int64 { +func (e *expression) evalOr(args []*TreeNode) int64 { cnt := len(args) if cnt < 2 { panic("operator missing arguments") } for i := 0; i < cnt; i++ { - if this.getString(args[i]) != "0" { + if e.getString(args[i]) != "0" { return 1 } } return 0 } -func (this *expression) getNumber(node *TreeNode) int64 { +func (e *expression) getNumber(node *TreeNode) int64 { switch v := node.Value.(type) { case *NumberToken: return v.Value case *IdentityToken: - r1 := this.getValue(v) - return this.toInt64(r1) + r1 := e.getValue(v) + return e.toInt64(r1) case *OperatorToken: - return this.switchFunction(node) + return e.switchFunction(node) case *GroupToken: if v.GroupType == "()" { - return this.eval(node) + return e.eval(node) } panic("unexpected grouping type: " + node.String()) case *TextToken: - return this.toInt64(node.Value.(*TextToken).Text) + return e.toInt64(node.Value.(*TextToken).Text) default: panic("unexpected value: " + node.String()) } } -func (this *expression) evalMathOperator(fn func(int64, int64) int64, args []*TreeNode) int64 { +func (e *expression) evalMathOperator(fn func(int64, int64) int64, args []*TreeNode) int64 { cnt := len(args) switch { case cnt < 2: @@ -250,101 +250,101 @@ func (this *expression) evalMathOperator(fn func(int64, int64) int64, args []*Tr case cnt == 2: if n, ok := args[0].Value.(*IdentityToken); ok { // Remove VR search due to the limited player count - if (n.Name == "ev" || n.Name == "eb") && this.queryGame == "mariokartwii" { + if (n.Name == "ev" || n.Name == "eb") && e.queryGame == "mariokartwii" { return 1 } } - return fn(this.getNumber(args[0]), this.getNumber(args[1])) + return fn(e.getNumber(args[0]), e.getNumber(args[1])) default: - answ := fn(this.getNumber(args[0]), this.getNumber(args[1])) + answ := fn(e.getNumber(args[0]), e.getNumber(args[1])) for i := 2; i < cnt; i++ { - answ = fn(answ, this.getNumber(args[i])) + answ = fn(answ, e.getNumber(args[i])) } return answ } } -func (this *expression) evalMathPlus(val1, val2 int64) int64 { +func (e *expression) evalMathPlus(val1, val2 int64) int64 { return val1 + val2 } -func (this *expression) evalMathMinus(val1, val2 int64) int64 { +func (e *expression) evalMathMinus(val1, val2 int64) int64 { return val1 - val2 } -func (this *expression) evalMathGreater(val1, val2 int64) int64 { +func (e *expression) evalMathGreater(val1, val2 int64) int64 { if val1 > val2 { return 1 } return 0 } -func (this *expression) evalMathLess(val1, val2 int64) int64 { +func (e *expression) evalMathLess(val1, val2 int64) int64 { if val1 < val2 { return 1 } return 0 } -func (this *expression) evalMathGreaterOrEqual(val1, val2 int64) int64 { +func (e *expression) evalMathGreaterOrEqual(val1, val2 int64) int64 { if val1 >= val2 { return 1 } return 0 } -func (this *expression) evalMathLessOrEqual(val1, val2 int64) int64 { +func (e *expression) evalMathLessOrEqual(val1, val2 int64) int64 { if val1 <= val2 { return 1 } return 0 } -func (this *expression) evalMathAnd(val1, val2 int64) int64 { +func (e *expression) evalMathAnd(val1, val2 int64) int64 { return val1 & val2 } -func (this *expression) evalMathOr(val1, val2 int64) int64 { +func (e *expression) evalMathOr(val1, val2 int64) int64 { return val1 | val2 } -func (this *expression) evalMathXor(val1, val2 int64) int64 { +func (e *expression) evalMathXor(val1, val2 int64) int64 { return val1 ^ val2 } -func (this *expression) evalMathLShift(val1, val2 int64) int64 { +func (e *expression) evalMathLShift(val1, val2 int64) int64 { return val1 << val2 } -func (this *expression) evalMathRShift(val1, val2 int64) int64 { +func (e *expression) evalMathRShift(val1, val2 int64) int64 { return val1 >> val2 } -func (this *expression) evalLike(args []*TreeNode) int64 { +func (e *expression) evalLike(args []*TreeNode) int64 { cnt := len(args) switch { case cnt < 2: panic("operator missing arguments") case cnt == 2: - return this.evalLikeSingle(args[0], args[1]) + return e.evalLikeSingle(args[0], args[1]) default: - panic("operator like does not support multiple arguments") + panic("operator LIKE does not support multiple arguments") } } -func (this *expression) evalLikeSingle(arg1, arg2 *TreeNode) int64 { - val1 := this.getString(arg1) - val2 := this.getString(arg2) +func (e *expression) evalLikeSingle(arg1, arg2 *TreeNode) int64 { + val1 := e.getString(arg1) + val2 := e.getString(arg2) allowedCharacters := `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_%\` regexString := "^" - // Convert SQL like pattern to regex + // Convert SQL LIKE pattern to regex for i, c := range val2 { - if strings.IndexRune(allowedCharacters, c) < 0 { - panic("invalid character in like pattern: " + string(c)) + if !strings.ContainsRune(allowedCharacters, c) { + panic("invalid character in LIKE pattern: " + string(c)) } if i != 0 && val2[i-1] == '\\' { @@ -384,11 +384,11 @@ func (this *expression) evalLikeSingle(arg1, arg2 *TreeNode) int64 { } // Get a value from the context. -func (this *expression) getValue(token *IdentityToken) string { - return this.context[token.Name] +func (e *expression) getValue(token *IdentityToken) string { + return e.context[token.Name] } -func (this *expression) toInt64(value string) int64 { +func (e *expression) toInt64(value string) int64 { val, err := strconv.ParseInt(value, 10, 64) if err != nil { panic(err) diff --git a/filter/parse.go b/filter/parse.go index ac06271..2c949e7 100644 --- a/filter/parse.go +++ b/filter/parse.go @@ -33,73 +33,68 @@ func Parse(input string) (root *TreeNode, err error) { return root, err } -func (this *parser) getCurr() Token { - if this.curr != nil { - return this.curr.Value +func (p *parser) getCurr() Token { + if p.curr != nil { + return p.curr.Value } return nil } -func (this *parser) parse() { - this.pumpExpression() +func (p *parser) parse() { + p.pumpExpression() } -func (this *parser) add(token Token) *TreeNode { - return this.curr.Add(token) +func (p *parser) add(token Token) *TreeNode { + return p.curr.Add(token) } -func (this *parser) push(token Token) *TreeNode { - return this.curr.Push(token) +func (p *parser) push(token Token) *TreeNode { + return p.curr.Push(token) } -func (this *parser) lastNode() *TreeNode { - return this.curr.LastElement() +func (p *parser) lastNode() *TreeNode { + return p.curr.LastElement() } -func (this *parser) parentNode() *TreeNode { - return this.curr.Parent() -} - -func (this *parser) commit() string { - return this.scan.Commit() +func (p *parser) commit() string { + return p.scan.Commit() } // parseOpenBracket -func (this *parser) parseOpenBracket() bool { - this.curr = this.add(NewGroupToken("()")) - this.commit() +func (p *parser) parseOpenBracket() bool { + p.curr = p.add(NewGroupToken("()")) + p.commit() return true } // parseCloseBracket -func (this *parser) parseCloseBracket() stateFn { +func (p *parser) parseCloseBracket() stateFn { for { - v1, ok := this.curr.Value.(*GroupToken) + v1, ok := p.curr.Value.(*GroupToken) if ok && v1.GroupType == "()" { - this.commit() - this.curr = this.curr.Parent() + p.commit() + p.curr = p.curr.Parent() return branchExpressionOperatorPart } if ok && v1.GroupType == "" { //must be a bracket part of a parent loop, exit this sub loop. - this.scan.Backup() + p.scan.Backup() return nil } - if this.curr.Parent() == nil { + if p.curr.Parent() == nil { panic("brackets not closed") } - this.curr = this.curr.Parent() + p.curr = p.curr.Parent() } - panic("unreachable code") } -func (this *parser) AcceptOperator() bool { - scan := this.scan +func (p *parser) AcceptOperator() bool { + scan := p.scan state := scan.SaveState() for _, op := range operatorList { if scan.Prefix(op) || scan.Prefix(strings.ToUpper(op)) { p := scan.Peek() - if unicode.IsLetter(rune(op[0])) && (unicode.IsLetter(p) || unicode.IsNumber(p) || strings.IndexRune(charValidString, p) >= 0) { + if unicode.IsLetter(rune(op[0])) && (unicode.IsLetter(p) || unicode.IsNumber(p) || strings.ContainsRune(charValidString, p)) { // this is a prefix of a longer word scan.LoadState(state) continue @@ -111,10 +106,10 @@ func (this *parser) AcceptOperator() bool { } // parseOperator -func (this *parser) parseOperator() bool { - operator := this.commit() - lastnode := this.lastNode() - onode, ok := this.getCurr().(*OperatorToken) +func (p *parser) parseOperator() bool { + operator := p.commit() + lastnode := p.lastNode() + onode, ok := p.getCurr().(*OperatorToken) //push excisting operator up in tree structure if ok { //operator is the same current operator ignore @@ -125,51 +120,51 @@ func (this *parser) parseOperator() bool { //fmt.Println(onode, operator, onode.Precedence(operator)) if onode.Precedence(operator) > 0 { if lastnode != nil { - this.curr = lastnode.Push(NewOperatorToken(operator)) + p.curr = lastnode.Push(NewOperatorToken(operator)) return true } } //after */ presedence fallback and continue pushing +- operators from the bottom. if onode.Precedence(operator) < 0 { for { - v1, ok := this.curr.Parent().Value.(*OperatorToken) + v1, ok := p.curr.Parent().Value.(*OperatorToken) //if ok && strings.Index("+-", v1.Name) >= 0 { if ok && operators.Level(v1.Operator) >= 0 { - this.curr = this.curr.Parent() + p.curr = p.curr.Parent() } else { break } } } //standard operator push - this.curr = this.push(NewOperatorToken(operator)) + p.curr = p.push(NewOperatorToken(operator)) return true } //set previous found value as argument of the operator if lastnode != nil { - this.curr = lastnode.Push(NewOperatorToken(operator)) + p.curr = lastnode.Push(NewOperatorToken(operator)) } else { - this.state = nil + p.state = nil panic(fmt.Sprintf("expecting a value before operator %q", operator)) } return true } // parseLRFunc -func (this *parser) parseLRFunc() bool { - lrfunc := this.commit() - lastnode := this.lastNode() +func (p *parser) parseLRFunc() bool { + lrfunc := p.commit() + lastnode := p.lastNode() if lastnode != nil { - this.curr = lastnode.Push(NewLRFuncToken(lrfunc)) + p.curr = lastnode.Push(NewLRFuncToken(lrfunc)) } else { - this.state = nil + p.state = nil panic(fmt.Sprintf("expecting a value before operator %q", lrfunc)) } return false } -func (this *parser) ParseText() string { - scan := this.scan +func (p *parser) ParseText() string { + scan := p.scan r := scan.Next() if r == '"' || r == '\'' { scan.Ignore() diff --git a/filter/parse_branches.go b/filter/parse_branches.go index 7e2f863..c3ec4af 100644 --- a/filter/parse_branches.go +++ b/filter/parse_branches.go @@ -1,16 +1,16 @@ // Modified from github.com/zdebeer99/goexpression package filter -func (this *parser) pumpExpression() { - this.state = branchExpressionValuePart - for this.state != nil { - if this.err != nil { +func (p *parser) pumpExpression() { + p.state = branchExpressionValuePart + for p.state != nil { + if p.err != nil { break } - this.state = this.state(this) + p.state = p.state(p) } - endo := this.commit() - if len(endo) > 0 || !this.scan.IsEOF() { + endo := p.commit() + if len(endo) > 0 || !p.scan.IsEOF() { panic("unexpected end of expression '" + endo + "' not parsed") } } @@ -68,7 +68,6 @@ func branchFunctionArguments(this *parser) stateFn { ftoken, ok := this.curr.Value.(*FuncToken) if !ok { panic("expecting function token to add arguments to") - return nil } state := branchExpressionValuePart currnode := this.curr @@ -96,10 +95,8 @@ func branchFunctionArguments(this *parser) stateFn { this.curr = currnode if scan.IsEOF() { panic("arguments missing end bracket") - return nil } panic("invalid char '" + string(r) + "' in arguments") - return nil } } diff --git a/filter/scanner.go b/filter/scanner.go index 6bba162..14c4a9c 100644 --- a/filter/scanner.go +++ b/filter/scanner.go @@ -32,147 +32,144 @@ func NewScanner(template string) *Scanner { return &Scanner{input: template} } -func (this *Scanner) StartPosition() int { - return int(this.start) +func (s *Scanner) StartPosition() int { + return int(s.start) } -func (this *Scanner) SetPosition(pos int) { - this.pos = Pos(pos) +func (s *Scanner) SetPosition(pos int) { + s.pos = Pos(pos) } -func (this *Scanner) SetStartPosition(pos int) { - this.start = Pos(pos) +func (s *Scanner) SetStartPosition(pos int) { + s.start = Pos(pos) } // Token return the current selected text and move the start position to the current position -func (this *Scanner) Commit() string { - r1 := this.input[this.start:this.pos] - this.start = this.pos - this.prevState = this.SaveState() +func (s *Scanner) Commit() string { + r1 := s.input[s.start:s.pos] + s.start = s.pos + s.prevState = s.SaveState() return r1 } // IsEOF check if the end of the current string has been reached. -func (this *Scanner) IsEOF() bool { - return int(this.pos) >= len(this.input) +func (s *Scanner) IsEOF() bool { + return int(s.pos) >= len(s.input) } -func (this *Scanner) Size() int { - return len(this.input) +func (s *Scanner) Size() int { + return len(s.input) } -func (this *Scanner) MoveStart(pos int) { - this.start = this.start + Pos(pos) +func (s *Scanner) MoveStart(pos int) { + s.start = s.start + Pos(pos) } // Next returns the next rune in the input. -func (this *Scanner) Next() rune { - this.safebackup = true - if this.IsEOF() { - this.width = 0 +func (s *Scanner) Next() rune { + s.safebackup = true + if s.IsEOF() { + s.width = 0 return eof } - r, w := utf8.DecodeRuneInString(this.input[this.pos:]) - this.width = Pos(w) - this.pos += this.width - this.curr = r + r, w := utf8.DecodeRuneInString(s.input[s.pos:]) + s.width = Pos(w) + s.pos += s.width + s.curr = r return r } -func (this *Scanner) Skip() { - this.Next() - this.Commit() +func (s *Scanner) Skip() { + s.Next() + s.Commit() } // Peek returns but does not consume the next rune in the input. -func (this *Scanner) Peek() rune { - r := this.Next() - this.Backup() +func (s *Scanner) Peek() rune { + r := s.Next() + s.Backup() return r } // Backup steps back one rune. Can only be called once per call of next. -func (this *Scanner) Backup() { - this.pos -= this.width +func (s *Scanner) Backup() { + s.pos -= s.width } // Rollback move the curr pos back to the start pos. -func (this *Scanner) Rollback() { - this.LoadState(this.prevState) +func (s *Scanner) Rollback() { + s.LoadState(s.prevState) } // Ignore skips over the pending input before this point. -func (this *Scanner) Ignore() { - this.start = this.pos +func (s *Scanner) Ignore() { + s.start = s.pos } // accept consumes the next rune if it's from the valid set. -func (this *Scanner) Accept(valid string) bool { - if strings.IndexRune(valid, this.Next()) >= 0 { +func (s *Scanner) Accept(valid string) bool { + if strings.ContainsRune(valid, s.Next()) { return true } - this.Backup() + s.Backup() return false } // acceptRun consumes a run of runes from the valid set. -func (this *Scanner) AcceptRun(valid string) (found int) { - for strings.IndexRune(valid, this.Next()) >= 0 { +func (s *Scanner) AcceptRun(valid string) (found int) { + for strings.ContainsRune(valid, s.Next()) { found++ } - this.Backup() + s.Backup() return found } // runTo consumes a run of runes until an item in the valid set is found. -func (this *Scanner) RunTo(valid string) rune { +func (s *Scanner) RunTo(valid string) rune { for { - r := this.Next() + r := s.Next() if r == eof { return r } - if strings.IndexRune(valid, r) >= 0 { + if strings.ContainsRune(valid, r) { return r } } - this.Backup() - return eof } -func (this *Scanner) Prefix(pre string) bool { - if strings.HasPrefix(this.input[this.pos:], pre) { - this.pos += Pos(len(pre)) +func (s *Scanner) Prefix(pre string) bool { + if strings.HasPrefix(s.input[s.pos:], pre) { + s.pos += Pos(len(pre)) return true } return false } -func (this *Scanner) SkipSpaces() { - for IsSpace(this.Next()) { +func (s *Scanner) SkipSpaces() { + for IsSpace(s.Next()) { } - this.Backup() - this.Ignore() + s.Backup() + s.Ignore() } -func (this *Scanner) SkipToNewLine() { +func (s *Scanner) SkipToNewLine() { for { - r := this.Next() - if this.IsEOF() { + r := s.Next() + if s.IsEOF() { break } if r == '\n' { break } } - this.Ignore() - return + s.Ignore() } // lineNumber reports which line we're on, based on the position of // the previous item returned by nextItem. Doing it this way // means we don't have to worry about peek double counting. -func (this *Scanner) LineNumber() int { - return 1 + strings.Count(this.input[:this.pos], "\n") +func (s *Scanner) LineNumber() int { + return 1 + strings.Count(s.input[:s.pos], "\n") } type ScannerState struct { @@ -181,10 +178,10 @@ type ScannerState struct { width Pos } -func (this *Scanner) SaveState() ScannerState { - return ScannerState{start: this.start, pos: this.pos, width: this.width} +func (s *Scanner) SaveState() ScannerState { + return ScannerState{start: s.start, pos: s.pos, width: s.width} } -func (this *Scanner) LoadState(state ScannerState) { - this.start, this.pos, this.width = state.start, state.pos, state.width +func (s *Scanner) LoadState(state ScannerState) { + s.start, s.pos, s.width = state.start, state.pos, state.width } diff --git a/filter/scanner_helper.go b/filter/scanner_helper.go index 7d5007a..1b3cccd 100644 --- a/filter/scanner_helper.go +++ b/filter/scanner_helper.go @@ -19,65 +19,65 @@ func IsNumber(r rune) bool { // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. func IsAlphaNumeric(r rune) bool { - return unicode.IsLetter(r) || unicode.IsDigit(r) || strings.IndexRune(charValidString, r) >= 0 + return unicode.IsLetter(r) || unicode.IsDigit(r) || strings.ContainsRune(charValidString, r) } func IsQoute(r rune) bool { - return strings.IndexRune("\"'", r) >= 0 + return strings.ContainsRune("\"'", r) } func HasChar(r rune, accept string) bool { - return strings.IndexRune(accept, r) >= 0 + return strings.ContainsRune(accept, r) } -func (this *Scanner) Scan(valid func(r rune) bool) bool { +func (s *Scanner) Scan(valid func(r rune) bool) bool { var isvalid bool - for valid(this.Next()) { + for valid(s.Next()) { isvalid = true } - this.Backup() + s.Backup() return isvalid } -//scan upto to the end of a word, returns true if a word was scanned. -//a word must start with a letter or '_' and can contain numbers after the first character. -func (this *Scanner) ScanWord() bool { - r := this.Next() - if unicode.IsLetter(r) || strings.IndexRune(charValidString, r) >= 0 { +// scan upto to the end of a word, returns true if a word was scanned. +// a word must start with a letter or '_' and can contain numbers after the first character. +func (s *Scanner) ScanWord() bool { + r := s.Next() + if unicode.IsLetter(r) || strings.ContainsRune(charValidString, r) { for { - r = this.Next() + r = s.Next() if IsAlphaNumeric(r) { continue } else { - this.Backup() + s.Backup() return true } } } - this.Backup() + s.Backup() return false } -func (this *Scanner) ScanNumber() bool { - state := this.SaveState() - r := this.Next() +func (s *Scanner) ScanNumber() bool { + state := s.SaveState() + r := s.Next() isdigit := unicode.IsDigit(r) if !isdigit && (r == '-' || r == '.') { //if the first char is '-' or '.' the next char must be a digit. - if !unicode.IsDigit(this.Next()) { - this.LoadState(state) + if !unicode.IsDigit(s.Next()) { + s.LoadState(state) return false } else { isdigit = true } } else if !isdigit { - this.Backup() + s.Backup() return false } - if this.Scan(IsNumber) || isdigit { + if s.Scan(IsNumber) || isdigit { return true } else { - this.LoadState(state) + s.LoadState(state) return false } } diff --git a/filter/tokens.go b/filter/tokens.go index 3740504..48877b2 100644 --- a/filter/tokens.go +++ b/filter/tokens.go @@ -31,30 +31,22 @@ func NewEmptyToken() *EmptyToken { return &EmptyToken{CatOther, nil} } -func (this *EmptyToken) Category() TokenCategory { - return this.tokencat +func (t *EmptyToken) Category() TokenCategory { + return t.tokencat } -func (this *EmptyToken) Error() error { - return this.err +func (t *EmptyToken) Error() error { + return t.err } -func (this *EmptyToken) SetError(err error) { - this.err = err +func (t *EmptyToken) SetError(err error) { + t.err = err } -func (this *EmptyToken) String() string { +func (t *EmptyToken) String() string { return "Base()" } -type ErrorToken struct { - EmptyToken -} - -func NewErrorToken(err string) *ErrorToken { - return &ErrorToken{EmptyToken{CatOther, fmt.Errorf(err)}} -} - type NumberToken struct { EmptyToken Value int64 @@ -65,14 +57,13 @@ func NewNumberToken(value string) *NumberToken { val1, err := strconv.ParseInt(value, 10, 64) if err != nil { panic("number node failed to parse string to number (" + value + ")") - return node } node.Value = val1 return node } -func (this *NumberToken) String() string { - return fmt.Sprintf("Number(%v)", this.Value) +func (t *NumberToken) String() string { + return fmt.Sprintf("Number(%v)", t.Value) } type IdentityToken struct { @@ -84,8 +75,8 @@ func NewIdentityToken(name string) *IdentityToken { return &IdentityToken{EmptyToken{CatValue, nil}, name} } -func (this *IdentityToken) String() string { - return fmt.Sprintf("Identity(%s)", this.Name) +func (t *IdentityToken) String() string { + return fmt.Sprintf("Identity(%s)", t.Name) } type FuncToken struct { @@ -98,16 +89,16 @@ func NewFuncToken(name string) *FuncToken { return &FuncToken{EmptyToken{CatFunction, nil}, name, make([]*TreeNode, 0)} } -func (this *FuncToken) AddArgument(arg *TreeNode) { - this.Arguments = append(this.Arguments, arg) +func (t *FuncToken) AddArgument(arg *TreeNode) { + t.Arguments = append(t.Arguments, arg) } -func (this *FuncToken) String() string { - args := make([]string, len(this.Arguments)) - for i, v := range this.Arguments { - args[i] = fmt.Sprintf("%s", strings.Replace(v.String(), "\n", ",", -1)) +func (t *FuncToken) String() string { + args := make([]string, len(t.Arguments)) + for i, v := range t.Arguments { + args[i] = strings.ReplaceAll(v.String(), "\n", ",") } - return fmt.Sprintf("Func %s(%s)", this.Name, args) + return fmt.Sprintf("Func %s(%s)", t.Name, args) } type OperatorToken struct { @@ -122,36 +113,36 @@ func NewOperatorToken(operator string) *OperatorToken { return op } -func (this *OperatorToken) SetOperator(operator string) { - this.Operator = operator - this.lvl = operators.Level(operator) - if this.lvl < 0 { +func (t *OperatorToken) SetOperator(operator string) { + t.Operator = operator + t.lvl = operators.Level(operator) + if t.lvl < 0 { panic(fmt.Sprintf("invalid operator %q", operator)) } } // OperatorPrecedence return true if the operator argument is lower than the current operator. -func (this *OperatorToken) Precedence(operator string) int { +func (t *OperatorToken) Precedence(operator string) int { lvl := operators.Level(operator) switch { - case lvl == this.lvl: + case lvl == t.lvl: return 0 - case lvl > this.lvl: + case lvl > t.lvl: return 1 - case lvl < this.lvl: + case lvl < t.lvl: return -1 } panic("unreachable code") } -func (this *OperatorToken) String() string { - return fmt.Sprintf("Func(%s)", this.Operator) +func (t *OperatorToken) String() string { + return fmt.Sprintf("Func(%s)", t.Operator) } type OperatorPrecedence [][]string -func (this OperatorPrecedence) Level(operator string) int { - for level, operators := range this { +func (op OperatorPrecedence) Level(operator string) int { + for level, operators := range op { for _, op := range operators { if op == strings.ToLower(operator) { return 5 - level @@ -161,12 +152,10 @@ func (this OperatorPrecedence) Level(operator string) int { return -1 } -func (this OperatorPrecedence) All() []string { +func (op OperatorPrecedence) All() []string { out := make([]string, 0) - for _, operators := range this { - for _, op := range operators { - out = append(out, op) - } + for _, operators := range op { + out = append(out, operators...) } return out } @@ -190,8 +179,8 @@ func NewLRFuncToken(name string) *LRFuncToken { return &LRFuncToken{EmptyToken{CatFunction, nil}, name} } -func (this *LRFuncToken) String() string { - return fmt.Sprintf("Func(%s)", this.Name) +func (t *LRFuncToken) String() string { + return fmt.Sprintf("Func(%s)", t.Name) } type GroupToken struct { @@ -203,8 +192,8 @@ func NewGroupToken(group string) *GroupToken { return &GroupToken{EmptyToken{CatOther, nil}, group} } -func (this *GroupToken) String() string { - return fmt.Sprintf("Group(%s)", this.GroupType) +func (t *GroupToken) String() string { + return fmt.Sprintf("Group(%s)", t.GroupType) } type TextToken struct { @@ -216,6 +205,6 @@ func NewTextToken(text string) *TextToken { return &TextToken{EmptyToken{CatValue, nil}, text} } -func (this *TextToken) String() string { - return fmt.Sprintf("%q", this.Text) +func (t *TextToken) String() string { + return fmt.Sprintf("%q", t.Text) } diff --git a/filter/treenode.go b/filter/treenode.go index 0a0b8ba..8151230 100644 --- a/filter/treenode.go +++ b/filter/treenode.go @@ -18,12 +18,12 @@ func NewTreeNode(value Token) *TreeNode { } // Parent Returns the current element parent -func (this *TreeNode) Parent() *TreeNode { - return this.parent +func (n *TreeNode) Parent() *TreeNode { + return n.parent } -func (this *TreeNode) Root() *TreeNode { - p := this +func (n *TreeNode) Root() *TreeNode { + p := n for p.parent != nil { p = p.parent } @@ -32,43 +32,43 @@ func (this *TreeNode) Root() *TreeNode { // setParent sets the current nodes parent value. // Warning: does not add the node as a child -func (this *TreeNode) setParent(element *TreeNode) { - if this.parent != nil { +func (n *TreeNode) setParent(element *TreeNode) { + if n.parent != nil { panic("TreeNode already attached to a parent node") } - this.parent = element + n.parent = element } -func (this *TreeNode) LastElement() *TreeNode { - if len(this.items) == 0 { +func (n *TreeNode) LastElement() *TreeNode { + if len(n.items) == 0 { return nil } - return this.items[len(this.items)-1] + return n.items[len(n.items)-1] } -func (this *TreeNode) Last() Token { - last := this.LastElement() +func (n *TreeNode) Last() Token { + last := n.LastElement() if last != nil { return last.Value } return nil } -func (this *TreeNode) Items() []*TreeNode { - return this.items +func (n *TreeNode) Items() []*TreeNode { + return n.items } // Add adds a TreeElement to the end of the children items of the current node. -func (this *TreeNode) AddElement(element *TreeNode) *TreeNode { - element.setParent(this) - this.items = append(this.items, element) +func (n *TreeNode) AddElement(element *TreeNode) *TreeNode { + element.setParent(n) + n.items = append(n.items, element) return element } // Add adds a value to the end of the children items of the current node. -func (this *TreeNode) Add(value Token) *TreeNode { +func (n *TreeNode) Add(value Token) *TreeNode { element := NewTreeNode(value) - return this.AddElement(element) + return n.AddElement(element) } // Push, removes the current element from its current parent, place the new value @@ -78,27 +78,27 @@ func (this *TreeNode) Add(value Token) *TreeNode { // tree: A(B) // B.Push(C) // tree: A(C(B)) -func (this *TreeNode) PushElement(element *TreeNode) *TreeNode { - parent := this.Parent() +func (n *TreeNode) PushElement(element *TreeNode) *TreeNode { + parent := n.Parent() if parent != nil { //replace the current node with the new node - index := parent.indexOf(this) + index := parent.indexOf(n) parent.items[index] = element element.setParent(parent) - this.parent = nil + n.parent = nil } //add the current node to the new node - element.AddElement(this) + element.AddElement(n) return element } -func (this *TreeNode) Push(value Token) *TreeNode { - return this.PushElement(NewTreeNode(value)) +func (n *TreeNode) Push(value Token) *TreeNode { + return n.PushElement(NewTreeNode(value)) } // FindChildElement Finds a child element in the current nodes children -func (this *TreeNode) indexOf(element *TreeNode) int { - for i, v := range this.items { +func (n *TreeNode) indexOf(element *TreeNode) int { + for i, v := range n.items { if v == element { return i } @@ -106,23 +106,23 @@ func (this *TreeNode) indexOf(element *TreeNode) int { return -1 } -func (this *TreeNode) StringContent() string { - lines := make([]string, len(this.items)) - for i, v := range this.items { +func (n *TreeNode) StringContent() string { + lines := make([]string, len(n.items)) + for i, v := range n.items { lines[i] = v.String() } - if this.Value.Error() != nil { - return fmt.Sprintf("[ERROR: %s]", this.Value.Error()) + if n.Value.Error() != nil { + return fmt.Sprintf("[ERROR: %s]", n.Value.Error()) } else if len(lines) > 0 { - return fmt.Sprintf("%s", strings.Join(lines, ",")) + return strings.Join(lines, ",") } else { return "" } } -func (this *TreeNode) String() string { - if this.StringContent() == "" { - return this.Value.String() +func (n *TreeNode) String() string { + if n.StringContent() == "" { + return n.Value.String() } - return fmt.Sprintf("[%s:%s]", this.Value.String(), this.StringContent()) + return fmt.Sprintf("[%s:%s]", n.Value.String(), n.StringContent()) }