module Data.Kicad.SExpr.Parse
( parse
, parseWithFilename
)
where
import Text.ParserCombinators.Parsec hiding (spaces, parse)
import qualified Text.ParserCombinators.Parsec as Parsec (parse)
import Text.Parsec.Char (endOfLine)
import Text.Parsec (getPosition)
import Data.Kicad.SExpr.SExpr
parse :: String -> Either String SExpr
parse = parseWithFilename ""
parseWithFilename :: String -> String -> Either String SExpr
parseWithFilename filename input =
case Parsec.parse parseListOrComment filename input of
Left err -> Left $ "Parse Error: " ++ show err
Right val -> Right val
parseListOrComment :: Parser SExpr
parseListOrComment = do
spaces
skipMany parseComment
s <- parseList
return s
parseComment :: Parser String
parseComment = do
char '#'
s <- many (noneOf "\r\n")
endOfLine
spaces
return s
parseList :: Parser SExpr
parseList = do
pos <- getPosition
char '('
spaces
list <- try parseExpr `sepEndBy` spaces
char ')'
spaces
return $ List pos list
parseExpr :: Parser SExpr
parseExpr = try parseString
<|> try parseListOrComment
<?> "a double, string or s-expression"
parseString :: Parser SExpr
parseString =
do pos <- getPosition
str <- parseQuotedString <|> parseUnquotedString <?> "string"
return $ Atom pos str
where
parseQuotedString = do
char '"'
x <- many (noneOf "\\\"" <|> (char '\\' >> anyChar))
char '"'
return x
parseUnquotedString = many1 (noneOf " ()\r\n")
spaces = skipMany spaceChar
spaceChar = oneOf "\r\n\t "