diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-28 23:00:33 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-28 23:00:33 +0900 |
commit | d2aaffc083bb1aa54301d0e908be0a0e412af8c9 (patch) | |
tree | 5616e785ecafd489c28bab9c558d604cc1e5eaa8 | |
parent | Count the number of each line in consecutive lines (diff) | |
download | urubu-d2aaffc083bb1aa54301d0e908be0a0e412af8c9.tar.gz urubu-d2aaffc083bb1aa54301d0e908be0a0e412af8c9.tar.xz |
Add a token position and detailed info to a lexical error message
-rw-r--r-- | spec/lexer.go | 12 | ||||
-rw-r--r-- | spec/lexer_test.go | 6 | ||||
-rw-r--r-- | spec/parser.go | 10 |
3 files changed, 21 insertions, 7 deletions
diff --git a/spec/lexer.go b/spec/lexer.go index 1f50a27..30757c6 100644 --- a/spec/lexer.go +++ b/spec/lexer.go @@ -88,10 +88,11 @@ func newEOFToken() *token { } } -func newInvalidToken(text string) *token { +func newInvalidToken(text string, pos Position) *token { return &token{ kind: tokenKindInvalid, text: text, + pos: pos, } } @@ -157,7 +158,7 @@ func (l *lexer) lexAndSkipWSs() (*token, error) { return nil, err } if tok.Invalid { - newInvalidToken(tok.Text()) + return newInvalidToken(tok.Text(), newPosition(l.row)), nil } if tok.EOF { return newEOFToken(), nil @@ -182,8 +183,9 @@ func (l *lexer) lexAndSkipWSs() (*token, error) { case "identifier": if strings.HasPrefix(tok.Text(), "_") { return nil, &verr.SpecError{ - Cause: synErrAutoGenID, - Row: l.row, + Cause: synErrAutoGenID, + Detail: tok.Text(), + Row: l.row, } } return newIDToken(tok.Text(), newPosition(l.row)), nil @@ -257,6 +259,6 @@ func (l *lexer) lexAndSkipWSs() (*token, error) { case "expansion": return newSymbolToken(tokenKindExpantion, newPosition(l.row)), nil default: - return newInvalidToken(tok.Text()), nil + return newInvalidToken(tok.Text(), newPosition(l.row)), nil } } diff --git a/spec/lexer_test.go b/spec/lexer_test.go index 569f278..e016def 100644 --- a/spec/lexer_test.go +++ b/spec/lexer_test.go @@ -24,6 +24,10 @@ func TestLexer_Run(t *testing.T) { return newPositionToken(num, newPosition(1)) } + invalidTok := func(text string) *token { + return newInvalidToken(text, newPosition(1)) + } + tests := []struct { caption string src string @@ -131,7 +135,7 @@ bar // This is the fourth comment. src: `abc!!!def`, tokens: []*token{ idTok("abc"), - newInvalidToken("!!!"), + invalidTok("!!!"), idTok("def"), newEOFToken(), }, diff --git a/spec/parser.go b/spec/parser.go index 4773da6..29248f4 100644 --- a/spec/parser.go +++ b/spec/parser.go @@ -76,6 +76,14 @@ func raiseSyntaxError(row int, synErr *SyntaxError) { }) } +func raiseSyntaxErrorWithDetail(row int, synErr *SyntaxError, detail string) { + panic(&verr.SpecError{ + Cause: synErr, + Detail: detail, + Row: row, + }) +} + func Parse(src io.Reader) (*RootNode, error) { p, err := newParser(src) if err != nil { @@ -426,7 +434,7 @@ func (p *parser) consume(expected tokenKind) bool { } p.pos = tok.pos if tok.kind == tokenKindInvalid { - raiseSyntaxError(p.pos.Row, synErrInvalidToken) + raiseSyntaxErrorWithDetail(p.pos.Row, synErrInvalidToken, tok.text) } if tok.kind == expected { p.lastTok = tok |