aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-07-28 23:00:33 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-07-28 23:00:33 +0900
commitd2aaffc083bb1aa54301d0e908be0a0e412af8c9 (patch)
tree5616e785ecafd489c28bab9c558d604cc1e5eaa8
parentCount the number of each line in consecutive lines (diff)
downloadurubu-d2aaffc083bb1aa54301d0e908be0a0e412af8c9.tar.gz
urubu-d2aaffc083bb1aa54301d0e908be0a0e412af8c9.tar.xz
Add a token position and detailed info to a lexical error message
-rw-r--r--spec/lexer.go12
-rw-r--r--spec/lexer_test.go6
-rw-r--r--spec/parser.go10
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