@@ -8,10 +8,15 @@ import Core.TT
8import Text.ParserCombinators.Parsec
8import Text.ParserCombinators.Parsec
9import Text.ParserCombinators.Parsec.Expr
9import Text.ParserCombinators.Parsec.Expr
10import Text.ParserCombinators.Parsec.Language
10import Text.ParserCombinators.Parsec.Language
11+import Text.ParserCombinators.Parsec.Prim
12+import Text.ParserCombinators.Parsec.Char
13+import Text.ParserCombinators.Parsec.Combinator
11import qualified Text.ParserCombinators.Parsec.Token as PTok
14import qualified Text.ParserCombinators.Parsec.Token as PTok
13import Control.Monad.State
16import Control.Monad.State
17+import Control.Monad.Identity
14import Data.Char
18import Data.Char
15import Debug.Trace
20import Debug.Trace
17type TokenParser a = PTok.TokenParser a
22type TokenParser a = PTok.TokenParser a
@@ -38,21 +43,22 @@ iOpLetter = oneOf ":!#$%&*+./<=>?@\\^|-~"
38-- <|> letter
43-- <|> letter
40idrisLexer :: TokenParser a
45idrisLexer :: TokenParser a
41−idrisLexer = (PTok.makeTokenParser idrisDef) { PTok.whiteSpace = lexWS }
46+idrisLexer = idrisMakeTokenParser idrisDef
43lexer = idrisLexer
48lexer = idrisLexer
45-- Taken from Parsec source code
50-- Taken from Parsec source code
51+lexWS = do i <- getInput
46−lexWS = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")
52+ skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")
49 simpleSpace = skipMany1 (satisfy isSpace)
55 simpleSpace = skipMany1 (satisfy isSpace)
50− oneLineComment = do try (string ("--"))
56+ oneLineComment = do try (do string ("--")
51− satisfy (/= '|')
57+ satisfy (\x -> x /= '|' && x /= '^'))
52 skipMany (satisfy (/= '\n'))
58 skipMany (satisfy (/= '\n'))
54− multiLineComment = do try (string "{-")
60+ multiLineComment = do try (do string "{-"
55− satisfy (/= '|')
61+ satisfy (\x -> x /= '|' && x /= '^'))
56 inCommentMulti
62 inCommentMulti
58 inCommentMulti
64 inCommentMulti
@@ -75,6 +81,7 @@ identifier= PTok.identifier lexer
75reserved = PTok.reserved lexer
81reserved = PTok.reserved lexer
76operator = PTok.operator lexer
82operator = PTok.operator lexer
77reservedOp= PTok.reservedOp lexer
83reservedOp= PTok.reservedOp lexer
84+strlit = PTok.stringLiteral lexer
78lchar = lexeme.char
85lchar = lexeme.char
80type CParser a = GenParser Char a
87type CParser a = GenParser Char a
@@ -124,13 +131,23 @@ mkName (n, ns) = NS (UN n) (reverse (parseNS ns))
124 (x, '.':y) -> x : parseNS y
131 (x, '.':y) -> x : parseNS y
126pDocComment :: Char -> CParser a String
133pDocComment :: Char -> CParser a String
127−pDocComment c
134+pDocComment c
128− = do string "--"
135+ = try (do string ("--" ++ [c])
130− i <- getInput
136+ i <- getInput
131− let (doc, rest) = span (/='\n') i
137+ let (doc, rest) = span (/='\n') i
141+ <|> try (do string ("{-" ++ [c])
144+ let (doc, rest) = spanComment "" i
132− setInput rest
145+ setInput rest
133− return doc
147+ return doc)
148+ where spanComment acc ('-':'}':xs) = (reverse acc, xs)
149+ spanComment acc (x:xs) = spanComment (x : acc) xs
150+ spanComment acc [] = (acc, [])
135pDef :: CParser a (Name, RDef)
152pDef :: CParser a (Name, RDef)
136pDef = try (do x <- iName []; lchar ':'; ty <- pTerm
153pDef = try (do x <- iName []; lchar ':'; ty <- pTerm
@@ -208,3 +225,340 @@ pConstructor = do lchar '|'
208 c <- iName []; lchar ':'; ty <- pTerm
225 c <- iName []; lchar ':'; ty <- pTerm
209 return (c, ty)
226 return (c, ty)
228+------ borrowed from Parsec
229+-- (c) Daan Leijen 1999-2001, (c) Paolo Martini 2007
231+idrisMakeTokenParser languageDef
233+ PTok.identifier = identifier
234+ , PTok.reserved = reserved
235+ , PTok.operator = operator
236+ , PTok.reservedOp = reservedOp
238+ , PTok.charLiteral = charLiteral
239+ , PTok.stringLiteral = stringLiteral
240+ , PTok.natural = natural
241+ , PTok.integer = integer
242+ , PTok.float = float
243+ , PTok.naturalOrFloat = naturalOrFloat
244+ , PTok.decimal = decimal
245+ , PTok.hexadecimal = hexadecimal
246+ , PTok.octal = octal
248+ , PTok.symbol = symbol
249+ , PTok.lexeme = lexeme
250+ , PTok.whiteSpace = lexWS
252+ , PTok.parens = parens
253+ , PTok.braces = braces
254+ , PTok.angles = angles
255+ , PTok.brackets = brackets
256+ , PTok.squares = brackets
258+ , PTok.comma = comma
259+ , PTok.colon = colon
261+ , PTok.semiSep = semiSep
262+ , PTok.semiSep1 = semiSep1
263+ , PTok.commaSep = commaSep
264+ , PTok.commaSep1 = commaSep1
268+ -----------------------------------------------------------
270+ -----------------------------------------------------------
271+ parens p = between (symbol "(") (symbol ")") p
272+ braces p = between (symbol "{") (symbol "}") p
273+ angles p = between (symbol "<") (symbol ">") p
274+ brackets p = between (symbol "[") (symbol "]") p
281+ commaSep p = sepBy p comma
282+ semiSep p = sepBy p semi
284+ commaSep1 p = sepBy1 p comma
285+ semiSep1 p = sepBy1 p semi
288+ -----------------------------------------------------------
290+ -----------------------------------------------------------
291+ charLiteral = lexeme (between (char '\'')
292+ (char '\'' <?> "end of character")
296+ characterChar = charLetter <|> charEscape
297+ <?> "literal character"
299+ charEscape = do{ char '\\'; escapeCode }
300+ charLetter = satisfy (\c -> (c /= '\'') && (c /= '\\') && (c > '\026'))
304+ stringLiteral = lexeme (
305+ do{ str <- between (char '"')
306+ (char '"' <?> "end of string")
308+ ; return (foldr (maybe id (:)) "" str)
310+ <?> "literal string")
312+ stringChar = do{ c <- stringLetter; return (Just c) }
314+ <?> "string character"
316+ stringLetter = satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))
318+ stringEscape = do{ char '\\'
319+ ; do{ escapeGap ; return Nothing }
320+ <|> do{ escapeEmpty; return Nothing }
321+ <|> do{ esc <- escapeCode; return (Just esc) }
324+ escapeEmpty = char '&'
325+ escapeGap = do{ many1 space
326+ ; char '\\' <?> "end of string gap"
332+ escapeCode = charEsc <|> charNum <|> charAscii <|> charControl
335+ charControl = do{ char '^'
337+ ; return (toEnum (fromEnum code - fromEnum 'A'))
340+ charNum = do{ code <- decimal
341+ <|> do{ char 'o'; number 8 octDigit }
342+ <|> do{ char 'x'; number 16 hexDigit }
343+ ; return (toEnum (fromInteger code))
346+ charEsc = choice (map parseEsc escMap)
348+ parseEsc (c,code) = do{ char c; return code }
350+ charAscii = choice (map parseAscii asciiMap)
352+ parseAscii (asc,code) = try (do{ string asc; return code })
355+ -- escape code tables
356+ escMap = zip ("abfnrtv\\\"\'") ("\a\b\f\n\r\t\v\\\"\'")
357+ asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)
359+ ascii2codes = ["BS","HT","LF","VT","FF","CR","SO","SI","EM",
360+ "FS","GS","RS","US","SP"]
361+ ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK","BEL",
362+ "DLE","DC1","DC2","DC3","DC4","NAK","SYN","ETB",
363+ "CAN","SUB","ESC","DEL"]
365+ ascii2 = ['\BS','\HT','\LF','\VT','\FF','\CR','\SO','\SI',
366+ '\EM','\FS','\GS','\RS','\US','\SP']
367+ ascii3 = ['\NUL','\SOH','\STX','\ETX','\EOT','\ENQ','\ACK',
368+ '\BEL','\DLE','\DC1','\DC2','\DC3','\DC4','\NAK',
369+ '\SYN','\ETB','\CAN','\SUB','\ESC','\DEL']
372+ -----------------------------------------------------------
374+ -----------------------------------------------------------
375+ naturalOrFloat = lexeme (natFloat) <?> "number"
377+ float = lexeme floating <?> "float"
378+ integer = lexeme int <?> "integer"
379+ natural = lexeme nat <?> "natural"
383+ floating = do{ n <- decimal
388+ natFloat = do{ char '0'
393+ zeroNumFloat = do{ n <- hexadecimal <|> octal
400+ decimalFloat = do{ n <- decimal
405+ fractFloat n = do{ f <- fractExponent n
409+ fractExponent n = do{ fract <- fraction
410+ ; expo <- option 1.0 exponent'
411+ ; return ((fromInteger n + fract)*expo)
414+ do{ expo <- exponent'
415+ ; return ((fromInteger n)*expo)
418+ fraction = do{ char '.'
419+ ; digits <- many1 digit <?> "fraction"
420+ ; return (foldr op 0.0 digits)
424+ op d f = (f + fromIntegral (digitToInt d))/10.0
426+ exponent' = do{ oneOf "eE"
428+ ; e <- decimal <?> "exponent"
429+ ; return (power (f e))
433+ power e | e < 0 = 1.0/power(-e)
434+ | otherwise = fromInteger (10^e)
437+ -- integers and naturals
438+ int = do{ f <- lexeme sign
443+ sign = (char '-' >> return negate)
444+ <|> (char '+' >> return id)
447+ nat = zeroNumber <|> decimal
449+ zeroNumber = do{ char '0'
450+ ; hexadecimal <|> octal <|> decimal <|> return 0
454+ decimal = number 10 digit
455+ hexadecimal = do{ oneOf "xX"; number 16 hexDigit }
456+ octal = do{ oneOf "oO"; number 8 octDigit }
458+ number base baseDigit
459+ = do{ digits <- many1 baseDigit
460+ ; let n = foldl (\x d -> base*x + toInteger (digitToInt d)) 0 digits
464+ -----------------------------------------------------------
465+ -- Operators & reserved ops
466+ -----------------------------------------------------------
470+ ; notFollowedBy (opLetter languageDef) <?> ("end of " ++ show name)
476+ ; if (isReservedOp name)
477+ then unexpected ("reserved operator " ++ show name)
482+ do{ c <- (opStart languageDef)
483+ ; cs <- many (opLetter languageDef)
489+ isReserved (sort (reservedOpNames languageDef)) name
492+ -----------------------------------------------------------
493+ -- Identifiers & Reserved words
494+ -----------------------------------------------------------
498+ ; notFollowedBy (identLetter languageDef) <?> ("end of " ++ show name)
502+ | caseSensitive languageDef = string name
503+ | otherwise = do{ walk name; return name }
506+ walk (c:cs) = do{ caseChar c <?> msg; walk cs }
508+ caseChar c | isAlpha c = char (toLower c) <|> char (toUpper c)
509+ | otherwise = char c
517+ ; if (isReservedName name)
518+ then unexpected ("reserved word " ++ show name)
524+ = do{ c <- identStart languageDef
525+ ; cs <- many (identLetter languageDef)
531+ = isReserved theReservedNames caseName
533+ caseName | caseSensitive languageDef = name
534+ | otherwise = map toLower name
537+ isReserved names name
541+ scan (r:rs) = case (compare r name) of
547+ | caseSensitive languageDef = sortedNames
548+ | otherwise = map (map toLower) sortedNames
550+ sortedNames = sort (reservedNames languageDef)
554+ -----------------------------------------------------------
555+ -- White space & symbols
556+ -----------------------------------------------------------
558+ = lexeme (string name)
561+ = do{ x <- p; whiteSpace; return x }