github.com/chenzhuoyu/iasm@v0.9.1/expr/parser.go (about)

     1  package expr
     2  
     3  import (
     4      `strconv`
     5      `unicode`
     6      `unsafe`
     7  )
     8  
     9  type _TokenKind uint8
    10  
    11  const (
    12      _T_end _TokenKind = iota + 1
    13      _T_int
    14      _T_punc
    15      _T_name
    16  )
    17  
    18  const (
    19      _OP2 = 0x80
    20      _POW = _OP2 | '*'
    21      _SHL = _OP2 | '<'
    22      _SHR = _OP2 | '>'
    23  )
    24  
    25  type _Slice struct {
    26      p unsafe.Pointer
    27      n int
    28      c int
    29  }
    30  
    31  type _Token struct {
    32      pos int
    33      ptr *rune
    34      u64 uint64
    35      tag _TokenKind
    36  }
    37  
    38  func (self _Token) str() (v string) {
    39      return string(self.rbuf())
    40  }
    41  
    42  func (self _Token) rbuf() (v []rune) {
    43      (*_Slice)(unsafe.Pointer(&v)).c = int(self.u64)
    44      (*_Slice)(unsafe.Pointer(&v)).n = int(self.u64)
    45      (*_Slice)(unsafe.Pointer(&v)).p = unsafe.Pointer(self.ptr)
    46      return
    47  }
    48  
    49  func tokenEnd(p int) _Token {
    50      return _Token {
    51          pos: p,
    52          tag: _T_end,
    53      }
    54  }
    55  
    56  func tokenInt(p int, v uint64) _Token {
    57      return _Token {
    58          pos: p,
    59          u64: v,
    60          tag: _T_int,
    61      }
    62  }
    63  
    64  func tokenPunc(p int, v rune) _Token {
    65      return _Token {
    66          pos: p,
    67          tag: _T_punc,
    68          u64: uint64(v),
    69      }
    70  }
    71  
    72  func tokenName(p int, v []rune) _Token {
    73      return _Token {
    74          pos: p,
    75          ptr: &v[0],
    76          tag: _T_name,
    77          u64: uint64(len(v)),
    78      }
    79  }
    80  
    81  // Repository represents a repository of Term's.
    82  type Repository interface {
    83      Get(name string) (Term, error)
    84  }
    85  
    86  // Parser parses an expression string to it's AST representation.
    87  type Parser struct {
    88      pos int
    89      src []rune
    90  }
    91  
    92  var binaryOps = [...]func(*Expr, *Expr) *Expr {
    93      '+'  : (*Expr).Add,
    94      '-'  : (*Expr).Sub,
    95      '*'  : (*Expr).Mul,
    96      '/'  : (*Expr).Div,
    97      '%'  : (*Expr).Mod,
    98      '&'  : (*Expr).And,
    99      '^'  : (*Expr).Xor,
   100      '|'  : (*Expr).Or,
   101      _SHL : (*Expr).Shl,
   102      _SHR : (*Expr).Shr,
   103      _POW : (*Expr).Pow,
   104  }
   105  
   106  var precedence = [...]map[int]bool {
   107      {_SHL: true, _SHR: true},
   108      {'|' : true},
   109      {'^' : true},
   110      {'&' : true},
   111      {'+' : true, '-': true},
   112      {'*' : true, '/': true, '%': true},
   113      {_POW: true},
   114  }
   115  
   116  func (self *Parser) ch() rune {
   117      return self.src[self.pos]
   118  }
   119  
   120  func (self *Parser) eof() bool {
   121      return self.pos >= len(self.src)
   122  }
   123  
   124  func (self *Parser) rch() (v rune) {
   125      v, self.pos = self.src[self.pos], self.pos + 1
   126      return
   127  }
   128  
   129  func (self *Parser) hex(ss []rune) bool {
   130      if len(ss) == 1 && ss[0] == '0' {
   131          return unicode.ToLower(self.ch()) == 'x'
   132      } else if len(ss) <= 1 || unicode.ToLower(ss[1]) != 'x' {
   133          return unicode.IsDigit(self.ch())
   134      } else {
   135          return ishexdigit(self.ch())
   136      }
   137  }
   138  
   139  func (self *Parser) int(p int, ss []rune) (_Token, error) {
   140      var err error
   141      var val uint64
   142  
   143      /* find all the digits */
   144      for !self.eof() && self.hex(ss) {
   145          ss = append(ss, self.rch())
   146      }
   147  
   148      /* parse the value */
   149      if val, err = strconv.ParseUint(string(ss), 0, 64); err != nil {
   150          return _Token{}, err
   151      } else {
   152          return tokenInt(p, val), nil
   153      }
   154  }
   155  
   156  func (self *Parser) name(p int, ss []rune) _Token {
   157      for !self.eof() && isident(self.ch()) { ss = append(ss, self.rch()) }
   158      return tokenName(p, ss)
   159  }
   160  
   161  func (self *Parser) read(p int, ch rune) (_Token, error) {
   162      if isdigit(ch) {
   163          return self.int(p, []rune { ch })
   164      } else if isident0(ch) {
   165          return self.name(p, []rune { ch }), nil
   166      } else if isop2ch(ch) && !self.eof() && self.ch() == ch {
   167          return tokenPunc(p, _OP2 | self.rch()), nil
   168      } else if isop1ch(ch) {
   169          return tokenPunc(p, ch), nil
   170      } else {
   171          return _Token{}, newSyntaxError(self.pos, "invalid character " + strconv.QuoteRuneToASCII(ch))
   172      }
   173  }
   174  
   175  func (self *Parser) next() (_Token, error) {
   176      for {
   177          var p int
   178          var c rune
   179  
   180          /* check for EOF */
   181          if self.eof() {
   182              return tokenEnd(self.pos), nil
   183          }
   184  
   185          /* read the next char */
   186          p = self.pos
   187          c = self.rch()
   188  
   189          /* parse the token if not a space */
   190          if !unicode.IsSpace(c) {
   191              return self.read(p, c)
   192          }
   193      }
   194  }
   195  
   196  func (self *Parser) grab(tk _Token, repo Repository) (*Expr, error) {
   197      if repo == nil {
   198          return nil, newSyntaxError(tk.pos, "unresolved symbol: " + tk.str())
   199      } else if term, err := repo.Get(tk.str()); err != nil {
   200          return nil, err
   201      } else {
   202          return Ref(term), nil
   203      }
   204  }
   205  
   206  func (self *Parser) nest(nest int, repo Repository) (*Expr, error) {
   207      var err error
   208      var ret *Expr
   209      var ntk _Token
   210  
   211      /* evaluate the nested expression */
   212      if ret, err = self.expr(0, nest + 1, repo); err != nil {
   213          return nil, err
   214      }
   215  
   216      /* must follows with a ')' */
   217      if ntk, err = self.next(); err != nil {
   218          return nil, err
   219      } else if ntk.tag != _T_punc || ntk.u64 != ')' {
   220          return nil, newSyntaxError(ntk.pos, "')' expected")
   221      } else {
   222          return ret, nil
   223      }
   224  }
   225  
   226  func (self *Parser) unit(nest int, repo Repository) (*Expr, error) {
   227      if tk, err := self.next(); err != nil {
   228          return nil, err
   229      } else if tk.tag == _T_int {
   230          return Int(int64(tk.u64)), nil
   231      } else if tk.tag == _T_name {
   232          return self.grab(tk, repo)
   233      } else if tk.tag == _T_punc && tk.u64 == '(' {
   234          return self.nest(nest, repo)
   235      } else if tk.tag == _T_punc && tk.u64 == '+' {
   236          return self.unit(nest, repo)
   237      } else if tk.tag == _T_punc && tk.u64 == '-' {
   238          return neg2(self.unit(nest, repo))
   239      } else if tk.tag == _T_punc && tk.u64 == '~' {
   240          return not2(self.unit(nest, repo))
   241      } else {
   242          return nil, newSyntaxError(tk.pos, "integer, unary operator or nested expression expected")
   243      }
   244  }
   245  
   246  func (self *Parser) term(prec int, nest int, repo Repository) (*Expr, error) {
   247      var err error
   248      var val *Expr
   249  
   250      /* parse the LHS operand */
   251      if val, err = self.expr(prec + 1, nest, repo); err != nil {
   252          return nil, err
   253      }
   254  
   255      /* parse all the operators of the same precedence */
   256      for {
   257          var op int
   258          var rv *Expr
   259          var tk _Token
   260  
   261          /* peek the next token */
   262          pp := self.pos
   263          tk, err = self.next()
   264  
   265          /* check for errors */
   266          if err != nil {
   267              return nil, err
   268          }
   269  
   270          /* encountered EOF */
   271          if tk.tag == _T_end {
   272              return val, nil
   273          }
   274  
   275          /* must be an operator */
   276          if tk.tag != _T_punc {
   277              return nil, newSyntaxError(tk.pos, "operators expected")
   278          }
   279  
   280          /* check for the operator precedence */
   281          if op = int(tk.u64); !precedence[prec][op] {
   282              self.pos = pp
   283              return val, nil
   284          }
   285  
   286          /* evaluate the RHS operand, and combine the value */
   287          if rv, err = self.expr(prec + 1, nest, repo); err != nil {
   288              return nil, err
   289          } else {
   290              val = binaryOps[op](val, rv)
   291          }
   292      }
   293  }
   294  
   295  func (self *Parser) expr(prec int, nest int, repo Repository) (*Expr, error) {
   296      if prec >= len(precedence) {
   297          return self.unit(nest, repo)
   298      } else {
   299          return self.term(prec, nest, repo)
   300      }
   301  }
   302  
   303  // Parse parses the expression, and returns it's AST tree.
   304  func (self *Parser) Parse(repo Repository) (*Expr, error) {
   305      return self.expr(0, 0, repo)
   306  }
   307  
   308  // SetSource resets the expression parser and sets the expression source.
   309  func (self *Parser) SetSource(src string) *Parser {
   310      self.pos = 0
   311      self.src = []rune(src)
   312      return self
   313  }