Make lexer errors more verbose
This commit is contained in:
parent
0ab1758dec
commit
76ee42a0a6
|
@ -88,6 +88,11 @@ func (l *Lexer) next() rune {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the value for the next token
|
||||||
|
func (l *Lexer) val() string {
|
||||||
|
return l.input[l.start:l.pos]
|
||||||
|
}
|
||||||
|
|
||||||
// Returns but does not consume the next rune in the input
|
// Returns but does not consume the next rune in the input
|
||||||
func (l *Lexer) peek() rune {
|
func (l *Lexer) peek() rune {
|
||||||
r := l.next()
|
r := l.next()
|
||||||
|
@ -198,7 +203,7 @@ func lexNull(l *Lexer) stateFn {
|
||||||
if l.acceptString("null") {
|
if l.acceptString("null") {
|
||||||
l.emit(Null)
|
l.emit(Null)
|
||||||
} else {
|
} else {
|
||||||
return l.errorf("Unexpected token")
|
return l.errorf("Unexpected (null) token: %q", l.val())
|
||||||
}
|
}
|
||||||
return lexInitial
|
return lexInitial
|
||||||
}
|
}
|
||||||
|
@ -206,6 +211,8 @@ func lexNull(l *Lexer) stateFn {
|
||||||
func lexBool(l *Lexer) stateFn {
|
func lexBool(l *Lexer) stateFn {
|
||||||
if l.acceptString("true") || l.acceptString("false") {
|
if l.acceptString("true") || l.acceptString("false") {
|
||||||
l.emit(Bool)
|
l.emit(Bool)
|
||||||
|
} else {
|
||||||
|
return l.errorf("Unexpected (bool) token: %q", l.val())
|
||||||
}
|
}
|
||||||
return lexInitial
|
return lexInitial
|
||||||
}
|
}
|
||||||
|
@ -225,7 +232,7 @@ func lexNumber(l *Lexer) stateFn {
|
||||||
default:
|
default:
|
||||||
l.backup()
|
l.backup()
|
||||||
if numDots > 1 || last == '.' {
|
if numDots > 1 || last == '.' {
|
||||||
return l.errorf("Invalid number")
|
return l.errorf("Invalid number: %q", l.val())
|
||||||
}
|
}
|
||||||
l.emit(Number)
|
l.emit(Number)
|
||||||
return lexInitial
|
return lexInitial
|
||||||
|
@ -263,12 +270,16 @@ func lexString(l *Lexer) stateFn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debug
|
||||||
|
//
|
||||||
|
|
||||||
func (i Item) String() string {
|
func (i Item) String() string {
|
||||||
switch i.Token {
|
switch i.Token {
|
||||||
case EOF:
|
case EOF:
|
||||||
return "EOF"
|
return "EOF"
|
||||||
case Error:
|
case Error:
|
||||||
return "Error: " + i.Val
|
return fmt.Sprintf("(Error: %q)", i.Val)
|
||||||
case BraceOpen:
|
case BraceOpen:
|
||||||
return "{"
|
return "{"
|
||||||
case BraceClose:
|
case BraceClose:
|
||||||
|
@ -284,13 +295,13 @@ func (i Item) String() string {
|
||||||
case Comma:
|
case Comma:
|
||||||
return ","
|
return ","
|
||||||
case Null:
|
case Null:
|
||||||
return "NULL"
|
return fmt.Sprintf("(NULL: %q)", i.Val)
|
||||||
case Bool:
|
case Bool:
|
||||||
return "Bool: " + i.Val
|
return fmt.Sprintf("(Bool: %q)", i.Val)
|
||||||
case Number:
|
case Number:
|
||||||
return "Number: " + i.Val
|
return fmt.Sprintf("(Number: %q)", i.Val)
|
||||||
case String:
|
case String:
|
||||||
return "String: " + i.Val
|
return fmt.Sprintf("(String: %q)", i.Val)
|
||||||
default:
|
default:
|
||||||
panic("Unreachable")
|
panic("Unreachable")
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,10 @@ func TestNumber(t *testing.T) {
|
||||||
Item{EOF, "", 0},
|
Item{EOF, "", 0},
|
||||||
})
|
})
|
||||||
compare(t, lex("123.456.789"), []Item{
|
compare(t, lex("123.456.789"), []Item{
|
||||||
Item{Error, "Invalid number", 0},
|
Item{Error, `Invalid number: "123.456.789"`, 0},
|
||||||
})
|
})
|
||||||
compare(t, lex("123."), []Item{
|
compare(t, lex("123."), []Item{
|
||||||
Item{Error, "Invalid number", 0},
|
Item{Error, `Invalid number: "123."`, 0},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue