{-# LANGUAGE OverloadedStrings, OverloadedLists, RecursiveDo #-} module Pinchot.Examples.Postal where import Pinchot import Data.Monoid ((<>)) -- | A grammar for simple U.S. postal addresses. This example would never -- hold up to real-world usage but it gives you a flavor of how -- Pinchot works. -- -- The grammar is ambiguous. postal :: Pinchot Char (Rule Char) postal = mdo digit <- terminal "Digit" (include '0' '9') "digit from 0 to 9" digits <- list1 digit letter <- terminal "Letter" (include 'a' 'z' <> include 'A' 'Z') "letter from A to Z" north <- terminal "North" (solo 'N') south <- terminal "South" (solo 'S') east <- terminal "East" (solo 'E') west <- terminal "West" (solo 'W') direction <- union "Direction" [north, south, east, west] street <- terminalSeq "Street" ['S', 't'] avenue <- terminalSeq "Avenue" ['A', 'v', 'e'] way <- terminalSeq "Way" ['W', 'a', 'y'] boulevard <- terminalSeq "Boulevard" ['B', 'l', 'v', 'd'] suffix <- union "Suffix" [street, avenue, way, boulevard] space <- terminal "Space" (solo ' ') comma <- terminal "Comma" (solo ',') -- You could do this with 'list' but this demonstrates how to write -- a recurvsive rule. letters <- nonTerminal "Letters" [ ("NoLetter", []) , ("ConsLetter", [letter, letters]) ] -- Named "PostalWord" to avoid clash with Prelude.Word word <- record "PostalWord" [letter, letters] preSpacedWord <- record "PreSpacedWord" [space, word] preSpacedWords <- list preSpacedWord words <- record "Words" [word, preSpacedWords] number <- wrap "Number" digits streetName <- wrap "StreetName" words city <- wrap "City" words state <- wrap "State" word zipCode <- wrap "ZipCode" digits directionSpace <- record "DirectionSpace" [direction, space] spaceSuffix <- record "SpaceSuffix" [space, suffix] optDirection <- option directionSpace optSuffix <- option spaceSuffix address <- record "Address" [ number, space, optDirection, streetName, optSuffix, comma, space, city, comma, space, state, space, zipCode ] return address