module Language.Dart.Pretty
( prettyPrint
) where
import Data.Char (toLower)
import Data.List (partition)
import Text.PrettyPrint
import Text.Printf (printf)
import Language.Dart.Syntax
prettyPrint :: Pretty a => a -> String
prettyPrint = show . pretty
parenPrec :: Int -> Int -> Doc -> Doc
parenPrec inheritedPrec currentPrec t
| inheritedPrec > currentPrec = parens t
| otherwise = t
class Pretty a where
pretty :: a -> Doc
pretty = prettyPrec 0
prettyPrec :: Int -> a -> Doc
prettyPrec _ = pretty
instance Pretty MapLiteralEntry where
prettyPrec p (MapLiteralEntry key value) =
hsep [ prettyPrec p key
, colon
, prettyPrec p value
]
instance Pretty TypedLiteral where
prettyPrec p (MapLiteral isConst mTypeArguments entries) =
hsep [ optKeyword isConst "const"
, maybePP p mTypeArguments
] <> braces (hsep (ppIntersperse p comma entries))
prettyPrec p (ListLiteral isConst mTypeArguments elements) =
hsep [ optKeyword isConst "const"
, maybePP p mTypeArguments
] <> brackets (hsep (ppIntersperse p comma elements))
instance Pretty Literal where
prettyPrec p (NullLiteral) = text "null"
prettyPrec p (BooleanLiteral b) = text . map toLower $ show b
prettyPrec p (DoubleLiteral d) = text (show d)
prettyPrec p (IntegerLiteral i) = text (show i)
prettyPrec p (TypedLiteral t) = prettyPrec p t
prettyPrec p (StringLiteral' s) = prettyPrec p s
prettyPrec p (SymbolLiteral ts) = pound <> hsep (punctuate period (map text ts))
instance Pretty InterpolationElement where
prettyPrec p (InterpolationString s) = text s
prettyPrec p (InterpolationExpression expression) =
dollar <> braces (prettyPrec p expression)
instance Pretty SingleStringLiteral where
prettyPrec p (SimpleStringLiteral value) =
doubleQuotes (text (concatMap escapeString value))
prettyPrec p (StringInterpolation elements) =
doubleQuotes (hcat (map (prettyPrec p) elements))
instance Pretty StringLiteral where
prettyPrec p (SingleStringLiteral' l) = prettyPrec p l
prettyPrec p (AdjacentStrings strings) =
hsep (map (prettyPrec p) strings)
instance Pretty Combinator where
prettyPrec p (ShowCombinator shownNames) = text "show" <+>
hsep (ppIntersperse p comma shownNames)
prettyPrec p (HideCombinator hiddenNames) = text "hide" <+>
hsep (ppIntersperse p comma hiddenNames)
instance Pretty NamespaceDirective where
prettyPrec p (ExportDirective _ metadata libraryUri _ combinators) =
ppMetadata p metadata $$
hsep [ text "export"
, prettyPrec p libraryUri
, hsep (ppIntersperse p comma combinators)
] <> semi
prettyPrec p (ImportDirective _ metadata libraryUri _ isDeferred mPrefix combinators) =
ppMetadata p metadata $$
hsep [ text "import"
, prettyPrec p libraryUri
, optKeyword isDeferred "deferred"
, maybe empty ((text "as" <+>) . prettyPrec p) mPrefix
, hsep (ppIntersperse p comma combinators)
] <> semi
instance Pretty UriBasedDirective where
prettyPrec p (NamespaceDirective nsDir) = prettyPrec p nsDir
prettyPrec p (PartDirective _ metadata partUri) =
ppMetadata p metadata $$ prettyPrec p partUri <> semi
instance Pretty Directive where
prettyPrec p (UriBasedDirective dir) = prettyPrec p dir
prettyPrec p (PartOfDirective _ metadata libraryName) =
ppMetadata p metadata $$
text "part of" <> prettyPrec p libraryName <> semi
prettyPrec p (LibraryDirective _ metadata libraryName) =
ppMetadata p metadata $$
text "library" <> prettyPrec p libraryName <> semi
instance Pretty AsyncModifier where
prettyPrec p AsyncStar = text "async*"
prettyPrec p Async = text "async"
prettyPrec p SyncStar = text "sync*"
prettyPrec p Sync = empty
instance Pretty NormalFormalParameter where
prettyPrec p (FunctionTypedFormalParameter _ metadata mReturnType identifier mTypeParameters parameters) =
ppMetadata p metadata $$
hsep [ maybePP p mReturnType
, hcat [ prettyPrec p identifier
, maybePP p mTypeParameters
, prettyPrec p parameters
]
]
prettyPrec p (FieldFormalParameter _ metadata kind explicitThis identifier) =
ppMetadata p metadata $$
hsep [ maybePP p kind
, opt explicitThis (text "this.") <> prettyPrec p identifier
]
prettyPrec p (SimpleFormalParameter _ metadata kind identifier) =
ppMetadata p metadata $$
hsep [ prettyPrec p kind
, prettyPrec p identifier
]
instance Pretty FormalParameter where
prettyPrec p (NormalFormalParameter' parameter) = prettyPrec p parameter
prettyPrec p (DefaultFormalParameter parameter kind mDefaultValue) =
hsep [ prettyPrec p parameter
, maybe empty ((separator kind <+>) . prettyPrec p) mDefaultValue
]
where separator Positional = equals
separator Named = colon
instance Pretty FormalParameterList where
prettyPrec p (FormalParameterList parameters) =
let (normals, defaults) = partition isNormal parameters
in parens $ hcat [ hsep (ppIntersperse p comma normals)
, opt (not $ null defaults) (comma <+> (matchingBracket (head defaults)) (hsep (ppIntersperse p comma defaults)))
]
where isNormal (NormalFormalParameter' _) = True
isNormal _ = False
matchingBracket (DefaultFormalParameter _ Positional _) = brackets
matchingBracket _ = braces
instance Pretty ConstructorName where
prettyPrec p (ConstructorName type' mName) =
hsep [ prettyPrec p type'
, maybe empty ((period <>) . prettyPrec p) mName
]
instance Pretty SimpleIdentifier where
prettyPrec _ (SimpleIdentifier token) = text token
instance Pretty LibraryIdentifier where
prettyPrec p (LibraryIdentifier components) =
hcat (ppIntersperse p period components)
instance Pretty Identifier where
prettyPrec p (SimpleIdentifier' simpleId) = prettyPrec p simpleId
prettyPrec p (PrefixedIdentifier prefix identifier) =
hcat [ prettyPrec p prefix
, period
, prettyPrec p identifier
]
prettyPrec p (LibraryIdentifier' libraryName) = prettyPrec p libraryName
instance Pretty TypeArgumentList where
prettyPrec p (TypeArgumentList args) =
angleBrackets (hsep (ppIntersperse p comma args))
instance Pretty TypeName where
prettyPrec p (TypeName name typeArgList) = prettyPrec p name <> maybePP p typeArgList
instance Pretty PropertyKeyword where
prettyPrec p Get = text "get"
prettyPrec p Set = text "set"
prettyPrec p Empty = empty
instance Pretty ArgumentList where
prettyPrec p (ArgumentList args) =
parens (hsep (ppIntersperse p comma args))
instance Pretty Annotation where
prettyPrec p (Annotation name mConstructorName mArguments) =
hcat [ at
, prettyPrec p name
, maybe empty ((period <>) . prettyPrec p) mConstructorName
, maybePP p mArguments
]
instance Pretty ExtendsClause where
prettyPrec p (ExtendsClause superclass) = text "extends" <+>
prettyPrec p superclass
instance Pretty WithClause where
prettyPrec p (WithClause mixinTypes) = text "with" <+>
hsep (ppIntersperse p comma mixinTypes)
instance Pretty ImplementsClause where
prettyPrec p (ImplementsClause interfaces) = text "implements" <+>
hsep (ppIntersperse p comma interfaces)
instance Pretty TypeAlias where
prettyPrec p (ClassTypeAlias _ metadata name mTypeParameters isAbstract superclass withClause mImplementsClause) =
ppMetadata p metadata $$
hsep [ optKeyword isAbstract "abstract"
, text "class"
, hcat [ prettyPrec p name
, maybePP p mTypeParameters
]
, equals
, prettyPrec p superclass
, prettyPrec p withClause
, maybePP p mImplementsClause
] <> semi
prettyPrec p (FunctionTypeAlias _ metadata mReturnType name mTypeParameters parameters) =
ppMetadata p metadata $$
hsep [ text "typedef"
, maybePP p mReturnType
, hcat [ prettyPrec p name
, maybePP p mTypeParameters
, prettyPrec p parameters
]
] <> semi
instance Pretty EnumConstantDeclaration where
prettyPrec p (EnumConstantDeclaration _ metadata name) =
ppMetadata p metadata $$ prettyPrec p name
instance Pretty TypeParameter where
prettyPrec p (TypeParameter _ metadata name mBound) =
ppMetadata p metadata $$
hsep [ prettyPrec p name
, maybe empty ((text "extends" <+>) . prettyPrec p) mBound
]
instance Pretty TypeParameterList where
prettyPrec p (TypeParameterList typeParameters) =
angleBrackets (hsep (ppIntersperse p comma typeParameters))
instance Pretty Label where
prettyPrec p (Label label) = prettyPrec p label <> char ':'
instance Pretty FinalConstVarOrType where
prettyPrec p (FCVTFinal type') = text "final" <+> prettyPrec p type'
prettyPrec p (FCVTConst type') = text "const" <+> prettyPrec p type'
prettyPrec p (FCVTType type') = prettyPrec p type'
prettyPrec p FCVTVar = text "var"
instance Pretty FinalVarOrType where
prettyPrec p (FVTFinal type') = text "final" <+> prettyPrec p type'
prettyPrec p (FVTType type') = prettyPrec p type'
prettyPrec p FVTVar = text "var"
instance Pretty VariableDeclaration where
prettyPrec p (VariableDeclaration name mInitializer) =
hsep [ prettyPrec p name
, maybe empty ((equals <+>) . prettyPrec p) mInitializer
]
instance Pretty VariableDeclarationList where
prettyPrec p (VariableDeclarationList _ metadata kind variables) =
ppMetadata p metadata $$
prettyPrec p kind <+> hsep (ppIntersperse p comma variables)
instance Pretty CatchClause where
prettyPrec p (CatchClause mExceptionType exceptionParameter mStackTraceParameter body) =
case mExceptionType of
Nothing -> text "catch" <+> parens (ppExceptionParameter p exceptionParameter mStackTraceParameter) $$ prettyPrec p body
Just exceptionType -> text "on" <+> prettyPrec p exceptionType $$ prettyPrec p body
where ppExceptionParameter p ep Nothing = prettyPrec p ep
ppExceptionParameter p ep (Just stp) = hsep (ppIntersperse p comma [ep, stp])
instance Pretty SwitchMember where
prettyPrec p (SwitchCase labels expression statements) =
vcat (map (prettyPrec p) labels) $$
vcat (ppSwitchCase p expression : map (nest 2 . prettyPrec p) statements)
where ppSwitchCase p expression = text "case" <+> prettyPrec p expression <> colon
prettyPrec p (SwitchDefault labels statements) =
vcat (map (prettyPrec p) labels) $$
vcat (ppSwitchDefault : map (nest 2 . prettyPrec p) statements)
where ppSwitchDefault = text "default" <> colon
instance Pretty DeclaredIdentifier where
prettyPrec p (DeclaredIdentifier _ metadata kind identifier) =
ppMetadata p metadata $$
hsep [ prettyPrec p kind
, prettyPrec p identifier
]
instance Pretty Statement where
prettyPrec p (Block' block) = prettyPrec p block
prettyPrec p (VariableDeclarationStatement variableList) =
prettyPrec p variableList <> semi
prettyPrec p (ForStatement mVariableList mInitialization mCondition updaters body) =
text "for" <+> (parens $ hsep [ maybe empty ((<> semi) . prettyPrec p) mVariableList
, maybe empty ((<> semi) . prettyPrec p) mInitialization
, maybePP p mCondition <> semi
, hsep (ppIntersperse p comma updaters)
]) $+$ prettyNestedStmt p body
prettyPrec p (ForEachStatementWithDeclaration isAwait loopVariable iterator body) = undefined
hsep [ optKeyword isAwait "await"
, text "for"
, parens $ hsep [ prettyPrec p loopVariable
, text "in"
, prettyPrec p iterator
]
, prettyPrec p body
]
prettyPrec p (ForEachStatementWithReference isAwait identifier iterator body) =
hsep [ optKeyword isAwait "await"
, text "for"
, parens $ hsep [ prettyPrec p identifier
, text "in"
, prettyPrec p iterator
]
, prettyPrec p body
]
prettyPrec p (WhileStatement condition body) =
text "while" <+> parens (prettyPrec p condition) $+$ prettyNestedStmt 0 body
prettyPrec p (DoStatement body condition) =
text "do" $+$ prettyPrec p body <+> text "while" <+> parens (prettyPrec p condition) <> semi
prettyPrec p (SwitchStatement expression members) =
text "switch" <+> parens (prettyPrec p expression)
$$ braceBlock (map (prettyPrec p) members)
prettyPrec p (IfStatement condition thenStatement mElseStatement) =
text "if" <+> parens (prettyPrec p condition) $+$
prettyNestedStmt 0 thenStatement $+$ ppElseStatement mElseStatement
where ppElseStatement Nothing = empty
ppElseStatement (Just elseStatement) = text "else" $+$ prettyNestedStmt 0 elseStatement
prettyPrec p (TryStatement body catchCaluses mFinallyBlock) =
text "try" $$ prettyPrec p body $$
vcat (map (prettyPrec p) catchCaluses ++ [ppFinally mFinallyBlock])
where ppFinally Nothing = empty
ppFinally (Just finally) = text "finally" $$ prettyPrec p finally
prettyPrec p (BreakStatement mLabel) =
text "break" <+> maybePP p mLabel <> semi
prettyPrec p (ContinueStatement mLabel) =
text "continue" <+> maybePP p mLabel <> semi
prettyPrec p (ReturnStatement mExpression) =
text "return" <+> maybePP p mExpression <> semi
prettyPrec p (ExpressionStatement expression) =
prettyPrec p expression <> semi
prettyPrec p (FunctionDeclarationStatement functionDeclaration) =
prettyPrec p functionDeclaration <> semi
prettyPrec p (AssertStatement condition _) =
hcat [ text "assert"
, parens (prettyPrec p condition)
, semi
]
prettyPrec p (YieldStatement isStar expression) =
hsep [ text "yield"
, opt isStar star
, prettyPrec p expression
] <> semi
prettyPrec p (EmptyStatement) = semi
prettyPrec p (LabeledStatement labels statement) =
vcat (map (prettyPrec p) labels) $$
prettyPrec p statement
instance Pretty Block where
prettyPrec p (Block statements) = braceBlock (map (prettyPrec p) statements)
instance Pretty NewOrConst where
prettyPrec p NCNew = text "new"
prettyPrec p NCConst = text "const"
instance Pretty InvocationExpression where
prettyPrec p (FunctionExpressionInvocation function mTypeArguments argumentList) =
hcat [ prettyPrec p function
, maybePP p mTypeArguments
, prettyPrec p argumentList
]
prettyPrec p (MethodInvocation mTarget methodName mTypeArguments argumentList) =
hcat [ maybe empty ((<> period) . prettyPrec p) mTarget
, prettyPrec p methodName
, maybePP p mTypeArguments
, prettyPrec p argumentList
]
instance Pretty Expression where
prettyPrec p (Literal' literal) = prettyPrec p literal
prettyPrec p (Identifier' identifier) = prettyPrec p identifier
prettyPrec p (PrefixExpression operator operand) =
parenPrec p 15 $ text operator <> prettyPrec 15 operand
prettyPrec p (PostfixExpression operand operator) =
parenPrec p 16 $ prettyPrec 15 operand <> text operator
prettyPrec p (BinaryExpression leftOperand operator rightOperand) =
let prec = opPrec operator
in parenPrec p prec $ hsep [ prettyPrec prec leftOperand
, text operator
, prettyPrec prec rightOperand
]
prettyPrec p (AssignmentExpression leftHandSide operator rightHandSide) =
hsep [ prettyPrec p leftHandSide
, text operator
, prettyPrec p rightHandSide
]
prettyPrec p (FunctionExpression' functionExpression) = prettyPrec p functionExpression
prettyPrec p (InstanceCreationExpression newOrConst constructorName argumentList) =
hsep [ prettyPrec p newOrConst
, hcat [ prettyPrec p constructorName
, prettyPrec p argumentList
]
]
prettyPrec p (AsExpression expression type') =
parenPrec p 8 $ hsep [ prettyPrec 8 expression
, text "as"
, prettyPrec 8 type'
]
prettyPrec p (IsExpression expression isNot type') =
parenPrec p 8 $ hsep [ prettyPrec 8 expression
, text "is"
, opt isNot exclamation
, prettyPrec 8 type'
]
prettyPrec p (ThrowExpression expression) = text "throw" <+> prettyPrec p expression
prettyPrec p (RethrowExpression) = text "rethrow"
prettyPrec p (ThisExpression) = text "this"
prettyPrec p (SuperExpression) = text "super"
prettyPrec p (ParenthesizedExpression expression) = parens (prettyPrec p expression)
prettyPrec p (PropertyAccess target propertyName) =
hcat [ prettyPrec p target
, period
, prettyPrec p propertyName
]
prettyPrec p (NamedExpression name expression) =
hsep [ prettyPrec p name <> colon
, prettyPrec p expression
]
prettyPrec p (InvocationExpression invocationExpression) =
prettyPrec p invocationExpression
prettyPrec p (ConditionalExpression condition thenExpression elseExpression) =
parenPrec p 3 $ hsep [ prettyPrec 3 condition
, questionMark
, prettyPrec p thenExpression
, colon
, prettyPrec 3 elseExpression
]
prettyPrec p (CascadeExpression target cascadeSections) =
let sections = target:cascadeSections
in parenPrec p 2 $ hsep (ppIntersperse 2 (text "..") sections)
prettyPrec p (IndexExpressionForCasecade index) = brackets (prettyPrec p index)
prettyPrec p (IndexExpressionForTarget target index) =
prettyPrec p target <> brackets (prettyPrec p index)
prettyPrec p (AwaitExpression expression) =
hsep [ text "await"
, prettyPrec p expression
]
instance Pretty FunctionBody where
prettyPrec p (BlockFunctionBody asyncModifier block) =
prettyPrec p asyncModifier <+> prettyPrec p block
prettyPrec p (EmptyFunctionBody) = semi
prettyPrec p (ExpressionFunctionBody isAsync expression) =
hsep [ optKeyword isAsync "async"
, text "=>"
, prettyPrec p expression
] <> semi
prettyPrec p (NativeFunctionBody stringLiteral) =
text "native" <+> prettyPrec p stringLiteral <> semi
instance Pretty FunctionExpression where
prettyPrec p (FunctionExpression mTypeParameters parameters body) =
case body of
BlockFunctionBody _ _ -> ppParams $$ prettyPrec p body
ExpressionFunctionBody _ _ -> ppParams <+> prettyPrec p body
_ -> ppParams <> semi
where ppParams = maybePP p mTypeParameters <> prettyPrec p parameters
instance Pretty FunctionDeclaration where
prettyPrec p (FunctionDeclaration _ metadata isExternal mReturnType propertyKeyword name (FunctionExpression mTypeParameters parameters body)) =
ppMetadata p metadata $$
hsep [ optKeyword isExternal "external"
, maybePP p mReturnType
, prettyPrec p propertyKeyword
, hcat [ prettyPrec p name
, maybePP p mTypeParameters
, prettyPrec p parameters
]
] $$$ prettyPrec p body
where ($$$) = case body of
(ExpressionFunctionBody _ _) -> (<+>)
(BlockFunctionBody _ _) -> ($$)
_ -> (<>)
instance Pretty ConstructorInitializer where
prettyPrec p (RedirectingConstructorInvocation mConstructorName argumentList) =
hcat [ text "this"
, maybe empty ((period <>) . prettyPrec p) mConstructorName
, prettyPrec p argumentList
]
prettyPrec p (ConstructorFieldInitializer explicitThis fieldName expression) =
hsep [ hcat [ opt explicitThis (text "this.")
, prettyPrec p fieldName
]
, equals
, prettyPrec p expression
]
prettyPrec p (SuperConstructorInvocation mConstructorName argumentList) =
hcat [ text "super"
, maybe empty ((period <>) . prettyPrec p) mConstructorName
, prettyPrec p argumentList
]
instance Pretty MethodModifier where
prettyPrec _ Abstract = text "abstract"
prettyPrec _ Static = text "static"
instance Pretty NamedCompilationUnitMember where
prettyPrec p (FunctionDeclaration' funDecl) = prettyPrec p funDecl
prettyPrec p (TypeAlias typeAlias) = prettyPrec p typeAlias
prettyPrec p (EnumDeclaration _ metadata name constants) =
ppMetadata p metadata $$
hsep [ text "enum"
, prettyPrec p name
] $$ braceBlock (ppIntersperse p comma constants)
prettyPrec p (ClassDeclaration _ metadata isAbstract name mTypeParameters mExtendsClause mWithClause mImplementsClause members) =
ppMetadata p metadata $$
hsep [ optKeyword isAbstract "abstract"
, text "class"
, prettyPrec p name <> maybePP p mTypeParameters
, maybePP p mExtendsClause
, maybePP p mWithClause
, maybePP p mImplementsClause
] $$ braceBlock (map (prettyPrec p) members)
instance Pretty CompilationUnitMember where
prettyPrec p (TopLevelVariableDeclaration _ metadata variableList) =
ppMetadata p metadata $$ prettyPrec p variableList
prettyPrec p (NamedCompilationUnitMember member) = prettyPrec p member
instance Pretty ScriptTag where
prettyPrec _ (ScriptTag token) = text token
instance Pretty CompilationUnit where
prettyPrec p (CompilationUnit mScriptTag dirs members) =
vcat $ [maybePP p mScriptTag] ++ map (prettyPrec p) dirs ++ map (prettyPrec p) members
ppMetadata :: Int -> [Annotation] -> Doc
ppMetadata p metadata = vcat (map (prettyPrec p) metadata)
instance Pretty ClassMember where
prettyPrec p (ConstructorDeclaration _ metadata isExternal isConst isFactory className mName parameters initializers mRedirectedConstructor mBody) =
ppMetadata p metadata $$
case mRedirectedConstructor of
Nothing -> hsep [ optKeyword isExternal "external"
, optKeyword isConst "const"
, optKeyword isFactory "factory"
, hcat [ prettyPrec p className
, maybe empty ((period <>) . prettyPrec p) mName
, prettyPrec p parameters
]
, opt (not $ null initializers) (colon <+> vcat (ppIntersperse p comma initializers))
] <> maybe semi (const empty) mBody $$ maybePP p mBody
Just redirectedConstructor -> hsep [ optKeyword isConst "const"
, text "factory"
, hcat [ prettyPrec p className
, maybe empty ((period <>) . prettyPrec p) mName
, prettyPrec p parameters
]
, equals
, prettyPrec p redirectedConstructor <> semi
]
prettyPrec p (MethodDeclaration _ metadata isExternal methodModifier mReturnType propertyKeyword isOperator name mTypeParameters mParameters body) =
ppMetadata p metadata $$
hsep [ optKeyword isExternal "external"
, maybePP p methodModifier
, maybePP p mReturnType
, prettyPrec p propertyKeyword
, optKeyword isOperator "operator"
, hcat [ prettyPrec p name, maybePP p mTypeParameters, maybePP p mParameters]
] $$ prettyPrec p body
prettyPrec p (FieldDeclaration _ metadata isStatic fieldList) =
ppMetadata p metadata $$
optKeyword isStatic "static" <+> prettyPrec p fieldList <> semi
ppIntersperse :: (Pretty a) => Int -> Doc -> [a] -> [Doc]
ppIntersperse p s as = punctuate s (map (prettyPrec p) as)
prettyNestedStmt :: Int -> Statement -> Doc
prettyNestedStmt prio b@(Block' _) = prettyPrec prio b
prettyNestedStmt prio s = nest 2 (prettyPrec prio s)
maybePP :: Pretty a => Int -> Maybe a -> Doc
maybePP p = maybe empty (prettyPrec p)
pound :: Doc
pound = char '#'
period :: Doc
period = char '.'
star :: Doc
star = char '*'
at :: Doc
at = char '@'
dollar :: Doc
dollar = char '$'
questionMark :: Doc
questionMark = char '?'
exclamation :: Doc
exclamation = char '!'
angleBrackets :: Doc -> Doc
angleBrackets p = char '<' <> p <> char '>'
opt :: Bool -> Doc -> Doc
opt x a = if x then a else empty
optKeyword :: Bool -> String -> Doc
optKeyword x s = opt x (text s)
block :: Char -> Char -> [Doc] -> Doc
block open close xs = char open
$+$ nest 2 (vcat xs)
$+$ char close
braceBlock :: [Doc] -> Doc
braceBlock = block '{' '}'
bracketBlock :: [Doc] -> Doc
bracketBlock = block '[' ']'
escapeGeneral :: Char -> String
escapeGeneral '\b' = "\\b"
escapeGeneral '\t' = "\\t"
escapeGeneral '\n' = "\\n"
escapeGeneral '\f' = "\\f"
escapeGeneral '\r' = "\\r"
escapeGeneral '\\' = "\\\\"
escapeGeneral c | c >= ' ' && c < '\DEL' = [c]
| c <= '\xFFFF' = printf "\\u%04x" (fromEnum c)
| otherwise = error $ "Language.Dart.Pretty.escapeGeneral: Char " ++ show c ++ " too large for Dart char"
escapeChar :: Char -> String
escapeChar '\'' = "\\'"
escapeChar c = escapeGeneral c
escapeString :: Char -> String
escapeString '"' = "\\\""
escapeString c | c <= '\xFFFF' = escapeGeneral c
| otherwise = escapeGeneral lead ++ escapeGeneral trail
where c' = fromEnum c 0x010000
lead = toEnum $ 0xD800 + c' `div` 0x0400
trail = toEnum $ 0xDC00 + c' `mod` 0x0400
opPrec :: String -> Int
opPrec "*" = 14
opPrec "/" = 14
opPrec "~/" = 14
opPrec "%" = 14
opPrec "+" = 13
opPrec "-" = 13
opPrec "<<" = 12
opPrec ">>" = 12
opPrec "&" = 11
opPrec "^" = 10
opPrec "|" = 9
opPrec "<" = 8
opPrec ">" = 8
opPrec "<=" = 8
opPrec ">=" = 8
opPrec "==" = 7
opPrec "!=" = 7
opPrec "&&" = 6
opPrec "||" = 5
opPrec "??" = 4