mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 23:42:26 -06:00 
			
		
		
		
	Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
		
			
				
	
	
		
			329 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//
 | 
						|
// Copyright 2024 CloudWeGo Authors
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
//
 | 
						|
 | 
						|
package expr
 | 
						|
 | 
						|
import (
 | 
						|
    `strconv`
 | 
						|
    `unicode`
 | 
						|
    `unsafe`
 | 
						|
)
 | 
						|
 | 
						|
type _TokenKind uint8
 | 
						|
 | 
						|
const (
 | 
						|
    _T_end _TokenKind = iota + 1
 | 
						|
    _T_int
 | 
						|
    _T_punc
 | 
						|
    _T_name
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
    _OP2 = 0x80
 | 
						|
    _POW = _OP2 | '*'
 | 
						|
    _SHL = _OP2 | '<'
 | 
						|
    _SHR = _OP2 | '>'
 | 
						|
)
 | 
						|
 | 
						|
type _Slice struct {
 | 
						|
    p unsafe.Pointer
 | 
						|
    n int
 | 
						|
    c int
 | 
						|
}
 | 
						|
 | 
						|
type _Token struct {
 | 
						|
    pos int
 | 
						|
    ptr *rune
 | 
						|
    u64 uint64
 | 
						|
    tag _TokenKind
 | 
						|
}
 | 
						|
 | 
						|
func (self _Token) str() (v string) {
 | 
						|
    return string(self.rbuf())
 | 
						|
}
 | 
						|
 | 
						|
func (self _Token) rbuf() (v []rune) {
 | 
						|
    (*_Slice)(unsafe.Pointer(&v)).c = int(self.u64)
 | 
						|
    (*_Slice)(unsafe.Pointer(&v)).n = int(self.u64)
 | 
						|
    (*_Slice)(unsafe.Pointer(&v)).p = unsafe.Pointer(self.ptr)
 | 
						|
    return
 | 
						|
}
 | 
						|
 | 
						|
func tokenEnd(p int) _Token {
 | 
						|
    return _Token {
 | 
						|
        pos: p,
 | 
						|
        tag: _T_end,
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func tokenInt(p int, v uint64) _Token {
 | 
						|
    return _Token {
 | 
						|
        pos: p,
 | 
						|
        u64: v,
 | 
						|
        tag: _T_int,
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func tokenPunc(p int, v rune) _Token {
 | 
						|
    return _Token {
 | 
						|
        pos: p,
 | 
						|
        tag: _T_punc,
 | 
						|
        u64: uint64(v),
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func tokenName(p int, v []rune) _Token {
 | 
						|
    return _Token {
 | 
						|
        pos: p,
 | 
						|
        ptr: &v[0],
 | 
						|
        tag: _T_name,
 | 
						|
        u64: uint64(len(v)),
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// Repository represents a repository of Term's.
 | 
						|
type Repository interface {
 | 
						|
    Get(name string) (Term, error)
 | 
						|
}
 | 
						|
 | 
						|
// Parser parses an expression string to it's AST representation.
 | 
						|
type Parser struct {
 | 
						|
    pos int
 | 
						|
    src []rune
 | 
						|
}
 | 
						|
 | 
						|
var binaryOps = [...]func(*Expr, *Expr) *Expr {
 | 
						|
    '+'  : (*Expr).Add,
 | 
						|
    '-'  : (*Expr).Sub,
 | 
						|
    '*'  : (*Expr).Mul,
 | 
						|
    '/'  : (*Expr).Div,
 | 
						|
    '%'  : (*Expr).Mod,
 | 
						|
    '&'  : (*Expr).And,
 | 
						|
    '^'  : (*Expr).Xor,
 | 
						|
    '|'  : (*Expr).Or,
 | 
						|
    _SHL : (*Expr).Shl,
 | 
						|
    _SHR : (*Expr).Shr,
 | 
						|
    _POW : (*Expr).Pow,
 | 
						|
}
 | 
						|
 | 
						|
var precedence = [...]map[int]bool {
 | 
						|
    {_SHL: true, _SHR: true},
 | 
						|
    {'|' : true},
 | 
						|
    {'^' : true},
 | 
						|
    {'&' : true},
 | 
						|
    {'+' : true, '-': true},
 | 
						|
    {'*' : true, '/': true, '%': true},
 | 
						|
    {_POW: true},
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) ch() rune {
 | 
						|
    return self.src[self.pos]
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) eof() bool {
 | 
						|
    return self.pos >= len(self.src)
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) rch() (v rune) {
 | 
						|
    v, self.pos = self.src[self.pos], self.pos + 1
 | 
						|
    return
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) hex(ss []rune) bool {
 | 
						|
    if len(ss) == 1 && ss[0] == '0' {
 | 
						|
        return unicode.ToLower(self.ch()) == 'x'
 | 
						|
    } else if len(ss) <= 1 || unicode.ToLower(ss[1]) != 'x' {
 | 
						|
        return unicode.IsDigit(self.ch())
 | 
						|
    } else {
 | 
						|
        return ishexdigit(self.ch())
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) int(p int, ss []rune) (_Token, error) {
 | 
						|
    var err error
 | 
						|
    var val uint64
 | 
						|
 | 
						|
    /* find all the digits */
 | 
						|
    for !self.eof() && self.hex(ss) {
 | 
						|
        ss = append(ss, self.rch())
 | 
						|
    }
 | 
						|
 | 
						|
    /* parse the value */
 | 
						|
    if val, err = strconv.ParseUint(string(ss), 0, 64); err != nil {
 | 
						|
        return _Token{}, err
 | 
						|
    } else {
 | 
						|
        return tokenInt(p, val), nil
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) name(p int, ss []rune) _Token {
 | 
						|
    for !self.eof() && isident(self.ch()) { ss = append(ss, self.rch()) }
 | 
						|
    return tokenName(p, ss)
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) read(p int, ch rune) (_Token, error) {
 | 
						|
    if isdigit(ch) {
 | 
						|
        return self.int(p, []rune { ch })
 | 
						|
    } else if isident0(ch) {
 | 
						|
        return self.name(p, []rune { ch }), nil
 | 
						|
    } else if isop2ch(ch) && !self.eof() && self.ch() == ch {
 | 
						|
        return tokenPunc(p, _OP2 | self.rch()), nil
 | 
						|
    } else if isop1ch(ch) {
 | 
						|
        return tokenPunc(p, ch), nil
 | 
						|
    } else {
 | 
						|
        return _Token{}, newSyntaxError(self.pos, "invalid character " + strconv.QuoteRuneToASCII(ch))
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) next() (_Token, error) {
 | 
						|
    for {
 | 
						|
        var p int
 | 
						|
        var c rune
 | 
						|
 | 
						|
        /* check for EOF */
 | 
						|
        if self.eof() {
 | 
						|
            return tokenEnd(self.pos), nil
 | 
						|
        }
 | 
						|
 | 
						|
        /* read the next char */
 | 
						|
        p = self.pos
 | 
						|
        c = self.rch()
 | 
						|
 | 
						|
        /* parse the token if not a space */
 | 
						|
        if !unicode.IsSpace(c) {
 | 
						|
            return self.read(p, c)
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) grab(tk _Token, repo Repository) (*Expr, error) {
 | 
						|
    if repo == nil {
 | 
						|
        return nil, newSyntaxError(tk.pos, "unresolved symbol: " + tk.str())
 | 
						|
    } else if term, err := repo.Get(tk.str()); err != nil {
 | 
						|
        return nil, err
 | 
						|
    } else {
 | 
						|
        return Ref(term), nil
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) nest(nest int, repo Repository) (*Expr, error) {
 | 
						|
    var err error
 | 
						|
    var ret *Expr
 | 
						|
    var ntk _Token
 | 
						|
 | 
						|
    /* evaluate the nested expression */
 | 
						|
    if ret, err = self.expr(0, nest + 1, repo); err != nil {
 | 
						|
        return nil, err
 | 
						|
    }
 | 
						|
 | 
						|
    /* must follows with a ')' */
 | 
						|
    if ntk, err = self.next(); err != nil {
 | 
						|
        return nil, err
 | 
						|
    } else if ntk.tag != _T_punc || ntk.u64 != ')' {
 | 
						|
        return nil, newSyntaxError(ntk.pos, "')' expected")
 | 
						|
    } else {
 | 
						|
        return ret, nil
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) unit(nest int, repo Repository) (*Expr, error) {
 | 
						|
    if tk, err := self.next(); err != nil {
 | 
						|
        return nil, err
 | 
						|
    } else if tk.tag == _T_int {
 | 
						|
        return Int(int64(tk.u64)), nil
 | 
						|
    } else if tk.tag == _T_name {
 | 
						|
        return self.grab(tk, repo)
 | 
						|
    } else if tk.tag == _T_punc && tk.u64 == '(' {
 | 
						|
        return self.nest(nest, repo)
 | 
						|
    } else if tk.tag == _T_punc && tk.u64 == '+' {
 | 
						|
        return self.unit(nest, repo)
 | 
						|
    } else if tk.tag == _T_punc && tk.u64 == '-' {
 | 
						|
        return neg2(self.unit(nest, repo))
 | 
						|
    } else if tk.tag == _T_punc && tk.u64 == '~' {
 | 
						|
        return not2(self.unit(nest, repo))
 | 
						|
    } else {
 | 
						|
        return nil, newSyntaxError(tk.pos, "integer, unary operator or nested expression expected")
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) term(prec int, nest int, repo Repository) (*Expr, error) {
 | 
						|
    var err error
 | 
						|
    var val *Expr
 | 
						|
 | 
						|
    /* parse the LHS operand */
 | 
						|
    if val, err = self.expr(prec + 1, nest, repo); err != nil {
 | 
						|
        return nil, err
 | 
						|
    }
 | 
						|
 | 
						|
    /* parse all the operators of the same precedence */
 | 
						|
    for {
 | 
						|
        var op int
 | 
						|
        var rv *Expr
 | 
						|
        var tk _Token
 | 
						|
 | 
						|
        /* peek the next token */
 | 
						|
        pp := self.pos
 | 
						|
        tk, err = self.next()
 | 
						|
 | 
						|
        /* check for errors */
 | 
						|
        if err != nil {
 | 
						|
            return nil, err
 | 
						|
        }
 | 
						|
 | 
						|
        /* encountered EOF */
 | 
						|
        if tk.tag == _T_end {
 | 
						|
            return val, nil
 | 
						|
        }
 | 
						|
 | 
						|
        /* must be an operator */
 | 
						|
        if tk.tag != _T_punc {
 | 
						|
            return nil, newSyntaxError(tk.pos, "operators expected")
 | 
						|
        }
 | 
						|
 | 
						|
        /* check for the operator precedence */
 | 
						|
        if op = int(tk.u64); !precedence[prec][op] {
 | 
						|
            self.pos = pp
 | 
						|
            return val, nil
 | 
						|
        }
 | 
						|
 | 
						|
        /* evaluate the RHS operand, and combine the value */
 | 
						|
        if rv, err = self.expr(prec + 1, nest, repo); err != nil {
 | 
						|
            return nil, err
 | 
						|
        } else {
 | 
						|
            val = binaryOps[op](val, rv)
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
func (self *Parser) expr(prec int, nest int, repo Repository) (*Expr, error) {
 | 
						|
    if prec >= len(precedence) {
 | 
						|
        return self.unit(nest, repo)
 | 
						|
    } else {
 | 
						|
        return self.term(prec, nest, repo)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// Parse parses the expression, and returns it's AST tree.
 | 
						|
func (self *Parser) Parse(repo Repository) (*Expr, error) {
 | 
						|
    return self.expr(0, 0, repo)
 | 
						|
}
 | 
						|
 | 
						|
// SetSource resets the expression parser and sets the expression source.
 | 
						|
func (self *Parser) SetSource(src string) *Parser {
 | 
						|
    self.pos = 0
 | 
						|
    self.src = []rune(src)
 | 
						|
    return self
 | 
						|
}
 |