{-#LANGUAGE TupleSections #-}moduleText.HPaco.Readers.Capo.Statements(statements,statement)whereimportControl.MonadimportControl.Monad.IO.ClassimportControl.Applicative((<$>),(<*>))importText.HPaco.ReaderimportText.HPaco.Readers.Paco.BasicsimportText.HPaco.Readers.Paco.ParserInternalsimportText.HPaco.Readers.Commonhiding(Parser)importText.HPaco.Readers.Paco.ExpressionsimportText.HPaco.Readers.Paco.IncludeimportText.HPaco.AST.ASTimportText.HPaco.AST.StatementimportText.HPaco.AST.ExpressionimportControl.Exception(throw)importSystem.IO(withFile,IOMode(ReadMode))importSystem.IO.StrictimportSystem.FilePathstatements::Parser[Statement]statements=doss_stmts<-manySepBystatementss_ss_returnstmtsstatement=trydefStatement<|>trycallStatement<|>tryletStatement<|>standaloneStatementletStatement=do(ident,expr)<-withSemicolonassignmentss_body<-option[NullStatement]statements-- TODO: warn if null statementreturn$LetStatementidentexpr$StatementSequencebodydefStatement=dokeyword"def"ss_defName<-identifierss_char'='ss_body<-standaloneStatementaddDefdefNamebodyreturnNullStatementcallStatement=doCallStatement<$>withSemicolonidentifierassignment::Parser(String,Expression)assignment=(,)<$>identifier<*>(betweenSpaces(char'=')>>expression)betweenSpacesa=doss_v<-ass_returnv-- A standalone statement can appear at any level of the parse tree; it does-- not need to be explicitly enclosed in a block.standaloneStatement=trylineComment<|>tryblockComment<|>tryprintStatement<|>tryprintHtmlStatement<|>tryprintUrlStatement<|>tryifStatement<|>trywithStatement<|>tryforStatement<|>tryswitchStatement<|>tryincludeStatement<|>tryblock<?>"Statement"lineComment=dostring"//"many(noneOf['\n'])char'\n'returnNullStatementblockComment=dostring"/*"manyTill(try(discardblockComment)<|>discardanyChar)(try$string"*/")returnNullStatementprintStatement=printStatementBase"print"idprintHtmlStatement=printStatementBase"printHtml"(EscapeExpressionEscapeHTML)printUrlStatement=printStatementBase"printUrl"(EscapeExpressionEscapeURL)printStatementBasekwenc=withSemicolon$StatementSequence.map(PrintStatement.enc)<$>(ss_>>keywordkw>>ss_>>(parenthesized$manySepByexpression(betweenSpaces$char',')))includeStatement::ParserStatementincludeStatement=doss_keyword"include"ss_filename<-(parenthesized.betweenSpaces)anyQuotedStringss_char';'ss_performIncludefilenameNothingifStatement=doss_keyword"if"cond<-parenthesizedexpressiontrue<-standaloneStatementfalse<-optionNullStatement$tryfalseBranchreturn$IfStatementcondtruefalsewherefalseBranch=doss_keyword"else"assertEndOfWordss_standaloneStatementswitchStatement=doss_keyword"switch"SwitchStatement<$>parenthesizedexpression<*>switchBodywhereswitchBody=braced$manyswitchCaseswitchCase=doss_keyword"case"ss_expr<-expressionss_char':'body<-StatementSequence<$>statementsss_optional$withSemicolon$keyword"break"ss_return(expr,body)withStatement=withOrFor"with"letAssignmentfoldLetStatementwhereletAssignment=tryassignment<|>try((".",)<$>expression)foldLetStatement::[(String,Expression)]->Statement->StatementfoldLetStatementassignmentsbody=foldrcombineAssignmentbodyassignmentswherecombineAssignment(ident,expr)stmt=LetStatementidentexprstmtforStatement=withOrFor"for"forAssignmentfoldForStatementwhereforAssignment=trycomplexForAssignment<|>try((Nothing,".",)<$>expression)complexForAssignment=doexpr<-expressionss_discard(keyword"as")<|>discard(string":")ss_ident1<-identifierident2<-optionMaybe$doss_string"=>"<|>string"->"ss_identifiercaseident2ofNothing->return(Nothing,ident1,expr)JustvalIdent->return(Justident1,valIdent,expr)foldForStatement::[(MaybeString,String,Expression)]->Statement->StatementfoldForStatementassignmentsbody=foldrcombineAssignmentbodyassignmentswherecombineAssignment(keyIdent,valueIdent,expr)stmt=ForStatementkeyIdentvalueIdentexprstmtwithOrFor::String->Parsera->([a]->Statement->Statement)->ParserStatementwithOrForkwacombine=dokeywordkwassignments<-parenthesized$manySepBya(ss_>>char','>>ss_)body<-standaloneStatementreturn$combineassignmentsbodyblock=StatementSequence<$>bracedstatementswithSemicolon::Parsera->ParserawithSemicolonp=dov<-pss_char';'returnvparenthesized=bracedWith'('')'braced=bracedWith'{''}'bracedWith::Char->Char->Parsera->ParserabracedWithlrp=doss_charlss_val<-pss_charrss_returnval