about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-08-30 00:28:12 +0000
committerMel <einebeere@gmail.com>2022-08-30 00:28:12 +0000
commitc935cde4c4ec65192d51933202e270da1e4d2050 (patch)
tree5773163fc290f12afedad843ceca7c4d18cefd9e
parent6f5014e6589ca6b60c12e1ce94685c122eb6d590 (diff)
downloadjinx-c935cde4c4ec65192d51933202e270da1e4d2050.tar.zst
jinx-c935cde4c4ec65192d51933202e270da1e4d2050.zip
Scanner escape sequences
-rw-r--r--pkg/lang/scanner/errors.go8
-rw-r--r--pkg/lang/scanner/scanner.go35
2 files changed, 43 insertions, 0 deletions
diff --git a/pkg/lang/scanner/errors.go b/pkg/lang/scanner/errors.go
index 6a6f9d9..a982b60 100644
--- a/pkg/lang/scanner/errors.go
+++ b/pkg/lang/scanner/errors.go
@@ -14,3 +14,11 @@ type ErrUnknownChar struct {
 func (e ErrUnknownChar) Error() string {
 	return "unknown character: " + string(e.Char)
 }
+
+type ErrUnknownEscapeSequence struct {
+	Char rune
+}
+
+func (e ErrUnknownEscapeSequence) Error() string {
+	return "unknown escape sequence: \\" + string(e.Char)
+}
diff --git a/pkg/lang/scanner/scanner.go b/pkg/lang/scanner/scanner.go
index 35c30cd..eb7da89 100644
--- a/pkg/lang/scanner/scanner.go
+++ b/pkg/lang/scanner/scanner.go
@@ -178,6 +178,24 @@ func (s *Scanner) scanString() (token.Token, error) {
 			break
 		}
 
+		if c == '\\' {
+			sequence, eof, err := s.src.Next()
+			if err != nil {
+				return token.Token{}, err
+			}
+
+			if eof {
+				return token.Token{}, ErrUnclosedString
+			}
+
+			escaped, err := escapedChar(sequence)
+			if err != nil {
+				return token.Token{}, err
+			}
+
+			c = escaped
+		}
+
 		buf.WriteRune(c)
 	}
 
@@ -322,3 +340,20 @@ func (s *Scanner) skipWhitespace() (bool, source.Loc, error) {
 
 	return hadNewline, firstNewline, nil
 }
+
+func escapedChar(c rune) (rune, error) {
+	switch c {
+	case 'n':
+		return '\n', nil
+	case 'r':
+		return '\r', nil
+	case 't':
+		return '\t', nil
+	case '\\':
+		return '\\', nil
+	case '"':
+		return '"', nil
+	}
+
+	return c, ErrUnknownEscapeSequence{Char: c}
+}