123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- 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
- }
|