diff options
author | Akshay <[email protected]> | 2020-10-11 09:42:22 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2020-10-11 09:42:22 +0100 |
commit | 2d9320bf71912b2c682c15a8933031394de40936 (patch) | |
tree | bb62edb3d24e3411347291bb573e483dfe490149 /src/Parser.hs | |
parent | 883092e4ff4f8beb59e3d705ef247c235baa6bb7 (diff) |
handle lists and dottedlists without backtracking
Diffstat (limited to 'src/Parser.hs')
-rw-r--r-- | src/Parser.hs | 34 |
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 | ||
12 | import Control.Applicative ((<$>)) | 10 | import Control.Applicative ((<$>)) |
@@ -14,6 +12,8 @@ import Control.Monad (liftM) | |||
14 | import Text.ParserCombinators.Parsec | 12 | import 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 | ||
17 | data Expr = List [Expr] | 17 | data 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 | ||
27 | quotedChar = noneOf ['\"'] <|> try (string "\\\"" >> return '"') | ||
28 | |||
26 | parseString :: Parser Expr | 29 | parseString :: Parser Expr |
27 | parseString = do | 30 | parseString = 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 | |||
56 | whiteSpace :: Parser () | 59 | whiteSpace :: Parser () |
57 | whiteSpace = skipMany1 space | 60 | whiteSpace = skipMany1 space |
58 | 61 | ||
59 | parseList :: Parser Expr | ||
60 | parseList = List <$> sepBy parseLispValue whiteSpace | ||
61 | |||
62 | parseDottedList :: Parser Expr | ||
63 | parseDottedList = do | ||
64 | head <- endBy parseLispValue whiteSpace | ||
65 | char '.' | ||
66 | whiteSpace | ||
67 | DottedList head <$> parseLispValue | ||
68 | |||
69 | type Alias = String | 62 | type Alias = String |
70 | parseModifier :: Char -> Alias -> Parser Expr | 63 | parseModifier :: Char -> Alias -> Parser Expr |
71 | parseModifier c alias = do | 64 | parseModifier c alias = do |
@@ -76,7 +69,7 @@ parseModifier c alias = do | |||
76 | parseQuote = parseModifier '\'' "quote" | 69 | parseQuote = parseModifier '\'' "quote" |
77 | parseQuasiquote = parseModifier '`' "quasiquote" | 70 | parseQuasiquote = parseModifier '`' "quasiquote" |
78 | parseUnquote = parseModifier ',' "unquote" | 71 | parseUnquote = parseModifier ',' "unquote" |
79 | -- TODO: add modifier for unquote splicing | 72 | -- TODO: add modifier for unquote splicing: ,@ |
80 | 73 | ||
81 | parseLispValue :: Parser Expr | 74 | parseLispValue :: Parser Expr |
82 | parseLispValue = | 75 | parseLispValue = |
@@ -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 | ||
97 | showLispList :: [Expr] -> String | 93 | showLispList :: [Expr] -> String |
98 | showLispList = unwords . map show | 94 | showLispList = unwords . map show |