packages feed

tempus-0.1.0: Tempus/Parser.y

{
{-# OPTIONS_GHC -w #-}
module Tempus.Parser (
    parseProgram,
    parseDecl,
    parseType,
    parseExpr
) where

import Prelude hiding (lex)

import Tempus.Loc
import Tempus.Lexer
import Tempus.Syntax

}

%name pparseProgram prog
%name pparseDecl decl
%name pparseType type
%name pparseExpr expr

%tokentype { Loc Token }
%monad { Parser }
%lexer { lex } { Loc _ EOF }

%error { parseError }
%token
    var             { Loc _ (Variable _) }
    natlit          { Loc _ (NatLit _) }
    '='             { Loc $$ Equals }
    '->'            { Loc $$ ArrowRight }
    '+'             { Loc $$ Plus }
    '*'             { Loc $$ Times }
    '('             { Loc $$ ParenOpen }
    ')'             { Loc $$ ParenClose }
    '0'             { Loc $$ Zero }
    '1'             { Loc $$ One }
    mu              { Loc $$ Mu }
    nu              { Loc $$ Nu }
    '.'             { Loc $$ Dot }
    ','             { Loc $$ Comma }
    lam             { Loc $$ Lambda }
    '['             { Loc $$ SquareOpen }
    ']'             { Loc $$ SquareClose }
    langle          { Loc $$ AngleOpen }
    rangle          { Loc $$ AngleClose }
    '<*>'           { Loc $$ CircledAsterisk }
    '<.>'           { Loc $$ CircledDot }
    '?'             { Loc $$ QuestionMark }
    'behavior'      { Loc $$ KWBehavior }
    'case'          { Loc $$ KWCase }
    'const'         { Loc $$ KWConst }
    'event'         { Loc $$ KWEvent }
    'expand'        { Loc $$ KWExpand }
    'first'         { Loc $$ KWFirst }
    'fold'          { Loc $$ KWFold }
    'left'          { Loc $$ KWLeft }
    'positive'      { Loc $$ KWPositive }
    'never'         { Loc $$ KWNever }
    'pack'          { Loc $$ KWPack }
    'race'          { Loc $$ KWRace }
    'reflect'       { Loc $$ KWReflect }
    'right'         { Loc $$ KWRight }
    'second'        { Loc $$ KWSecond }
    'ultraswitch'   { Loc $$ KWUltraswitch }
    'type'          { Loc $$ KWType }
    'ultrajump'     { Loc $$ KWUltrajump }
    'unfold'        { Loc $$ KWUnfold }
    'unpack'        { Loc $$ KWUnpack }
    'value'         { Loc $$ KWValue }

%%

prog        :: { Program }
prog        : decls                             { reverse $1 }

decls       :: { [Decl] }
decls       :                                   { [] }
            | decls decl                        { $2 : $1 }

decl        :: { Decl }
decl        : typedecl                          { $1 }
            | valdecl                           { $1 }

typedecl    :: { Decl }
typedecl    : 'type' var formalargs '=' type    { DeclType $1 (var $2) (reverse $3) $5 }

formalargs  :: { [Var] }
formalargs  :                                   { [] }
            | formalargs var                    { var $2 : $1 }

valdecl     :: { Decl }
valdecl     : 'value' var '=' expr              { DeclVal $1 (var $2) $4 }

type        :: { Type }
type        : type0                             { $1 }

type0       :: { Type }
type0       : mutype                            { TyMu $1 }
            | nutype                            { TyNu $1 }
            | type1                             { $1 }

type1       :: { Type }
type1       : type2 '->' type1                  { TyFun $1 $3 }
            | type2                             { $1 }

type2       :: { Type }
type2       : type3 '+' type2                   { TyPlus $1 $3 }
            | type3                             { $1 }

type3       :: { Type }
type3       : type4 '*' type3                   { TyPair $1 $3 }
            | type4                             { $1 }

type4       :: { Type }
type4       : var typeargs                      { TyApp (var $1) $2 }
            | 'behavior' type5                  { TyBehav $2 }
            | 'event' type5                     { TyEvent $2 }
            | type5                             { $1 }

type5       :: { Type }
type5       : var                               { TyApp (var $1) [] }
            | 'positive'                        { TyNat }
            | '(' type0 ')'                     { $2 }
            | '0'                               { TyZero }
            | '1'                               { TyUnit }

typeargs    :: { [Type] }
typeargs    : type5                             { [$1] }
            | typeargs type5                    { $2 : $1 }

mutype      :: { MuType }
mutype      : mu var '.' type0                  { MuType (var $2) $4 }

nutype      :: { NuType }
nutype      : nu var '.' type0                  { NuType (var $2) $4 }

expr        :: { Expr }
expr        : expr0                             { $1 }

expr0       :: { Expr }
expr0       : expr1 ',' expr0                   { ExPair $1 $3 }
            | expr1                             { $1 }

expr1       :: { Expr }
expr1       : lam var '.' expr1                 { ExLam (var $2) $4 }
            | expr2                             { $1 }

expr2       :: { Expr }
expr2       : expr2 '<*>' expr3                 { ExLiftAppB $1 $3 }
            | expr2 '<.>' expr3                 { ExLiftAppE $1 $3 }
            | expr3                             { $1 }

expr3       :: { Expr }
expr3       : expr3 expr4                       { ExApp $1 $2 }
            | 'const' expr4                     { ExConst $2 }
            | 'behavior' expr4                  { ExBehav $2 }
            | 'event' expr4 expr4               { ExEvent $2 $3 }
            | foldvals '[' type ']' expr4       { $1 $3 $5 }
            | expr4                             { $1 }

expr4       :: { Expr }
expr4       : var                               { ExVar $ var $1 }
            | '1'                               { ExNatLit 1 }
            | natlit                            { ExNatLit $ nat $1 }
            | '(' expr0 ')'                     { $2 }
            | '?'                               { ExNull }
            | langle rangle                     { ExUnit }
            | '(' ')'                           { ExUnit }
            | packvals '[' type ']'             { $1 $3 }
            | baseval                           { $1 }

foldvals    :: { Type -> Expr -> Expr }
foldvals    : 'fold'                            { ExFold }
            | 'unfold'                          { ExUnfold }

packvals    :: { Type -> Expr }
packvals    : 'pack'                            { ExPack }
            | 'unpack'                          { ExUnpack }

baseval     :: { Expr }
baseval     : 'left'                            { ExLeft }
            | 'right'                           { ExRight }
            | 'case'                            { ExCase }
            | 'first'                           { ExFst }
            | 'second'                          { ExSnd }
            | 'expand'                          { ExExpand }
            | 'never'                           { ExNever }
            | 'race'                            { ExRace }
            | 'reflect'                         { ExReflect }
            | 'ultraswitch'                     { ExUSwitch }
            | 'ultrajump'                       { ExUJump }


{

-- | Parses a complete Tempus program.
parseProgram :: String -> ParseResult Program
parseProgram = initParser pparseProgram

-- | Parses a single Tempus type or value declaration.
parseDecl :: String -> ParseResult Decl
parseDecl = initParser pparseDecl

-- | Parses a Tempus type expression.
parseType :: String -> ParseResult Type
parseType = initParser pparseType

-- | Parses a Tempus expression.
parseExpr :: String -> ParseResult Expr
parseExpr = initParser pparseExpr


var :: Loc Token -> Var
var (Loc _ (Variable v)) = Var v
var _ = error "internal parser error: unexpected token in var"

nat :: Loc Token -> Integer
nat (Loc _ (NatLit i)) = i
nat _ = error "internal parser error: unexpected token in nat"

parseError :: Loc Token -> Parser a
parseError (Loc loc tok) = fail $ "error parsing token `" ++ showToken tok ++ "' at " ++ show loc

}