| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 | package exprimport (    `strconv`    `unicode`    `unsafe`)type _TokenKind uint8const (    _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}
 |