6 import Numeric( readFloat )
8 isNameChar c = isAlpha c || isDigit c || (c == '_') || (c == '\'')
9 isKeywordChar c = isAlpha c || (c == '_')
11 lexer :: (Token -> P a) -> P a
12 lexer cont [] = cont TKEOF []
13 lexer cont ('\n':cs) = \line -> lexer cont cs (line+1)
14 lexer cont ('-':'>':cs) = cont TKrarrow cs
17 | isSpace c = lexer cont cs
18 | isLower c || (c == '_') = lexName cont TKname (c:cs)
19 | isUpper c = lexName cont TKcname (c:cs)
20 | isDigit c || (c == '-') = lexNum cont (c:cs)
22 lexer cont ('%':cs) = lexKeyword cont cs
23 lexer cont ('\'':cs) = lexChar cont cs
24 lexer cont ('\"':cs) = lexString [] cont cs
25 lexer cont ('#':cs) = cont TKhash cs
26 lexer cont ('(':cs) = cont TKoparen cs
27 lexer cont (')':cs) = cont TKcparen cs
28 lexer cont ('{':cs) = cont TKobrace cs
29 lexer cont ('}':cs) = cont TKcbrace cs
30 lexer cont ('=':cs) = cont TKeq cs
31 lexer cont (':':':':cs) = cont TKcoloncolon cs
32 lexer cont ('*':cs) = cont TKstar cs
33 lexer cont ('.':cs) = cont TKdot cs
34 lexer cont ('\\':cs) = cont TKlambda cs
35 lexer cont ('@':cs) = cont TKat cs
36 lexer cont ('?':cs) = cont TKquestion cs
37 lexer cont (';':cs) = cont TKsemicolon cs
38 lexer cont (c:cs) = failP "invalid character" [c]
42 lexChar cont ('\\':'x':h1:h0:'\'':cs)
43 | isHexEscape [h1,h0] = cont (TKchar (hexToChar h1 h0)) cs
44 lexChar cont ('\\':cs) = failP "invalid char character" ('\\':(take 10 cs))
45 lexChar cont ('\'':cs) = failP "invalid char character" ['\'']
46 lexChar cont ('\"':cs) = failP "invalid char character" ['\"']
47 lexChar cont (c:'\'':cs) = cont (TKchar c) cs
50 lexString s cont ('\\':'x':h1:h0:cs)
51 | isHexEscape [h1,h0] = lexString (s++[hexToChar h1 h0]) cont cs
52 lexString s cont ('\\':cs) = failP "invalid string character" ['\\']
53 lexString s cont ('\'':cs) = failP "invalid string character" ['\'']
54 lexString s cont ('\"':cs) = cont (TKstring s) cs
55 lexString s cont (c:cs) = lexString (s++[c]) cont cs
57 isHexEscape = all (\c -> isHexDigit c && (isDigit c || isLower c))
59 hexToChar h1 h0 = chr (digitToInt h1 * 16 + digitToInt h0)
67 case span isDigit cs of
69 | isDigit c -> cont (TKrational r) rest'
70 where ((r,rest'):_) = readFloat (digits ++ ('.':c:rest))
71 -- When reading a floating-point number, which is
72 -- a bit comlicated, use the Haskell 98 library function
73 (digits,rest) -> cont (TKinteger (sgn * (read digits))) rest
75 lexName cont cstr cs = cont (cstr name) rest
76 where (name,rest) = span isNameChar cs
79 case span isKeywordChar cs of
80 ("module",rest) -> cont TKmodule rest
81 ("data",rest) -> cont TKdata rest
82 ("newtype",rest) -> cont TKnewtype rest
83 ("forall",rest) -> cont TKforall rest
84 ("rec",rest) -> cont TKrec rest
85 ("let",rest) -> cont TKlet rest
86 ("in",rest) -> cont TKin rest
87 ("case",rest) -> cont TKcase rest
88 ("of",rest) -> cont TKof rest
89 ("coerce",rest) -> cont TKcoerce rest
90 ("note",rest) -> cont TKnote rest
91 ("external",rest) -> cont TKexternal rest
92 ("_",rest) -> cont TKwild rest
93 _ -> failP "invalid keyword" ('%':cs)