From: <cod...@go...> - 2008-10-08 00:04:28
|
Author: wol...@gm... Date: Tue Oct 7 17:01:15 2008 New Revision: 336 Modified: trunk/hoc/InterfaceGenerator2/Parser.hs Log: Multiple improvements to the parser, mostly for parsing ApplicationServices.framework * when skipping things, take comments into account * ignore all .*EXTERN_C_BEGIN and .*EXTERN_C_END macros at the top level * more operators for constant int expressions (*,/,+,-,>>,|) * accept all .*EXTERN and .*EXPORT macros in place of extern * accept all .*INLINE macros in place of inline * accept "static" in function prototypes * accept prototypes for inline functions * accept EXTERN_API[_C] and CALLBACK_API[_C] macros (for parsing Carbon headers) Modified: trunk/hoc/InterfaceGenerator2/Parser.hs ============================================================================== --- trunk/hoc/InterfaceGenerator2/Parser.hs (original) +++ trunk/hoc/InterfaceGenerator2/Parser.hs Tue Oct 7 17:01:15 2008 @@ -3,8 +3,9 @@ import Data.Maybe ( isJust, fromJust ) import Data.Char ( ord, isUpper, isDigit ) -import Data.Bits ( shiftL, (.|.) ) -import Control.Monad ( guard ) +import Data.Bits ( shiftL, shiftR, (.|.) ) +import Data.List ( isSuffixOf ) +import Control.Monad ( guard, unless ) import Text.Parsec import Text.Parsec.Token @@ -52,7 +53,7 @@ return things uninterestingThing :: Parser (Maybe Declaration) -uninterestingThing = skipMany1 (satisfy (\x -> x /= '@' && x /= ';')) >> return Nothing +uninterestingThing = skip1 (satisfy (\x -> x /= '@' && x /= ';')) >> return Nothing interestingThing = ignoredToplevelThing @@ -61,29 +62,37 @@ <|> interface_decl <|> empty_decl <|> type_declaration - <|> inline_function <|> extern_decl <|> (semi objc >> return []) +definedKeyword f = try (do x <- identifier objc + unless (all (\c -> c == '_' || isUpper c) x && f x) $ + fail "") + ignoredToplevelThing - = (foldl1 (<|>) . map (reserved objc)) - ["CA_EXTERN_C_BEGIN", "CA_EXTERN_C_END", - "CF_EXTERN_C_BEGIN", "CF_EXTERN_C_END"] - >> return [] + = definedKeyword (\x -> "EXTERN_C_BEGIN" `isSuffixOf` x + || "EXTERN_C_END" `isSuffixOf` x) + >> return [] -- -skipParens = parens objc (skipMany ( +skip p = do + whiteSpace objc + (p >> skip p) <|> return () + +skip1 p = p >> skip p + +skipParens = parens objc (skip ( (satisfy (\x -> x /= '(' && x /= ')') >> return ()) <|> skipParens )) -skipBlockContents = (skipMany ( +skipBlockContents = (skip ( (satisfy (\x -> x /= '{' && x /= '}') >> return ()) <|> skipBlock )) skipBlock = braces objc skipBlockContents -skipEnumValue = skipMany1 (satisfy (\x -> x /= '}' && x /= ',')) +skipEnumValue = skip (satisfy (\x -> x /= '}' && x /= ',')) -- Plain C @@ -101,7 +110,12 @@ <|> definedConstant <|> parens objc expr - optable = [ [Infix (op "<<" (cast2nd shiftL)) AssocLeft], + optable = [ [Infix (op "*" (*)) AssocLeft, + Infix (op "/" div) AssocLeft], + [Infix (op "+" (+)) AssocLeft, + Infix (op "-" (-)) AssocLeft], + [Infix (op "<<" (cast2nd shiftL)) AssocLeft, + Infix (op ">>" (cast2nd shiftR)) AssocLeft], [Infix (op "|" (.|.)) AssocLeft] ] where op str f = reservedOp objc str >> return f @@ -147,6 +161,7 @@ t <- id_type <|> enum_type <|> struct_type + <|> (reserved objc "STACK_UPP_TYPE" >> parens objc simple_type) <|> try builtin_type <|> do n <- identifier objc protos <- protocol_spec -- TOOD: use these protocols @@ -197,10 +212,14 @@ postfix_operator = brackets objc (optional (integer objc) >> return CTPointer) - <|> do - (args, vararg) <- parens objc arguments - return (\retval -> CTFunction retval args vararg) - + <|> function_call_declarator + + +function_call_declarator + = do + (args, vararg) <- parens objc arguments + return (\retval -> CTFunction retval args vararg) + where arguments = do args <- commaSep objc argument @@ -294,16 +313,27 @@ semi objc return [ (modifier typ, name) | (name, modifier) <- things ] +typedef = reserved objc "typedef" >> (carbon_callback <|> real_typedef) + where + carbon_callback = do + reserved objc "CALLBACK_API" <|> reserved objc "CALLBACK_API_C" + (t,i) <- parens objc ( do t <- simple_type + comma objc + i <- identifier objc + return (t,i) ) + f <- function_call_declarator + availability + semi objc + return $ [ Typedef (f t) i ] -typedef = do - reserved objc "typedef" - baseType <- simple_type - - newTypes <- commaSep objc id_declarator - availability - semi objc - return $ [Typedef (typeFun baseType) name - | (name, typeFun) <- newTypes ] + real_typedef = do + baseType <- simple_type + + newTypes <- commaSep objc id_declarator + availability + semi objc + return $ [Typedef (typeFun baseType) name + | (name, typeFun) <- newTypes ] ctypeDecl = do typ <- enum_type <|> struct_type @@ -315,12 +345,26 @@ extern_decl = do - optional extern_keyword - t <- simple_type - vars <- commaSep objc (one_var t) - availability - semi objc - return vars + t <- carbon_extern_api <|> + (many storage_class >> simple_type) + firstVar <- one_var t + + let single_declaration_end = do + availability + semi objc + return [firstVar] + multiple_declaration_end = do + comma objc + moreVars <- commaSep objc (one_var t) + availability + semi objc + return $ firstVar : moreVars + function_definition = do + availability + skipBlock + return [] + + single_declaration_end <|> multiple_declaration_end <|> function_definition where one_var t = do (n, typeOperators) <- id_declarator @@ -330,24 +374,17 @@ otherType -> ExternVar otherType n + carbon_extern_api = (reserved objc "EXTERN_API" <|> reserved objc "EXTERN_API_C") + >> parens objc simple_type + extern_keyword = reserved objc "extern" - <|> reserved objc "FOUNDATION_EXPORT" -- N.B. "Export" vs. "Extern". - <|> reserved objc "APPKIT_EXTERN" - <|> reserved objc "GS_EXPORT" - <|> reserved objc "CA_EXTERN" - <|> reserved objc "CF_EXPORT" - <|> reserved objc "COREDATA_EXTERN" - -inline_function = - do - reserved objc "inline" <|> reserved objc "NS_INLINE" - <|> reserved objc "CF_INLINE" - t <- simple_type - (n, tf) <- id_declarator - skipBlock - return [] + <|> definedKeyword (\x -> "EXTERN" `isSuffixOf` x || "EXPORT" `isSuffixOf` x) +inline_keyword = + reserved objc "inline" <|> definedKeyword ("_INLINE" `isSuffixOf`) + +storage_class = extern_keyword <|> inline_keyword <|> reserved objc "static" -- Ignore __attribute__((...)) and Apple's countless different availability macros, -- which all expand to some __attribute__. My favourite example is @@ -433,7 +470,7 @@ classOrInstanceMethod <- (symbol objc "-" >> return InstanceMethod) <|> (symbol objc "+" >> return ClassMethod) - -- str <- many (satisfy (\c -> c /= ';' && c /= '@')) + rettype <- option (CTIDType []) (parens objc ctype) (name,types,vararg) <- ( do |