packages feed

apple-0.3.0.0: src/Parser.y

{
    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE OverloadedStrings #-}
    module Parser ( parseWithMaxCtx
                  , ParseE (..)
                  ) where

import Control.Exception (Exception)
import Control.Monad.Except (ExceptT, runExceptT, throwError)
import Control.Monad.Trans.Class (lift)
import Control.DeepSeq (NFData)
import Data.Bifunctor (first)
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Char8 as ASCII
import Data.Functor (void)
import qualified Data.Text as T
import GHC.Generics (Generic)
import qualified Nm
import Nm hiding (loc)
import A
import L
import Prettyprinter (Pretty (pretty), (<+>))

}

%name parseE E
%tokentype { Tok }
%error { parseErr }
%monad { Parse } { (>>=) } { pure }
%lexer { lift alexMonadScan >>= } { EOF _ }

%token

    lbrace { TokSym $$ LBrace }
    rbrace { TokSym $$ RBrace }
    lsqbracket { TokSym $$ LSqBracket }
    rsqbracket { TokSym $$ RSqBracket }
    lparen { TokSym $$ LParen }
    rparen { TokSym $$ RParen }
    dot { TokSym $$ Dot }
    bind { TokSym $$ Bind }
    lbind { TokSym $$ LBind }
    polybind { TokSym $$ PolyBind }
    semicolon { TokSym $$ Semicolon }
    comma { TokSym $$ Comma }
    therefore { TokSym $$ Therefore }
    underscore { TokSym $$ Underscore }
    question { TokSym $$ QuestionMark }
    condSplit { TokSym $$ CondSplit }
    coronis { TokSym $$ Cor }
    larr { TokSym $$ ArrL }
    rarr { TokSym $$ ArrR }
    colon { TokSym $$ Colon }
    lrank { TokSym $$ LRank }
    compose { TokSym $$ Compose }
    sig { TokSym $$ Sig }
    tsig { TokSym $$ TSig }
    arrow { TokSym $$ L.Arrow }
    di { TokSym $$ DIS }
    succ { TokSym $$ L.Succ }
    conv { TokSym $$ L.Conv }
    last { TokSym $$ L.Last }
    lastM { TokSym $$ L.LastM }
    head { TokSym $$ L.Head }
    headM { TokSym $$ L.HeadM }
    tail { TokSym $$ L.Tail }
    tailM { TokSym $$ L.TailM }
    init { TokSym $$ L.Init }
    initM { TokSym $$ L.InitM }
    do { TokSym $$ Do }
    tensor { TokSym $$ Tensor }
    geq { TokSym $$ Geq }
    gt { TokSym $$ L.Gt }
    leq { TokSym $$ Leq }
    lt { TokSym $$ L.Lt }
    eq { TokSym $$ L.Eq }
    neq { TokSym $$ L.Neq }
    and { TokSym $$ L.And }
    or { TokSym $$ L.Or }
    xor { TokSym $$ L.Xor }
    not { TokSym $$ Not }
    tilde { TokSym $$ Tilde }
    pp { TokSym $$ PlusPlus }
    rot { TokSym $$ Rotate }
    sr { TokSym $$ L.Sr }
    sl { TokSym $$ L.Sl }
    inv { TokSym $$ Inv }

    plus { TokSym $$ L.Plus }
    minus { TokSym $$ L.Minus }
    times { TokSym $$ L.Times }
    percent { TokSym $$ Percent }
    idiv { TokSym $$ L.IDiv }
    caret { TokSym $$ Caret }
    max { TokSym $$ MaxS }
    min { TokSym $$ MinS }
    pow { TokSym $$ Pow }
    at { $$@(TokSym _ Access{}) }
    consS { TokSym $$ L.Cons }
    snoc { TokSym $$ L.Snoc }
    trans { TokSym $$ Transp }
    bcyc { TokSym $$ L.Cyc }
    iat { TokSym $$ L.A1 }
    mod { TokSym $$ L.Mod }
    atDot { TokSym $$ AtDot }
    -- weier { TokSym $$ Weier }
    ice { TokSym $$ Ice }
    para { TokSym $$ Para }
    eye { TokSym $$ L.Eye }

    folds { TokSym $$ L.FoldS }
    fold { TokSym $$ L.Fold }
    foldl { TokSym $$ L.Foldl }
    foldA { TokSym $$ L.FoldA }
    quot { TokSym $$ Quot }
    zip { TokSym $$ L.Zip }
    flat { TokSym $$ L.B }
    addd { TokSym $$ Sharp }

    lam { TokSym $$ L.Lam }

    name { TokName _ $$ }

    intLit { $$@(TokInt _ _) }
    floatLit { $$@(TokFloat _ _) }
    six { $$@(TokIx _ _) }

    x { TokResVar $$ VarX }
    y { TokResVar $$ VarY }

    frange { TokB $$ BuiltinFRange }
    iota { TokB $$ BuiltinIota }
    floor { TokB $$ BuiltinFloor }
    e { TokB $$ BuiltinE }
    i { TokB $$ BuiltinI }
    f { TokB $$ BuiltinF }
    t { TokB $$ BuiltinT }
    tt { TokB $$ BuiltinTrue }
    ff { TokB $$ BuiltinFalse }
    sqrt { TokB $$ BuiltinSqrt }
    pi { TokB $$ BuiltinPi }
    gen { TokB $$ BuiltinGen }
    log { TokSym $$ SymLog }
    re { TokB $$ BuiltinRep }
    diag { TokB $$ BuiltinD }
    nil { TokB $$ BuiltinNil }
    cons { TokB $$ BuiltinCons }
    arr { TokB $$ BuiltinArr }
    ixTimes { TokSym $$ IxTimes }
    vec { TokB $$ BuiltinVec }
    matrix { TokB $$ BuiltinM }
    int { TokB $$ BuiltinInt }
    bool { TokB $$ BuiltinBool }
    float { TokB $$ BuiltinFloat }
    scanS { TokB $$ BuiltinScanS }
    scan { TokB $$ BuiltinScan }
    mul { TokB $$ BuiltinMMul }
    vmul { TokB $$ BuiltinVMul }
    r { TokB $$ BuiltinR }
    sin { TokB $$ BuiltinSin }
    cos { TokB $$ BuiltinCos }
    tan { TokB $$ BuiltinTan }
    cyc { TokB $$ BuiltinCyc }
    even { TokB $$ BuiltinEven }
    odd { TokB $$ BuiltinOdd }
    abs { TokB $$ BuiltinAbs }

%left paren
%nonassoc leq geq gt lt neq eq

%%

many(p)
    : many(p) p { $2 : $1 }
    | { [] }

sepBy(p,q)
    : sepBy(p,q) q p { $3 : $1 }
    | p { [$1] }

tupled(p,q)
    : tupled(p,q) q p { $3 : $1 }
    | p q p { $3 : [$1] }

braces(p)
    : lbrace p rbrace { $2 }

brackets(p)
    : lsqbracket p rsqbracket { $2 }

parens(p)
    : lparen p rparen { $2 }

flipSeq(p,q)
    : p q { $1 }

I :: { I AlexPosn }
  : intLit { Ix (loc $1) (fromInteger $ int $1) }
  | name { IVar (Nm.loc $1) $1 }
  | I plus I { StaPlus $2 $1 $3 }

Sh :: { Sh AlexPosn }
   : nil { Nil }
   | I cons Sh { A.Cons $1 $3 }
   | name { SVar $1 }
   | parens(Sh) { $1 }
   | parens(sepBy(I, ixTimes)) { foldl (flip A.Cons) Nil $1 }

T :: { T AlexPosn }
  : arr Sh T { Arr $2 $3 }
  | vec I T { Arr ($2 `A.Cons` Nil) $3 }
  | matrix six comma six T { Arr ((Ix (loc $2) (six $2)) `A.Cons` (Ix (loc $4) (six $4)) `A.Cons` Nil) $5 }
  | matrix T {% do {i <- lift $ freshName "i"; j <- lift $ freshName "j"; pure $ Arr (IVar $1 i `A.Cons` IVar $1 j `A.Cons` Nil) $2 } }
  | int { I } | bool { A.B } | float { F }
  | parens(T) { $1 }
  | T arrow T { A.Arrow $1 $3 }

R :: { (Int, Maybe [Int]) }
  : intLit compose lsqbracket sepBy(intLit,comma) rsqbracket { (fromInteger $ int $1, Just (reverse (fmap (fromInteger.int) $4))) }
  | intLit { (fromInteger $ int $1, Nothing) }

-- binary operator
BBin :: { E AlexPosn }
     : plus { Builtin $1 A.Plus } | minus { Builtin $1 A.Minus }
     | times { Builtin $1 A.Times } | percent { Builtin $1 Div }
     | idiv { Builtin $1 A.IDiv }
     | caret { Builtin $1 IntExp }
     | max { Builtin $1 Max } | min { Builtin $1 Min }
     | scan { Builtin $1 Scan }
     | quot { Builtin $1 Map }
     | di intLit { Builtin $1 (DI (fromInteger $ int $2)) }
     | conv braces(sepBy(intLit,comma)) { Builtin $1 (A.Conv (reverse (fmap (fromInteger.int) $2))) }
     -- FIXME: not necessarily binary operator!!
     | lrank sepBy(R,comma) rbrace { Builtin $1 (Rank (reverse $2)) }
     | succ { Builtin $1 A.Succ }
     | pow { Builtin $1 Exp }
     | consS { Builtin $1 ConsE }
     | snoc { Builtin $1 A.Snoc }
     | mul { Builtin $1 Mul }
     | vmul { Builtin $1 VMul }
     | geq { Builtin $1 Gte } | gt { Builtin $1 A.Gt }
     | leq { Builtin $1 Lte } | lt { Builtin $1 A.Lt }
     | eq { Builtin $1 A.Eq } | neq { Builtin $1 A.Neq }
     | pp { Builtin $1 CatE }
     | rot { Builtin $1 Rot }
     | fold { Builtin $1 A.Fold }
     | bcyc { Builtin $1 A.Cyc }
     | iat { Builtin $1 A.A1 }
     | mod { Builtin $1 A.Mod }
     | atDot { Builtin $1 IOf }
     | and { Builtin $1 A.And } | or { Builtin $1 A.Or }
     | xor { Builtin $1 A.Xor }
     | ice { Builtin $1 Ices }
     | para { Builtin $1 Filt }
     | sr { Builtin $1 A.Sr } | sl { Builtin $1 A.Sl }
     | therefore { Builtin $1 C }

B :: { (Bnd, (Nm AlexPosn, E AlexPosn)) }
  : name bind E { (L, ($1, $3)) }
  | name lbind E { (LL, ($1, $3)) }
  | name polybind E { (D, ($1, $3)) }

E :: { E AlexPosn }
  : name { Var (Nm.loc $1) $1 }
  | intLit { ILit (loc $1) (int $1) }
  | floatLit { FLit (loc $1) (float $1) }
  | pi { FLit $1 pi }
  | tt { BLit $1 True }
  | ff { BLit $1 False }
  | inv E { EApp $1 (EApp $1 (Builtin $1 Div) (FLit $1 1)) $2 }
  | parens(inv) { EApp $1 (Builtin $1 Div) (FLit $1 1) }
  | parens(BBin) { $1 }
  | lparen E BBin rparen { Parens $1 (EApp $1 $3 $2) }
  | lparen BBin E rparen {% do { n <- lift $ freshName "x" ; pure (A.Lam $1 n (EApp $1 (EApp $1 $2 (Var (Nm.loc n) n)) $3)) } }
  | E BBin E { EApp (eAnn $1) (EApp (eAnn $3) $2 $1) $3 }
  | parens(E) { Parens (eAnn $1) $1 }
  | larr sepBy(E,comma) rarr { ALit $1 (reverse $2) }
  | lparen tupled(E,comma) rparen { Tup $1 (reverse $2) }
  | lam name dot E { A.Lam $1 $2 $4 }
  | lbrace many(flipSeq(B,semicolon)) E rbrace { mkLet $1 (reverse $2) $3 }
  | coronis many(flipSeq(B,semicolon)) E { mkLet $1 (reverse $2) $3 }
  | lsqbracket E rsqbracket { Dfn $1 $2 }
  | frange { Builtin $1 FRange } | iota { Builtin $1 IRange }
  | floor { Builtin $1 Floor } | sqrt { Builtin $1 Sqrt } | log { Builtin $1 Log }
  | underscore { Builtin $1 Neg }
  | gen { Builtin $1 Gen }
  | colon { Builtin $1 Size }
  | i { Builtin $1 ItoF }
  | t { Builtin $1 Dim }
  | E folds E E { EApp (eAnn $1) (EApp (eAnn $1) (EApp $2 (Builtin $2 A.FoldS) $1) $3) $4 }
  | E foldl E E { EApp (eAnn $1) (EApp (eAnn $1) (EApp $2 (Builtin $2 A.Foldl) $1) $3) $4 }
  | E foldA E E { EApp (eAnn $1) (EApp (eAnn $1) (EApp $2 (Builtin $2 A.FoldA) $1) $3) $4 }
  | E scanS E E { EApp (eAnn $1) (EApp (eAnn $1) (EApp $2 (Builtin $2 ScanS) $1) $3) $4 }
  | E zip E E { EApp (eAnn $1) (EApp (eAnn $1) (EApp $2 (Builtin $2 A.Zip) $1) $3) $4 }
  | E do E E { EApp (eAnn $1) (EApp $2 (EApp $2 (Builtin $2 Iter) $1) $3) $4 }
  | E E { EApp (eAnn $1) $1 $2 }
  | x { ResVar $1 X } | y { ResVar $1 Y }
  | f { Builtin $1 Fib }
  | last { Builtin $1 A.Last } | lastM { Builtin $1 A.LastM }
  | head { Builtin $1 A.Head } | headM { Builtin $1 A.HeadM }
  | tail { Builtin $1 A.Tail } | tailM { Builtin $1 A.TailM }
  | init { Builtin $1 A.Init } | initM { Builtin $1 A.InitM }
  | re { Builtin $1 Re }
  | diag { Builtin $1 Di }
  | question E condSplit E condSplit E { Cond $1 $2 $4 $6 }
  | E sig T { Ann $2 $1 $3 }
  | E tsig parens(Sh) {% do{a <- lift$freshName "a"; pure$Ann $2 $1 (Arr $3 (TVar a))} }
  | e { EApp $1 (Builtin $1 Exp) (FLit $1 (exp 1)) }
  | E at { EApp (eAnn $1) (Builtin (loc $2) (TAt (iat $ sym $2))) $1 }
  | parens(at) { Builtin (loc $1) (TAt (iat $ sym $1)) }
  | E E tensor E { EApp (eAnn $1) (EApp (eAnn $4) (EApp (eAnn $2) (Builtin $3 Outer) $2) $1) $4 }
  | trans { Builtin $1 T }
  | r { Builtin $1 R }
  | sin { Builtin $1 Sin }
  | cos { Builtin $1 Cos }
  | tan { Builtin $1 Tan }
  | cyc { Builtin $1 A.Cyc }
  | tilde { Builtin $1 RevE }
  | odd { Builtin $1 Odd }
  | even { Builtin $1 Even }
  | abs { Builtin $1 Abs }
  | flat { Builtin $1 Flat }
  | addd { Builtin $1 AddDim }
  | not { Builtin $1 N }
  | eye { Builtin $1 A.Eye }

{

parseErr :: Tok -> Parse a
parseErr = throwError . Unexpected

data Bnd = L | LL | D

mkLet :: a -> [(Bnd, (Nm a, E a))] -> E a -> E a
mkLet _ [] e            = e
mkLet l ((L, b):bs) e   = Let l b (mkLet l bs e)
mkLet l ((LL, b):bs) e  = LLet l b (mkLet l bs e)
mkLet l ((D, b):bs) e   = Def l b (mkLet l bs e)

data ParseE = Unexpected Tok
            | LexErr String
            deriving (Generic)

instance Pretty ParseE where
    pretty (Unexpected tok)  = pretty (loc tok) <+> "Unexpected" <+> pretty tok
    pretty (LexErr str)      = pretty (T.pack str)

instance Show ParseE where
    show = show . pretty

instance Exception ParseE

instance NFData ParseE where

type Parse = ExceptT ParseE Alex

parseAll :: AlexUserState -> BSL.ByteString -> Either ParseE (AlexUserState, E AlexPosn)
parseAll = runParseSt parseE

parseWithMaxCtx :: AlexUserState -> BSL.ByteString -> Either ParseE (Int, E AlexPosn)
parseWithMaxCtx st b = fmap (first fst3) (parseAll st b) where fst3 (x, _, _) = x

runParseSt :: Parse a -> AlexUserState -> BSL.ByteString -> Either ParseE (AlexUserState, a)
runParseSt parser u bs = liftErr $ withAlexSt bs u (runExceptT parser)

liftErr :: Either String (b, Either ParseE c) -> Either ParseE (b, c)
liftErr (Left err)            = Left (LexErr err)
liftErr (Right (_, Left err)) = Left err
liftErr (Right (i, Right x))  = Right (i, x)

}