Skip to content

Instantly share code, notes, and snippets.

@jxxcarlson
Created September 3, 2020 04:56
Show Gist options
  • Save jxxcarlson/5eb1e9cb0efde9abd14ec4e84a738c43 to your computer and use it in GitHub Desktop.
Save jxxcarlson/5eb1e9cb0efde9abd14ec4e84a738c43 to your computer and use it in GitHub Desktop.
module Parse exposing (AST(..), toAST)
{-
Parse a string of Lisp text, return Just AST if it is legal, Nothing if not.
-}
import Parser exposing (..)
import ParserHelpers exposing (..)
type AST
= Str String
| Num Int
| LIST (List AST)
{-|
> toAST "(* 2 (+ 3 4))"
Just (LIST [Str "*",Num 2,LIST [Str "+",Num 3,Num 4]])
-}
toAST : String -> Maybe AST
toAST str =
case run parse str of
Ok ast ->
Just ast
Err _ ->
Nothing
parse : Parser AST
parse =
oneOf [ lazy (\_ -> list), string, integer ]
list : Parser AST
list =
(succeed identity
|. symbol "("
|. spaces
|= many parse
|. spaces
|. symbol ")"
|. spaces
)
|> map LIST
-- STRING
string : Parser AST
string =
oneOf [ operator, string_ ]
string_ : Parser AST
string_ =
getChompedString
(succeed ()
|. chompIf (\c -> Char.isAlpha c)
|. chompWhile (\c -> Char.isAlphaNum c)
|. symbol " "
)
|> map (String.trim >> Str)
-- OPERATORS
operator : Parser AST
operator =
oneOf [ plus, minus, times, divide ]
plus : Parser AST
plus =
(succeed "+"
|. symbol "+"
)
|> map Str
minus : Parser AST
minus =
(succeed "-"
|. symbol "-"
)
|> map Str
times : Parser AST
times =
(succeed "*"
|. symbol "*"
)
|> map Str
divide : Parser AST
divide =
(succeed "/"
|. symbol "/"
)
|> map Str
-- INTEGER
integer : Parser AST
integer =
(succeed identity
|= int
)
|> map Num
-- HELPERS
many : Parser a -> Parser (List a)
many p =
loop [] (manyHelp p)
manyHelp : Parser a -> List a -> Parser (Step (List a) (List a))
manyHelp p vs =
oneOf
[ succeed (\v -> Loop (v :: vs))
|= p
|. spaces
, succeed ()
|> map (\_ -> Done (List.reverse vs))
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment