packages feed

BNFC-meta 0.3.0.5 → 0.4

raw patch · 14 files changed

+289/−351 lines, 14 files

Files

BNFC-meta.cabal view
@@ -1,26 +1,40 @@-Name:		BNFC-meta-version:	0.3.0.5+Name:	        BNFC-meta+version:        0.4 cabal-Version:  >= 1.6 build-type:     Simple license:        GPL-2 license-file:   LICENSE-author:		Jonas Duregård+author:		    Jonas Duregård maintainer:     Jonas Duregård (jonas.duregard@chalmers.se)-category:	Development-synopsis:	Deriving Quasi-Quoters from BNF Grammars-description:    This package provides a comfortable way of defining quasi-quoters. +category:	    Development+synopsis:	    Deriving Parsers and Quasi-Quoters from BNF Grammars+description:    This package provides a very simple way of defining a compiler   +  front-end for a language by embedding a BNF grammar directly into a Haskell +  source file. +     Specifically, given a quasi-quoted LBNF grammar (as used by the BNF Converter)  -  it generates (using Template Haskell) an LALR parser and pretty pretty printer -  for the language. The parser is then used to define a quasi-quoter. With a simple-  pragma, the user can define a universal syntax for anti-quoting. This means that -  any grammar non-terminal can be replaced by a quoted Haskell expression of the -  appropriate type. A few examples are included in the source tarball.+  it generates (using Template Haskell) a LALR parser and pretty pretty printer +  for the language. The parser is then used to automatically define a +  quasi-quoter for the defined language so it can also be seamlessly embedded+  in Haskell source code. With a +  simple addition to the grammar, the user can define a universal syntax for +  anti-quoting. This +  means that any grammar non-terminal can be replaced by a quoted Haskell +  expression of the appropriate type. A few example languages are included in+  the source tarball.+  .  +  The LBNF grammar formalism is described thoroughly in the BNF Converter +  documentation: <http://bnfc.digitalgrammars.com/>+  .  +  This library and the additions it makes to LBNF is described in a +  2011 Haskell Symposium paper titled \"Embedded Parser Generators\":+  <http://wiki.portal.chalmers.se/cse/pmwiki.php/FP/EmbeddedParserGenerators>  extra-source-files:-  examples/ghc7/jll/JavaletteLight.hs-  examples/ghc7/jll/UseJll.hs-  examples/ghc6/jll/JavaletteLight.hs-  examples/ghc6/jll/UseJll.hs+  examples/jll/JavaletteLight.hs+  examples/jll/UseJll.hs+  examples/typesafe/Example.hs+  examples/typesafe/Typesafe.hs   Bootstrap/Bootstrap.hs  Library
Language/LBNF.hs view
@@ -1,8 +1,16 @@ {-# OPTIONS_GHC -fno-warn-missing-fields #-}++-- | Contains the main language definition routines of BNFC-meta. module Language.LBNF (-    lbnf                 -- QuasiQuoter for LBNF-  , bnfc                 -- Parser meta-generator function-  , dumpAlex, dumpHappy, dumpHappyM, dumpCode, getCode -- Debug / code generation+  -- * Main language definition routines+    lbnf                 +  , bnfc+  -- * Debugging functions+  , dumpCode+  , getCode+  , dumpAlex +  , dumpHappy+--  , dumpHappyM   , module Language.LBNF.Compiletime --  , module Language.LBNF.Grammar   ) where@@ -26,10 +34,16 @@  import Data.List(isPrefixOf, intersperse) -+-- | QuasiQuoter for LBNF. Usage: @[lbnf| \<grammar for your language\>|]@+-- +-- The spliced code is an expression of type 'Grammar'. lbnf :: QuasiQuoter lbnf = grammar +-- | Typical usage (as a top level declaration): @bnfc [lbnf|\<grammar\>|]@+-- +-- The spliced code contains a parser, a pretty-printer and a Quasi-Quoter for +-- the language defined by the grammar. bnfc :: Grammar -> Q [Dec] bnfc = compile . toCF  @@ -72,7 +86,8 @@       (filter isNormal (allCats cf)) ++ if hasIdent cf then ["Ident(..)"] else []  -+-- | Equivalent to 'bnfc' with the side-effect of dumping the parser +-- definition into a file named "dump.y" dumpHappy :: Grammar -> Q [Dec] dumpHappy g = location >>= \l -> dumpHappyM g (loc_module l, loc_package l) >> bnfc g @@ -82,17 +97,23 @@   runIO $ writeFile "dump.y" $ cf2Happy (Loc {loc_module = m, loc_package = p}) cf   -- compile cf +-- | Equivalent to 'bnfc' with the side-effect of dumping the lexer +-- definition into a file named dump.x dumpAlex :: Grammar -> Q [Dec] dumpAlex g = do   let cf = toCF g   runIO $ writeFile "dump.x" $ cf2alex2 cf   compile cf   +-- | Equivalent to 'bnfc' with the side-effect of dumping ALL the spliced code +-- into a file named dump.hs dumpCode :: Grammar -> Q [Dec] dumpCode g = do   runIO $ getCode ("Main") g >>= writeFile "dump.hs"   bnfc g +-- | Computes the Haskell source code that would be spliced by a grammar and +-- wraps it into a compilable Haskell module. getCode :: String -> Grammar -> IO String getCode m g = do   let cf = toCF g
Language/LBNF/CFtoHappy.hs view
@@ -221,7 +221,7 @@     prActionQ rulz (MkAction fun ms) = maybe (thrd $ head ms) pf fun where             thrd (_,_,m) = m             pf f -              | isAqFun f = fun ++ " " ++ unwords (map (\(b,c,m) -> m) ms)+              | isAqFun f = fun ++ " " ++ unwords (map (\(b,c,m) -> if b then "(reverse "++m++")" else m) ms)               | isTokenRule rulz = fromToken ++ "\""++f++"\" $1"               | otherwise       = constr++" ["++                  (concat $ intersperse "," [m1|(_,c,m1) <- ms])
Language/LBNF/CFtoLayout.hs view
@@ -69,61 +69,40 @@  in fmap mkRename $        fmap (DataD [] (mkName "Block") [] [NormalC (mkName "Implicit") [(NotStrict,ConT ''Int)],        NormalC (mkName "Explicit") []] [''Show]:)-       (makedecs top lay stop cf) +       (makedecs top lay stop (sort (reservedWords cf ++ symbols cf)))+       +-- Hack to make haddock work+makedecs :: Bool -> [String] -> [String] -> [String] -> Q [Dec]+makedecs top lay stop resws = [d| --- | makedecs -makedecs :: Bool -> [String] -> [String] -> CF -> Q [Dec]-makedecs top lay stop cf = [d|     topLayout = $(lift top)   layoutWords = $(lift lay)   layoutStopWords = $(lift stop) -  -- layout separators-     layoutOpen  = $(lift layoutOpen')   layoutClose = $(lift layoutClose')   layoutSep   = $(lift layoutSep')   -  -- | Replace layout syntax with explicit layout tokens.-  --resolveLayout :: Bool    -- ^ Whether to use top-level layout.-  --              -> [Token] -> [Token]+   resolveLayout tp = res Nothing [if tl then Implicit 1 else Explicit]     where-    -- Do top-level layout if the function parameter and the grammar say so.     tl = tp && topLayout-  -    --res :: Maybe Token -- ^ The previous token, if any.-    --    -> [Block] -- ^ A stack of layout blocks.-    --    -> [Token] -> [Token]-  -    -- The stack should never be empty.     res _ [] ts = error $ "Layout error: stack empty. Tokens: " ++ show ts        res _ st (t0:ts)-      -- We found an open brace in the input,-      -- put an explicit layout block on the stack.-      -- This is done even if there was no layout word,-      -- to keep opening and closing braces.       | isLayoutOpen t0 = moveAlong (Explicit:st) [t0] ts        res _ st (t0:ts)-      -- Start a new layout block if the first token is a layout word       | isLayout t0 =           case ts of-              -- Explicit layout, just move on. The case above-              -- will push an explicit layout block.               t1:_ | isLayoutOpen t1 -> moveAlong st [t0] ts-                       -- at end of file, the start column doesn't matter               _ -> let col = if null ts then column t0 else column (head ts)-                       -- insert an open brace after the layout word                        b:ts' = addToken (nextPos t0) layoutOpen ts-                       -- save the start column                        st' = Implicit col:st                      in moveAlong st' [t0,b] ts'   -      -- If we encounter a closing brace, exit the first explicit layout block.       | isLayoutClose t0 =              let st' = drop 1 (dropWhile isImplicit st)              in if null st' @@ -132,35 +111,22 @@                                   ++ ") without an explicit layout block."                    else moveAlong st' [t0] ts   -    -- We are in an implicit layout block     res pt st@(Implicit n:ns) (t0:ts)   -        -- End of implicit block by a layout stop word       | isStop t0 = -             -- Exit the current block and all implicit blocks -             -- more indented than the current token          let (ebs,ns') = span (`moreIndent` column t0) ns              moreIndent (Implicit x) y = x > y              moreIndent Explicit _ = False-             -- the number of blocks exited              b = 1 + length ebs              bs = replicate b layoutClose-             -- Insert closing braces after the previous token.              (ts1,ts2) = splitAt (1+b) $ addTokens (afterPrev pt) bs (t0:ts)           in moveAlong ns' ts1 ts2   -      -- End of an implicit layout block       | newLine && column t0 < n  = -             -- Insert a closing brace after the previous token.          let b:t0':ts' = addToken (afterPrev pt) layoutClose (t0:ts)-             -- Repeat, with the current block removed from the stack           in moveAlong ns [b] (t0':ts')   -      -- Encounted a new line in an implicit layout block.       | newLine && column t0 == n = -         -- Insert a semicolon after the previous token.-         -- unless we are the beginning of the file,-         -- or the previous token is a semicolon or open brace.          if isNothing pt || isTokenIn [layoutSep,layoutOpen] (fromJust pt)              then moveAlong st [t0] ts             else let b:t0':ts' = addToken (afterPrev pt) layoutSep (t0:ts)@@ -169,135 +135,83 @@                              Nothing -> True                              Just t  -> line t /= line t0   -    -- Nothing to see here, move along.     res _ st (t:ts)  = moveAlong st [t] ts   -    -- At EOF: skip explicit blocks.     res (Just t) (Explicit:bs) [] | null bs = []                                   | otherwise = res (Just t) bs []   -    -- If we are using top-level layout, insert a semicolon after-    -- the last token, if there isn't one already     res (Just t) [Implicit n] []         | isTokenIn [layoutSep] t = []         | otherwise = addToken (nextPos t) layoutSep []   -    -- At EOF in an implicit, non-top-level block: close the block     res (Just t) (Implicit n:bs) [] =        let c = addToken (nextPos t) layoutClose []         in moveAlong bs c []   -    -- This should only happen if the input is empty.     res Nothing st [] = []   -    -- | Move on to the next token.-    --moveAlong :: [Block] -- ^ The layout stack.-    --          -> [Token] -- ^ Any tokens just processed.-    --          -> [Token] -- ^ the rest of the tokens.-    --          -> [Token]     moveAlong st [] ts = error $ "Layout error: moveAlong got [] as old tokens"     moveAlong st ot ts = ot ++ res (Just $ last ot) st ts-  +   type Position = Posn-  -  -- | Check if s block is implicit.+   isImplicit :: Block -> Bool   isImplicit (Implicit _) = True   isImplicit _ = False-  -  -- | Insert a number of tokens at the begninning of a list of tokens.-  addTokens :: Position -- ^ Position of the first new token.-            -> [String] -- ^ Token symbols.-            -> [Token]  -- ^ The rest of the tokens. These will have their-                        --   positions updated to make room for the new tokens .+   +  addTokens :: Position+            -> [String]+            -> [Token]              -> [Token]                          addTokens p ss ts = foldr (addToken p) ts ss-  -  -- | Insert a new symbol token at the begninning of a list of tokens.-  addToken :: Position -- ^ Position of the new token.-           -> String   -- ^ Symbol in the new token.-           -> [Token]  -- ^ The rest of the tokens. These will have their-                       --   positions updated to make room for the new token.",  "         -> [Token]++  addToken :: Position +           -> String  +           -> [Token]+                                 -> [Token]   addToken p s ts = sToken p s : map (incrGlobal p (length s)) ts-  -  -- | Get the position immediately to the right of the given token.-  --   If no token is given, gets the first position in the file.-  -- afterPrev :: Maybe Token -> Position+   afterPrev = maybe (Pn 0 1 1) nextPos   -  -- | Get the position immediately to the right of the given token.-  -- nextPos :: Token -> Position    nextPos t = Pn (g + s) l (c + s + 1)      where Pn g l c = position t           s = tokenLength t   -  -- | Add to the global and column positions of a token.-  --   The column position is only changed if the token is on-  --   the same line as the given position.- -- incrGlobal :: Position -- ^ If the token is on the same line- --                        --   as this position, update the column position.- --            -> Int      -- ^ Number of characters to add to the position.- --            -> Token -> Token   incrGlobal (Pn _ l0 _) i (PT (Pn g l c) t) =     if l /= l0 then PT (Pn (g + i) l c) t                else PT (Pn (g + i) l (c + i)) t   incrGlobal _ _ p = error $ "cannot add token at " ++ show p   -  -- | Create a symbol token.-  -  reservedwords = $(lift $ zip resws ([1..] :: [Int]))+    +  reservedwords = $(resnum)      sToken :: Position -> String -> Token   sToken p s = PT p (TS s i)     where i = maybe (error $ "not a reserved word: " ++ show s) id (lookup s reservedwords)-  --  where-  --    i = case s of-  --      [ "      " ++ show s ++ " -> " ++ show i-  --        | (s, i) <- -  --      ] ++-  --      _ -> error $ "not a reserved word: " ++ show s-  -  -- | Get the position of a token.- -- position :: Token -> Position+   position t = case t of     PT p _ -> p     Err p -> p   -  -- | Get the line number of a token.- -- line :: Token -> Int   line t = case position t of Pn _ l _ -> l   -  -- | Get the column number of a token.- -- column :: Token -> Int   column t = case position t of Pn _ _ c -> c   -  -- | Check if a token is one of the given symbols.- -- isTokenIn :: [String] -> Token -> Bool   isTokenIn ts t = case t of     PT _ (TS r _) | elem r ts -> True     _ -> False-  -  -- | Check if a word is a layout start token.- -- isLayout :: Token -> Bool+   isLayout = isTokenIn layoutWords   -  -- | Check if a token is a layout stop token.-  -- isStop :: Token -> Bool   isStop = isTokenIn layoutStopWords   -  -- | Check if a token is the layout open token.- -- isLayoutOpen :: Token -> Bool   isLayoutOpen = isTokenIn [layoutOpen]   -  -- | Check if a token is the layout close token.- -- isLayoutClose :: Token -> Bool   isLayoutClose = isTokenIn [layoutClose]   -  -- | Get the number of characters in the token.- -- tokenLength :: Token -> Int   tokenLength t = length $ $(varE $ mkName "prToken") t+   |]-  -  where-   resws = sort (reservedWords cf ++ symbols cf)+  where resnum = lift $ zip resws ([1..] :: [Int])+   
Language/LBNF/Compiletime.hs view
@@ -1,7 +1,10 @@ {-#LANGUAGE TemplateHaskell#-} {-# OPTIONS_GHC -fno-warn-missing-fields #-}+-- | Contains things needed by BNFC-meta language definitions and+-- by the code generated from those. Typical users don't need to browse this +-- module. module Language.LBNF.Compiletime(-  -- * Happy and Alex runtimes+  -- * Happy and Alex    HappyStk(..)   , utf8Encode   , Posn(Pn)@@ -11,7 +14,8 @@   , listArray   , (!)   , Array  -  -- * Pretty printing runtimes++  -- * Pretty printing    , printTree   , doc   , concatD@@ -19,13 +23,17 @@   , prPrec   , PrintPlain(..) -  -- * Quasi quoting runtimes+  -- * Quasi quoting    , parseToQuoter, parseToMonQuoter   , ParseMonad(..)   , errq   , Q   , BNFC_QQType(..), appEPAll, appEPAllL, fromString, fromLit, fromToken, fromPositionToken   , Lift (..)+  , LocType+  , Literal(..)+  , IsChar(..)+  -- ** Helper functions for defining Anti-quotation   , printAq   , stringAq   
Language/LBNF/Runtime.hs view
@@ -1,5 +1,6 @@ {-#LANGUAGE TemplateHaskell #-}-+-- | Contains things that are typically needed in modules that use +-- languages defined using BNFC-meta. module Language.LBNF.Runtime(   -- * Happy and Alex runtimes   -- ord@@ -7,21 +8,19 @@   -- , (!)   -- , Array   -- , parseToQuoter+     ParseMonad(..)   , err      -- * Pretty printing runtimes   , printTree+  , Doc   , doc   , concatD   , Print(..)   , prPrec   , PrintPlain(..) -  -- * Quasi quoting runtimes-  --, Q-  --, BNFC_QQType, appEPAll, appEPAllL, fromLit, fromString, fromToken-  --, Lift (..)   ) where  @@ -38,6 +37,7 @@ -- Lexing, Parsing ------------------ +-- * The result of a parse. data ParseMonad a = Ok a | Bad String   deriving (Read, Show, Eq, Ord) @@ -55,6 +55,8 @@ --  mplus (Bad _) y = y --  mplus x       _ = x +-- * An eliminator for a parse result. Takes a function that recovers from any +-- parse errors. Typical usage: @err error (pCategory (tokens s)) :: Category@  err :: (String -> a) -> ParseMonad a -> a err e b = case b of      Bad s -> e s@@ -65,6 +67,7 @@ -- PRINTING ----------- +-- * Overloaded pretty-printer printTree :: Print a => a -> String printTree = render . prt 0 
− examples/ghc6/jll/JavaletteLight.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}--module JavaletteLight where--import Language.LBNF(lbnf, dumpCode, bnfc)-import Language.LBNF.Compiletime-import qualified Language.LBNF.Grammar----bnfc [$lbnf|---- This is a new pragma. The rest of the grammar is original JL.-antiquote "[" ":" ":]" ;---- Javalette Light: a simple subset of C, covering--- programs with a single zero-argument function.--- example: koe.jll--- ordinary rules--Fun.      Prog     ::= Typ Ident "(" ")" "{" [Stm] "}" ;--SDecl.    Stm      ::= Typ Ident ";"  ;-SAss.     Stm      ::= Ident "=" Expr ";"  ;-SIncr.    Stm      ::= Ident "++" ";"  ;-SWhile.   Stm      ::= "while" "(" Expr ")" "{" [Stm] "}" ;--ELt.      Expr0     ::= Expr1 "<" Expr1 ;-EPlus.    Expr1     ::= Expr1 "+" Expr2 ;-ETimes.   Expr2     ::= Expr2 "*" Expr3 ;-EVar.     Expr3     ::= Ident ;-EInt.     Expr3     ::= Integer ;-EDouble.  Expr3     ::= Double ;--[].       [Stm]    ::= ;-(:).      [Stm]    ::= Stm [Stm] ;---- coercions--_.        Stm      ::= Stm ";" ;--_.  Expr      ::= Expr0 ;-_.  Expr0     ::= Expr1 ;-_.  Expr1     ::= Expr2 ;-_.  Expr2     ::= Expr3 ;-_.  Expr3     ::= "(" Expr ")" ;--TInt.     Typ  ::= "int" ;-TDouble.  Typ  ::= "double" ;---- pragmas--comment "/*" "*/" ;-comment "//" ;--entrypoints Prog, Stm, Expr ;-  |]--
− examples/ghc6/jll/UseJll.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE QuasiQuotes #-}-import JavaletteLight-import Language.LBNF.Runtime -- overloaded pretty-printing function-import Prelude hiding (exp)--{- This Javalette Light program is parsed at compile time, -and replaced by it's abstract syntax representation.-The 'holes' in square brackets are anti-quoted Haskell -expression. --The QuasiQuoter prog is generated from the grammar in JavaletteLight.hs-(it corresponds to the category Prog).--}---prg x v e = [$prog|-int f() {- int a; - [:SWhile (EInt 10 :: Expr) [x]:]- int a;- int [:v:];- int tmp;- while (n < [Expr:e:]) {-   n = n + 1;-   tmp = a + b;-   a = b;-   b = tmp;- }-}-|] --st v = [$stm| [:v:] = 1; |]-pr = prg (st (Ident "n")) (Ident "n") [$expr|n|]-main = putStr $ printTree pr---eval vs = eval' where-  eval' [$expr| [:a:] < [:b:]  |] = if eval' a < eval' b then 1 else 0-  eval' [$expr| [:a:] + [:b:]  |] = eval' a + eval' b-  eval' [$expr| [:a:] * [:b:]  |] = eval' a * eval' b-  eval' [$expr| [Integer: n:]  |] = fromInteger n-  eval' [$expr| [Double:  n:]  |] = n-  eval' [$expr| [Ident:   v:]  |] = varval v-  varval v = maybe (error $ "undefined variable" ++ printTree v) id $ flip lookup vs v--h = eval [(Ident "a",5)] [$expr|a+2+3*4|]
− examples/ghc7/jll/JavaletteLight.hs
@@ -1,60 +0,0 @@-{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}--module JavaletteLight where--import Language.LBNF(lbnf, dumpCode, bnfc)-import Language.LBNF.Compiletime-import qualified Language.LBNF.Grammar-----bnfc [lbnf|---- This is a new pragma. The rest of the grammar is original JL.-antiquote "[" ":" ":]" ;---- Javalette Light: a simple subset of C, covering--- programs with a single zero-argument function.--- example: koe.jll--- ordinary rules--Fun.      Prog     ::= Typ Ident "(" ")" "{" [Stm] "}" ;--SDecl.    Stm      ::= Typ Ident ";"  ;-SAss.     Stm      ::= Ident "=" Expr ";"  ;-SIncr.    Stm      ::= Ident "++" ";"  ;-SWhile.   Stm      ::= "while" "(" Expr ")" "{" [Stm] "}" ;--ELt.      Expr0     ::= Expr1 "<" Expr1 ;-EPlus.    Expr1     ::= Expr1 "+" Expr2 ;-ETimes.   Expr2     ::= Expr2 "*" Expr3 ;-EVar.     Expr3     ::= Ident ;-EInt.     Expr3     ::= Integer ;-EDouble.  Expr3     ::= Double ;--[].       [Stm]    ::= ;-(:).      [Stm]    ::= Stm [Stm] ;---- coercions--_.        Stm      ::= Stm ";" ;--_.  Expr      ::= Expr0 ;-_.  Expr0     ::= Expr1 ;-_.  Expr1     ::= Expr2 ;-_.  Expr2     ::= Expr3 ;-_.  Expr3     ::= "(" Expr ")" ;--TInt.     Typ  ::= "int" ;-TDouble.  Typ  ::= "double" ;---- pragmas--comment "/*" "*/" ;-comment "//" ;--entrypoints Prog, Stm, Expr ;-  |]--
− examples/ghc7/jll/UseJll.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE QuasiQuotes #-}-import JavaletteLight-import Language.LBNF.Runtime -- overloaded pretty-printing function-import Prelude hiding (exp)--{- This Javalette Light program is parsed at compile time, -and replaced by it's abstract syntax representation.-The 'holes' in square brackets are anti-quoted Haskell -expression. --The QuasiQuoter prog is generated from the grammar in JavaletteLight.hs-(it corresponds to the category Prog).--}---prg x v e = [prog|-int f() {- int a; - [:SWhile (EInt 10 :: Expr) [x]:]- int a;- int [:v:];- int tmp;- while (n < [Expr:e:]) {-   n = n + 1;-   tmp = a + b;-   a = b;-   b = tmp;- }-}-|] --st v = [stm| [:v:] = 1; |]-pr = prg (st (Ident "n")) (Ident "n") [expr|n|]-main = putStr $ printTree pr---eval vs = eval' where-  varval v = maybe (error $ "undefined variable" ++ printTree v) id $ flip lookup vs v-  eval' [expr| [:a:] < [:b:]  |] = if eval' a < eval' b then 1 else 0-  eval' [expr| [:a:] + [:b:]  |] = eval' a + eval' b-  eval' [expr| [:a:] * [:b:]  |] = eval' a * eval' b-  eval' [expr| [Integer: n:]  |] = fromInteger n-  eval' [expr| [Double:  n:]  |] = n-  eval' [expr| [Ident:   v:]  |] = varval v--h = eval [(Ident "a",5)] [expr|a+2+3*4|]
+ examples/jll/JavaletteLight.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}++module JavaletteLight where++import Language.LBNF.Compiletime++import Language.LBNF(lbnf, dumpCode, bnfc)+bnfc [lbnf|++Fun.      Prog     ::= Typ Ident "(" ")" "{" [Stm] "}" ;++SDecl.    Stm      ::= Typ Ident ";"  ;+SAss.     Stm      ::= Ident "=" Expr ";"  ;+SIncr.    Stm      ::= Ident "++" ";"  ;+SWhile.   Stm      ::= "while" "(" Expr ")" "{" [Stm] "}" ;+SFunApp.  Stm      ::= Ident "(" [Expr] ")" ";" ;+_.        Stm      ::= Stm ";" ;++ELt.      Expr0     ::= Expr1 "<" Expr1 ;+EPlus.    Expr1     ::= Expr1 "+" Expr2 ;+ETimes.   Expr2     ::= Expr2 "*" Expr3 ;+EVar.     Expr3     ::= Ident ;+EInt.     Expr3     ::= Integer ;+EDouble.  Expr3     ::= Double ;+$.        Expr3     ::= "$" Ident;+[].       [Stm]    ::= ;+(:).      [Stm]    ::= Stm [Stm] ;++separator Expr "," ;+++++_.  Expr      ::= Expr0 ;+_.  Expr0     ::= Expr1 ;+_.  Expr1     ::= Expr2 ;+_.  Expr2     ::= Expr3 ;+_.  Expr3     ::= "(" Expr ")" ;++TInt.     Typ  ::= "int" ;+TDouble.  Typ  ::= "double" ;+|]++
+ examples/jll/UseJll.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE QuasiQuotes #-}+import JavaletteLight+import Language.LBNF.Runtime -- overloaded pretty-printing function+import Prelude hiding (exp)++{- This Javalette Light program is parsed at compile time, +and replaced by it's abstract syntax representation.+The 'holes' in square brackets are anti-quoted Haskell +expression. ++The QuasiQuoter prog is generated from the grammar in JavaletteLight.hs+(it corresponds to the category Prog).+-}++printing' :: Expr -> Prog+printing' e = [prog| +   int main (  ) { +     print ( $e ) ; +   } +   |]++printing e = Fun TInt (Ident "main") [SFunApp (Ident "print") [e]]++print10 :: Prog+print10 = printing' [expr| 5 + 5 |]+
+ examples/typesafe/Example.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE QuasiQuotes #-}+import Typesafe+import Language.LBNF.Runtime(printTree) -- overloaded pretty-printing function+import Prelude hiding (exp)+++-- All variables are meta-variables. +-- Variables must be declared in the function parameters+-- Boolean and numeric variables are type checked by Haskell.+prg n tmp x = [prog|+f() {+  n = 0;+  x := True ;+  tmp = 0;+  while ( tmp < 10 ) {+    tmp++;+    n = n * n;+  }+}+|]++main = putStr $ printTree $ fresh vars prg where+  vars = (map return ['a'..'z']) ++ ['v' : show n  |n <- [0..]]++++class Variable a where+  fromString :: String -> a++instance Variable NVar where+  fromString = NVar . Ident++instance Variable BVar where+  fromString = BVar . Ident+++class Fresh a where+  fresh :: [String] -> a -> Prog+  +instance Fresh Prog where+  fresh _ e = e+  +instance (Variable a, Fresh b) => Fresh  (a -> b) where+  fresh (s:ss) g = fresh ss $ g (fromString s)++
+ examples/typesafe/Typesafe.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+++module Typesafe where++import Language.LBNF+  ++bnfc [lbnf|++Fun.      Prog     ::=  Ident "(" ")" "{" [Stm] "}" ;++SBAss.    Stm      ::= BVar ":=" BExp ";"  ;+SAss.     Stm      ::= NVar "=" Exp ";"  ;++SIncr.    Stm      ::= NVar "++" ";"  ;+SWhile.   Stm      ::= "while" "(" BExp ")" "{" [Stm] "}" ;+SBlock.   Stm      ::= "{" [Stm] "}" ;+++ +EAnd.     BExp0     ::= BExp "&" BExp1 ;+ENeg.     BExp1     ::= "!" BExp1 ;+ELt.      BExp1     ::= Exp "<" Exp ;+ETruth.   BExp1     ::= Truth ;+EBVar.    BExp1     ::= BVar ;++EPlus.    Exp0     ::= Exp0 "+" Exp1 ;+ETimes.   Exp1     ::= Exp1 "*" Exp2 ;+EInt.     Exp2     ::= Integer ;+EVar.     Exp2     ::= NVar ;+++TTrue.    Truth    ::= "True" ;+TFalse.   Truth    ::= "False" ;++[].       [Stm]    ::= ;+(:).      [Stm]    ::= Stm [Stm] ;++internal BVar. BVar ::= Ident ;+$ .            BVar ::= Ident ;++internal NVar. NVar ::= Ident ;+$.             NVar ::= Ident ;++++-- coercions++_.        Stm      ::= Stm ";" ;++_.  Exp      ::= Exp0 ;+_.  Exp0     ::= Exp1 ;+_.  Exp1     ::= Exp2 ;+_.  Exp2     ::= "[" Exp "]" ;+++_.  BExp      ::= BExp0 ;+_.  BExp0     ::= BExp1 ;+_.  BExp1     ::= "(" BExp ")" ;++++comment "/*" "*/" ;+comment "//" ;++entrypoints Prog, Stm, Exp, BExp ;+  |]++ ++