packages feed

cimple 0.0.15 → 0.0.16

raw patch · 17 files changed

+1018/−287 lines, 17 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Cimple: Error :: LexemeClass
- Language.Cimple.Diagnostics: instance Language.Cimple.Diagnostics.HasLocation (Language.Cimple.Lexer.Lexeme text)
- Language.Cimple.Diagnostics: instance Language.Cimple.Diagnostics.HasLocation lexeme => Language.Cimple.Diagnostics.HasLocation (Language.Cimple.Ast.Node lexeme)
+ Language.Cimple: AttrPrintf :: lexeme -> lexeme -> a -> NodeF lexeme a
+ Language.Cimple: CmtAttr :: LexemeClass
+ Language.Cimple: CmtPrefix :: LexemeClass
+ Language.Cimple: CommentInfo :: Comment lexeme -> NodeF lexeme a
+ Language.Cimple: CommentSection :: a -> [a] -> a -> NodeF lexeme a
+ Language.Cimple: DocAssignOp :: AssignOp -> a -> a -> CommentF lexeme a
+ Language.Cimple: DocAttention :: [a] -> CommentF lexeme a
+ Language.Cimple: DocBinaryOp :: BinaryOp -> a -> a -> CommentF lexeme a
+ Language.Cimple: DocBrief :: [a] -> CommentF lexeme a
+ Language.Cimple: DocColon :: lexeme -> CommentF lexeme a
+ Language.Cimple: DocComment :: [a] -> CommentF lexeme a
+ Language.Cimple: DocDeprecated :: [a] -> CommentF lexeme a
+ Language.Cimple: DocExtends :: lexeme -> CommentF lexeme a
+ Language.Cimple: DocImplements :: lexeme -> CommentF lexeme a
+ Language.Cimple: DocLParen :: a -> CommentF lexeme a
+ Language.Cimple: DocLine :: [a] -> CommentF lexeme a
+ Language.Cimple: DocList :: [a] -> CommentF lexeme a
+ Language.Cimple: DocNewline :: CommentF lexeme a
+ Language.Cimple: DocOLItem :: lexeme -> [a] -> CommentF lexeme a
+ Language.Cimple: DocP :: lexeme -> CommentF lexeme a
+ Language.Cimple: DocParagraph :: [a] -> CommentF lexeme a
+ Language.Cimple: DocParam :: Maybe lexeme -> lexeme -> [a] -> CommentF lexeme a
+ Language.Cimple: DocPrivate :: CommentF lexeme a
+ Language.Cimple: DocRParen :: a -> CommentF lexeme a
+ Language.Cimple: DocRef :: lexeme -> CommentF lexeme a
+ Language.Cimple: DocReturn :: [a] -> CommentF lexeme a
+ Language.Cimple: DocRetval :: lexeme -> [a] -> CommentF lexeme a
+ Language.Cimple: DocSee :: lexeme -> [a] -> CommentF lexeme a
+ Language.Cimple: DocSentence :: [a] -> lexeme -> CommentF lexeme a
+ Language.Cimple: DocULItem :: [a] -> [a] -> CommentF lexeme a
+ Language.Cimple: DocWord :: lexeme -> CommentF lexeme a
+ Language.Cimple: ErrorToken :: LexemeClass
+ Language.Cimple: Group :: [a] -> NodeF lexeme a
+ Language.Cimple: IgnBody :: LexemeClass
+ Language.Cimple: IgnEnd :: LexemeClass
+ Language.Cimple: IgnStart :: LexemeClass
+ Language.Cimple: Ignore :: CommentStyle
+ Language.Cimple: KwGnuPrintf :: LexemeClass
+ Language.Cimple: Section :: CommentStyle
+ Language.Cimple: data CommentF lexeme a
+ Language.Cimple: type Comment lexeme = Fix (CommentF lexeme)
+ Language.Cimple.MapAst: doComment :: AstActions f itext otext -> FilePath -> Comment (Lexeme itext) -> f (Comment (Lexeme otext)) -> f (Comment (Lexeme otext))
+ Language.Cimple.MapAst: doComments :: AstActions f itext otext -> FilePath -> [Comment (Lexeme itext)] -> f [Comment (Lexeme otext)] -> f [Comment (Lexeme otext)]
+ Language.Cimple.MapAst: instance Language.Cimple.MapAst.MapAst itext otext (Language.Cimple.Ast.Comment (Language.Cimple.Lexer.Lexeme itext))
+ Language.Cimple.MapAst: instance Language.Cimple.MapAst.MapAst itext otext [Language.Cimple.Ast.Comment (Language.Cimple.Lexer.Lexeme itext)]
+ Language.Cimple.Pretty: render :: Doc -> Text
+ Language.Cimple.TraverseAst: doComment :: AstActions f text -> FilePath -> Comment (Lexeme text) -> f () -> f ()
+ Language.Cimple.TraverseAst: doComments :: AstActions f text -> FilePath -> [Comment (Lexeme text)] -> f () -> f ()
+ Language.Cimple.TraverseAst: instance Language.Cimple.TraverseAst.TraverseAst text (Language.Cimple.Ast.Comment (Language.Cimple.Lexer.Lexeme text))
+ Language.Cimple.TraverseAst: instance Language.Cimple.TraverseAst.TraverseAst text [Language.Cimple.Ast.Comment (Language.Cimple.Lexer.Lexeme text)]
- Language.Cimple: parseTranslationUnit :: Alex [StringNode]
+ Language.Cimple: parseTranslationUnit :: Alex [NonTerm]

Files

cimple.cabal view
@@ -1,5 +1,5 @@ name:                 cimple-version:              0.0.15+version:              0.0.16 synopsis:             Simple C-like programming language homepage:             https://toktok.github.io/ license:              GPL-3@@ -36,9 +36,12 @@   other-modules:       Language.Cimple.Annot     , Language.Cimple.Ast+    , Language.Cimple.CommentParser+    , Language.Cimple.DescribeAst     , Language.Cimple.Flatten     , Language.Cimple.Graph     , Language.Cimple.Lexer+    , Language.Cimple.ParseResult     , Language.Cimple.Parser     , Language.Cimple.SemCheck.Includes     , Language.Cimple.Tokens@@ -53,7 +56,6 @@     , containers     , data-fix     , filepath-    , groom     , monad-parallel     , mtl     , recursion-schemes
src/Language/Cimple/Ast.hs view
@@ -13,12 +13,14 @@     , Node, NodeF (..)     , Scope (..)     , CommentStyle (..)+    , Comment+    , CommentF (..)     ) where  import           Data.Aeson                   (FromJSON, FromJSON1, ToJSON,                                                ToJSON1) import           Data.Fix                     (Fix)-import           Data.Functor.Classes         (Eq1, Read1, Show1)+import           Data.Functor.Classes         (Eq1, Ord1, Read1, Show1) import           Data.Functor.Classes.Generic (FunctorClassesDefault (..)) import           GHC.Generics                 (Generic, Generic1) @@ -44,10 +46,15 @@     | LicenseDecl lexeme [a]     | CopyrightDecl lexeme (Maybe lexeme) [lexeme]     | Comment CommentStyle lexeme [lexeme] lexeme+    | CommentSection a [a] a     | CommentSectionEnd lexeme     | Commented a a+    | CommentInfo (Comment lexeme)     -- Namespace-like blocks     | ExternC [a]+    -- An inferred coherent block of nodes, printed without empty lines+    -- between them.+    | Group [a]     -- Statements     | CompoundStmt [a]     | Break@@ -104,6 +111,7 @@     | TyStd lexeme     | TyUserDefined lexeme     -- Functions+    | AttrPrintf lexeme lexeme a     | FunctionDecl Scope a     | FunctionDefn Scope a a     | FunctionPrototype a lexeme [a]@@ -113,14 +121,53 @@     -- Constants     | ConstDecl a lexeme     | ConstDefn Scope a lexeme a-    deriving (Show, Read, Eq, Generic, Generic1, Functor, Foldable, Traversable)-    deriving (Show1, Read1, Eq1) via FunctorClassesDefault (NodeF lexeme)+    deriving (Show, Read, Eq, Ord, Generic, Generic1, Functor, Foldable, Traversable)+    deriving (Show1, Read1, Eq1, Ord1) via FunctorClassesDefault (NodeF lexeme)  type Node lexeme = Fix (NodeF lexeme)  instance FromJSON lexeme => FromJSON1 (NodeF lexeme) instance ToJSON lexeme => ToJSON1 (NodeF lexeme) +data CommentF lexeme a+    = DocComment [a]+    | DocWord lexeme+    | DocSentence [a] lexeme+    | DocNewline++    | DocAttention [a]+    | DocBrief [a]+    | DocDeprecated [a]+    | DocExtends lexeme+    | DocImplements lexeme+    | DocParam (Maybe lexeme) lexeme [a]+    | DocReturn [a]+    | DocRetval lexeme [a]+    | DocSee lexeme [a]++    | DocPrivate++    | DocParagraph [a]+    | DocLine [a]+    | DocList [a]+    | DocULItem [a] [a]+    | DocOLItem lexeme [a]++    | DocColon lexeme+    | DocRef lexeme+    | DocP lexeme+    | DocLParen a+    | DocRParen a+    | DocAssignOp AssignOp a a+    | DocBinaryOp BinaryOp a a+    deriving (Show, Read, Eq, Ord, Generic, Generic1, Functor, Foldable, Traversable)+    deriving (Show1, Read1, Eq1, Ord1) via FunctorClassesDefault (CommentF lexeme)++type Comment lexeme = Fix (CommentF lexeme)++instance FromJSON lexeme => FromJSON1 (CommentF lexeme)+instance ToJSON lexeme => ToJSON1 (CommentF lexeme)+ data AssignOp     = AopEq     | AopMul@@ -133,7 +180,7 @@     | AopMod     | AopLsh     | AopRsh-    deriving (Show, Read, Eq, Generic)+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON AssignOp instance ToJSON AssignOp@@ -157,7 +204,7 @@     | BopGt     | BopGe     | BopRsh-    deriving (Show, Read, Eq, Generic)+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON BinaryOp instance ToJSON BinaryOp@@ -170,7 +217,7 @@     | UopDeref     | UopIncr     | UopDecr-    deriving (Show, Read, Eq, Generic)+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON UnaryOp instance ToJSON UnaryOp@@ -181,7 +228,7 @@     | Bool     | String     | ConstId-    deriving (Show, Read, Eq, Generic)+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON LiteralType instance ToJSON LiteralType@@ -189,7 +236,7 @@ data Scope     = Global     | Static-    deriving (Show, Read, Eq, Generic)+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON Scope instance ToJSON Scope@@ -197,8 +244,10 @@ data CommentStyle     = Regular     | Doxygen+    | Section     | Block-    deriving (Show, Read, Eq, Generic)+    | Ignore+    deriving (Enum, Bounded, Ord, Show, Read, Eq, Generic)  instance FromJSON CommentStyle instance ToJSON CommentStyle
+ src/Language/Cimple/CommentParser.y view
@@ -0,0 +1,240 @@+{+{-# LANGUAGE OverloadedStrings #-}+module Language.Cimple.CommentParser+    ( parseComment+    ) where++import           Data.Fix                    (Fix (..))+import           Data.Text                   (Text)+import qualified Data.Text                   as Text++import           Language.Cimple.Ast         (AssignOp (..), BinaryOp (..),+                                              Comment, CommentF (..))+import           Language.Cimple.DescribeAst (describeLexeme, sloc)+import           Language.Cimple.Lexer       (Lexeme (..))+import           Language.Cimple.ParseResult (ParseResult)+import           Language.Cimple.Tokens      (LexemeClass (..))+}++%name parseComment Comment++%expect 0++%error {parseError}+%errorhandlertype explist+%monad {ParseResult}+%tokentype {Term}+%token+    '@attention'		{ L _ CmtCommand "@attention"	}+    '@brief'			{ L _ CmtCommand "@brief"	}+    '@deprecated'		{ L _ CmtCommand "@deprecated"	}+    '@extends'			{ L _ CmtCommand "@extends"	}+    '@implements'		{ L _ CmtCommand "@implements"	}+    '@param'			{ L _ CmtCommand "@param"	}+    '@private'			{ L _ CmtCommand "@private"	}+    '@ref'			{ L _ CmtCommand "@ref"		}+    '@p'			{ L _ CmtCommand "@p"		}+    '@return'			{ L _ CmtCommand "@return"	}+    '@retval'			{ L _ CmtCommand "@retval"	}+    '@see'			{ L _ CmtCommand "@see"		}++    ' '				{ L _ CmtIndent		" "	}+    'INDENT1'			{ L _ CmtIndent		"   "	}+    'INDENT2'			{ L _ CmtIndent		"    " 	}+    'INDENT3'			{ L _ CmtIndent		"     "	}++    '('				{ L _ PctLParen			_ }+    ')'				{ L _ PctRParen			_ }+    ','				{ L _ PctComma			_ }+    ':'				{ L _ PctColon			_ }+    '/'				{ L _ PctSlash			_ }+    '='				{ L _ PctEq			_ }+    '=='			{ L _ PctEqEq			_ }+    '!='			{ L _ PctEMarkEq		_ }+    '>='			{ L _ PctGreaterEq		_ }+    ';'				{ L _ PctSemicolon		_ }+    '.'				{ L _ PctPeriod			_ }+    '...'			{ L _ PctEllipsis		_ }+    '?'				{ L _ PctQMark			_ }+    '!'				{ L _ PctEMark			_ }+    '-'				{ L _ PctMinus			_ }+    '+'				{ L _ PctPlus			_ }+    '\n'			{ L _ PpNewline			_ }+    '/**'			{ L _ CmtStartDoc		_ }+    '*/'			{ L _ CmtEnd			_ }+    LIT_INTEGER			{ L _ LitInteger		_ }+    LIT_STRING			{ L _ LitString			_ }+    CMT_ATTR			{ L _ CmtAttr			_ }+    CMT_CODE			{ L _ CmtCode			_ }+    CMT_WORD			{ L _ CmtWord			_ }+    CMT_REF			{ L _ CmtRef			_ }++%right '='+%left '.' '?' ',' ';' '!'+%left '!=' '=='+%left '>='+%left '-' '+'+%left '/'+%left '(' ')'++%%++Comment :: { NonTerm }+Comment+:	'/**' '\n' Blocks '*/'					{ Fix $ DocComment $3 }+|	'/**' DocLine '*/'					{ Fix $ DocComment $2 }+|	'/**' Command(DocLine) '*/'				{ Fix $ DocComment [$2] }+|	'/**' Command(IndentedSentence) Blocks '*/'		{ Fix $ DocComment ($2 : $3) }++Blocks :: { [NonTerm] }+Blocks+:	BlockList						{ reverse $1 }++BlockList :: { [NonTerm] }+BlockList+:	Block							{ [$1] }+|	BlockList Block						{ $2 : $1 }++Block :: { NonTerm }+Block+:	'\n'							{ Fix DocNewline }+|	' ' Command(IndentedSentence)				{ $2 }+|	' ' Paragraph						{ Fix $ DocParagraph $2 }+|	' ' NumberedListItem					{ Fix $ DocList [$2] }+|	' ' BulletListItem					{ Fix $ DocList [$2] }++Paragraph :: { [NonTerm] }+Paragraph+:	Word(NonInt) Punctuation MaybeWords			{ Fix (DocSentence [$1] $2) : $3 }+|	Word(NonInt) MaybeWords					{ prepend $1 $2 }++Punctuation :: { Term }+Punctuation+:	'.'							{ $1 }+|	','							{ $1 }+|	';'							{ $1 }+|	'?'							{ $1 }++MaybeWords :: { [NonTerm] }+MaybeWords+:								{ [] }+|	IndentedSentence					{ $1 }++IndentedSentence :: { [NonTerm] }+IndentedSentence+:	DocLine '\n'						{ $1 }+|	DocLine '\n' 'INDENT1' IndentedSentence			{ $1 ++ $4 }++DocLine :: { [NonTerm] }+DocLine+:	Words							{ [Fix $ DocLine $1] }++Command(x)+:	'@attention' x						{ Fix $ DocAttention $2 }+|	'@brief' x						{ Fix $ DocBrief $2 }+|	'@param' CMT_WORD x					{ Fix $ DocParam Nothing $2 $3 }+|	'@param' CMT_ATTR CMT_WORD x				{ Fix $ DocParam (Just $2) $3 $4 }+|	'@retval' Atom x					{ Fix $ DocRetval $2 $3 }+|	'@return' x						{ Fix $ DocReturn $2 }+|	'@return' '\n' BulletListItemII				{ Fix $ DocReturn (Fix (DocLine []) : $3) }+|	'@see' CMT_WORD x					{ Fix $ DocSee $2 $3 }+|	'@deprecated' x						{ Fix $ DocDeprecated $2 }+|	'@implements' CMT_WORD					{ Fix $ DocImplements $2 }+|	'@extends' CMT_WORD					{ Fix $ DocExtends $2 }+|	'@private'						{ Fix DocPrivate }++BulletListItem :: { NonTerm }+BulletListItem+:	'-' Words '\n' BulletICont				{ Fix $ DocULItem $2 $4 }++BulletICont :: { [NonTerm] }+BulletICont+:								{ [] }+|	'INDENT1' DocLine '\n' BulletICont			{ $2 ++ $4 }+|	BulletListItemII					{ $1 }++BulletListItemII :: { [NonTerm] }+BulletListItemII+:	'INDENT1' '-' Words '\n' BulletIICont			{ Fix (DocULItem ($3 ++ snd $5) []) : fst $5 }++BulletIICont :: { ([NonTerm], [NonTerm]) }+BulletIICont+:								{ ([], []) }+|	BulletListItemII					{ ($1, []) }+|	'INDENT3' DocLine '\n' BulletIICont			{ ([], $2) <> $4 }++NumberedListItem :: { NonTerm }+NumberedListItem+:	LIT_INTEGER '.' IndentedSentenceII			{ Fix (DocOLItem $1 $3) }++IndentedSentenceII :: { [NonTerm] }+IndentedSentenceII+:	DocLine '\n'						{ $1 }+|	DocLine '\n' 'INDENT2' IndentedSentenceII		{ $1 ++ $4 }++Words :: { [NonTerm] }+Words+:	SentenceList(WordList)					{ $1 }++WordList :: { [NonTerm] }+WordList+:	Word(Atom)						{ [$1] }+|	WordList Word(Atom)					{ $2 : $1 }++SentenceList(x)+:	x							{ reverse $1 }+|	SentenceList(x) ';'					{ [Fix (DocSentence $1 $2)] }+|	SentenceList(x) ','					{ [Fix (DocSentence $1 $2)] }+|	SentenceList(x) '.'					{ [Fix (DocSentence $1 $2)] }+|	SentenceList(x) '?'					{ [Fix (DocSentence $1 $2)] }+|	SentenceList(x) '!'					{ [Fix (DocSentence $1 $2)] }+|	SentenceList(x) ';' SentenceList(x)			{ Fix (DocSentence $1 $2) : $3 }+|	SentenceList(x) ',' SentenceList(x)			{ Fix (DocSentence $1 $2) : $3 }+|	SentenceList(x) '.' SentenceList(x)			{ Fix (DocSentence $1 $2) : $3 }+|	SentenceList(x) '?' SentenceList(x)			{ Fix (DocSentence $1 $2) : $3 }+|	SentenceList(x) '!' SentenceList(x)			{ Fix (DocSentence $1 $2) : $3 }++Word(x)+:	x							{ Fix $ DocWord $1 }+|	x ':'							{ Fix $ DocColon $1 }+|	Word(x) '=' Word(Atom)					{ Fix $ DocAssignOp AopEq $1 $3 }+|	Word(x) '+' Word(Atom)					{ Fix $ DocBinaryOp BopPlus $1 $3 }+|	Word(x) '-' Word(Atom)					{ Fix $ DocBinaryOp BopMinus $1 $3 }+|	Word(x) '/' Word(Atom)					{ Fix $ DocBinaryOp BopDiv $1 $3 }+|	Word(x) '!=' Word(Atom)					{ Fix $ DocBinaryOp BopNe $1 $3 }+|	Word(x) '>=' Word(Atom)					{ Fix $ DocBinaryOp BopGe $1 $3 }+|	Word(x) '==' Word(Atom)					{ Fix $ DocBinaryOp BopEq $1 $3 }+|	'@ref' Atom						{ Fix $ DocRef $2 }+|	'@p' Atom						{ Fix $ DocP $2 }+|	'(' Word(Atom)						{ Fix $ DocLParen $2 }+|	Word(x) ')'						{ Fix $ DocRParen $1 }++Atom :: { Term }+Atom+:	NonInt							{ $1 }+|	LIT_INTEGER						{ $1 }++NonInt :: { Term }+NonInt+:	CMT_WORD						{ $1 }+|	CMT_CODE						{ $1 }+|	LIT_STRING						{ $1 }+|	'...'							{ $1 }++{+type Term = Lexeme Text+type NonTerm = Comment Term++prepend :: NonTerm -> [NonTerm] -> [NonTerm]+prepend x [] = [x]+prepend x (Fix (DocLine xs):rest) = Fix (DocLine (x:xs)) : rest++failAt :: Lexeme Text -> String -> ParseResult a+failAt n msg =+    fail $ Text.unpack (sloc "" n) <> ": unexpected " <> describeLexeme n <> msg++parseError :: ([Lexeme Text], [String]) -> ParseResult a+parseError ([], options)  = fail $ " end of comment; expected one of " <> show options+parseError (n:_, [])      = failAt n "; expected end of comment"+parseError (n:_, options) = failAt n $ "; expected one of " <> show options+}
+ src/Language/Cimple/DescribeAst.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Strict            #-}+{-# LANGUAGE StrictData        #-}+module Language.Cimple.DescribeAst+    ( HasLocation (..)+    , describeLexeme+    , describeNode+    ) where++import           Data.Fix                (Fix (..), foldFix)+import           Data.Text               (Text)+import qualified Data.Text               as Text+import           Language.Cimple.Ast     (Node, NodeF (..))+import qualified Language.Cimple.Flatten as Flatten+import           Language.Cimple.Lexer   (Lexeme, lexemeLine)+++class HasLocation a where+    sloc :: FilePath -> a -> Text++instance HasLocation (Lexeme text) where+    sloc file l = Text.pack file <> ":" <> Text.pack (show (lexemeLine l))++instance HasLocation lexeme => HasLocation (Node lexeme) where+    sloc file n =+        case foldFix Flatten.lexemes n of+            []  -> Text.pack file <> ":0:0"+            l:_ -> sloc file l+++describeNode :: Show a => Node a -> String+describeNode node = case unFix node of+    PreprocIf{}     -> "#if/#endif block"+    PreprocIfdef{}  -> "#ifdef/#endif block"+    PreprocIfndef{} -> "#ifndef/#endif block"+    _               -> show $ (const ellipsis) <$> unFix node+  where+    ellipsis :: String+    ellipsis = "..."++describeLexeme :: Show a => Lexeme a -> String+describeLexeme = show
src/Language/Cimple/Diagnostics.hs view
@@ -9,14 +9,10 @@   , sloc   ) where -import           Control.Monad.State.Strict (State)-import qualified Control.Monad.State.Strict as State-import           Data.Fix                   (foldFix)-import           Data.Text                  (Text)-import qualified Data.Text                  as Text-import           Language.Cimple.Ast        (Node)-import qualified Language.Cimple.Flatten    as Flatten-import           Language.Cimple.Lexer      (Lexeme (..), lexemeLine)+import           Control.Monad.State.Strict  (State)+import qualified Control.Monad.State.Strict  as State+import           Data.Text                   (Text)+import           Language.Cimple.DescribeAst (HasLocation (..))  type DiagnosticsT diags a = State diags a type Diagnostics a = DiagnosticsT [Text] a@@ -32,16 +28,3 @@  instance HasDiagnostics [Text] where     addDiagnostic = (:)---class HasLocation a where-    sloc :: FilePath -> a -> Text--instance HasLocation (Lexeme text) where-    sloc file l = Text.pack file <> ":" <> Text.pack (show (lexemeLine l))--instance HasLocation lexeme => HasLocation (Node lexeme) where-    sloc file n =-        case foldFix Flatten.lexemes n of-            []  -> Text.pack file <> ":0:0"-            l:_ -> sloc file l
src/Language/Cimple/Flatten.hs view
@@ -7,10 +7,12 @@ {-# LANGUAGE TypeOperators         #-} module Language.Cimple.Flatten (lexemes) where +import           Data.Fix            (Fix (..)) import           Data.Maybe          (maybeToList) import           GHC.Generics-import           Language.Cimple.Ast (AssignOp, BinaryOp, CommentStyle,-                                      LiteralType, NodeF (..), Scope, UnaryOp)+import           Language.Cimple.Ast (AssignOp, BinaryOp, CommentF,+                                      CommentStyle, LiteralType, NodeF (..),+                                      Scope, UnaryOp)  class Concats t a where     concats :: t -> [a]@@ -53,11 +55,15 @@ instance {-# OVERLAPPABLE #-} GenConcatsFlatten b a => GenConcatsFlatten [b] a where     gconcatsFlatten = concatMap gconcatsFlatten +instance GenConcatsFlatten (Fix (CommentF a)) a where+    gconcatsFlatten = error "TODO: gconcatsFlatten for CommentF"+ instance GenConcatsFlatten t a => GenConcats (Rec0 t) a where     gconcats (K1 x) = gconcatsFlatten x  -- Uses the default signature, which delegates to the generic stuff instance Concats (NodeF a [a]) a+instance Concats (CommentF a [a]) a  lexemes :: NodeF lexeme [lexeme] -> [lexeme] lexemes = concats
src/Language/Cimple/IO.hs view
@@ -21,6 +21,7 @@ import           Language.Cimple.MapAst          (TextActions, mapAst,                                                   textActions) import qualified Language.Cimple.Parser          as Parser+import qualified Language.Cimple.ParseResult     as ParseResult import           Language.Cimple.Program         (Program) import qualified Language.Cimple.Program         as Program import           Language.Cimple.TranslationUnit (TranslationUnit)@@ -51,7 +52,7 @@  parseTextPedantic :: Text -> Either String [TextNode] parseTextPedantic =-    parseText >=> TreeParser.toEither . TreeParser.parseTranslationUnit+    parseText >=> ParseResult.toEither . TreeParser.parseTranslationUnit   parseFile :: FilePath -> IO (Either String (TranslationUnit Text))@@ -59,7 +60,7 @@     addSource . parseTextPedantic . Text.decodeUtf8 <$> BS.readFile source   where     -- Add source filename to the error message, if any.-    addSource (Left err) = Left $ source <> ":" <> err+    addSource (Left err) = Left $ source <> err     -- If there's no error message, record the source filename in the returned     -- TranslationUnit.     addSource (Right ok) = Right (source, ok)
src/Language/Cimple/Lexer.x view
@@ -29,7 +29,7 @@ tokens :-  -- Ignore attributes.-<0>		"GNU_PRINTF("[^\)]+")"			;+<0>		"GNU_PRINTF"				{ mkL KwGnuPrintf } <0>		"VLA"					{ mkL KwVla }  -- Winapi functions.@@ -104,12 +104,7 @@ <0>		"msgpack_zone"				{ mkL IdSueType }  -- Sodium constants.-<0,ppSC>	"crypto_auth_"[A-Z][A-Z0-9_]*		{ mkL IdConst }-<0,ppSC>	"crypto_box_"[A-Z][A-Z0-9_]*		{ mkL IdConst }-<0,ppSC>	"crypto_hash_sha256_"[A-Z][A-Z0-9_]*	{ mkL IdConst }-<0,ppSC>	"crypto_hash_sha512_"[A-Z][A-Z0-9_]*	{ mkL IdConst }-<0,ppSC>	"crypto_pwhash_scryptsalsa208sha256_"[A-Z][A-Z0-9_]*		{ mkL IdConst }-<0,ppSC>	"crypto_sign_"[A-Z][A-Z0-9_]*		{ mkL IdConst }+<0,ppSC>	"crypto_"[a-z0-9_]+[A-Z][A-Z0-9_]*	{ mkL IdConst }  -- Standard C (ish). <ppSC>		defined					{ mkL PpDefined }@@ -118,13 +113,13 @@ <ppSC>		\\\n					; <ppSC>		$white					; -<ignoreSC>	"//!TOKSTYLE+"				{ start 0 }-<ignoreSC>	[.\n]					;+<ignoreSC>	"//!TOKSTYLE+"				{ mkL IgnEnd `andBegin` 0 }+<ignoreSC>	([^\/]+|.|\n)				{ mkL IgnBody }  <0,ppSC>	"//"\n					; <0,ppSC>	"// ".*					; <0>		$white+					;-<0>		"//!TOKSTYLE-"				{ start ignoreSC }+<0>		"//!TOKSTYLE-"				{ mkL IgnStart `andBegin` ignoreSC } <0>		"/*"					{ mkL CmtStart `andBegin` cmtSC } <0>		"/**"					{ mkL CmtStartDoc `andBegin` cmtSC } <0>		"/** @{"				{ mkL CmtStartDocSection `andBegin` cmtSC }@@ -191,10 +186,10 @@ <0,ppSC>	[a-z][a-z0-9_]*_cb			{ mkL IdFuncType } <0,ppSC>	[a-z][A-Za-z0-9_]*			{ mkL IdVar } <0,ppSC,cmtSC>	[0-9]+[LU]*				{ mkL LitInteger }-<0,ppSC>	[0-9]+"."[0-9]+f?			{ mkL LitInteger }+<0,ppSC,cmtSC>	[0-9]+"."[0-9]+f?			{ mkL LitInteger } <0,ppSC>	0x[0-9a-fA-F]+[LU]*			{ mkL LitInteger } <0,ppSC,cmtSC>	"="					{ mkL PctEq }-<0,ppSC>	"=="					{ mkL PctEqEq }+<0,ppSC,cmtSC>	"=="					{ mkL PctEqEq } <0,ppSC>	"&"					{ mkL PctAmpersand } <0,ppSC>	"&&"					{ mkL PctAmpersandAmpersand } <0,ppSC>	"&="					{ mkL PctAmpersandEq }@@ -210,7 +205,7 @@ <0,ppSC,cmtSC>	"/"					{ mkL PctSlash } <0,ppSC>	"/="					{ mkL PctSlashEq } <0,ppSC,cmtSC>	"."					{ mkL PctPeriod }-<0,ppSC>	"..."					{ mkL PctEllipsis }+<0,ppSC,cmtSC>	"..."					{ mkL PctEllipsis } <0,ppSC>	"%"					{ mkL PctPercent } <0,ppSC>	"%="					{ mkL PctPercentEq } <0,ppSC,cmtSC>	";"					{ mkL PctSemicolon }@@ -222,7 +217,7 @@ <0,ppSC,cmtSC>	">"					{ mkL PctGreater } <0,ppSC>	">>"					{ mkL PctGreaterGreater } <0,ppSC>	">>="					{ mkL PctGreaterGreaterEq }-<0,ppSC>	">="					{ mkL PctGreaterEq }+<0,ppSC,cmtSC>	">="					{ mkL PctGreaterEq } <0,ppSC>	"|"					{ mkL PctPipe } <0,ppSC>	"||"					{ mkL PctPipePipe } <0,ppSC>	"|="					{ mkL PctPipeEq }@@ -234,7 +229,7 @@ <0,ppSC,cmtSC>	")"					{ mkL PctRParen } <0,ppSC,cmtSC>	"?"					{ mkL PctQMark } <0,ppSC,cmtSC>	"!"					{ mkL PctEMark }-<0,ppSC>	"!="					{ mkL PctEMarkEq }+<0,ppSC,cmtSC>	"!="					{ mkL PctEMarkEq } <0,ppSC>	"*"					{ mkL PctAsterisk } <0,ppSC>	"*="					{ mkL PctAsteriskEq } <0,ppSC>	"^"					{ mkL PctCaret }@@ -245,15 +240,26 @@ <cmtSC>		"SPDX-License-Identifier:"		{ mkL CmtSpdxLicense } <cmtSC>		"GPL-3.0-or-later"			{ mkL CmtWord } <cmtSC>		"TODO("[^\)]+"):"			{ mkL CmtWord }+<cmtSC>		[A-Z][A-Za-z]+"::"[a-z_]+		{ mkL CmtWord }+<cmtSC>		"E.g."					{ mkL CmtWord }+<cmtSC>		"e.g."					{ mkL CmtWord }+<cmtSC>		"etc."					{ mkL CmtWord }+<cmtSC>		"I.e."					{ mkL CmtWord }+<cmtSC>		"i.e."					{ mkL CmtWord }+<cmtSC>		[0-2][0-9](":"[0-5][0-9]){2}"."[0-9]{3}	{ mkL CmtWord }+<cmtSC>		"v"?[0-9]"."[0-9]"."[0-9]		{ mkL CmtWord } <cmtSC>		"@code"					{ mkL CmtCode `andBegin` codeSC } <cmtSC>		"<code>"				{ mkL CmtCode `andBegin` codeSC }+<cmtSC>		"["[^\]]+"]"				{ mkL CmtAttr }+<cmtSC>		"@retval"				{ mkL CmtCommand `andBegin` retvalSC } <cmtSC>		[@\\][a-z]+				{ mkL CmtCommand } <cmtSC>		"*"[A-Za-z][A-Za-z0-9_']*"*"		{ mkL CmtWord } <cmtSC>		"#"[A-Za-z][A-Za-z0-9_]*		{ mkL CmtRef } <cmtSC>		[A-Za-z][A-Za-z0-9_']*			{ mkL CmtWord } <cmtSC>		"#"[0-9]+				{ mkL CmtWord }-<cmtSC>		"http://"[^ ]+				{ mkL CmtWord }+<cmtSC>		"http://"[^\ ]+				{ mkL CmtWord } <cmtSC>		[0-9]+"%"				{ mkL LitInteger }+<cmtSC>		"-1"					{ mkL LitInteger } <cmtSC>		"`"([^`]|"\`")+"`"			{ mkL CmtCode } <cmtSC>		"${"([^\}])+"}"				{ mkL CmtCode } <cmtSC>		"–"					{ mkL CmtWord }@@ -261,26 +267,37 @@ <cmtSC>		\n					{ mkL PpNewline `andBegin` cmtNewlineSC } <cmtSC>		" "+					; +<retvalSC>	[^\ ]+					{ mkL CmtWord `andBegin` cmtSC }+<retvalSC>	" "+					;+ <cmtNewlineSC>	" "+"*"+"/"				{ mkL CmtEnd `andBegin` 0 }-<cmtNewlineSC>	" "+"*"					{ mkL CmtIndent `andBegin` cmtSC }+<cmtNewlineSC>	" "+"*"					{ begin cmtStartSC } +<cmtStartSC>	" "+					{ mkL CmtIndent `andBegin` cmtSC }+<cmtStartSC>	\n					{ mkL PpNewline `andBegin` cmtNewlineSC }++<codeStartSC>	" "+					{ mkL CmtIndent `andBegin` codeSC }+<codeStartSC>	\n					{ mkL PpNewline `andBegin` codeNewlineSC }++<codeNewlineSC>	" "+"*"					{ begin codeStartSC }+ -- <code></code> blocks in comments. <codeSC>	"@endcode"				{ mkL CmtCode `andBegin` cmtSC } <codeSC>	"</code>"				{ mkL CmtCode `andBegin` cmtSC }-<codeSC>	\n					{ mkL PpNewline }-<codeSC>	\n" "+"*"				{ mkL PpNewline }+<codeSC>	\n					{ mkL PpNewline `andBegin` codeNewlineSC } <codeSC>	[^@\<]+					{ mkL CmtCode }  -- Error handling.-<0,ppSC,cmtSC,codeSC>	.				{ mkL Error }+<0,ppSC,cmtSC,codeSC>	.				{ mkL ErrorToken }  {+deriving instance Ord AlexPosn deriving instance Generic AlexPosn instance FromJSON AlexPosn instance ToJSON AlexPosn  data Lexeme text = L AlexPosn LexemeClass text-    deriving (Show, Eq, Generic, Functor, Foldable, Traversable)+    deriving (Ord, Eq, Show, Generic, Functor, Foldable, Traversable)  instance FromJSON text => FromJSON (Lexeme text) instance ToJSON text => ToJSON (Lexeme text)
src/Language/Cimple/MapAst.hs view
@@ -11,6 +11,7 @@      , doFiles, doFile     , doNodes, doNode+    , doComment, doComments     , doLexemes, doLexeme     , doText @@ -20,7 +21,8 @@     ) where  import           Data.Fix              (Fix (..))-import           Language.Cimple.Ast   (Node, NodeF (..))+import           Language.Cimple.Ast   (Comment, CommentF (..), Node,+                                        NodeF (..)) import           Language.Cimple.Lexer (Lexeme (..))  class MapAst itext otext a where@@ -39,13 +41,15 @@ mapAst = flip mapFileAst "<stdin>"  data AstActions f itext otext = AstActions-    { doFiles     :: [(FilePath, [Node (Lexeme itext)])] -> f [(FilePath, [Node (Lexeme otext)])] -> f [(FilePath, [Node (Lexeme otext)])]-    , doFile      ::  (FilePath, [Node (Lexeme itext)])  -> f  (FilePath, [Node (Lexeme otext)])  -> f  (FilePath, [Node (Lexeme otext)])-    , doNodes     :: FilePath -> [Node (Lexeme itext)]   -> f             [Node (Lexeme otext)]   -> f             [Node (Lexeme otext)]-    , doNode      :: FilePath ->  Node (Lexeme itext)    -> f             (Node (Lexeme otext))   -> f             (Node (Lexeme otext))-    , doLexemes   :: FilePath ->       [Lexeme itext]    -> f                   [Lexeme otext]    -> f                   [Lexeme otext]-    , doLexeme    :: FilePath ->        Lexeme itext     -> f                   (Lexeme otext)    -> f                   (Lexeme otext)-    , doText      :: FilePath ->               itext                                              -> f                           otext+    { doFiles     :: [(FilePath, [Node    (Lexeme itext)])] -> f [(FilePath, [Node    (Lexeme otext)])] -> f [(FilePath, [Node    (Lexeme otext)])]+    , doFile      ::  (FilePath, [Node    (Lexeme itext)])  -> f  (FilePath, [Node    (Lexeme otext)])  -> f  (FilePath, [Node    (Lexeme otext)])+    , doNodes     :: FilePath -> [Node    (Lexeme itext)]   -> f             [Node    (Lexeme otext)]   -> f             [Node    (Lexeme otext)]+    , doNode      :: FilePath ->  Node    (Lexeme itext)    -> f             (Node    (Lexeme otext))   -> f             (Node    (Lexeme otext))+    , doComment   :: FilePath ->  Comment (Lexeme itext)    -> f             (Comment (Lexeme otext))   -> f             (Comment (Lexeme otext))+    , doComments  :: FilePath -> [Comment (Lexeme itext)]   -> f             [Comment (Lexeme otext)]   -> f             [Comment (Lexeme otext)]+    , doLexemes   :: FilePath ->          [Lexeme itext]    -> f                      [Lexeme otext]    -> f                      [Lexeme otext]+    , doLexeme    :: FilePath ->           Lexeme itext     -> f                      (Lexeme otext)    -> f                      (Lexeme otext)+    , doText      :: FilePath ->                  itext                                                 -> f                              otext     }  instance MapAst itext otext        a@@ -64,6 +68,8 @@     , doFile      = const id     , doNodes     = const $ const id     , doNode      = const $ const id+    , doComment   = const $ const id+    , doComments  = const $ const id     , doLexeme    = const $ const id     , doLexemes   = const $ const id     , doText      = const ft@@ -92,6 +98,82 @@     mapFileAst actions@AstActions{..} currentFile = doLexemes currentFile <*>         traverse (mapFileAst actions currentFile) +instance MapAst itext otext (Comment (Lexeme itext)) where+    type Mapped itext otext (Comment (Lexeme itext))+                          =  Comment (Lexeme otext)+    mapFileAst+        :: forall f . Applicative f+        => AstActions f itext otext+        -> FilePath+        ->    Comment (Lexeme itext)+        -> f (Comment (Lexeme otext))+    mapFileAst actions@AstActions{..} currentFile = doComment currentFile <*> \comment -> case unFix comment of+        DocComment docs ->+            Fix <$> (DocComment <$> recurse docs)+        DocWord word ->+            Fix <$> (DocWord <$> recurse word)+        DocSentence docs ending ->+            Fix <$> (DocSentence <$> recurse docs <*> recurse ending)+        DocNewline -> pure $ Fix DocNewline++        DocAttention docs ->+            Fix <$> (DocAttention <$> recurse docs)+        DocBrief docs ->+            Fix <$> (DocBrief <$> recurse docs)+        DocDeprecated docs ->+            Fix <$> (DocDeprecated <$> recurse docs)+        DocExtends feat ->+            Fix <$> (DocExtends <$> recurse feat)+        DocImplements feat ->+            Fix <$> (DocImplements <$> recurse feat)+        DocParam attr name docs ->+            Fix <$> (DocParam <$> recurse attr <*> recurse name <*> recurse docs)+        DocReturn docs ->+            Fix <$> (DocReturn <$> recurse docs)+        DocRetval expr docs ->+            Fix <$> (DocRetval <$> recurse expr <*> recurse docs)+        DocSee ref docs ->+            Fix <$> (DocSee <$> recurse ref <*> recurse docs)++        DocPrivate -> pure $ Fix DocPrivate++        DocParagraph docs ->+            Fix <$> (DocParagraph <$> recurse docs)+        DocLine docs ->+            Fix <$> (DocLine <$> recurse docs)+        DocList docs ->+            Fix <$> (DocList <$> recurse docs)+        DocOLItem docs sublist ->+            Fix <$> (DocOLItem <$> recurse docs <*> recurse sublist)+        DocULItem docs sublist ->+            Fix <$> (DocULItem <$> recurse docs <*> recurse sublist)++        DocColon docs ->+            Fix <$> (DocColon <$> recurse docs)+        DocRef doc ->+            Fix <$> (DocRef <$> recurse doc)+        DocP doc ->+            Fix <$> (DocP <$> recurse doc)+        DocLParen docs ->+            Fix <$> (DocLParen <$> recurse docs)+        DocRParen docs ->+            Fix <$> (DocRParen <$> recurse docs)+        DocAssignOp op lhs rhs ->+            Fix <$> (DocAssignOp op <$> recurse lhs <*> recurse rhs)+        DocBinaryOp op lhs rhs ->+            Fix <$> (DocBinaryOp op <$> recurse lhs <*> recurse rhs)++      where+        recurse :: MapAst itext otext a => a -> f (Mapped itext otext a)+        recurse = mapFileAst actions currentFile++instance MapAst itext otext [Comment (Lexeme itext)] where+    type Mapped itext otext [Comment (Lexeme itext)]+                          = [Comment (Lexeme otext)]+    mapFileAst actions@AstActions{..} currentFile = doComments currentFile <*>+        traverse (mapFileAst actions currentFile)++ instance MapAst itext otext (Node (Lexeme itext)) where     type Mapped itext otext (Node (Lexeme itext))                           =  Node (Lexeme otext)@@ -140,12 +222,18 @@             Fix <$> (CopyrightDecl <$> recurse from <*> recurse to <*> recurse owner)         Comment doc start contents end ->             Fix <$> (Comment doc <$> recurse start <*> recurse contents <*> recurse end)+        CommentSection start decls end ->+            Fix <$> (CommentSection <$> recurse start <*> recurse decls <*> recurse end)         CommentSectionEnd comment ->             Fix <$> (CommentSectionEnd <$> recurse comment)         Commented comment subject ->             Fix <$> (Commented <$> recurse comment <*> recurse subject)+        CommentInfo comment ->+            Fix <$> (CommentInfo <$> recurse comment)         ExternC decls ->             Fix <$> (ExternC <$> recurse decls)+        Group decls ->+            Fix <$> (Group <$> recurse decls)         CompoundStmt stmts ->             Fix <$> (CompoundStmt <$> recurse stmts)         Break ->@@ -248,6 +336,8 @@             Fix <$> (TyStd <$> recurse name)         TyUserDefined name ->             Fix <$> (TyUserDefined <$> recurse name)+        AttrPrintf fmt ellipsis fun ->+            Fix <$> (AttrPrintf <$> recurse fmt <*> recurse ellipsis <*> recurse fun)         FunctionDecl scope proto ->             Fix <$> (FunctionDecl scope <$> recurse proto)         FunctionDefn scope proto body ->
+ src/Language/Cimple/ParseResult.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Language.Cimple.ParseResult+    ( ParseResult+    , toEither+    ) where++newtype ParseResult a = ParseResult { toEither :: Either String a }+    deriving (Functor, Applicative, Monad)++instance MonadFail ParseResult where+    fail = ParseResult . Left
src/Language/Cimple/Parser.y view
@@ -22,7 +22,7 @@ %errorhandlertype explist %lexer {lexwrap} {L _ Eof _} %monad {Alex}-%tokentype {Lexeme String}+%tokentype {StringLexeme} %token     ID_CONST			{ L _ IdConst			_ }     ID_FUNC_TYPE		{ L _ IdFuncType		_ }@@ -39,6 +39,7 @@     enum			{ L _ KwEnum			_ }     extern			{ L _ KwExtern			_ }     for				{ L _ KwFor			_ }+    GNU_PRINTF			{ L _ KwGnuPrintf		_ }     goto			{ L _ KwGoto			_ }     if				{ L _ KwIf			_ }     non_null			{ L _ KwNonNull			_ }@@ -122,14 +123,19 @@     '/** @{'			{ L _ CmtStartDocSection	_ }     '/** @} */'			{ L _ CmtEndDocSection		_ }     '/***'			{ L _ CmtStartBlock		_ }-    ' * '			{ L _ CmtIndent			_ }+    ' * '			{ L _ CmtPrefix			_ }+    ' '				{ L _ CmtIndent			_ }     '*/'			{ L _ CmtEnd			_ }     'Copyright'			{ L _ CmtSpdxCopyright		_ }     'License'			{ L _ CmtSpdxLicense		_ }+    CMT_ATTR			{ L _ CmtAttr			_ }     CMT_CODE			{ L _ CmtCode			_ }     CMT_COMMAND			{ L _ CmtCommand		_ }     CMT_WORD			{ L _ CmtWord			_ }     CMT_REF			{ L _ CmtRef			_ }+    IGN_START			{ L _ IgnStart			_ }+    IGN_BODY			{ L _ IgnBody			_ }+    IGN_END			{ L _ IgnEnd			_ }  %left ',' %right '=' '+=' '-=' '*=' '/=' '%=' '<<=' '>>=' '&=' '^=' '|='@@ -149,23 +155,23 @@  %% -TranslationUnit :: { [StringNode] }+TranslationUnit :: { [NonTerm] } TranslationUnit :	ToplevelDecls						{ reverse $1 } |	LicenseDecl ToplevelDecls				{ $1 : reverse $2 } -LicenseDecl :: { StringNode }+LicenseDecl :: { NonTerm } LicenseDecl :	'/*' 'License' CMT_WORD '\n' CopyrightDecls '*/'	{ Fix $ LicenseDecl $3 (reverse $5) } -CopyrightDecls :: { [StringNode] }+CopyrightDecls :: { [NonTerm] } CopyrightDecls :	CopyrightDecl						{ [$1] } |	CopyrightDecls CopyrightDecl				{ $2 : $1 } -CopyrightDecl :: { StringNode }+CopyrightDecl :: { NonTerm } CopyrightDecl-:	' * ' 'Copyright' CopyrightDates CopyrightOwner '\n'	{ Fix $ CopyrightDecl (fst $3) (snd $3) $4 }+:	' ' 'Copyright' CopyrightDates CopyrightOwner '\n'	{ Fix $ CopyrightDecl (fst $3) (snd $3) $4 }  CopyrightDates :: { (StringLexeme, Maybe StringLexeme) } CopyrightDates@@ -176,12 +182,12 @@ CopyrightOwner :	CMT_WORD CommentWords					{ $1 : reverse $2 } -ToplevelDecls :: { [StringNode] }+ToplevelDecls :: { [NonTerm] } ToplevelDecls :	ToplevelDecl						{ [$1] } |	ToplevelDecls ToplevelDecl				{ $2 : $1 } -ToplevelDecl :: { StringNode }+ToplevelDecl :: { NonTerm } ToplevelDecl :	AggregateDecl						{ $1 } |	Comment							{ $1 }@@ -197,17 +203,18 @@ |	StaticAssert						{ $1 } |	TypedefDecl						{ $1 } -StaticAssert :: { StringNode }+StaticAssert :: { NonTerm } StaticAssert :	static_assert '(' ConstExpr ',' LIT_STRING ')' ';'	{ Fix $ StaticAssert $3 $5 } -Comment :: { StringNode }+Comment :: { NonTerm } Comment :	'/*' CommentTokens '*/'					{ Fix $ Comment Regular $1 (reverse $2) $3 } |	'/**' CommentTokens '*/'				{ Fix $ Comment Doxygen $1 (reverse $2) $3 }-|	'/** @{' CommentTokens '*/'				{ Fix $ Comment Block $1 (reverse $2) $3 }+|	'/** @{' CommentTokens '*/'				{ Fix $ Comment Section $1 (reverse $2) $3 } |	'/***' CommentTokens '*/'				{ Fix $ Comment Block $1 (reverse $2) $3 } |	'/** @} */'						{ Fix $ CommentSectionEnd $1 }+|	Ignore							{ $1 }  CommentTokens :: { [StringLexeme] } CommentTokens@@ -219,6 +226,7 @@ :	CommentWord						{ $1 } |	'\n'							{ $1 } |	' * '							{ $1 }+|	' '							{ $1 }  CommentWords :: { [StringLexeme] } CommentWords@@ -229,11 +237,13 @@ CommentWord :	CMT_WORD						{ $1 } |	CMT_COMMAND						{ $1 }+|	CMT_ATTR						{ $1 } |	CMT_REF							{ $1 } |	CMT_CODE						{ $1 } |	LIT_INTEGER						{ $1 } |	LIT_STRING						{ $1 } |	'.'							{ $1 }+|	'...'							{ $1 } |	'?'							{ $1 } |	'!'							{ $1 } |	','							{ $1 }@@ -247,7 +257,19 @@ |	'+'							{ $1 } |	'-'							{ $1 } |	'='							{ $1 }+|	'=='							{ $1 }+|	'!='							{ $1 }+|	'>='							{ $1 } +Ignore :: { NonTerm }+Ignore+:	IGN_START IgnoreBody IGN_END				{ Fix $ Comment Ignore $1 (reverse $2) $3 }++IgnoreBody :: { [StringLexeme] }+IgnoreBody+:	IGN_BODY						{ [$1] }+|	IgnoreBody IGN_BODY					{ $2 : $1 }+ PreprocIfdef(decls) :	'#ifdef' ID_CONST decls PreprocElse(decls) '#endif'	{ Fix $ PreprocIfdef $2 (reverse $3) $4 } |	'#ifndef' ID_CONST decls PreprocElse(decls) '#endif'	{ Fix $ PreprocIfndef $2 (reverse $3) $4 }@@ -263,47 +285,47 @@ :								{ Fix $ PreprocElse [] } |	'#else' decls						{ Fix $ PreprocElse (reverse $2) } -PreprocInclude :: { StringNode }+PreprocInclude :: { NonTerm } PreprocInclude :	'#include' LIT_STRING					{ Fix $ PreprocInclude $2 } |	'#include' LIT_SYS_INCLUDE				{ Fix $ PreprocInclude $2 } -PreprocDefine :: { StringNode }+PreprocDefine :: { NonTerm } PreprocDefine :	'#define' ID_CONST '\n'					{ Fix $ PreprocDefine $2 } |	'#define' ID_CONST PreprocSafeExpr(ConstExpr) '\n'	{ Fix $ PreprocDefineConst $2 $3 } |	'#define' ID_CONST MacroParamList MacroBody '\n'	{ Fix $ PreprocDefineMacro $2 $3 $4 } -PreprocUndef :: { StringNode }+PreprocUndef :: { NonTerm } PreprocUndef :	'#undef' ID_CONST					{ Fix $ PreprocUndef $2 } -PreprocConstExpr :: { StringNode }+PreprocConstExpr :: { NonTerm } PreprocConstExpr :	PureExpr(PreprocConstExpr)				{ $1 } |	'defined' '(' ID_CONST ')'				{ Fix $ PreprocDefined $3 } -MacroParamList :: { [StringNode] }+MacroParamList :: { [NonTerm] } MacroParamList :	'(' ')'							{ [] } |	'(' MacroParams ')'					{ reverse $2 } |	'(' MacroParams ',' '...' ')'				{ reverse $ Fix Ellipsis : $2 } -MacroParams :: { [StringNode] }+MacroParams :: { [NonTerm] } MacroParams :	MacroParam						{ [$1] } |	MacroParams ',' MacroParam				{ $3 : $1 } -MacroParam :: { StringNode }+MacroParam :: { NonTerm } MacroParam :	ID_VAR							{ Fix $ MacroParam $1 } -MacroBody :: { StringNode }+MacroBody :: { NonTerm } MacroBody :	do CompoundStmt while '(' LIT_INTEGER ')'		{% macroBodyStmt $2 $5 } |	FunctionCall						{ Fix $ MacroBodyFunCall $1 } -ExternC :: { StringNode }+ExternC :: { NonTerm } ExternC :	'#ifdef' ID_CONST 	extern LIT_STRING '{'@@ -313,12 +335,12 @@ 	'}' 	'#endif'						{% externC $2 $4 (reverse $7) $9 } -Stmts :: { [StringNode] }+Stmts :: { [NonTerm] } Stmts :	Stmt							{ [$1] } |	Stmts Stmt						{ $2 : $1 } -Stmt :: { StringNode }+Stmt :: { NonTerm } Stmt :	PreprocIfdef(Stmts)					{ $1 } |	PreprocIf(Stmts)					{ $1 }@@ -329,6 +351,7 @@ |	ForStmt							{ $1 } |	WhileStmt						{ $1 } |	DoWhileStmt						{ $1 }+|	StaticAssert						{ $1 } |	AssignExpr ';'						{ Fix $ ExprStmt $1 } |	ExprStmt ';'						{ Fix $ ExprStmt $1 } |	FunctionCall ';'					{ Fix $ ExprStmt $1 }@@ -341,96 +364,96 @@ |	switch '(' Expr ')' '{' SwitchCases '}'			{ Fix $ SwitchStmt $3 (reverse $6) } |	Comment							{ $1 } -IfStmt :: { StringNode }+IfStmt :: { NonTerm } IfStmt :	if '(' Expr ')' CompoundStmt				{ Fix $ IfStmt $3 $5 Nothing } |	if '(' Expr ')' CompoundStmt else IfStmt		{ Fix $ IfStmt $3 $5 (Just $7) } |	if '(' Expr ')' CompoundStmt else CompoundStmt		{ Fix $ IfStmt $3 $5 (Just $7) } -ForStmt :: { StringNode }+ForStmt :: { NonTerm } ForStmt :	for '(' ForInit Expr ';' ForNext ')' CompoundStmt	{ Fix $ ForStmt $3 $4 $6 $8 } -ForInit :: { StringNode }+ForInit :: { NonTerm } ForInit :	AssignExpr ';'						{ Fix $ ExprStmt $1 } |	VarDeclStmt						{ $1 } -ForNext :: { StringNode }+ForNext :: { NonTerm } ForNext :	ExprStmt						{ $1 } |	AssignExpr						{ $1 } -WhileStmt :: { StringNode }+WhileStmt :: { NonTerm } WhileStmt :	while '(' Expr ')' CompoundStmt				{ Fix $ WhileStmt $3 $5 } -DoWhileStmt :: { StringNode }+DoWhileStmt :: { NonTerm } DoWhileStmt :	do CompoundStmt while '(' Expr ')' ';'			{ Fix $ DoWhileStmt $2 $5 } -SwitchCases :: { [StringNode] }+SwitchCases :: { [NonTerm] } SwitchCases :	SwitchCase						{ [$1] } |	SwitchCases SwitchCase					{ $2 : $1 } -SwitchCase :: { StringNode }+SwitchCase :: { NonTerm } SwitchCase :	case Expr ':' SwitchCaseBody				{ Fix $ Case $2 $4 } |	default ':' SwitchCaseBody				{ Fix $ Default $3 } -SwitchCaseBody :: { StringNode }+SwitchCaseBody :: { NonTerm } SwitchCaseBody :	CompoundStmt						{ $1 } |	SwitchCase						{ $1 } |	return Expr ';'						{ Fix $ Return (Just $2) } -DeclStmt :: { StringNode }+DeclStmt :: { NonTerm } DeclStmt :	VarDeclStmt						{ $1 } |	VLA '(' QualType ',' ID_VAR ',' Expr ')' ';'		{ Fix $ VLA $3 $5 $7 } -VarDeclStmt :: { StringNode }+VarDeclStmt :: { NonTerm } VarDeclStmt :	VarDecl '=' InitialiserExpr ';'				{ Fix $ VarDeclStmt $1 (Just $3) } |	VarDecl ';'						{ Fix $ VarDeclStmt $1 Nothing } -VarDecl :: { StringNode }+VarDecl :: { NonTerm } VarDecl :	QualType ID_VAR DeclSpecArrays				{ Fix $ VarDecl $1 $2 $3 } |	ID_FUNC_TYPE '*' ID_VAR DeclSpecArrays			{ Fix $ VarDecl (Fix $ TyPointer $ Fix $ TyFunc $1) $3 $4 } -DeclSpecArrays :: { [StringNode] }+DeclSpecArrays :: { [NonTerm] } DeclSpecArrays :								{ [] } |	DeclSpecArrays DeclSpecArray				{ $2 : $1 } -DeclSpecArray :: { StringNode }+DeclSpecArray :: { NonTerm } DeclSpecArray :	'[' ']'							{ Fix $ DeclSpecArray Nothing } |	'[' Expr ']'						{ Fix $ DeclSpecArray (Just $2) } -InitialiserExpr :: { StringNode }+InitialiserExpr :: { NonTerm } InitialiserExpr :	InitialiserList						{ Fix $ InitialiserList $1 } |	Expr							{ $1 } -InitialiserList :: { [StringNode] }+InitialiserList :: { [NonTerm] } InitialiserList :	'{' Initialisers '}'					{ reverse $2 } |	'{' Initialisers ',' '}'				{ reverse $2 } -Initialisers :: { [StringNode] }+Initialisers :: { [NonTerm] } Initialisers :	Initialiser						{ [$1] } |	Initialisers ',' Initialiser				{ $3 : $1 } -Initialiser :: { StringNode }+Initialiser :: { NonTerm } Initialiser :	Expr							{ $1 } |	InitialiserList						{ Fix $ InitialiserList $1 } -CompoundStmt :: { StringNode }+CompoundStmt :: { NonTerm } CompoundStmt :	'{' Stmts '}'						{ Fix $ CompoundStmt (reverse $2) } @@ -439,10 +462,10 @@ :	LiteralExpr						{ $1 } |	'(' x ')'						{ Fix $ ParenExpr $2 } |	'(' QualType ')' x %prec CAST				{ Fix $ CastExpr $2 $4 }-|	sizeof '(' x ')'					{ Fix $ SizeofExpr $3 }+|	sizeof '(' Expr ')'					{ Fix $ SizeofExpr $3 } |	sizeof '(' QualType ')'					{ Fix $ SizeofType $3 } -ConstExpr :: { StringNode }+ConstExpr :: { NonTerm } ConstExpr :	PureExpr(ConstExpr)					{ $1 } @@ -472,7 +495,7 @@ |	'-' x %prec NEG						{ Fix $ UnaryExpr UopMinus $2 } |	'&' x %prec ADDRESS					{ Fix $ UnaryExpr UopAddress $2 } -LiteralExpr :: { StringNode }+LiteralExpr :: { NonTerm } LiteralExpr :	StringLiteralExpr					{ $1 } |	LIT_CHAR						{ Fix $ LiteralExpr Char $1 }@@ -481,12 +504,12 @@ |	LIT_TRUE						{ Fix $ LiteralExpr Bool $1 } |	ID_CONST						{ Fix $ LiteralExpr ConstId $1 } -StringLiteralExpr :: { StringNode }+StringLiteralExpr :: { NonTerm } StringLiteralExpr :	LIT_STRING						{ Fix $ LiteralExpr String $1 } |	StringLiteralExpr LIT_STRING				{ $1 } -LhsExpr :: { StringNode }+LhsExpr :: { NonTerm } LhsExpr :	ID_VAR							{ Fix $ VarExpr $1 } |	'*' LhsExpr %prec DEREF					{ Fix $ UnaryExpr UopDeref $2 }@@ -494,7 +517,7 @@ |	LhsExpr '->' ID_VAR					{ Fix $ PointerAccess $1 $3 } |	LhsExpr '[' Expr ']'					{ Fix $ ArrayAccess $1 $3 } -Expr :: { StringNode }+Expr :: { NonTerm } Expr :	LhsExpr							{ $1 } |	ExprStmt						{ $1 }@@ -503,11 +526,11 @@ |	PureExpr(Expr)						{ $1 }  -- Allow `(Type){0}` to set struct values to all-zero.-CompoundLiteral :: { StringNode }+CompoundLiteral :: { NonTerm } CompoundLiteral :	'(' QualType ')' '{' ZeroInitExpr '}'			{ Fix $ CompoundLiteral $2 $5 } -ZeroInitExpr :: { StringNode }+ZeroInitExpr :: { NonTerm } ZeroInitExpr :	ID_VAR							{ Fix $ VarExpr $1 } |	LIT_CHAR						{ Fix $ LiteralExpr Char $1 }@@ -516,7 +539,7 @@ |	ID_CONST						{ Fix $ LiteralExpr ConstId $1 } |	'{' ZeroInitExpr '}'					{ Fix $ InitialiserList [$2] } -AssignExpr :: { StringNode }+AssignExpr :: { NonTerm } AssignExpr :	LhsExpr AssignOperator Expr				{ Fix $ AssignExpr $1 $2 $3 } @@ -534,118 +557,127 @@ |	'<<='							{ AopLsh     } |	'>>='							{ AopRsh     } -ExprStmt :: { StringNode }+ExprStmt :: { NonTerm } ExprStmt :	'++' Expr						{ Fix $ UnaryExpr UopIncr $2 } |	'--' Expr						{ Fix $ UnaryExpr UopDecr $2 } -FunctionCall :: { StringNode }+FunctionCall :: { NonTerm } FunctionCall :	Expr ArgList						{ Fix $ FunctionCall $1 $2 } -ArgList :: { [StringNode] }+ArgList :: { [NonTerm] } ArgList :	'(' ')'							{ [] } |	'(' Args ')'						{ reverse $2 } -Args :: { [StringNode] }+Args :: { [NonTerm] } Args :	Arg							{ [$1] } |	Args ',' Arg						{ $3 : $1 } -Arg :: { StringNode }+Arg :: { NonTerm } Arg :	Expr							{ $1 } |	Comment Expr						{ Fix $ CommentExpr $1 $2 } -EnumDecl :: { StringNode }+EnumDecl :: { NonTerm } EnumDecl :	enum ID_SUE_TYPE EnumeratorList ';'			{ Fix $ EnumConsts (Just $2) $3 } |	enum             EnumeratorList ';'			{ Fix $ EnumConsts Nothing $2 } |	typedef enum ID_SUE_TYPE EnumeratorList ID_SUE_TYPE ';'	{ Fix $ EnumDecl $3 $4 $5 } -EnumeratorList :: { [StringNode] }+EnumeratorList :: { [NonTerm] } EnumeratorList :	'{' Enumerators '}'					{ reverse $2 } -Enumerators :: { [StringNode] }+Enumerators :: { [NonTerm] } Enumerators :	Enumerator						{ [$1] } |	Enumerators Enumerator					{ $2 : $1 } -Enumerator :: { StringNode }+Enumerator :: { NonTerm } Enumerator :	EnumeratorName ','					{ Fix $ Enumerator $1 Nothing } |	EnumeratorName '=' ConstExpr ','			{ Fix $ Enumerator $1 (Just $3) } |	Comment							{ $1 } -EnumeratorName :: { Lexeme String }+EnumeratorName :: { StringLexeme } EnumeratorName :	ID_CONST						{ $1 } |	ID_SUE_TYPE						{ $1 } -AggregateDecl :: { StringNode }+AggregateDecl :: { NonTerm } AggregateDecl :	AggregateType ';'					{ Fix $ AggregateDecl $1 } |	typedef AggregateType ID_SUE_TYPE ';'			{ Fix $ Typedef $2 $3 } -AggregateType :: { StringNode }+AggregateType :: { NonTerm } AggregateType :	struct ID_SUE_TYPE '{' MemberDeclList '}'		{ Fix $ Struct $2 $4 } |	union ID_SUE_TYPE '{' MemberDeclList '}'		{ Fix $ Union $2 $4 } -MemberDeclList :: { [StringNode] }+MemberDeclList :: { [NonTerm] } MemberDeclList :	MemberDecls						{ reverse $1 } -MemberDecls :: { [StringNode] }+MemberDecls :: { [NonTerm] } MemberDecls :	MemberDecl						{ [$1] } |	MemberDecls MemberDecl					{ $2 : $1 } -MemberDecl :: { StringNode }+MemberDecl :: { NonTerm } MemberDecl :	VarDecl ';'						{ Fix $ MemberDecl $1 Nothing } |	VarDecl ':' LIT_INTEGER ';'				{ Fix $ MemberDecl $1 (Just $3) } |	PreprocIfdef(MemberDeclList)				{ $1 } |	Comment							{ $1 } -TypedefDecl :: { StringNode }+TypedefDecl :: { NonTerm } TypedefDecl :	typedef QualType ID_SUE_TYPE ';'			{ Fix $ Typedef $2 $3 } |	typedef FunctionPrototype(ID_FUNC_TYPE) ';'		{ Fix $ TypedefFunction $2 } -QualType :: { StringNode }+QualType :: { NonTerm } QualType-:	LeafType						{                               $1 }-|	LeafType '*'						{                     tyPointer $1 }-|	LeafType '*' '*'					{ tyPointer          (tyPointer $1) }-|	LeafType '*' const					{            tyConst (tyPointer $1) }-|	LeafType '*' const '*'					{ tyPointer (tyConst (tyPointer $1)) }-|	LeafType const						{                                tyConst $1 }-|	LeafType const '*'					{                     tyPointer (tyConst $1) }-|	LeafType const '*' const				{            tyConst (tyPointer (tyConst $1)) }-|	LeafType const '*' const '*'				{ tyPointer (tyConst (tyPointer (tyConst $1))) }-|	const LeafType						{                                tyConst $2 }-|	const LeafType '*'					{                     tyPointer (tyConst $2) }-|	const LeafType '*' const				{            tyConst (tyPointer (tyConst $2)) }-|	const LeafType '*' const '*'				{ tyPointer (tyConst (tyPointer (tyConst $2))) }+:	LeafType						{                                        $1 }+|	LeafType '*'						{                              tyPointer $1 }+|	LeafType '*' '*'					{          tyPointer          (tyPointer $1) }+|	LeafType '*' '*' const					{ tyConst (tyPointer          (tyPointer $1)) }+|	LeafType '*' const					{                     tyConst (tyPointer $1) }+|	LeafType '*' const '*'					{          tyPointer (tyConst (tyPointer $1)) }+|	LeafType '*' const '*' const				{ tyConst (tyPointer (tyConst (tyPointer $1))) }+|	LeafType const						{                                         tyConst $1 }+|	LeafType const '*'					{                              tyPointer (tyConst $1) }+|	LeafType const '*' const				{                     tyConst (tyPointer (tyConst $1)) }+|	LeafType const '*' const '*'				{          tyPointer (tyConst (tyPointer (tyConst $1))) }+|	LeafType const '*' const '*' const			{ tyConst (tyPointer (tyConst (tyPointer (tyConst $1)))) }+|	const LeafType						{                                         tyConst $2 }+|	const LeafType '*'					{                              tyPointer (tyConst $2) }+|	const LeafType '*' const				{                     tyConst (tyPointer (tyConst $2)) }+|	const LeafType '*' const '*'				{          tyPointer (tyConst (tyPointer (tyConst $2))) }+|	const LeafType '*' const '*' const			{ tyConst (tyPointer (tyConst (tyPointer (tyConst $2)))) } -LeafType :: { StringNode }+LeafType :: { NonTerm } LeafType :	struct ID_SUE_TYPE					{ Fix $ TyStruct $2 } |	void							{ Fix $ TyStd $1 } |	ID_STD_TYPE						{ Fix $ TyStd $1 } |	ID_SUE_TYPE						{ Fix $ TyUserDefined $1 } -FunctionDecl :: { StringNode }+FunctionDecl :: { NonTerm } FunctionDecl :	FunctionDeclarator					{ $1 Global } |	static FunctionDeclarator				{ $2 Static } |	NonNull FunctionDeclarator				{ $1 $ $2 Global } |	NonNull static FunctionDeclarator			{ $1 $ $3 Static }+|	NonNull Attrs FunctionDeclarator			{ $1 . $2 . $3 $ Global } -NonNull :: { StringNode -> StringNode }+Attrs :: { NonTerm -> NonTerm }+Attrs+:	GNU_PRINTF '(' LIT_INTEGER ',' LIT_INTEGER ')'		{ Fix . AttrPrintf $3 $5 }++NonNull :: { NonTerm -> NonTerm } NonNull :	non_null '(' ')'					{ Fix . NonNull [] [] } |	nullable '(' Ints ')'					{ Fix . NonNull [] $3 }@@ -660,13 +692,13 @@ :	LIT_INTEGER						{ [$1] } |	IntList ',' LIT_INTEGER					{ $3 : $1 } -FunctionDeclarator :: { Scope -> StringNode }+FunctionDeclarator :: { Scope -> NonTerm } FunctionDeclarator :	FunctionPrototype(ID_VAR) ';'				{ \s -> Fix $ FunctionDecl s $1 } |	FunctionPrototype(ID_VAR) CompoundStmt			{ \s -> Fix $ FunctionDefn s $1 $2 } |	CallbackDecl ';'					{ \s -> Fix $ FunctionDecl s $1 } -CallbackDecl :: { StringNode }+CallbackDecl :: { NonTerm } CallbackDecl :	ID_FUNC_TYPE ID_VAR					{ Fix $ CallbackDecl $1 $2 } @@ -674,23 +706,23 @@ :	QualType id FunctionParamList				{ Fix $ FunctionPrototype $1 $2 $3 } |	ID_FUNC_TYPE '*' id FunctionParamList			{ Fix $ FunctionPrototype (Fix $ TyPointer $ Fix $ TyFunc $1) $3 $4 } -FunctionParamList :: { [StringNode] }+FunctionParamList :: { [NonTerm] } FunctionParamList :	'(' ')'							{ [] } |	'(' void ')'						{ [Fix $ TyStd $2] } |	'(' FunctionParams ')'					{ reverse $2 } |	'(' FunctionParams ',' '...' ')'			{ reverse $ Fix Ellipsis : $2 } -FunctionParams :: { [StringNode] }+FunctionParams :: { [NonTerm] } FunctionParams :	FunctionParam						{ [$1] } |	FunctionParams ',' FunctionParam			{ $3 : $1 } -FunctionParam :: { StringNode }+FunctionParam :: { NonTerm } FunctionParam :	VarDecl							{ $1 } -ConstDecl :: { StringNode }+ConstDecl :: { NonTerm } ConstDecl :	extern const LeafType ID_VAR ';'			{ Fix $ ConstDecl $3 $4 } |	const LeafType ID_VAR '=' InitialiserExpr ';'		{ Fix $ ConstDefn Global $2 $3 $5 }@@ -698,15 +730,15 @@  { type StringLexeme = Lexeme String-type StringNode = Node StringLexeme+type NonTerm = Node StringLexeme -tyPointer, tyConst :: StringNode -> StringNode+tyPointer, tyConst :: NonTerm -> NonTerm tyPointer = Fix . TyPointer tyConst = Fix . TyConst  parseError :: Show text => (Lexeme text, [String]) -> Alex a parseError (L (AlexPn _ line col) c t, options) =-    alexError $ show line <> ":" <> show col <> ": Parse error near " <> show c <> ": "+    alexError $ ":" <> show line <> ":" <> show col <> ": Parse error near " <> show c <> ": "         <> show t <> "; expected one of " <> show options  lexwrap :: (Lexeme String -> Alex a) -> Alex a@@ -715,9 +747,9 @@ externC     :: Lexeme String     -> Lexeme String-    -> [StringNode]+    -> [NonTerm]     -> Lexeme String-    -> Alex StringNode+    -> Alex NonTerm externC (L _ _ "__cplusplus") (L _ _ "\"C\"") decls (L _ _ "__cplusplus") =     return $ Fix $ ExternC decls externC _ lang _ _ =@@ -725,9 +757,9 @@         <> ": extern \"C\" declaration invalid (did you spell __cplusplus right?)"  macroBodyStmt-    :: StringNode+    :: NonTerm     -> Lexeme String-    -> Alex StringNode+    -> Alex NonTerm macroBodyStmt decls (L _ _ "0") =     return $ Fix $ MacroBodyStmt decls macroBodyStmt _ cond =
src/Language/Cimple/Pretty.hs view
@@ -1,21 +1,30 @@ {-# OPTIONS_GHC -Wno-missing-signatures #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections     #-}-module Language.Cimple.Pretty (plain, ppTranslationUnit, showNode) where+module Language.Cimple.Pretty+    ( plain+    , render+    , ppTranslationUnit+    , showNode+    ) where  import           Data.Fix                     (foldFix) import qualified Data.List.Split              as List import           Data.Text                    (Text) import qualified Data.Text                    as Text import           Language.Cimple              (AssignOp (..), BinaryOp (..),+                                               Comment, CommentF (..),                                                CommentStyle (..), Lexeme (..),                                                LexemeClass (..), Node,                                                NodeF (..), Scope (..),-                                               UnaryOp (..), lexemeText)+                                               UnaryOp (..), lexemeLine,+                                               lexemeText) import           Prelude                      hiding ((<$>)) import           Text.PrettyPrint.ANSI.Leijen +indentWidth :: Int+indentWidth = 2+ kwBreak         = dullred   $ text "break" kwCase          = dullred   $ text "case" kwConst         = dullgreen $ text "const"@@ -26,6 +35,7 @@ kwEnum          = dullgreen $ text "enum" kwExtern        = dullgreen $ text "extern" kwFor           = dullred   $ text "for"+kwGnuPrintf     = dullgreen $ text "GNU_PRINTF" kwGoto          = dullred   $ text "goto" kwIf            = dullred   $ text "if" kwNonNull       = dullgreen $ text "non_null"@@ -40,6 +50,22 @@ kwUnion         = dullgreen $ text "union" kwWhile         = dullred   $ text "while" +kwDocAttention  = dullcyan $ text "@attention"+kwDocBrief      = dullcyan $ text "@brief"+kwDocDeprecated = dullcyan $ text "@deprecated"+kwDocExtends    = dullcyan $ text "@extends"+kwDocImplements = dullcyan $ text "@implements"+kwDocParam      = dullcyan $ text "@param"+kwDocPrivate    = dullcyan $ text "@private"+kwDocRef        = dullcyan $ text "@ref"+kwDocReturn     = dullcyan $ text "@return"+kwDocRetval     = dullcyan $ text "@retval"+kwDocP          = dullcyan $ text "@p"+kwDocSee        = dullcyan $ text "@see"++cmtPrefix :: Doc+cmtPrefix = dullyellow (char '*')+ ppText :: Text -> Doc ppText = text . Text.unpack @@ -99,32 +125,43 @@     UopIncr    -> text "++"     UopDecr    -> text "--" -ppCommentStyle :: CommentStyle -> Doc-ppCommentStyle = dullyellow . \case+ppCommentStart :: CommentStyle -> Doc+ppCommentStart = dullyellow . \case     Block   -> text "/***"     Doxygen -> text "/**"+    Section -> text "/** @{"     Regular -> text "/*"+    Ignore  -> text "//!TOKSTYLE-"  ppCommentBody :: [Lexeme Text] -> Doc-ppCommentBody = vsep . map (hsep . map ppWord) . groupLines+ppCommentBody body = vsep . prefixStars . map (hsep . map ppWord) . groupLines $ body   where+    -- If the "*/" is on a separate line, don't add an additional "*" before+    -- it. If "*/" is on the same line, then do add a "*" prefix on the last line.+    stars =+        case reverse body of+          e:c:_ | lexemeLine e > lexemeLine c -> 2+          _                                   -> 1+    prefixStars xs = zipWith (<>) (empty : replicate (length xs - stars) cmtPrefix ++ [empty]) xs     groupLines = List.splitWhen $ \case         L _ PpNewline _ -> True         _               -> False -    ppWord (L _ CmtIndent  _) = dullyellow $ char '*'-    ppWord (L _ CmtCommand t) = dullcyan   $ ppText t-    ppWord (L _ _          t) = dullyellow $ ppText t+ppWord (L _ CmtIndent  _) = empty+ppWord (L _ CmtCommand t) = dullcyan   $ ppText t+ppWord (L _ _          t) = dullyellow $ ppText t  ppComment :: CommentStyle -> [Lexeme Text] -> Lexeme Text -> Doc+ppComment Ignore cs _ =+    ppCommentStart Ignore <> hcat (map ppWord cs) <> dullyellow (text "//!TOKSTYLE+" <> line) ppComment style cs (L l c _) =-    nest 1 $ ppCommentStyle style <+> ppCommentBody (cs ++ [L l c "*/"])+    nest 1 $ ppCommentStart style <+> ppCommentBody (cs ++ [L l c "*/"])  ppInitialiserList :: [Doc] -> Doc ppInitialiserList l = lbrace <+> commaSep l <+> rbrace  ppParamList :: [Doc] -> Doc-ppParamList = parens . commaSep+ppParamList = parens . indent 0 . commaSep  ppFunctionPrototype     :: Doc@@ -176,7 +213,7 @@     -> [Doc]     -> Doc ppSwitchStmt c body =-    nest 2 (+    nest indentWidth (         kwSwitch <+> parens c <+> lbrace <$>         vcat body     ) <$> rbrace@@ -193,7 +230,7 @@  ppCompoundStmt :: [Doc] -> Doc ppCompoundStmt body =-    nest 2 (+    nest indentWidth (         lbrace <$>         ppToplevel body     ) <$> rbrace@@ -208,13 +245,80 @@  ppLicenseDecl :: Lexeme Text -> [Doc] -> Doc ppLicenseDecl l cs =-    dullyellow $ ppCommentStyle Regular <+> text "SPDX-License-Identifier: " <> ppLexeme l <$>+    dullyellow $ ppCommentStart Regular <+> text "SPDX-License-Identifier: " <> ppLexeme l <$>     vcat (map dullyellow cs) <$>     dullyellow (text " */")  ppIntList :: [Lexeme Text] -> Doc ppIntList = parens . commaSep . map (dullred . ppLexeme) +ppMacroBody :: Doc -> Doc+ppMacroBody =+    vcat+    . map dullmagenta+    . punctuate (text " \\")+    . map text+    . List.splitOn "\n"+    . renderS+    . plain++ppVerbatimComment :: Doc -> Doc+ppVerbatimComment =+    vcat+    . map dullyellow+    . zipWith (<>) (empty : repeat (text " * "))+    . map text+    . List.splitOn "\n"+    . renderS+    . plain++ppCommentInfo :: Comment (Lexeme Text) -> Doc+ppCommentInfo = foldFix go+  where+  ppBody     = vcat . zipWith (<>) (        repeat (dullyellow (text " * "  )))+  ppIndented = vcat . zipWith (<>) (empty : repeat (dullyellow (text " *   ")))+  ppRef      = underline . cyan . ppLexeme+  ppAttr     = maybe empty (blue . ppLexeme)++  go :: CommentF (Lexeme Text) Doc -> Doc+  go = dullyellow . \case+    DocComment docs ->+        text "/**" <$>+        ppBody docs <$>+        dullyellow (text " */")+    DocWord w -> ppLexeme w+    DocSentence docs ending -> fillSep docs <> ppLexeme ending+    DocNewline -> empty++    DocParam attr name docs ->+        kwDocParam <> ppAttr attr <+> underline (cyan (ppLexeme name)) <+> ppIndented docs++    DocAttention docs   -> kwDocAttention  <+> ppIndented docs+    DocBrief docs       -> kwDocBrief      <+> ppIndented docs+    DocDeprecated docs  -> kwDocDeprecated <+> ppIndented docs+    DocReturn docs      -> kwDocReturn     <+> ppIndented docs+    DocRetval expr docs -> kwDocRetval     <+> dullred (ppLexeme expr) <+> ppIndented docs+    DocSee name docs    -> kwDocSee        <+> ppRef name <+> ppIndented docs+    DocRef name         -> kwDocRef        <+> ppRef name+    DocP name           -> kwDocP          <+> ppRef name+    DocExtends feat     -> kwDocExtends    <+> ppLexeme feat+    DocImplements feat  -> kwDocImplements <+> ppLexeme feat+    DocPrivate          -> kwDocPrivate++    DocParagraph docs -> ppIndented docs+    DocLine docs -> fillSep docs+    DocList l -> ppVerbatimComment $ vcat l+    DocOLItem num docs -> ppLexeme num <> char '.' <+> nest 3 (fillSep docs)+    DocULItem docs sublist -> char '-' <+> nest 2 (vsep $ fillSep docs : sublist)++    DocLParen doc -> lparen <> doc+    DocRParen doc -> doc <> rparen+    DocColon doc -> ppLexeme doc <> char ':'+    DocBinaryOp BopMinus l r -> l <>  char '-'      <>  r+    DocBinaryOp BopDiv   l r -> l <>  char '/'      <>  r+    DocAssignOp op       l r -> l <+> ppAssignOp op <+> r+    DocBinaryOp op       l r -> l <+> ppBinaryOp op <+> r+ ppNode :: Node (Lexeme Text) -> Doc ppNode = foldFix go   where@@ -231,12 +335,16 @@         text " * Copyright © " <> ppLexeme from <+>         ppCommentBody owner -    Comment style _ cs e ->-        ppComment style cs e+    Comment style _ cs end ->+        ppComment style cs end+    CommentSection start decls end ->+        start <$> line <> ppToplevel decls <> line <$> end     CommentSectionEnd cs ->         dullyellow $ ppLexeme cs     Commented c d ->         c <$> d+    CommentInfo docs ->+        ppCommentInfo docs      VarExpr var          -> ppLexeme var     LiteralExpr _ l      -> dullred $ ppLexeme l@@ -272,22 +380,22 @@      ExternC decls ->         dullmagenta (text "#ifdef __cplusplus") <$>-        text "extern \"C\" {" <$>+        kwExtern <+> dullred (text "\"C\"") <+> lbrace <$>         dullmagenta (text "#endif") <$>         line <>         ppToplevel decls <$>         line <>         dullmagenta (text "#ifdef __cplusplus") <$>-        text "}" <$>+        rbrace <$>         dullmagenta (text "#endif") +    Group decls -> vcat decls+     MacroParam l -> ppLexeme l      MacroBodyFunCall e -> e     MacroBodyStmt body ->-        if False-           then kwDo <+> body <+> kwWhile <+> text "(0)"-           else text "do { nothing(); } while (0)  // macros aren't supported well yet"+        kwDo <+> body <+> kwWhile <+> text "(0)"      PreprocScopedDefine def stmts undef ->         def <$> ppToplevel stmts <$> undef@@ -299,7 +407,7 @@     PreprocDefineConst name value ->         dullmagenta $ text "#define" <+> ppLexeme name <+> value     PreprocDefineMacro name params body ->-        dullmagenta $ text "#define" <+> ppLexeme name <> ppParamList params <+> body+        ppMacroBody $ text "#define" <+> ppLexeme name <> ppParamList params <+> body     PreprocUndef name ->         dullmagenta $ text "#undef" <+> ppLexeme name @@ -312,12 +420,12 @@         dullmagenta (text "#ifdef" <+> ppLexeme name) <$>         ppToplevel decls <>         elseBranch <$>-        dullmagenta (text "#endif")+        dullmagenta (text "#endif  //" <+> ppLexeme name)     PreprocIfndef name decls elseBranch ->         dullmagenta (text "#ifndef" <+> ppLexeme name) <$>         ppToplevel decls <>         elseBranch <$>-        dullmagenta (text "#endif")+        dullmagenta (text "#endif  //" <+> ppLexeme name)     PreprocElse [] -> empty     PreprocElse decls ->         linebreak <>@@ -329,6 +437,8 @@         ppToplevel decls <>         elseBranch +    AttrPrintf fmt ellipsis fun ->+        kwGnuPrintf <> ppIntList [fmt, ellipsis] <$> fun     CallbackDecl ty name ->         ppLexeme ty <+> ppLexeme name     FunctionPrototype ty name params ->@@ -345,12 +455,12 @@      AggregateDecl struct -> struct <> semi     Struct name members ->-        nest 2 (+        nest indentWidth (             kwStruct <+> ppLexeme name <+> lbrace <$>             vcat members         ) <$> rbrace     Union name members ->-        nest 2 (+        nest indentWidth (             kwUnion <+> ppLexeme name <+> lbrace <$>             vcat members         ) <$> rbrace@@ -370,17 +480,17 @@         ppLexeme name <+> equals <+> value <> comma      EnumConsts Nothing enums ->-        nest 2 (+        nest indentWidth (             kwEnum <+> lbrace <$>             vcat enums         ) <$> text "};"     EnumConsts (Just name) enums ->-        nest 2 (+        nest indentWidth (             kwEnum <+> ppLexeme name <+> lbrace <$>             vcat enums         ) <$> text "};"     EnumDecl name enums ty ->-        nest 2 (+        nest indentWidth (             kwTypedef <+> kwEnum <+> dullgreen (ppLexeme name) <+> lbrace <$>             vcat enums         ) <$> rbrace <+> dullgreen (ppLexeme ty) <> semi@@ -404,7 +514,7 @@     IfStmt cond t e               -> ppIfStmt cond t e     ForStmt i c n body            -> ppForStmt i c n body     Default s                     -> kwDefault <> colon <+> s-    Label l s                     -> ppLexeme l <> colon <$> s+    Label l s                     -> indent (-99) (line <> ppLexeme l <> colon) <$> s     ExprStmt e                    -> e <> semi     Goto l                        -> kwGoto <+> ppLexeme l <> semi     Case e s                      -> kwCase <+> e <> colon <+> s@@ -422,3 +532,9 @@  showNode  :: Node (Lexeme Text) -> Text showNode = Text.pack . show . ppNode++renderS :: Doc -> String+renderS = flip displayS "" . renderSmart 1 120++render :: Doc -> Text+render = Text.pack . renderS
src/Language/Cimple/Tokens.hs view
@@ -23,6 +23,7 @@     | KwEnum     | KwExtern     | KwFor+    | KwGnuPrintf     | KwGoto     | KwIf     | KwNonNull@@ -103,7 +104,9 @@     | PpUndef     | CmtBlock     | CmtCommand+    | CmtAttr     | CmtEndDocSection+    | CmtPrefix     | CmtIndent     | CmtStart     | CmtStartBlock@@ -115,10 +118,13 @@     | CmtWord     | CmtRef     | CmtEnd+    | IgnStart+    | IgnBody+    | IgnEnd -    | Error+    | ErrorToken     | Eof-    deriving (Show, Eq, Generic, Ord)+    deriving (Enum, Bounded, Ord, Eq, Show, Generic)  instance FromJSON LexemeClass instance ToJSON LexemeClass
src/Language/Cimple/TraverseAst.hs view
@@ -12,6 +12,7 @@      , doFiles, doFile     , doNodes, doNode+    , doComment, doComments     , doLexemes, doLexeme     , doText @@ -20,9 +21,12 @@  import           Data.Fix              (Fix (..)) import           Data.Foldable         (traverse_)-import           Language.Cimple.Ast   (Node, NodeF (..))+import           Language.Cimple.Ast   (Comment, CommentF (..), Node,+                                        NodeF (..)) import           Language.Cimple.Lexer (Lexeme (..)) +{-# ANN module "HLint: ignore Reduce duplication" #-}+ class TraverseAst text a where     traverseFileAst         :: Applicative f@@ -38,18 +42,22 @@ traverseAst = flip traverseFileAst "<stdin>"  data AstActions f text = AstActions-    { doFiles   :: [(FilePath, [Node (Lexeme text)])] -> f () -> f ()-    , doFile    ::  (FilePath, [Node (Lexeme text)])  -> f () -> f ()-    , doNodes   :: FilePath -> [Node (Lexeme text)]   -> f () -> f ()-    , doNode    :: FilePath ->  Node (Lexeme text)    -> f () -> f ()-    , doLexemes :: FilePath ->       [Lexeme text]    -> f () -> f ()-    , doLexeme  :: FilePath ->        Lexeme text     -> f () -> f ()-    , doText    :: FilePath ->               text             -> f ()+    { doFiles    :: [(FilePath, [Node    (Lexeme text)])] -> f () -> f ()+    , doFile     ::  (FilePath, [Node    (Lexeme text)])  -> f () -> f ()+    , doNodes    :: FilePath -> [Node    (Lexeme text)]   -> f () -> f ()+    , doNode     :: FilePath ->  Node    (Lexeme text)    -> f () -> f ()+    , doComment  :: FilePath ->  Comment (Lexeme text)    -> f () -> f ()+    , doComments :: FilePath -> [Comment (Lexeme text)]   -> f () -> f ()+    , doLexemes  :: FilePath ->          [Lexeme text]    -> f () -> f ()+    , doLexeme   :: FilePath ->           Lexeme text     -> f () -> f ()+    , doText     :: FilePath ->                  text             -> f ()     }  instance TraverseAst text        a       => TraverseAst text (Maybe a) where-    traverseFileAst _ _ _ = pure ()+    traverseFileAst _ _ Nothing = pure ()+    traverseFileAst actions currentFile (Just x) =+        traverseFileAst actions currentFile x  astActions     :: Applicative f@@ -59,6 +67,8 @@     , doFile      = const id     , doNodes     = const $ const id     , doNode      = const $ const id+    , doComment   = const $ const id+    , doComments  = const $ const id     , doLexeme    = const $ const id     , doLexemes   = const $ const id     , doText      = const $ const $ pure ()@@ -75,6 +85,94 @@     traverseFileAst actions@AstActions{..} currentFile = doLexemes currentFile <*>         traverse_ (traverseFileAst actions currentFile) +instance TraverseAst text (Comment (Lexeme text)) where+    traverseFileAst+        :: forall f . Applicative f+        => AstActions f text+        -> FilePath+        -> Comment (Lexeme text)+        -> f ()+    traverseFileAst actions@AstActions{..} currentFile = doComment currentFile <*> \comment -> case unFix comment of+        DocComment docs ->+            recurse docs+        DocWord word ->+            recurse word+        DocSentence docs ending -> do+            _ <- recurse docs+            _ <- recurse ending+            pure ()+        DocNewline -> pure ()++        DocAttention docs ->+            recurse docs+        DocBrief docs ->+            recurse docs+        DocDeprecated docs ->+            recurse docs+        DocExtends feat ->+            recurse feat+        DocImplements feat ->+            recurse feat+        DocParam attr name docs -> do+            _ <- recurse attr+            _ <- recurse name+            _ <- recurse docs+            pure ()+        DocReturn docs ->+            recurse docs+        DocRetval expr docs -> do+            _ <- recurse expr+            _ <- recurse docs+            pure ()+        DocSee ref docs -> do+            _ <- recurse ref+            _ <- recurse docs+            pure ()++        DocPrivate -> pure ()++        DocParagraph docs ->+            recurse docs+        DocLine docs ->+            recurse docs+        DocList docs ->+            recurse docs+        DocOLItem docs sublist -> do+            _ <- recurse docs+            _ <- recurse sublist+            pure ()+        DocULItem docs sublist -> do+            _ <- recurse docs+            _ <- recurse sublist+            pure ()++        DocColon docs ->+            recurse docs+        DocRef doc ->+            recurse doc+        DocP doc ->+            recurse doc+        DocLParen docs ->+            recurse docs+        DocRParen docs ->+            recurse docs+        DocAssignOp _ lhs rhs -> do+            _ <- recurse lhs+            _ <- recurse rhs+            pure ()+        DocBinaryOp _ lhs rhs -> do+            _ <- recurse lhs+            _ <- recurse rhs+            pure ()++      where+        recurse :: TraverseAst text a => a -> f ()+        recurse = traverseFileAst actions currentFile++instance TraverseAst text [Comment (Lexeme text)] where+    traverseFileAst actions@AstActions{..} currentFile = doComments currentFile <*>+        traverse_ (traverseFileAst actions currentFile)+ instance TraverseAst text (Node (Lexeme text)) where     traverseFileAst         :: forall f . Applicative f@@ -151,6 +249,11 @@             _ <- recurse contents             _ <- recurse end             pure ()+        CommentSection start decls end -> do+            _ <- recurse start+            _ <- recurse decls+            _ <- recurse end+            pure ()         CommentSectionEnd comment -> do             _ <- recurse comment             pure ()@@ -158,8 +261,12 @@             _ <- recurse comment             _ <- recurse subject             pure ()+        CommentInfo comment ->+            recurse comment         ExternC decls ->             recurse decls+        Group decls ->+            recurse decls         CompoundStmt stmts ->             recurse stmts         Break ->@@ -327,6 +434,11 @@             recurse name         TyUserDefined name ->             recurse name+        AttrPrintf fmt ellipsis fun -> do+            _ <- recurse fmt+            _ <- recurse ellipsis+            _ <- recurse fun+            pure ()         FunctionDecl _scope proto ->             recurse proto         FunctionDefn _scope proto body -> do
src/Language/Cimple/TreeParser.y view
@@ -1,15 +1,19 @@ { {-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Language.Cimple.TreeParser-    ( TreeParser-    , parseTranslationUnit-    , toEither-    ) where+{-# LANGUAGE ViewPatterns               #-}+module Language.Cimple.TreeParser (parseTranslationUnit) where -import           Data.Fix              (Fix (..))-import           Data.Text             (Text)-import           Language.Cimple.Ast   (CommentStyle (..), Node, NodeF (..))-import           Language.Cimple.Lexer (Lexeme)+import           Data.Fix                      (Fix (..))+import           Data.Maybe                    (maybeToList)+import           Data.Text                     (Text)+import qualified Data.Text                     as Text+import           Language.Cimple.Ast           (CommentStyle (..), Node,+                                                NodeF (..))+import           Language.Cimple.CommentParser (parseComment)+import           Language.Cimple.DescribeAst   (describeNode, sloc)+import           Language.Cimple.Lexer         (Lexeme (..))+import           Language.Cimple.ParseResult   (ParseResult)+import           Language.Cimple.Tokens        (LexemeClass (..)) }  %name parseTranslationUnit TranslationUnit@@ -18,21 +22,21 @@  %error {parseError} %errorhandlertype explist-%monad {TreeParser}-%tokentype {TextNode}+%monad {ParseResult}+%tokentype {NonTerm} %token-    ifndefDefine	{ Fix (PreprocIfndef _ body (Fix (PreprocElse []))) | isDefine body }-    ifdefDefine		{ Fix (PreprocIfdef _ body (Fix (PreprocElse []))) | isDefine body }-    ifDefine		{ Fix (PreprocIf _ body (Fix (PreprocElse []))) | isDefine body }--    ifndefInclude	{ Fix (PreprocIfndef{}) | isPreproc tk && hasInclude tk }-    ifdefInclude	{ Fix (PreprocIfdef{}) | isPreproc tk && hasInclude tk }-    ifInclude		{ Fix (PreprocIf{}) | isPreproc tk && hasInclude tk }+    ifndefDefine	{ Fix (PreprocIfndef _ (isDefine -> True) (Fix (PreprocElse []))) }+    ifdefDefine		{ Fix (PreprocIfdef _ (isDefine -> True) (Fix (PreprocElse []))) }+    ifDefine		{ Fix (PreprocIf _ (isDefine -> True) (Fix (PreprocElse []))) }      docComment		{ Fix (Comment Doxygen _ _ _) }      -- Preprocessor-    preprocInclude	{ Fix (PreprocInclude{}) }+    localIncludeBlock	{ (isIncludeBlock LitString -> True) }+    sysIncludeBlock	{ (isIncludeBlock LitSysInclude -> True) }+    localInclude	{ Fix (PreprocInclude (L _ LitString _)) }+    sysInclude		{ Fix (PreprocInclude (L _ LitSysInclude _)) }+     preprocDefine	{ Fix (PreprocDefine{}) }     preprocDefineConst	{ Fix (PreprocDefineConst{}) }     preprocDefineMacro	{ Fix (PreprocDefineMacro{}) }@@ -51,8 +55,9 @@     -- Comments     licenseDecl		{ Fix (LicenseDecl{}) }     copyrightDecl	{ Fix (CopyrightDecl{}) }-    comment		{ Fix (Comment{}) }+    commentSectionStart	{ Fix (Comment Section _ _ _) }     commentSectionEnd	{ Fix (CommentSectionEnd{}) }+    comment		{ Fix (Comment{}) }     commented		{ Fix (Commented{}) }     -- Namespace-like blocks     externC		{ Fix (ExternC{}) }@@ -122,65 +127,65 @@  %% -TranslationUnit :: { [TextNode] }+TranslationUnit :: { [NonTerm] } TranslationUnit :	licenseDecl docComment Header				{ [$1, Fix $ Commented $2 $3] }-|	licenseDecl docComment Source				{ $1 : mapHead (Fix . Commented $2)$3 }+|	licenseDecl docComment Source				{ $1 : mapHead (Fix . Commented $2) $3 } |	licenseDecl            Header				{ [$1, $2] } |	licenseDecl            Source				{ $1 : $2 } -Header :: { TextNode }+Header :: { NonTerm } Header :	preprocIfndef						{% recurse parseHeaderBody $1 } -HeaderBody :: { [TextNode] }+HeaderBody :: { [NonTerm] } HeaderBody-:	preprocDefine Includes Decls				{ $1 : reverse $2 ++ $3 }+:	preprocDefine Includes Decls				{ $1 : $2 ++ $3 } -Source :: { [TextNode] }+Source :: { [NonTerm] } Source-:	Features preprocInclude Includes Decls			{ $1 ++ [$2] ++ reverse $3 ++ $4 }+:	Features localInclude Includes Decls			{ maybeToList $1 ++ [$2] ++ $3 ++ $4 } -Features :: { [TextNode] }+Features :: { Maybe NonTerm } Features-:								{ [] }-|	Features IfDefine					{ $2 : $1 }+:								{ Nothing }+|	NonEmptyList(IfDefine)					{ Just $ Fix $ Group $1 } -IfDefine :: { TextNode }+IfDefine :: { NonTerm } IfDefine :	ifndefDefine						{ $1 } |	ifdefDefine						{ $1 } |	ifDefine						{ $1 } -Includes :: { [TextNode] }+Includes :: { [NonTerm] } Includes :								{ [] }-|	Includes Include					{ $2 : $1 }+|	NonEmptyList(SysInclude)				{ [Fix $ Group $1] }+|	NonEmptyList(LocalInclude)				{ [Fix $ Group $1] }+|	NonEmptyList(SysInclude) NonEmptyList(LocalInclude)	{ [Fix $ Group $1, Fix $ Group $2] } -Include :: { TextNode }-Include-:	preprocInclude						{ $1 }-|	ifndefInclude						{ $1 }-|	ifdefInclude						{ $1 }-|	ifInclude						{ $1 }+LocalInclude :: { NonTerm }+LocalInclude+:	localInclude						{ $1 }+|	localIncludeBlock					{ $1 } -Decls :: { [TextNode] }-Decls-:	DeclList						{ reverse $1 }+SysInclude :: { NonTerm }+SysInclude+:	sysInclude						{ $1 }+|	sysIncludeBlock						{ $1 } -DeclList :: { [TextNode] }-DeclList-:								{ [] }-|	DeclList Decl						{ $2 : $1 }+Decls :: { [NonTerm] }+Decls+:	List(Decl)						{ $1 } -Decl :: { TextNode }+Decl :: { NonTerm } Decl :	comment							{ $1 }-|	commentSectionEnd					{ $1 }+|	commentSectionStart Decls commentSectionEnd		{ Fix $ CommentSection $1 $2 $3 } |	CommentableDecl						{ $1 }-|	docComment CommentableDecl				{ Fix $ Commented $1 $2 }+|	docComment CommentableDecl				{% fmap (\c -> Fix $ Commented c $2) $ parseDocComment $1 } -CommentableDecl :: { TextNode }+CommentableDecl :: { NonTerm } CommentableDecl :	functionDecl						{ $1 } |	functionDefn						{ $1 }@@ -203,29 +208,40 @@ |	typedefFunction						{ $1 } |	IfDefine						{ $1 } -{-type TextLexeme = Lexeme Text-type TextNode = Node TextLexeme+List(x)+:								{ [] }+|	NonEmptyList(x)						{ $1 } -newtype TreeParser a = TreeParser { toEither :: Either String a }-    deriving (Functor, Applicative, Monad)+NonEmptyList(x)+:	NonEmptyList_(x)					{ reverse $1 } -instance MonadFail TreeParser where-    fail = TreeParser . Left+NonEmptyList_(x)+:	x							{ [$1] }+|	NonEmptyList_(x) x					{ $2 : $1 } +{+type TextLexeme = Lexeme Text+type NonTerm = Node TextLexeme + mapHead :: (a -> a) -> [a] -> [a] mapHead _ [] = [] mapHead f (x:xs) = f x : xs  -isDefine :: [TextNode] -> Bool+isDefine :: [NonTerm] -> Bool isDefine (Fix PreprocUndef{}:d)     = isDefine d isDefine [Fix PreprocDefine{}]      = True isDefine [Fix PreprocDefineConst{}] = True isDefine _                          = False -isPreproc :: TextNode -> Bool+isIncludeBlock :: LexemeClass -> NonTerm -> Bool+isIncludeBlock style tk@(Fix PreprocIfndef{}) = isPreproc tk && hasInclude style tk+isIncludeBlock style tk@(Fix PreprocIfdef{})  = isPreproc tk && hasInclude style tk+isIncludeBlock style tk@(Fix PreprocIf{})     = isPreproc tk && hasInclude style tk+isIncludeBlock _ _                            = False++isPreproc :: NonTerm -> Bool isPreproc (Fix PreprocInclude{})        = True isPreproc (Fix PreprocUndef{})          = True isPreproc (Fix PreprocDefine{})         = True@@ -236,29 +252,37 @@ isPreproc (Fix (PreprocElse ed))        = all isPreproc ed isPreproc _                             = False -hasInclude :: TextNode -> Bool-hasInclude (Fix PreprocInclude{})        = True-hasInclude (Fix (PreprocIf _ td ed))     = any hasInclude td || hasInclude ed-hasInclude (Fix (PreprocIfdef _ td ed))  = any hasInclude td || hasInclude ed-hasInclude (Fix (PreprocIfndef _ td ed)) = any hasInclude td || hasInclude ed-hasInclude (Fix (PreprocElse ed))        = any hasInclude ed-hasInclude _                             = False+hasInclude :: LexemeClass -> NonTerm -> Bool+hasInclude style (Fix (PreprocInclude (L _ c _))) = c == style+hasInclude style (Fix (PreprocIf _ td ed))        = any (hasInclude style) td || (hasInclude style) ed+hasInclude style (Fix (PreprocIfdef _ td ed))     = any (hasInclude style) td || (hasInclude style) ed+hasInclude style (Fix (PreprocIfndef _ td ed))    = any (hasInclude style) td || (hasInclude style) ed+hasInclude style (Fix (PreprocElse ed))           = any (hasInclude style) ed+hasInclude _ _                                    = False  -recurse :: ([TextNode] -> TreeParser [TextNode]) -> TextNode -> TreeParser TextNode+recurse :: ([NonTerm] -> ParseResult [NonTerm]) -> NonTerm -> ParseResult NonTerm recurse f (Fix (ExternC ds))          = Fix <$> (ExternC <$> f ds)-recurse f (Fix (PreprocIf c t e))     = Fix <$> (PreprocIf c <$> f t <*> recurse f e)-recurse f (Fix (PreprocIfdef c t e))  = Fix <$> (PreprocIfdef c <$> f t <*> recurse f e)+recurse f (Fix (PreprocIf     c t e)) = Fix <$> (PreprocIf     c <$> f t <*> recurse f e)+recurse f (Fix (PreprocIfdef  c t e)) = Fix <$> (PreprocIfdef  c <$> f t <*> recurse f e) recurse f (Fix (PreprocIfndef c t e)) = Fix <$> (PreprocIfndef c <$> f t <*> recurse f e) recurse f (Fix (PreprocIfndef c t e)) = Fix <$> (PreprocIfndef c <$> f t <*> recurse f e)-recurse f (Fix (PreprocElif c t e))   = Fix <$> (PreprocElif c <$> f t <*> recurse f e)-recurse f (Fix (PreprocElse []))      = return $ Fix $ PreprocElse []-recurse f (Fix (PreprocElse e))       = Fix <$> (PreprocElse <$> f e)+recurse f (Fix (PreprocElif   c t e)) = Fix <$> (PreprocElif   c <$> f t <*> recurse f e)+recurse f (Fix (PreprocElse      [])) = Fix <$> pure (PreprocElse [])+recurse f (Fix (PreprocElse       e)) = Fix <$> (PreprocElse     <$>                 f e) recurse _ ns                          = fail $ "TreeParser.recurse: " <> show ns +parseDocComment :: NonTerm -> ParseResult NonTerm+parseDocComment (Fix (Comment Doxygen start body end)) =+    Fix . CommentInfo <$> parseComment (start : body ++ [end])+parseDocComment n = return n -parseError :: ([TextNode], [String]) -> TreeParser a-parseError ([], options)  = fail $ "end of file; expected one of " <> show options-parseError (n:_, [])      = fail $ show n <> "; expected end of file"-parseError (n:_, options) = fail $ show n <> "; expected one of " <> show options+failAt :: NonTerm -> String -> ParseResult a+failAt n msg =+    fail $ Text.unpack (sloc "" n) <> ": unexpected " <> describeNode n <> msg++parseError :: ([NonTerm], [String]) -> ParseResult a+parseError ([], options)  = fail $ " end of file; expected one of " <> show options+parseError (n:_, [])      = failAt n "; expected end of file"+parseError (n:_, options) = failAt n $ "; expected one of " <> show options }
test/Language/Cimple/ParserSpec.hs view
@@ -53,4 +53,4 @@         it "does not support multiple declarators per declaration" $ do             let ast = parseText "int main() { int a, b; }"             ast `shouldBe` Left-                "1:19: Parse error near PctComma: \",\"; expected one of [\"'='\",\"';'\"]"+                ":1:19: Parse error near PctComma: \",\"; expected one of [\"'='\",\"';'\"]"
tools/cimplefmt.hs view
@@ -3,16 +3,15 @@ import qualified Data.ByteString        as BS import           Data.List              (isPrefixOf) import           Data.Text              (Text)-import qualified Data.Text              as Text import qualified Data.Text.Encoding     as Text import           Language.Cimple        (Lexeme, Node) import           Language.Cimple.IO     (parseFile, parseText)-import           Language.Cimple.Pretty (plain, ppTranslationUnit)+import           Language.Cimple.Pretty (plain, ppTranslationUnit, render) import           System.Environment     (getArgs)   format :: Bool -> [Node (Lexeme Text)] -> Text-format color = Text.pack . show . maybePlain . ppTranslationUnit+format color = render . maybePlain . ppTranslationUnit   where     maybePlain = if color then id else plain @@ -32,11 +31,11 @@     putStrLn $ "Processing " ++ source     ast <- parseFile source     case ast of-        Left err -> fail err+        Left err -> putStrLn err >> fail "aborting after parse error"         Right (_, ok) ->-            if "--no-reparse" `elem` flags-               then BS.putStr . Text.encodeUtf8 . format True $ ok-               else reparseText $ format False ok+            if "--reparse" `elem` flags+               then reparseText $ format False ok+               else BS.putStr . Text.encodeUtf8 . format True $ ok   main :: IO ()