1{- arch-tag: ConfigParser lexer support
2Copyright (C) 2004, 2008 John Goerzen <jgoerzen@complete.org>
3
4This program is free software; you can redistribute it and/or modify it, as
5specified in the COPYRIGHT file, under the terms of either version 2.1 of
6the LGPL (or, at your option, any later version) or the 3-clause BSD license.
7-}
8
9{- |
10   Module     : Data.ConfigFile.Lexer
11   Copyright  : Copyright (C) 2004, 2008 John Goerzen
12   License    : Either LGPL or BSD3, as specified in the COPYRIGHT file.
13
14   Maintainer : John Goerzen <jgoerzen@complete.org>
15   Stability  : provisional
16   Portability: portable
17
18Lexer support for "Data.ConfigFile".  This module is not intended to be
19used directly by your programs.
20
21Copyright (c) 2004, 2008 John Goerzen, jgoerzen\@complete.org
22
23This program is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26
27-}
28module Data.ConfigFile.Lexer
29(
30       -- -- * Temporary for testing
31       --comment_chars, eol, optionsep, whitespace_chars, comment_line,
32       --empty_line, sectheader_chars, sectheader, oname_chars, value_chars,
33       --extension_line, optionkey, optionvalue, optionpair
34       loken,
35       CPTok(..)
36) where
37
38import Text.ParserCombinators.Parsec
39import Text.ParserCombinators.Parsec.Utils
40
41data CPTok = IGNOREDATA
42           | NEWSECTION String
43           | NEWSECTION_EOF String
44           | EXTENSIONLINE String
45           | NEWOPTION (String, String)
46             deriving (Eq, Show, Ord)
47
48comment_chars :: CharParser st Char
49comment_chars = oneOf "#;"
50eol :: GenParser Char st String
51eol = string "\n" <|> string "\r\n" <|> string "\r" <?> "End of line"
52eoleof :: GenParser Char st ()
53eoleof = eof <|> do {eol; return ()}
54optionsep :: GenParser Char st Char
55optionsep = oneOf ":=" <?> "option separator"
56whitespace_chars :: GenParser Char st Char
57whitespace_chars = oneOf " \t" <?> "whitespace"
58comment_line :: GenParser Char st ()
59comment_line = do skipMany whitespace_chars
60                  comment_chars             <?> "start of comment"
61                  (many $ noneOf "\r\n")   <?> "content of comment"
62                  eoleof
63eolstuff :: GenParser Char st ()
64eolstuff = (try comment_line) <|> (try empty_line)
65empty_line :: GenParser Char st ()
66empty_line = do many whitespace_chars
67                eoleof
68             <?> "empty line"
69sectheader_chars :: CharParser st Char
70sectheader_chars = noneOf "]\r\n"
71sectheader :: GenParser Char st String
72sectheader = do char '['
73                sname <- many1 $ sectheader_chars
74                char ']'
75                eolstuff
76                return sname
77             <?> "start of section"
78oname_chars :: CharParser st Char
79oname_chars = noneOf ":=\r\n"
80value_chars :: CharParser st Char
81value_chars = noneOf "\r\n"
82extension_line :: GenParser Char st String
83extension_line = do many1 whitespace_chars
84                    c1 <- noneOf "\r\n#;"
85                    remainder <- many value_chars
86                    eolstuff
87                    return (c1 : remainder)
88
89optionkey, optionvalue :: GenParser Char st String
90optionkey = many1 oname_chars
91optionvalue = many value_chars
92optionpair :: GenParser Char st (String, String)
93optionpair = do key <- optionkey
94                value <- option "" $ do { optionsep; optionvalue }
95                eolstuff
96                return (key, value)
97             <?> "key/value option"
98
99iloken :: Parser (GeneralizedToken CPTok)
100iloken =
101    -- Ignore these things
102    try (do {comment_line; togtok $ IGNOREDATA})
103    <|> try (do {empty_line; togtok $ IGNOREDATA})
104
105    -- Real stuff
106    <|> (do {sname <- sectheader; togtok $ NEWSECTION sname})
107    <|> try (do {extension <- extension_line; togtok $ EXTENSIONLINE extension})
108    <|> try (do {pair <- optionpair; togtok $ NEWOPTION pair})
109--    <?> "Invalid syntax in configuration file"
110
111loken :: Parser [GeneralizedToken CPTok]
112loken = do x <- manyTill iloken eof
113           return $ filter (\y -> snd y /= IGNOREDATA) x
114