Skip to content

Commit

Permalink
export query parsing error type for getting offset and token
Browse files Browse the repository at this point in the history
  • Loading branch information
itchyny committed Mar 29, 2024
1 parent 857f6a7 commit 7ab8af4
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 24 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func main() {
```
- Firstly, use [`gojq.Parse(string) (*Query, error)`](https://pkg.go.dev/github.com/itchyny/gojq#Parse) to get the query from a string.
- Use [`gojq.ParseError`](https://pkg.go.dev/github.com/itchyny/gojq#ParseError) to get the error position and token of the parsing error.
- Secondly, get the result iterator
- using [`query.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Query.Run) or [`query.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Query.RunWithContext)
- or alternatively, compile the query using [`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq#Compile) and then [`code.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Code.Run) or [`code.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Code.RunWithContext). You can reuse the `*Code` against multiple inputs to avoid compilation of the same query. But for arguments of `code.Run`, do not give values sharing same data between multiple calls.
Expand Down
9 changes: 5 additions & 4 deletions cli/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package cli

import (
"encoding/json"
"errors"
"fmt"
"io"
"strconv"
"strings"
"unicode/utf8"

"github.com/itchyny/gojq"
"github.com/mattn/go-runewidth"
)

Expand Down Expand Up @@ -73,10 +75,9 @@ type queryParseError struct {

func (err *queryParseError) Error() string {
var offset int
if e, ok := err.err.(interface{ Token() (string, int) }); ok {
var token string
token, offset = e.Token()
offset -= len(token) - 1
var e *gojq.ParseError
if errors.As(err.err, &e) {
offset = e.Offset - len(e.Token) + 1
}
linestr, line, column := getLineByOffset(err.contents, offset)
if err.fname != "<arg>" || containsNewline(err.contents) {
Expand Down
21 changes: 9 additions & 12 deletions lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,37 +521,34 @@ func quoteAndEscape(src string, quote bool, controls int) []byte {
return buf
}

type parseError struct {
offset int
token string
// ParseError represents a description of a query parsing error.
type ParseError struct {
Offset int // the error occurred after reading Offset bytes
Token string // the Token that caused the error (may be empty)
tokenType int
}

func (err *parseError) Error() string {
func (err *ParseError) Error() string {
switch err.tokenType {
case eof:
return "unexpected EOF"
case tokInvalid:
return "invalid token " + jsonMarshal(err.token)
return "invalid token " + jsonMarshal(err.Token)
case tokInvalidEscapeSequence:
return `invalid escape sequence "` + err.token + `" in string literal`
return `invalid escape sequence "` + err.Token + `" in string literal`
case tokUnterminatedString:
return "unterminated string literal"
default:
return "unexpected token " + jsonMarshal(err.token)
return "unexpected token " + jsonMarshal(err.Token)
}
}

func (err *parseError) Token() (string, int) {
return err.token, err.offset
}

func (l *lexer) Error(string) {
offset, token := l.offset, l.token
if l.tokenType != eof && l.tokenType < utf8.RuneSelf {
token = string(rune(l.tokenType))
}
l.err = &parseError{offset, token, l.tokenType}
l.err = &ParseError{offset, token, l.tokenType}
}

func isWhite(ch byte) bool {
Expand Down
8 changes: 4 additions & 4 deletions parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions parser.go.y
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package gojq

// Parse a query string, and returns the query struct.
//
// If parsing failed, the returned error has the method Token() (string, int),
// which reports the invalid token and the byte offset in the query string. The
// token is empty if the error occurred after scanning the entire query string.
// The byte offset is the scanned bytes when the error occurred.
// If parsing failed, it returns an error of type [*ParseError], which has
// the byte offset and the invalid token. The byte offset is the scanned bytes
// when the error occurred. The token is empty if the error occurred after
// scanning the entire query string.
func Parse(src string) (*Query, error) {
l := newLexer(src)
if yyParse(l) > 0 {
Expand Down

0 comments on commit 7ab8af4

Please sign in to comment.