github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/errors.go (about) 1 package expressions 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/lmorg/murex/lang/expressions/symbols" 8 "github.com/lmorg/murex/utils/readline" 9 ) 10 11 func raiseError(expression []rune, node *astNodeT, pos int, message string) error { 12 if node == nil { 13 if expression != nil { 14 if pos < 1 { 15 pos = 1 16 } 17 18 exprRune, exprPos := cropCodeInErrMsg(expression, pos) 19 expr := string(exprRune) 20 21 return fmt.Errorf("%s\nExpression: %s\n : %s\nCharacter : %d", 22 message, expr, 23 strings.Repeat(" ", exprPos)+"^", pos) 24 } 25 26 exprRune, _ := cropCodeInErrMsg(expression, pos) 27 expr := string(exprRune) 28 29 return fmt.Errorf("%s\nExpression: %s", message, expr) 30 } 31 32 pos = node.pos 33 if node.pos < 0 { 34 pos = 0 35 } 36 37 if expression != nil { 38 exprRune, exprPos := cropCodeInErrMsg(expression, pos) 39 expr := string(exprRune) 40 41 return fmt.Errorf("%s\nExpression: %s\n : %s\nCharacter : %d\nSymbol : %s\nValue : '%s'", 42 message, expr, 43 strings.Repeat(" ", exprPos)+"^", pos+1, 44 node.key.String(), node.Value()) 45 46 } else { 47 return fmt.Errorf("%s at char %d\nSymbol : %s\nValue : '%s'", 48 message, pos+1, node.key.String(), node.Value()) 49 50 } 51 } 52 53 var errMessage = map[symbols.Exp]string{ 54 symbols.Undefined: "parser error", 55 symbols.Unexpected: "unexpected symbol", 56 symbols.SubExpressionEnd: "more closing parenthesis then opening parenthesis", 57 symbols.ObjectEnd: "more closing curly braces then opening braces", 58 symbols.ArrayEnd: "more closing square brackets then opening brackets", 59 symbols.InvalidHyphen: "unexpected hyphen", 60 } 61 62 func cropCodeInErrMsg(code []rune, pos int) ([]rune, int) { 63 width := readline.GetTermWidth() 64 if width < 80 { 65 width = 80 66 } 67 68 r := make([]rune, len(code)) 69 copy(r, code) 70 replaceRune(r, '\n', ' ') 71 replaceRune(r, '\r', ' ') 72 replaceRune(r, '\t', ' ') 73 74 if pos >= len(r) { 75 pos = len(r) - 1 76 } 77 78 if pos < 0 { 79 pos = 0 80 } 81 82 return _cropCodeInErrMsg(r, pos, width-20) 83 } 84 85 func _cropCodeInErrMsg(r []rune, pos, width int) ([]rune, int) { 86 switch { 87 case len(r) <= width: 88 return r, pos 89 case pos < width-2: 90 return r[:width], pos 91 case len(r)-pos < width: 92 return r[len(r)-width:], width - (len(r) - pos) 93 default: 94 w := width / 2 95 return r[pos-w : pos+w], w 96 } 97 } 98 99 func replaceRune(r []rune, find, replace rune) { 100 for i := range r { 101 if r[i] == find { 102 r[i] = replace 103 } 104 } 105 }