aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-10-11 09:42:22 +0100
committerAkshay <[email protected]>2020-10-11 09:42:22 +0100
commit2d9320bf71912b2c682c15a8933031394de40936 (patch)
treebb62edb3d24e3411347291bb573e483dfe490149 /src
parent883092e4ff4f8beb59e3d705ef247c235baa6bb7 (diff)
handle lists and dottedlists without backtracking
Diffstat (limited to 'src')
-rw-r--r--src/Parser.hs34
1 files changed, 15 insertions, 19 deletions
diff --git a/src/Parser.hs b/src/Parser.hs
index 5053d0a..37b0b9d 100644
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -4,9 +4,7 @@ module Parser ( parseLispValue
4 , parseInt 4 , parseInt
5 , parseFloat 5 , parseFloat
6 , parseId 6 , parseId
7 , parseList
8 , parseQuote 7 , parseQuote
9 , parseDottedList
10 ) where 8 ) where
11 9
12import Control.Applicative ((<$>)) 10import Control.Applicative ((<$>))
@@ -14,6 +12,8 @@ import Control.Monad (liftM)
14import Text.ParserCombinators.Parsec 12import Text.ParserCombinators.Parsec
15 13
16-- TODO: use LispNumber (src/Operators.hs) here instead of IntLiteral and FloatLiteral 14-- TODO: use LispNumber (src/Operators.hs) here instead of IntLiteral and FloatLiteral
15-- TODO: add character literals: \#a \#b \#c \#space \#newline
16-- TODO: add support for complex numbers, oct and hex numbers
17data Expr = List [Expr] 17data Expr = List [Expr]
18 | DottedList [Expr] Expr 18 | DottedList [Expr] Expr
19 | StringLiteral String 19 | StringLiteral String
@@ -23,10 +23,13 @@ data Expr = List [Expr]
23 | Id String 23 | Id String
24 deriving (Eq) 24 deriving (Eq)
25 25
26-- backslash double quote escapes a quote inside strings
27quotedChar = noneOf ['\"'] <|> try (string "\\\"" >> return '"')
28
26parseString :: Parser Expr 29parseString :: Parser Expr
27parseString = do 30parseString = do
28 char '"' 31 char '"'
29 innards <- many (noneOf "\"") 32 innards <- many quotedChar
30 char '"' 33 char '"'
31 return (StringLiteral innards) 34 return (StringLiteral innards)
32 35
@@ -56,16 +59,6 @@ parseId = do
56whiteSpace :: Parser () 59whiteSpace :: Parser ()
57whiteSpace = skipMany1 space 60whiteSpace = skipMany1 space
58 61
59parseList :: Parser Expr
60parseList = List <$> sepBy parseLispValue whiteSpace
61
62parseDottedList :: Parser Expr
63parseDottedList = do
64 head <- endBy parseLispValue whiteSpace
65 char '.'
66 whiteSpace
67 DottedList head <$> parseLispValue
68
69type Alias = String 62type Alias = String
70parseModifier :: Char -> Alias -> Parser Expr 63parseModifier :: Char -> Alias -> Parser Expr
71parseModifier c alias = do 64parseModifier c alias = do
@@ -76,7 +69,7 @@ parseModifier c alias = do
76parseQuote = parseModifier '\'' "quote" 69parseQuote = parseModifier '\'' "quote"
77parseQuasiquote = parseModifier '`' "quasiquote" 70parseQuasiquote = parseModifier '`' "quasiquote"
78parseUnquote = parseModifier ',' "unquote" 71parseUnquote = parseModifier ',' "unquote"
79-- TODO: add modifier for unquote splicing 72-- TODO: add modifier for unquote splicing: ,@
80 73
81parseLispValue :: Parser Expr 74parseLispValue :: Parser Expr
82parseLispValue = 75parseLispValue =
@@ -87,12 +80,15 @@ parseLispValue =
87 <|> parseQuote 80 <|> parseQuote
88 <|> parseQuasiquote 81 <|> parseQuasiquote
89 <|> parseUnquote 82 <|> parseUnquote
83 -- handles lists and dotted lists
90 <|> do 84 <|> do
91 char '(' 85 char '(' >> spaces
92 x <- try parseList <|> parseDottedList 86 x <- sepEndBy parseLispValue whiteSpace
93 char ')' 87 spaces
94 return x 88 t <- optionMaybe $ char '.' >> space >> parseLispValue
95 <?> "expected lisp value!" 89 spaces >> char ')'
90 return $ maybe (List x) (DottedList x) t
91 <?> "lisp value"
96 92
97showLispList :: [Expr] -> String 93showLispList :: [Expr] -> String
98showLispList = unwords . map show 94showLispList = unwords . map show