├── LICENSE ├── README.md ├── Setup.hs ├── example.nix ├── nixfmt.cabal ├── src └── Main.hs └── stack.yaml /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Author name here (c) 2016 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `nixfmt` 2 | 3 | This is my Munihac project to write an automatic code formatter for the Nix 4 | expression language. It's very messy, pathologically slow on some code, and 5 | also rejects some valid Nix expressions, but I'm sharing my latest draft for 6 | other people to browse so they can see what a mess I made. 7 | 8 | I'll probably revisit this later and polish it more when I have more time. If 9 | you feel the desire to contribute to this just ask! The best way to jump in is 10 | to submit a pull request or open an issue to discuss ways to contribute. 11 | 12 | # Usage 13 | 14 | $ nix-shell -p stack haskell.compiler.ghc7103 15 | $ stack build 16 | $ stack exec -- nixfmt < somefile.nix 17 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /example.nix: -------------------------------------------------------------------------------- 1 | {pkgs}: 2 | rec { a = [ 1 2 3 ]; b = { b1 = true; b2 = { b21 = 1; really-really-long-name = { b221 = "foo"; b22 = [ 1 2 3 4 5 6 7 8]; }; }; }; 3 | c = f { 4 | inherit a; str = ''#! ${pkgs.stdenv.shell}\n echo "Hello!"\n''; 5 | environment.systemPackages = with pkgs; [ tmux vim ]; 6 | }; 7 | d = let tool = "nixfmt"; in "${tool} is awesome"; 8 | e = let lots = "lots"; 9 | of = "of"; 10 | binds = "binds"; 11 | which = "which"; 12 | were = "were"; 13 | originally = "originally"; 14 | unaligned = "unaligned"; in "wow!"; 15 | } 16 | -------------------------------------------------------------------------------- /nixfmt.cabal: -------------------------------------------------------------------------------- 1 | name: nixfmt 2 | version: 1.0.0 3 | synopsis: Auto-format Nix code 4 | description: Please see README.md 5 | homepage: https://github.com/Gabriel439/nixfmt#readme 6 | license: BSD3 7 | license-file: LICENSE 8 | author: Gabriel Gonzalez 9 | maintainer: Gabriel439@gmail.com 10 | copyright: 2016 Gabriel Gonzalez 11 | category: Compiler 12 | build-type: Simple 13 | cabal-version: >=1.10 14 | 15 | executable nixfmt 16 | hs-source-dirs: src 17 | main-is: Main.hs 18 | default-language: Haskell2010 19 | build-tools: alex, happy 20 | build-depends: base >= 4.7 && < 5 21 | , Earley 22 | , parsec 23 | , pretty 24 | , text 25 | ghc-options: -Wall 26 | -------------------------------------------------------------------------------- /src/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {-# LANGUAGE RecursiveDo #-} 3 | 4 | module Main where 5 | 6 | import Control.Applicative 7 | import Data.Monoid ((<>)) 8 | import Data.Text (Text) 9 | import Text.Earley 10 | import Text.PrettyPrint (Doc, (<+>)) 11 | 12 | import qualified Data.Char 13 | import qualified Data.Text 14 | import qualified Data.Text.IO 15 | import qualified Text.PrettyPrint 16 | 17 | main :: IO () 18 | main = do 19 | str <- Data.Text.IO.getContents 20 | let (solutions, report) = fullParses (parser expr) str 21 | case solutions of 22 | [] -> do 23 | print report 24 | fail "No valid parses!" 25 | x:_ -> putStrLn (Text.PrettyPrint.renderStyle (Text.PrettyPrint.style { Text.PrettyPrint.lineLength = 80 }) x) 26 | 27 | space :: Prod r Text Char Char 28 | space = satisfy Data.Char.isSpace "space" 29 | 30 | spaces :: Prod r Text Char String 31 | spaces = many space 32 | 33 | char :: Char -> Prod r Text Char Char 34 | char c = satisfy (== c) ("'" <> Data.Text.singleton c <> "'") 35 | 36 | string :: String -> Prod r Text Char String 37 | string s = 38 | traverse (\c -> satisfy (== c)) s ("\"" <> Data.Text.pack s <> "\"") 39 | 40 | anyChar :: Prod r Text Char Char 41 | anyChar = satisfy (\_ -> True) "any character" 42 | 43 | letter :: Prod r Text Char Char 44 | letter = satisfy Data.Char.isLetter "letter" 45 | 46 | alphaNum :: Prod r Text Char Char 47 | alphaNum = satisfy Data.Char.isAlphaNum "letter or digit" 48 | 49 | digit :: Prod r Text Char Char 50 | digit = satisfy Data.Char.isDigit "digit" 51 | 52 | oneOf :: String -> Prod r Text Char Char 53 | oneOf cs = satisfy (`elem` cs) ("one of " <> Data.Text.pack (show cs)) 54 | 55 | noneOf :: String -> Prod r Text Char Char 56 | noneOf cs = 57 | satisfy (`notElem` cs) ("not one of " <> Data.Text.pack (show cs)) 58 | 59 | infixr <#>, , <@> 60 | 61 | (<#>) :: Prod r Text Char Doc -> Prod r Text Char Doc -> Prod r Text Char Doc 62 | x <#> y = adapt <$> x <*> spaces <*> y 63 | where 64 | adapt a _ b = a <+> b 65 | 66 | () :: (Applicative f, Monoid m) => f m -> f m -> f m 67 | () = liftA2 mappend 68 | 69 | (<@>) :: Applicative f => f Doc -> f Doc -> f Doc 70 | x <@> y = (<+>) <$> x <*> y 71 | 72 | match :: String -> Prod r Text Char Doc 73 | match s = fmap Text.PrettyPrint.text (string s) 74 | 75 | expr :: Grammar r (Prod r Text Char Doc) 76 | expr = mdo 77 | parseID <- rule $ do 78 | fmap Text.PrettyPrint.char (letter <|> char '_') 79 | fmap Text.PrettyPrint.text (many (alphaNum <|> oneOf "_'-")) 80 | 81 | parseINT <- rule $ do 82 | fmap Text.PrettyPrint.text (some digit) 83 | 84 | parseFLOAT <- rule $ do 85 | let alt0 = fmap Text.PrettyPrint.char (oneOf "123456789") 86 | fmap Text.PrettyPrint.text (many digit) 87 | fmap Text.PrettyPrint.char (char '.') 88 | fmap Text.PrettyPrint.text (many digit) 89 | let alt1 = (fmap Text.PrettyPrint.char (char '0') <|> pure mempty) 90 | fmap Text.PrettyPrint.char (char '.') 91 | fmap Text.PrettyPrint.text (some digit) 92 | let alt2 = fmap Text.PrettyPrint.char (oneOf "Ee") 93 | (fmap Text.PrettyPrint.char (oneOf "+-") <|> pure mempty) 94 | fmap Text.PrettyPrint.text (some digit) 95 | (alt0 <|> alt1) (alt2 <|> pure mempty) 96 | 97 | parsePATH <- rule $ do 98 | let charSet = alphaNum <|> oneOf "._-+" 99 | let alt0 = fmap Text.PrettyPrint.text (many charSet) 100 | let alt1 = fmap Text.PrettyPrint.char (char '/') alt0 101 | alt0 fmap mconcat (some alt1) 102 | 103 | parseHPATH <- rule $ do 104 | let charSet = alphaNum <|> oneOf "._-+" 105 | let alt0 = fmap Text.PrettyPrint.text (some charSet) 106 | let alt1 = fmap Text.PrettyPrint.char (char '/') alt0 107 | let alt2 = fmap mconcat (some alt1) 108 | fmap Text.PrettyPrint.char (char '~') alt2 109 | 110 | parseSPATH <- rule $ do 111 | let charSet = alphaNum <|> oneOf "._-+" 112 | let alt0 = fmap Text.PrettyPrint.text (some charSet) 113 | let alt1 = fmap Text.PrettyPrint.char (char '/') alt0 114 | let alt2 = fmap mconcat (some alt0) 115 | let alt3 = fmap mconcat (many alt1) 116 | let alt4 = fmap Text.PrettyPrint.char (char '<') 117 | alt2 118 | alt3 119 | fmap Text.PrettyPrint.char (char '>') 120 | alt4 121 | 122 | parseURI <- rule $ do 123 | let charSet0 = alphaNum <|> oneOf "+-." 124 | let charSet1 = alphaNum <|> oneOf "%/?:@&=+$,-_.!~*'" 125 | let alt0 = fmap Text.PrettyPrint.text (many charSet0) 126 | let alt1 = fmap Text.PrettyPrint.text (some charSet1) 127 | let alt2 = fmap Text.PrettyPrint.char letter 128 | alt0 129 | fmap Text.PrettyPrint.char (char ':') 130 | alt1 131 | alt2 132 | 133 | parseFormals <- rule $ do 134 | fmap Text.PrettyPrint.sep (many ((parseFormal <#> match ",") <* spaces)) 135 | <#> (parseFormal <|> match "..." <|> pure mempty) 136 | 137 | parseFormal <- rule $ do 138 | parseFormal0 139 | <|> parseFormal1 140 | 141 | parseFormal0 <- rule $ do 142 | parseID 143 | 144 | parseFormal1 <- rule $ do 145 | parseID 146 | <#> match "?" 147 | <#> parseExpr 148 | 149 | parseBinds <- rule $ do 150 | fmap Text.PrettyPrint.sep (many (parseBind <* spaces)) 151 | 152 | parseBind <- rule $ do 153 | parseBind0 154 | <|> parseBind1 155 | <|> parseBind2 156 | 157 | parseBind0 <- rule $ do 158 | let adapt a _ b _ c _ d = (a <+> b <+> c) <> d 159 | adapt 160 | <$> parseAttrPath 161 | <*> spaces 162 | <*> match "=" 163 | <*> spaces 164 | <*> parseExpr 165 | <*> spaces 166 | <*> match ";" 167 | 168 | parseBind1 <- rule $ do 169 | match "inherit" 170 | <#> parseAttrs 171 | <#> match ";" 172 | 173 | parseBind2 <- rule $ do 174 | match "inherit" 175 | <#> match "(" 176 | <#> parseExpr 177 | <#> match ")" 178 | <#> parseAttrs 179 | <#> match ";" 180 | 181 | parseAttrPath <- rule $ do 182 | fmap mconcat (many ((parseAttr <|> parseStringAttr) match ".")) 183 | (parseAttr <|> parseStringAttr) 184 | 185 | parseAttrs <- rule $ do 186 | let both = parseAttr <|> parseStringAttr 187 | let alt0 = many (both <* space <* spaces) 188 | let alt1 = (\xs x -> xs ++ [x]) <$> alt0 <*> both 189 | fmap Text.PrettyPrint.sep alt1 <|> pure mempty 190 | 191 | parseAttr <- rule $ do 192 | parseAttr0 193 | <|> parseAttr1 194 | 195 | parseAttr0 <- rule $ do 196 | parseID 197 | 198 | parseAttr1 <- rule $ do 199 | match "or" 200 | 201 | parseStringAttr <- rule $ do 202 | parseStringAttr0 203 | <|> parseStringAttr1 204 | 205 | parseStringAttr0 <- rule $ do 206 | match "\"" 207 | parseStringParts 208 | match "\"" 209 | 210 | parseStringAttr1 <- rule $ do 211 | match "${" 212 | <#> parseExpr 213 | <#> match "}" 214 | 215 | parseExprList <- rule $ do 216 | let alt0 = many (parseExprSelect <* space <* spaces) 217 | let alt1 = (\xs x -> xs ++ [x]) <$> alt0 <*> parseExprSelect 218 | fmap Text.PrettyPrint.sep alt1 <|> pure mempty 219 | 220 | parseStringParts <- rule $ do 221 | parseStringParts0 222 | <|> parseStringParts1 223 | <|> parseStringParts2 224 | 225 | parseStringParts0 <- rule $ do 226 | parseSTR 227 | 228 | parseStringParts1 <- rule $ do 229 | parseStringPartsInterpolated 230 | 231 | parseStringParts2 <- rule $ do 232 | pure mempty 233 | 234 | parseStringPartsInterpolated <- rule $ do 235 | fmap mconcat (many parseStringPartInterpolated) 236 | 237 | parseStringPartInterpolated <- rule $ do 238 | parseChar 239 | <|> ( match "${" 240 | <#> parseExpr 241 | <#> match "}" 242 | ) 243 | 244 | parseSTR <- rule $ do 245 | -- TODO: Fix 246 | parseSTR1 247 | 248 | parseChar <- rule $ do 249 | let alt0 = fmap Text.PrettyPrint.char (noneOf "$\"\\") 250 | let alt1 = fmap Text.PrettyPrint.char (char '$') 251 | fmap Text.PrettyPrint.char (noneOf "{\"\\") 252 | let alt2 = fmap Text.PrettyPrint.char (char '\\') 253 | fmap Text.PrettyPrint.char anyChar 254 | let alt3 = fmap Text.PrettyPrint.char (char '$') 255 | fmap Text.PrettyPrint.char (char '\\') 256 | fmap Text.PrettyPrint.char anyChar 257 | alt0 <|> alt1 <|> alt2 <|> alt3 258 | 259 | parseSTR1 <- rule $ do 260 | fmap mconcat (some parseChar) 261 | 262 | parseIND_STR <- rule $ do 263 | parseIND_STR0 264 | <|> parseIND_STR1 265 | <|> parseIND_STR2 266 | <|> parseIND_STR3 267 | <|> parseIND_STR4 268 | 269 | parseIND_STR0 <- rule $ do 270 | let alt0 = fmap Text.PrettyPrint.char (noneOf "$'") 271 | let alt1 = fmap Text.PrettyPrint.char (char '$') 272 | fmap Text.PrettyPrint.char (noneOf "{'") 273 | let alt2 = fmap Text.PrettyPrint.char (char '\'') 274 | fmap Text.PrettyPrint.char (noneOf "'$") 275 | alt0 <|> alt1 <|> alt2 276 | 277 | parseIND_STR1 <- rule $ do 278 | fmap Text.PrettyPrint.text (string "''$") 279 | 280 | parseIND_STR2 <- rule $ do 281 | fmap Text.PrettyPrint.text (string "'''") 282 | 283 | parseIND_STR3 <- rule $ do 284 | fmap Text.PrettyPrint.text (string "''.") 285 | 286 | parseIND_STR4 <- rule $ do 287 | fmap Text.PrettyPrint.char (char '\'') 288 | 289 | parseExpr <- rule $ do 290 | parseExprFunction 291 | 292 | parseExprFunction <- rule $ do 293 | parseExprFunction0 294 | <|> parseExprFunction1 295 | <|> parseExprFunction2 296 | <|> parseExprFunction3 297 | <|> parseExprFunction4 298 | <|> parseExprFunction5 299 | <|> parseExprFunction6 300 | <|> parseExprFunction7 301 | 302 | parseExprFunction0 <- rule $ do 303 | let adapt a _ b _ c = (a <+> b) <> c 304 | adapt <$> parseID <*> spaces <*> match ":" <*> spaces <*> parseExprFunction 305 | 306 | parseExprFunction1 <- rule $ do 307 | let adapt a _ b _ c _ d _ e = (a <+> b <+> c) <> (d <+> e) 308 | adapt 309 | <$> match "{" 310 | <*> spaces 311 | <*> parseFormals 312 | <*> spaces 313 | <*> match "}" 314 | <*> spaces 315 | <*> match ":" 316 | <*> spaces 317 | <*> parseExprFunction 318 | 319 | parseExprFunction2 <- rule $ do 320 | match "{" 321 | <#> parseFormals 322 | <#> match "}" 323 | <#> match "@" 324 | <#> parseID 325 | <#> match ":" 326 | <#> parseExprFunction 327 | 328 | parseExprFunction3 <- rule $ do 329 | parseID 330 | <#> match "@" 331 | <#> match "{" 332 | <#> parseFormals 333 | <#> match "}" 334 | <#> match ":" 335 | <#> parseExprFunction 336 | 337 | parseExprFunction4 <- rule $ do 338 | match "assert" 339 | <#> parseExpr 340 | <#> match ";" 341 | <#> parseExprFunction 342 | 343 | parseExprFunction5 <- rule $ do 344 | match "with" 345 | <#> parseExpr 346 | <#> match ";" 347 | <#> parseExprFunction 348 | 349 | parseExprFunction6 <- rule $ do 350 | match "let" 351 | <#> parseBinds 352 | <@> match "in" 353 | <#> parseExprFunction 354 | 355 | parseExprFunction7 <- rule $ do 356 | parseExprIf 357 | 358 | parseExprIf <- rule $ do 359 | parseExprIf0 360 | <|> parseExprIf1 361 | 362 | parseExprIf0 <- rule $ do 363 | match "if" 364 | <#> parseExpr 365 | <#> match "then" 366 | <#> parseExpr 367 | <#> match "else" 368 | <#> parseExpr 369 | 370 | parseExprIf1 <- rule $ do 371 | parseExprOp 372 | 373 | parseExprOp <- rule $ do 374 | parseExprOp00 375 | <|> parseExprOp01 376 | <|> parseExprOp02 377 | <|> parseExprOp03 378 | <|> parseExprOp04 379 | <|> parseExprOp05 380 | <|> parseExprOp06 381 | <|> parseExprOp07 382 | <|> parseExprOp08 383 | <|> parseExprOp09 384 | <|> parseExprOp10 385 | <|> parseExprOp11 386 | <|> parseExprOp12 387 | <|> parseExprOp13 388 | <|> parseExprOp14 389 | <|> parseExprOp15 390 | <|> parseExprOp16 391 | <|> parseExprOp17 392 | 393 | parseExprOp00 <- rule $ do 394 | match "!" 395 | <#> parseExprOp 396 | 397 | parseExprOp01 <- rule $ do 398 | match "-" 399 | <#> parseExprOp 400 | 401 | parseExprOp02 <- rule $ do 402 | parseExprOp 403 | <#> match "==" 404 | <#> parseExprOp 405 | 406 | parseExprOp03 <- rule $ do 407 | parseExprOp 408 | <#> match "!=" 409 | <#> parseExprOp 410 | 411 | parseExprOp04 <- rule $ do 412 | parseExprOp 413 | <#> match "<" 414 | <#> parseExprOp 415 | 416 | parseExprOp05 <- rule $ do 417 | parseExprOp 418 | <#> match "<=" 419 | <#> parseExprOp 420 | 421 | parseExprOp06 <- rule $ do 422 | parseExprOp 423 | <#> match ">" 424 | <#> parseExprOp 425 | 426 | parseExprOp07 <- rule $ do 427 | parseExprOp 428 | <#> match ">=" 429 | <#> parseExprOp 430 | 431 | parseExprOp08 <- rule $ do 432 | parseExprOp 433 | <#> match "&&" 434 | <#> parseExprOp 435 | 436 | parseExprOp09 <- rule $ do 437 | parseExprOp 438 | <#> match "||" 439 | <#> parseExprOp 440 | 441 | parseExprOp10 <- rule $ do 442 | parseExprOp 443 | <#> match "->" 444 | <#> parseExprOp 445 | 446 | parseExprOp11 <- rule $ do 447 | parseExprOp 448 | <#> match "//" 449 | <#> parseExprOp 450 | 451 | parseExprOp12 <- rule $ do 452 | parseExprOp 453 | <#> match "?" 454 | <#> parseExprOp 455 | 456 | parseExprOp13 <- rule $ do 457 | parseExprOp 458 | <#> match "+" 459 | <#> parseExprOp 460 | 461 | parseExprOp14 <- rule $ do 462 | parseExprOp 463 | <#> match "*" 464 | <#> parseExprOp 465 | 466 | parseExprOp15 <- rule $ do 467 | parseExprOp 468 | -- Slight hack so that `foo/bar/baz` is parsed as a path and not as 469 | -- "foo divided by bar divided by baz" 470 | <#> (space *> match "/" <* space) 471 | <#> parseExprOp 472 | 473 | parseExprOp16 <- rule $ do 474 | parseExprOp 475 | <#> match "++" 476 | <#> parseExprOp 477 | 478 | parseExprOp17 <- rule $ do 479 | parseExprApp 480 | 481 | parseExprApp <- rule $ do 482 | parseExprApp0 483 | <|> parseExprApp1 484 | 485 | parseExprApp0 <- rule $ do 486 | let adapt a _ _ b = a <+> b 487 | adapt <$> parseExprSelect <*> space <*> spaces <*> parseExprApp 488 | 489 | parseExprApp1 <- rule $ do 490 | parseExprSelect 491 | 492 | parseExprSelect <- rule $ do 493 | parseExprSelect0 494 | <|> parseExprSelect1 495 | <|> parseExprSelect2 496 | <|> parseExprSelect3 497 | 498 | parseExprSelect0 <- rule $ do 499 | parseExprSimple 500 | match "." 501 | parseAttrPath 502 | 503 | parseExprSelect1 <- rule $ 504 | ( parseExprSimple 505 | match "." 506 | parseAttrPath 507 | ) <#> match "or" 508 | <#> parseExprSelect 509 | 510 | parseExprSelect2 <- rule $ do 511 | parseExprSimple 512 | <#> match "or" 513 | 514 | parseExprSelect3 <- rule $ do 515 | parseExprSimple 516 | 517 | parseExprSimple <- rule $ do 518 | parseExprSimple00 519 | <|> parseExprSimple01 520 | <|> parseExprSimple02 521 | <|> parseExprSimple03 522 | <|> parseExprSimple04 523 | <|> parseExprSimple05 524 | <|> parseExprSimple06 525 | <|> parseExprSimple07 526 | <|> parseExprSimple08 527 | <|> parseExprSimple09 528 | <|> parseExprSimple10 529 | <|> parseExprSimple11 530 | <|> parseExprSimple12 531 | 532 | parseExprSimple00 <- rule $ do 533 | parseID 534 | 535 | parseExprSimple01 <- rule $ do 536 | parseINT 537 | 538 | parseExprSimple02 <- rule $ do 539 | parseFLOAT 540 | 541 | parseExprSimple03 <- rule $ do 542 | fmap Text.PrettyPrint.char (char '"') 543 | parseStringParts 544 | fmap Text.PrettyPrint.char (char '"') 545 | 546 | parseExprSimple04 <- rule $ do 547 | fmap Text.PrettyPrint.text (string "''") 548 | fmap Text.PrettyPrint.text spaces 549 | parseIndStringParts 550 | fmap Text.PrettyPrint.text (string "''") 551 | 552 | parseExprSimple05 <- rule $ do 553 | parsePATH 554 | 555 | parseExprSimple06 <- rule $ do 556 | parseHPATH 557 | 558 | parseExprSimple07 <- rule $ do 559 | parseSPATH 560 | 561 | parseExprSimple08 <- rule $ do 562 | parseURI 563 | 564 | parseExprSimple09 <- rule $ do 565 | match "let" 566 | <#> match "{" 567 | <#> parseBinds 568 | <@> match "}" 569 | 570 | parseExprSimple10 <- rule $ do 571 | let adapt a _ b _ = a <+> Text.PrettyPrint.braces b 572 | adapt 573 | <$> match "rec" 574 | <*> spaces 575 | <*> parseBinds 576 | <*> match "}" 577 | 578 | parseExprSimple11 <- rule $ do 579 | let adapt _ _ a _ = Text.PrettyPrint.braces a 580 | adapt 581 | <$> match "{" 582 | <*> spaces 583 | <*> parseBinds 584 | <*> match "}" 585 | 586 | parseExprSimple12 <- rule $ do 587 | let adapt _ _ a _ _ = Text.PrettyPrint.brackets a 588 | adapt 589 | <$> match "[" 590 | <*> spaces 591 | <*> parseExprList 592 | <*> spaces 593 | <*> match "]" 594 | 595 | parseIndStringParts <- rule $ do 596 | let alt0 = match "${" <#> parseExpr <#> match "}" 597 | let alt1 = fmap mconcat (many parseIND_STR) 598 | fmap mconcat (many (alt1 alt0)) alt1 599 | 600 | return (spaces *> parseExpr <* spaces) 601 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by 'stack init' 2 | # 3 | # Some commonly used options have been documented as comments in this file. 4 | # For advanced use and comprehensive documentation of the format, please see: 5 | # http://docs.haskellstack.org/en/stable/yaml_configuration/ 6 | 7 | # Resolver to choose a 'specific' stackage snapshot or a compiler version. 8 | # A snapshot resolver dictates the compiler version and the set of packages 9 | # to be used for project dependencies. For example: 10 | # 11 | # resolver: lts-3.5 12 | # resolver: nightly-2015-09-21 13 | # resolver: ghc-7.10.2 14 | # resolver: ghcjs-0.1.0_ghc-7.10.2 15 | # resolver: 16 | # name: custom-snapshot 17 | # location: "./custom-snapshot.yaml" 18 | resolver: lts-6.14 19 | 20 | # User packages to be built. 21 | # Various formats can be used as shown in the example below. 22 | # 23 | # packages: 24 | # - some-directory 25 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz 26 | # - location: 27 | # git: https://github.com/commercialhaskell/stack.git 28 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a 29 | # - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a 30 | # extra-dep: true 31 | # subdirs: 32 | # - auto-update 33 | # - wai 34 | # 35 | # A package marked 'extra-dep: true' will only be built if demanded by a 36 | # non-dependency (i.e. a user package), and its test suites and benchmarks 37 | # will not be run. This is useful for tweaking upstream packages. 38 | packages: 39 | - '.' 40 | # Dependency packages to be pulled from upstream that are not in the resolver 41 | # (e.g., acme-missiles-0.3) 42 | extra-deps: [] 43 | 44 | # Override default flag values for local packages and extra-deps 45 | flags: {} 46 | 47 | # Extra package databases containing global packages 48 | extra-package-dbs: [] 49 | 50 | # Control whether we use the GHC we find on the path 51 | # system-ghc: true 52 | # 53 | # Require a specific version of stack, using version ranges 54 | # require-stack-version: -any # Default 55 | # require-stack-version: ">=1.1" 56 | # 57 | # Override the architecture used by stack, especially useful on Windows 58 | # arch: i386 59 | # arch: x86_64 60 | # 61 | # Extra directories used by stack for building 62 | # extra-include-dirs: [/path/to/dir] 63 | # extra-lib-dirs: [/path/to/dir] 64 | # 65 | # Allow a newer minor version of GHC than the snapshot specifies 66 | # compiler-check: newer-minor --------------------------------------------------------------------------------