github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/error.go (about)

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