| 29 | } |
| 30 | |
| 31 | func (e *ParseError) Error() string { |
| 32 | var s strings.Builder |
| 33 | start := e.toSrcPos(e.item.Start) |
| 34 | end := e.toSrcPos(e.item.End) |
| 35 | rows := e.rows() |
| 36 | startLineIdx := max(start.Line-2, 0) |
| 37 | errorLineIdx := max(start.Line-1, 0) |
| 38 | |
| 39 | _, _ = fmt.Fprintf(&s, "error from %d:%d to %d:%d: %s\n\n", |
| 40 | start.Line, start.Col, |
| 41 | end.Line, end.Col, |
| 42 | e.msg) |
| 43 | |
| 44 | if len(rows) < start.Line { |
| 45 | s.WriteString("meta error: could not find source position in input\n") |
| 46 | return s.String() |
| 47 | } |
| 48 | |
| 49 | for line := startLineIdx; line <= errorLineIdx; line++ { |
| 50 | _, _ = fmt.Fprintf(&s, "%4d | %s\n", line, rows[line]) |
| 51 | } |
| 52 | s.WriteString(" | ") |
| 53 | for i, r := range rows[errorLineIdx] { |
| 54 | switch { |
| 55 | case start.Col == i: |
| 56 | s.WriteRune('^') |
| 57 | case start.Col <= i && i <= end.Col-1: |
| 58 | s.WriteRune('~') |
| 59 | case unicode.IsSpace(r): |
| 60 | s.WriteRune(r) |
| 61 | default: |
| 62 | s.WriteRune(' ') |
| 63 | } |
| 64 | } |
| 65 | s.WriteRune('\n') |
| 66 | |
| 67 | if errorLineIdx+1 < len(rows) { |
| 68 | _, _ = fmt.Fprintf(&s, "%4d | %s\n", errorLineIdx+1, rows[errorLineIdx+1]) |
| 69 | s.WriteRune('\n') |
| 70 | } |
| 71 | |
| 72 | return s.String() |
| 73 | } |
| 74 | |
| 75 | func (e *ParseError) ToAPI() *ketoapi.ParseError { |
| 76 | return &ketoapi.ParseError{ |