4 | module Language.TOML.Tokens
20 | data Bracket = Open | Close
25 | show Close = "close"
29 | (==) Open Open = True
30 | (==) Close Close = True
43 | Show Punctuation where
47 | show NewLine = "\\n"
48 | show (Square Open) = "["
49 | show (Square Close) = "]"
50 | show (Curly Open) = "("
51 | show (Curly Close) = ")"
54 | Eq Punctuation where
55 | (==) Comma Comma = True
57 | (==) Equal Equal = True
58 | (==) NewLine NewLine = True
59 | (==) (Square x) (Square y) = x == y
60 | (==) (Curly x) (Curly y) = x == y
66 | data StringType : Type where
74 | Literal : StringType
78 | BasicMultiline : StringType
81 | LiteralMultiline : StringType
84 | Show StringType where
85 | show Basic = "Basic"
86 | show Literal = "Literal"
87 | show BasicMultiline = "BasicMultiline"
88 | show LiteralMultiline = "LiteralMultiline"
92 | Basic == Basic = True
93 | Literal == Literal = True
94 | BasicMultiline == BasicMultiline = True
95 | LiteralMultiline == LiteralMultiline = True
104 | | TTString StringType
105 | | TTPunct Punctuation
111 | TOMLToken = Token TOMLTokenKind
114 | Show TOMLTokenKind where
115 | show TTBoolean = "boolean"
116 | show TTInt = "integer"
117 | show TTFloat = "float"
118 | show (TTString type) = "\{show type} string"
119 | show (TTPunct x) = show x
120 | show TTBare = "key"
121 | show TTIgnored = "comment"
124 | Eq TOMLTokenKind where
125 | (==) TTBoolean TTBoolean = True
126 | (==) TTInt TTInt = True
127 | (==) TTFloat TTFloat = True
128 | (==) (TTString x) (TTString y) = x == y
129 | (==) (TTPunct x) (TTPunct y) = x == y
130 | (==) TTBare TTBare = True
131 | (==) TTIgnored TTIgnored = True
134 | charToInt : Char -> Integer
136 | if '0' <= c && c <= '9'
137 | then cast $
ord c - ord '0'
138 | else cast $
ord (toLower c) - ord 'a'
140 | parameters (sign, base : Integer)
146 | parseIntLoop [] acc = acc
147 | parseIntLoop ('_'::rest) acc = parseIntLoop rest acc
148 | parseIntLoop (c::rest) acc =
149 | parseIntLoop rest (acc * base + charToInt c * sign)
152 | parseWithSign : List Char -> (sign : Integer) -> Integer
153 | parseWithSign [] sign = 0
154 | parseWithSign ('0'::'b'::rest) sign = parseIntLoop sign 2 rest 0
155 | parseWithSign ('0'::'o'::rest) sign = parseIntLoop sign 8 rest 0
156 | parseWithSign ('0'::'x'::rest) sign = parseIntLoop sign 16 rest 0
157 | parseWithSign rest sign = parseIntLoop sign 10 rest 0
160 | parseInt : List Char -> Integer
162 | parseInt ('+'::rest) = parseWithSign rest 1
163 | parseInt ('-'::rest) = parseWithSign rest (-
1)
164 | parseInt rest = parseWithSign rest 1
173 | parameters (sign : Double)
177 | (number : Double) ->
181 | parseExponent number acc [] = sign * number * pow 10 (cast acc)
182 | parseExponent number acc ('_'::rest) = parseExponent number acc rest
183 | parseExponent number acc (x::rest) = parseExponent number (10 * acc + charToInt x) rest
189 | (whole : Integer) ->
191 | (exponent : Double) ->
194 | parseDecimal whole acc exponent [] = sign * (cast whole + acc)
195 | parseDecimal whole acc exponent ('e'::rest) = parseExponent (cast whole + acc) 0 rest
196 | parseDecimal whole acc exponent ('E'::rest) = parseExponent (cast whole + acc) 0 rest
197 | parseDecimal whole acc exponent ('_'::rest) = parseDecimal whole acc exponent rest
198 | parseDecimal whole acc exponent (x::rest) =
201 | (acc + cast (charToInt x) * exponent)
206 | parseWhole : (acc : Integer) -> List Char -> Double
207 | parseWhole acc [] = 0.0
208 | parseWhole acc ('.'::rest) = parseDecimal acc 0.0 0.1 rest
209 | parseWhole acc ('e'::rest) = parseExponent (cast acc) 0 rest
210 | parseWhole acc ('E'::rest) = parseExponent (cast acc) 0 rest
211 | parseWhole acc ('_'::rest) = parseWhole acc rest
212 | parseWhole acc (x::rest) = parseWhole (10 * acc + charToInt x) rest
214 | parseSign : List Char -> Double
215 | parseSign ('+'::rest) = parseWhole 1.0 0 rest
216 | parseSign ('-'::rest) = parseWhole (-1.0) 0 rest
217 | parseSign rest = parseWhole 1.0 0 rest
220 | parseFloat : String -> Double
221 | parseFloat "nan" = nan
222 | parseFloat "+nan" = nan
223 | parseFloat "-nan" = -nan
224 | parseFloat "inf" = inf
225 | parseFloat "+inf" = inf
226 | parseFloat "-inf" = -inf
227 | parseFloat x = parseSign (unpack x)
230 | unescapeBasic : List Char -> Either String (List Char)
231 | unescapeBasic ('"'::rest) = loop rest
234 | hexToInt : Char -> Either String Int
238 | if '0' <= c && c <= '9'
239 | then ord c - ord '0'
240 | else ord (toLower c) - ord 'a'
241 | else Left "invalid hex character: '\{cast {to=String} c}'"
243 | unicodeEscape : List Char -> (acc : Int) -> Either String Char
244 | unicodeEscape [] acc = pure $
chr acc
245 | unicodeEscape (c::cs) acc = do
247 | unicodeEscape cs (acc * 16 + x)
249 | loop : List Char -> Either String (List Char)
250 | loop [] = Left "unexpected end of input"
251 | loop ('"'::_) = Right []
252 | loop ('\\'::'b'::rest) = ('\b' ::) <$> loop rest
253 | loop ('\\'::'t'::rest) = ('\t' ::) <$> loop rest
254 | loop ('\\'::'n'::rest) = ('\n' ::) <$> loop rest
255 | loop ('\\'::'f'::rest) = ('\f' ::) <$> loop rest
256 | loop ('\\'::'r'::rest) = ('\r' ::) <$> loop rest
257 | loop ('\\'::'"'::rest) = ('"' ::) <$> loop rest
258 | loop ('\\'::'\\'::rest) = ('\\' ::) <$> loop rest
259 | loop ('\\'::'u'::u0::u1::u2::u3::rest) = do
260 | c <- unicodeEscape [u0, u1, u2, u3] 0
261 | (c ::) <$> loop rest
262 | loop ('\\'::'U'::u0::u1::u2::u3::u4::u5::u6::u7::rest) = do
263 | c <- unicodeEscape [u0, u1, u2, u3, u4, u5, u6, u7] 0
264 | (c ::) <$> loop rest
265 | loop ('\\'::_) = Left "invalid escape code"
266 | loop (x::rest) = (x ::) <$> loop rest
267 | unescapeBasic _ = Left "expected quote"
270 | TokenKind TOMLTokenKind where
271 | TokType TTBoolean = Bool
272 | TokType TTInt = Integer
273 | TokType TTFloat = Double
276 | TokType (TTString _) = Either String String
277 | TokType (TTPunct _) = ()
278 | TokType TTBare = String
279 | TokType TTIgnored = ()
281 | tokValue TTBoolean s = s == strTrue
282 | tokValue TTInt s = parseInt (unpack s)
283 | tokValue TTFloat s = parseFloat s
285 | tokValue (TTString Basic) s = map pack $
unescapeBasic (unpack s)
286 | tokValue (TTString Literal) s = Left "unimplemted string type: literal"
287 | tokValue (TTString BasicMultiline) s = Left "unimplemted string type: basic multiline"
288 | tokValue (TTString LiteralMultiline) s = Left "unimplemted string type: literal multiline"
290 | tokValue (TTPunct _) _ = ()
291 | tokValue TTBare s = s
292 | tokValue TTIgnored _ = ()
295 | getString : Token TOMLTokenKind -> Maybe (Either String String)
296 | getString tok@(Tok ((TTString _)) text) = Just (value tok)
297 | getString _ = Nothing
300 | getKeyString : Token TOMLTokenKind -> Maybe (Either String String)
301 | getKeyString tok@(Tok ((TTString Basic)) text) = Just (value tok)
302 | getKeyString tok@(Tok ((TTString Literal)) text) = Just (value tok)
303 | getKeyString _ = Nothing
306 | ignored : WithBounds TOMLToken -> Bool
307 | ignored (MkBounded (Tok TTIgnored _) _ _) = True