commit 221cef8e919583af6a42b331061a155ad58f8124
parent d89f406026b6e5c9d19938ff59c27b1bb28f2c28
Author: James Eversole <james@eversole.co>
Date: Tue, 15 Apr 2025 10:52:53 -0500
String escaping using backslash
Diffstat:
3 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/src/Lexer.hs b/src/Lexer.hs
@@ -41,7 +41,6 @@ tricuLexer = do
, try stringLiteral
, assign
, colon
- , backslash
, openParen
, closeParen
, openBracket
@@ -94,9 +93,6 @@ assign = char '=' $> LAssign
colon :: Lexer LToken
colon = char ':' $> LColon
-backslash :: Lexer LToken
-backslash = char '\\' $> LBackslash
-
openParen :: Lexer LToken
openParen = char '(' $> LOpenParen
@@ -126,7 +122,22 @@ integerLiteral = do
stringLiteral :: Lexer LToken
stringLiteral = do
char '"'
- content <- many (noneOf ['"'])
- char '"' --"
+ content <- manyTill Lexer.charLiteral (char '"')
return (LStringLiteral content)
+charLiteral :: Lexer Char
+charLiteral = escapedChar <|> normalChar
+ where
+ normalChar = noneOf ['"', '\\']
+ escapedChar = do
+ void $ char '\\'
+ c <- oneOf ['n', 't', 'r', 'f', 'b', '\\', '"', '\'']
+ return $ case c of
+ 'n' -> '\n'
+ 't' -> '\t'
+ 'r' -> '\r'
+ 'f' -> '\f'
+ 'b' -> '\b'
+ '\\' -> '\\'
+ '"' -> '"'
+ '\'' -> '\''
diff --git a/src/Research.hs b/src/Research.hs
@@ -38,7 +38,6 @@ data LToken
| LAssign
| LColon
| LDot
- | LBackslash
| LOpenParen
| LCloseParen
| LOpenBracket
diff --git a/test/Spec.hs b/test/Spec.hs
@@ -51,7 +51,22 @@ lexer = testGroup "Lexer Tests"
, testCase "Lex escaped characters in strings" $ do
let input = "\"hello\\nworld\""
- expect = Right [LStringLiteral "hello\\nworld"]
+ expect = Right [LStringLiteral "hello\nworld"]
+ runParser tricuLexer "" input @?= expect
+
+ , testCase "Lex multiple escaped characters in strings" $ do
+ let input = "\"tab:\\t newline:\\n quote:\\\" backslash:\\\\\""
+ expect = Right [LStringLiteral "tab:\t newline:\n quote:\" backslash:\\"]
+ runParser tricuLexer "" input @?= expect
+
+ , testCase "Lex escaped characters in string literals" $ do
+ let input = "x = \"line1\\nline2\\tindented\""
+ expect = Right [LIdentifier "x", LAssign, LStringLiteral "line1\nline2\tindented"]
+ runParser tricuLexer "" input @?= expect
+
+ , testCase "Lex empty string with escape sequence" $ do
+ let input = "\"\\\"\""
+ expect = Right [LStringLiteral "\""]
runParser tricuLexer "" input @?= expect
, testCase "Lex mixed literals" $ do