From dec2e63b78a55e75ef32631d7bc8798990286660 Mon Sep 17 00:00:00 2001 From: Aleksandr Petrukhin Date: Tue, 24 Jan 2017 17:45:55 +0300 Subject: [PATCH] Added minor improvements --- jlexer/lexer.go | 99 +++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/jlexer/lexer.go b/jlexer/lexer.go index f0bc4d0..fc0af92 100644 --- a/jlexer/lexer.go +++ b/jlexer/lexer.go @@ -6,15 +6,15 @@ package jlexer import ( "encoding/base64" + "errors" "fmt" "io" "reflect" "strconv" + "unicode" + "unicode/utf16" "unicode/utf8" "unsafe" - "errors" - "unicode/utf16" - "unicode" ) // tokenKind determines type of a token. @@ -51,12 +51,11 @@ type Lexer struct { UseMultipleErrors bool // If we want to use multiple errors. fatalError error // Fatal error occured during lexing. It is usually a syntax error. - nowSem bool // If semantic error occured during parsing. multipleErrors []*LexerError // Semantic errors occured during lexing. Marshalling will be continued after finding this errors. } -// fetchToken scans the input for the next token. -func (r *Lexer) fetchToken() { +// FetchToken scans the input for the next token. +func (r *Lexer) FetchToken() { r.token.kind = tokenUndef r.start = r.pos @@ -395,7 +394,7 @@ func (r *Lexer) scanToken() { return } - r.fetchToken() + r.FetchToken() } // consume resets the current token to allow scanning the next one. @@ -450,7 +449,7 @@ func (r *Lexer) errInvalidToken(expected string) { r.addNonfatalError(&LexerError{ Reason: fmt.Sprintf("expected %s", expected), Offset: r.start, - Data: string(r.Data[r.start:]), + Data: string(r.Data[r.start:r.pos]), }) return } @@ -468,10 +467,14 @@ func (r *Lexer) errInvalidToken(expected string) { } } +func (r *Lexer) GetPos() int { + return r.pos +} + // Delim consumes a token and verifies that it is the given delimiter. func (r *Lexer) Delim(c byte) { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.delimValue != c { @@ -485,7 +488,7 @@ func (r *Lexer) Delim(c byte) { // IsDelim returns true if there was no scanning error and next token is the given delimiter. func (r *Lexer) IsDelim(c byte) bool { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } return !r.Ok() || r.token.delimValue == c } @@ -493,7 +496,7 @@ func (r *Lexer) IsDelim(c byte) bool { // Null verifies that the next token is null and consumes it. func (r *Lexer) Null() { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.kind != tokenNull { r.errInvalidToken("null") @@ -504,7 +507,7 @@ func (r *Lexer) Null() { // IsNull returns true if the next token is a null keyword. func (r *Lexer) IsNull() bool { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } return r.Ok() && r.token.kind == tokenNull } @@ -512,7 +515,7 @@ func (r *Lexer) IsNull() bool { // Skip skips a single token. func (r *Lexer) Skip() { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } r.consume() } @@ -605,28 +608,33 @@ func (r *Lexer) Consumed() { } } +func (r *Lexer) unsafeString() (string, []byte) { + if r.token.kind == tokenUndef && r.Ok() { + r.FetchToken() + } + if !r.Ok() || r.token.kind != tokenString { + r.errInvalidToken("string") + return "", nil + } + bytes := r.token.byteValue + ret := bytesToStr(r.token.byteValue) + r.consume() + return ret, bytes +} + // UnsafeString returns the string value if the token is a string literal. // // Warning: returned string may point to the input buffer, so the string should not outlive // the input buffer. Intended pattern of usage is as an argument to a switch statement. func (r *Lexer) UnsafeString() string { - if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() - } - if !r.Ok() || r.token.kind != tokenString { - r.errInvalidToken("string") - return "" - } - - ret := bytesToStr(r.token.byteValue) - r.consume() + ret, _ := r.unsafeString() return ret } // String reads a string literal. func (r *Lexer) String() string { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.kind != tokenString { r.errInvalidToken("string") @@ -640,7 +648,7 @@ func (r *Lexer) String() string { // Bytes reads a string literal and base64 decodes it into a byte slice. func (r *Lexer) Bytes() []byte { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.kind != tokenString { r.errInvalidToken("string") @@ -662,7 +670,7 @@ func (r *Lexer) Bytes() []byte { // Bool reads a true or false boolean keyword. func (r *Lexer) Bool() bool { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.kind != tokenBool { r.errInvalidToken("bool") @@ -675,7 +683,7 @@ func (r *Lexer) Bool() bool { func (r *Lexer) number() string { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() || r.token.kind != tokenNumber { r.errInvalidToken("number") @@ -697,6 +705,7 @@ func (r *Lexer) Uint8() uint8 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return uint8(n) @@ -713,6 +722,7 @@ func (r *Lexer) Uint16() uint16 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return uint16(n) @@ -729,6 +739,7 @@ func (r *Lexer) Uint32() uint32 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return uint32(n) @@ -745,6 +756,7 @@ func (r *Lexer) Uint64() uint64 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return n @@ -765,6 +777,7 @@ func (r *Lexer) Int8() int8 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return int8(n) @@ -781,6 +794,7 @@ func (r *Lexer) Int16() int16 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return int16(n) @@ -797,6 +811,7 @@ func (r *Lexer) Int32() int32 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return int32(n) @@ -813,6 +828,7 @@ func (r *Lexer) Int64() int64 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return n @@ -823,7 +839,7 @@ func (r *Lexer) Int() int { } func (r *Lexer) Uint8Str() uint8 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -833,13 +849,14 @@ func (r *Lexer) Uint8Str() uint8 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return uint8(n) } func (r *Lexer) Uint16Str() uint16 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -849,13 +866,14 @@ func (r *Lexer) Uint16Str() uint16 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return uint16(n) } func (r *Lexer) Uint32Str() uint32 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -865,13 +883,14 @@ func (r *Lexer) Uint32Str() uint32 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return uint32(n) } func (r *Lexer) Uint64Str() uint64 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -881,6 +900,7 @@ func (r *Lexer) Uint64Str() uint64 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return n @@ -891,7 +911,7 @@ func (r *Lexer) UintStr() uint { } func (r *Lexer) Int8Str() int8 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -901,13 +921,14 @@ func (r *Lexer) Int8Str() int8 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return int8(n) } func (r *Lexer) Int16Str() int16 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -917,13 +938,14 @@ func (r *Lexer) Int16Str() int16 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return int16(n) } func (r *Lexer) Int32Str() int32 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -933,13 +955,14 @@ func (r *Lexer) Int32Str() int32 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return int32(n) } func (r *Lexer) Int64Str() int64 { - s := r.UnsafeString() + s, b := r.unsafeString() if !r.Ok() { return 0 } @@ -949,6 +972,7 @@ func (r *Lexer) Int64Str() int64 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: string(b), }) } return n @@ -969,6 +993,7 @@ func (r *Lexer) Float32() float32 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return float32(n) @@ -985,6 +1010,7 @@ func (r *Lexer) Float64() float64 { r.addNonfatalError(&LexerError{ Offset: r.start, Reason: err.Error(), + Data: s, }) } return n @@ -1002,6 +1028,7 @@ func (r *Lexer) AddError(e error) { func (r *Lexer) addNonfatalError(err *LexerError) { if r.UseMultipleErrors { + // We don't want to add errors with the same offset. if len(r.multipleErrors) != 0 && r.multipleErrors[len(r.multipleErrors)-1].Offset == err.Offset { return } @@ -1018,7 +1045,7 @@ func (r *Lexer) GetNonFatalErrors() []*LexerError { // Interface fetches an interface{} analogous to the 'encoding/json' package. func (r *Lexer) Interface() interface{} { if r.token.kind == tokenUndef && r.Ok() { - r.fetchToken() + r.FetchToken() } if !r.Ok() {