Changeset 10092 for src/Pugs/Lexer.hs

Show
Ignore:
Timestamp:
04/26/06 19:49:52 (3 years ago)
Author:
audreyt
Message:

* Pugs.Lexer - merge Pugs.Rule.Token to handle all

char codes correctly. The <ws> handling has made
parsing ~30% slower again -- I'll see if I can find
some clever way to fix that.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Lexer.hs

    r10091 r10092  
    3131import Pugs.Types 
    3232import Pugs.Parser.Types 
    33 import qualified Pugs.Rule.Token as P 
    34 import Text.ParserCombinators.Parsec.Language 
    3533import qualified Text.ParserCombinators.Parsec.Char as C (satisfy) 
    3634 
    37 perl6Def  :: LanguageDef st 
    38 perl6Def  = javaStyle 
    39           { P.commentStart   = "#" 
    40           , P.commentEnd     = "" 
    41           , P.commentLine    = "#" 
    42           , P.nestedComments = False 
    43           , P.identStart     = C.satisfy isWordAlpha 
    44           , P.identLetter    = C.satisfy isWordAny 
    45           , P.caseSensitive  = False 
    46           } 
     35identStart  = satisfy isWordAlpha 
     36identLetter = satisfy isWordAny 
    4737 
    4838wordAlpha   :: RuleParser Char 
     
    5646isWordAlpha x = (isAlpha x || x == '_') 
    5747 
    58 perl6Lexer :: P.TokenParser st 
    59 perl6Lexer = P.makeTokenParser perl6Def 
    60  
    6148maybeParens :: RuleParser a -> RuleParser a 
    6249maybeParens p = choice [ parens p, p ] 
     
    6956mandatoryWhiteSpace :: RuleParser () 
    7057mandatoryWhiteSpace = skipMany1 (satisfy isSpace) 
    71  
    72 whiteSpace :: RuleParser () 
    73 whiteSpace = P.whiteSpace perl6Lexer 
    74 lexeme     :: RuleParser a -> RuleParser a 
    75 lexeme     = P.lexeme     perl6Lexer 
    76 identifier :: RuleParser String 
    77 identifier = P.identifier perl6Lexer 
    78 decimal    :: RuleParser Integer 
    79 decimal    = P.decimal    perl6Lexer 
    8058 
    8159balancedDelim :: Char -> Char 
     
    175153ruleVerbatimIdentifier :: RuleParser String 
    176154ruleVerbatimIdentifier = (<?> "identifier") $ do 
    177     c  <- P.identStart perl6Def 
    178     cs <- many (P.identLetter perl6Def) 
     155    c  <- identStart 
     156    cs <- many identLetter 
    179157    return (c:cs) 
    180158 
     
    438416verbatimBraces :: RuleParser a -> RuleParser a 
    439417verbatimBraces = between (lexeme $ char '{') (char '}') 
     418 
     419 
     420----------------------------------------------------------- 
     421-- Chars & Strings 
     422----------------------------------------------------------- 
     423----------------------------------------------------------- 
     424-- Numbers 
     425----------------------------------------------------------- 
     426-- naturalOrFloat :: CharParser st (Either Integer Double) 
     427naturalOrFloat  = lexeme (natFloat) <?> "number" 
     428 
     429float           = lexeme floating   <?> "float" 
     430integer         = lexeme int        <?> "integer" 
     431natural         = lexeme nat        <?> "natural" 
     432 
     433 
     434-- floats 
     435floating        = do{ n <- decimal  
     436                    ; fractExponent n 
     437                    } 
     438 
     439 
     440natFloat        = do{ char '0' 
     441                    ; zeroNumFloat 
     442                    } 
     443                    <|> decimalFloat 
     444                     
     445zeroNumFloat    =  do{ n <- hexadecimal <|> octal 
     446                        ; return (Left n) 
     447                        } 
     448                <|> decimalFloat 
     449                <|> fractFloat 0 
     450                <|> return (Left 0)                   
     451                     
     452decimalFloat    = do{ n <- decimal 
     453                    ; option (Left n)  
     454                                (fractFloat n) 
     455                    } 
     456 
     457fractFloat n    = do{ f <- fractExponent n 
     458                    ; return (Right f) 
     459                    } 
     460                     
     461fractExponent n = do{ fract <- fraction 
     462                    ; expo  <- option 1.0 exponent' 
     463                    ; return ((fromInteger n + fract)*expo) 
     464                    } 
     465                <|> 
     466                    do{ expo <- exponent' 
     467                    ; return ((fromInteger n)*expo) 
     468                    } 
     469 
     470fraction        = do{ char '.' 
     471                    ; digits <- many1 digit <?> "fraction" 
     472                    ; return (foldr op 0.0 digits) 
     473                    } 
     474                    <?> "fraction" 
     475                where 
     476                    op d f    = (f + fromIntegral (digitToInt d))/10.0 
     477                     
     478exponent'       = do{ oneOf "eE" 
     479                    ; f <- sign 
     480                    ; e <- decimal <?> "exponent" 
     481                    ; return (power (f e)) 
     482                    } 
     483                    <?> "exponent" 
     484                where 
     485                    power e  | e < 0      = 1.0/power(-e) 
     486                            | otherwise  = fromInteger (10^e) 
     487 
     488 
     489-- integers and naturals 
     490int             = do{ f <- lexeme sign 
     491                    ; n <- nat 
     492                    ; return (f n) 
     493                    } 
     494                     
     495-- sign            :: CharParser st (Integer -> Integer) 
     496sign            =   (char '-' >> return negate)  
     497                <|> (char '+' >> return id)      
     498                <|> return id 
     499 
     500nat             = zeroNumber <|> decimal 
     501     
     502zeroNumber      = do{ char '0' 
     503                    ; hexadecimal <|> octal <|> decimal <|> return 0 
     504                    } 
     505                    <?> ""        
     506 
     507decimal         = number 10 digit         
     508hexadecimal     = do{ oneOf "xX"; number 16 hexDigit } 
     509octal           = do{ oneOf "oO"; number 8 octDigit  } 
     510 
     511----------------------------------------------------------- 
     512-- Identifiers & Reserved words 
     513----------------------------------------------------------- 
     514identifier = lexeme $ try $ ident 
     515     
     516ident            
     517    = do{ c <- identStart 
     518        ; cs <- many identLetter 
     519        ; return (c:cs) 
     520        } 
     521    <?> "identifier" 
     522 
     523----------------------------------------------------------- 
     524-- White space & symbols 
     525----------------------------------------------------------- 
     526lexeme p        
     527    = do{ x <- p; whiteSpace; return x  } 
     528     
     529     
     530--whiteSpace     
     531whiteSpace = skipMany (simpleSpace <|> comment) 
     532 
     533comment = do 
     534    char '#' <?> "comment" 
     535    pos <- getPosition 
     536    if sourceColumn pos /= 2 then multiLineComment <|> skipToLineEnd else do 
     537    -- Beginning of line - parse #line directive 
     538    isPlain <- (<|> return True) $ try $ do 
     539        string "line" 
     540        many1 $ satisfy (\x -> isSpace x && x /= '\n') 
     541        return False 
     542    if isPlain then skipToLineEnd else do 
     543    line <- decimal 
     544    file <- (<|> return Nothing) $ try $ do 
     545        many1 $ satisfy (\x -> isSpace x && x /= '\n') 
     546        fileNameQuoted <|> fileNameBare 
     547    if file == Just Nothing then skipToLineEnd else do 
     548    many $ satisfy (/= '\n') 
     549    setPosition $ pos 
     550        `setSourceLine`     (fromInteger line - 1) 
     551        `setSourceColumn`   1 
     552        `setSourceName`     maybe (sourceName pos) fromJust file 
     553    return () 
     554 
     555fileNameQuoted = try $ do 
     556    char '"' 
     557    file <- many (satisfy (/= '"')) 
     558    char '"' 
     559    many $ satisfy (\x -> isSpace x && x /= '\n') 
     560    lookAhead (satisfy (== '\n')) 
     561    return $ Just $ Just file 
     562 
     563fileNameBare = try $ do 
     564    file <- many1 $ satisfy (not . isSpace) 
     565    many $ satisfy (\x -> isSpace x && x /= '\n') 
     566    (<|> return (Just Nothing)) $ try $ do 
     567        lookAhead (satisfy (== '\n')) 
     568        return $ Just $ Just file 
     569 
     570skipToLineEnd = do 
     571    skipMany (satisfy (/= '\n')) 
     572    return () 
     573         
     574simpleSpace = 
     575    skipMany1 (satisfy isSpace)     
     576     
     577-- XXX - nesting 
     578multiLineComment = do 
     579    openOne <- satisfy (\x -> balancedDelim x /= x) 
     580    more    <- many (char openOne) 
     581    let closeOne = balancedDelim openOne 
     582        openAll  = string (openOne:more) 
     583        closeAll = string (replicate (1 + length more) (balancedDelim openOne)) 
     584        scanOne  = do 
     585            c <- anyChar 
     586            if c == closeOne then return () else do 
     587            if c == openOne then scanOne >> scanOne else do 
     588            scanOne 
     589        scanAll  = choice 
     590            [ do { try closeAll; return () } 
     591            , do { try openAll; scanAll; scanAll } 
     592            , do { anyChar; scanAll } 
     593            ] 
     594    if null more then scanOne else scanAll