error.go raw

   1  package ast
   2  
   3  import (
   4      `fmt`
   5      `strings`
   6      `unsafe`
   7  
   8      `github.com/bytedance/sonic/internal/native/types`
   9  )
  10  
  11  
  12  func newError(err types.ParsingError, msg string) *Node {
  13      return &Node{
  14          t: V_ERROR,
  15          l: uint(err),
  16          p: unsafe.Pointer(&msg),
  17      }
  18  }
  19  
  20  func newErrorPair(err SyntaxError) *Pair {
  21     return &Pair{0, "", *newSyntaxError(err)}
  22  }
  23  
  24  // Error returns error message if the node is invalid
  25  func (self Node) Error() string {
  26      if self.t != V_ERROR {
  27          return ""
  28      } else {
  29          return *(*string)(self.p)
  30      } 
  31  }
  32  
  33  func newSyntaxError(err SyntaxError) *Node {
  34      msg := err.Description()
  35      return &Node{
  36          t: V_ERROR,
  37          l: uint(err.Code),
  38          p: unsafe.Pointer(&msg),
  39      }
  40  }
  41  
  42  func (self *Parser) syntaxError(err types.ParsingError) SyntaxError {
  43      return SyntaxError{
  44          Pos : self.p,
  45          Src : self.s,
  46          Code: err,
  47      }
  48  }
  49  
  50  func unwrapError(err error) *Node {
  51      if se, ok := err.(*Node); ok {
  52          return se
  53      }else if sse, ok := err.(Node); ok {
  54          return &sse
  55      } else {
  56          msg := err.Error()
  57          return &Node{
  58              t: V_ERROR,
  59              p: unsafe.Pointer(&msg),
  60          }
  61      }
  62  }
  63  
  64  type SyntaxError struct {
  65      Pos  int
  66      Src  string
  67      Code types.ParsingError
  68      Msg  string
  69  }
  70  
  71  func (self SyntaxError) Error() string {
  72      return fmt.Sprintf("%q", self.Description())
  73  }
  74  
  75  func (self SyntaxError) Description() string {
  76      return "Syntax error " + self.description()
  77  }
  78  
  79  func (self SyntaxError) description() string {
  80      i := 16
  81      p := self.Pos - i
  82      q := self.Pos + i
  83  
  84      /* check for empty source */
  85      if self.Src == "" {
  86          return fmt.Sprintf("no sources available, the input json is empty: %#v", self)
  87      }
  88  
  89      /* prevent slicing before the beginning */
  90      if p < 0 {
  91          p, q, i = 0, q - p, i + p
  92      }
  93  
  94      /* prevent slicing beyond the end */
  95      if n := len(self.Src); q > n {
  96          n = q - n
  97          q = len(self.Src)
  98  
  99          /* move the left bound if possible */
 100          if p > n {
 101              i += n
 102              p -= n
 103          }
 104      }
 105  
 106      /* left and right length */
 107      x := clamp_zero(i)
 108      y := clamp_zero(q - p - i - 1)
 109  
 110      /* compose the error description */
 111      return fmt.Sprintf(
 112          "at index %d: %s\n\n\t%s\n\t%s^%s\n",
 113          self.Pos,
 114          self.Message(),
 115          self.Src[p:q],
 116          strings.Repeat(".", x),
 117          strings.Repeat(".", y),
 118      )
 119  }
 120  
 121  func (self SyntaxError) Message() string {
 122      if self.Msg == "" {
 123          return self.Code.Message()
 124      }
 125      return self.Msg
 126  }
 127  
 128  func clamp_zero(v int) int {
 129      if v < 0 {
 130          return 0
 131      } else {
 132          return v
 133      }
 134  }
 135