string escapes
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"monkey/token"
|
||||
"strings"
|
||||
)
|
||||
@@ -119,7 +120,13 @@ func (l *Lexer) NextToken() token.Token {
|
||||
tok.Type = token.EOF
|
||||
case '"':
|
||||
tok.Type = token.STRING
|
||||
tok.Literal = l.readString()
|
||||
str, err := l.readString()
|
||||
if err != nil {
|
||||
tok = newToken(token.ILLEGAL, l.prevCh)
|
||||
} else {
|
||||
tok.Type = token.STRING
|
||||
tok.Literal = str
|
||||
}
|
||||
case '[':
|
||||
tok = newToken(token.LBRACKET, l.ch)
|
||||
case ']':
|
||||
@@ -181,12 +188,39 @@ func (l *Lexer) skipWhitespace() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) readString() string {
|
||||
func (l *Lexer) readString() (string, error) {
|
||||
b := &strings.Builder{}
|
||||
for {
|
||||
l.readChar()
|
||||
if l.ch == '\\' && l.peekChar() == '"' {
|
||||
if l.ch == '\\' {
|
||||
switch l.peekChar() {
|
||||
case '"':
|
||||
b.WriteByte('"')
|
||||
case 'n':
|
||||
b.WriteString("\n")
|
||||
case 'r':
|
||||
b.WriteString("\r")
|
||||
case 't':
|
||||
b.WriteString("\t")
|
||||
case '\\':
|
||||
b.WriteString("\\")
|
||||
case 'x':
|
||||
// Skip over the '\\', 'x' and the next two bytes (hex)
|
||||
l.readChar()
|
||||
l.readChar()
|
||||
l.readChar()
|
||||
src := string([]byte{l.prevCh, l.ch})
|
||||
dst, err := hex.DecodeString(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b.Write(dst)
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip over the '\\' and the matched single escape char
|
||||
l.readChar()
|
||||
continue
|
||||
} else {
|
||||
if l.ch == '"' || l.ch == 0 {
|
||||
break
|
||||
@@ -195,7 +229,7 @@ func (l *Lexer) readString() string {
|
||||
|
||||
b.WriteByte(l.ch)
|
||||
}
|
||||
return b.String()
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
func (l *Lexer) readLine() string {
|
||||
|
||||
Reference in New Issue
Block a user