22
33
44module Language.Java.Parser (
5- parser ,
5+ parser , parserWithMode , ParserMode ( .. ),
66
77 compilationUnit , packageDecl , importDecl , typeDecl ,
88
@@ -43,10 +43,9 @@ import Language.Java.Pretty (pretty)
4343import Text.Parsec hiding ( Empty )
4444import Text.Parsec.Pos
4545
46- import Prelude hiding ( exp , catch , (>>) , (>>=) )
46+ import Prelude hiding ( exp , (>>) , (>>=) )
4747import qualified Prelude as P ( (>>) , (>>=) )
48- import Data.Maybe ( isJust , catMaybes , maybeToList )
49- import Control.Monad ( ap )
48+ import Data.Maybe ( isJust , catMaybes )
5049
5150#if __GLASGOW_HASKELL__ < 707
5251import Control.Applicative ( (<$>) , (<$) , (<*) )
@@ -59,7 +58,20 @@ import Control.Applicative ( (<$>), (<$), (<*), (<*>) )
5958import GHC.IO (unsafePerformIO )
6059#endif
6160
62- type P = Parsec [L Token ] ()
61+ data ParserState
62+ = ParserState
63+ { ps_mode :: ParserMode }
64+ deriving (Eq , Show )
65+
66+ data ParserMode =
67+ ParseFull -- the default
68+ | ParseShallow -- do not parse methods bodies
69+ deriving (Eq , Show )
70+
71+ defaultParserState :: ParserState
72+ defaultParserState = ParserState ParseFull
73+
74+ type P = Parsec [L Token ] ParserState
6375
6476getNextTok :: P (Maybe (L Token ))
6577getNextTok = do
@@ -79,20 +91,27 @@ logToFile msg =
7991-- A trick to allow >> and >>=, normally infixr 1, to be
8092-- used inside branches of <|>, which is declared as infixl 1.
8193-- There are no clashes with other operators of precedence 2.
94+ (>>) :: P a -> P b -> P b
8295(>>) = (P. >>)
96+
97+ (>>=) :: P a -> (a -> P b ) -> P b
8398(>>=) = (P. >>=)
99+
84100infixr 2 >> , >>=
85101-- Note also when reading that <$> is infixl 4 and thus has
86102-- lower precedence than all the others (>>, >>=, and <|>).
87103
88104----------------------------------------------------------------------------
89105-- Top-level parsing
90106
91- parseCompilationUnit :: String -> Either ParseError CompilationUnit
92- parseCompilationUnit inp =
93- runParser compilationUnit () " " (lexer inp)
107+ parser :: P a -> FilePath -> String -> Either ParseError a
108+ parser = parserWithState defaultParserState
109+
110+ parserWithMode :: ParserMode -> P a -> FilePath -> String -> Either ParseError a
111+ parserWithMode mode = parserWithState (ParserState mode)
94112
95- parser p = runParser p () " " . lexer
113+ parserWithState :: ParserState -> P a -> FilePath -> String -> Either ParseError a
114+ parserWithState state p srcName src = runParser p state srcName (lexer src)
96115
97116-- class Parse a where
98117-- parse :: String -> a
@@ -461,7 +480,24 @@ arrayInit = braces $ do
461480-- Statements
462481
463482block :: P Block
464- block = braces $ Block <$> list blockStmt
483+ block = do
484+ state <- getState
485+ case ps_mode state of
486+ ParseFull -> braces $ Block <$> list blockStmt
487+ ParseShallow -> Block <$> parseNestedCurly (- 1 )
488+
489+ -- | Parses anything between properly balance curly brackets.
490+ -- level must initially be -1
491+ parseNestedCurly :: Int -> P [a ]
492+ parseNestedCurly level = do
493+ newLevel <-
494+ javaToken $ \ t ->
495+ case t of
496+ OpenCurly -> Just (level + 1 )
497+ _ | level < 0 -> Nothing -- need to start with {
498+ CloseCurly -> Just (level - 1 )
499+ _ -> Just level
500+ if newLevel < 0 then return [] else parseNestedCurly newLevel
465501
466502blockStmt :: P BlockStmt
467503blockStmt =
@@ -1352,10 +1388,3 @@ colon = tok Op_Colon
13521388semiColon = tok SemiColon
13531389period = tok Period
13541390
1355- ------------------------------------------------------------
1356-
1357- test = " public class Foo { }"
1358- testFile file = do
1359- i <- readFile file
1360- let r = parseCompilationUnit i
1361- putStrLn $ either ((" Parsing error:\n " ++ ) . show ) (show . pretty) r
0 commit comments