packages feed

MiniAgda-0.2025.7.23: src/Parser.y

{
{-# LANGUAGE BangPatterns #-}
module Parser (parse) where

import qualified Lexer as T
import qualified Concrete as C

import Abstract (Decoration(..),Dec,defaultDec,Override(..))
import Polarity (Pol(..))
import qualified Abstract as A
import qualified Polarity as A
import Concrete (Name,patApp)
}

%name parse
%tokentype { T.Token }
%error { parseError }

%token

id      { T.Id $$ _ }
qualid  { T.QualId $$ _ }
number  { T.Number $$ _ }
data    { T.Data _ }
codata  { T.CoData _ }
record  { T.Record _ }
sized   { T.Sized _ }
fields  { T.Fields _ }
mutual  { T.Mutual _ }
fun     { T.Fun _ }
cofun   { T.CoFun _ }
pattern { T.Pattern _ }
case    { T.Case _ }
def     { T.Def _ }
let     { T.Let _ }
in      { T.In _ }
eval    { T.Eval _ }
fail    { T.Fail _ }
check   { T.Check _ }
trustme { T.TrustMe _ }
impredicative { T.Impredicative _ }
type    { T.Type _ }
set     { T.Set _ }
coset   { T.CoSet _ }
size    { T.Size _ }
infty   { T.Infty _ }
succ    { T.Succ _ }
max     { T.Max _ }
'<|'    { T.LTri _ }
'|>'    { T.RTri _ }
'<'     { T.AngleOpen _ }
'>'     { T.AngleClose _ }
'{'     { T.BrOpen _ }
'}'     { T.BrClose _ }
'['     { T.BracketOpen _ }
']'     { T.BracketClose _ }
'('     { T.PrOpen _ }
')'     { T.PrClose _ }
'|'     { T.Bar _ }
','     { T.Comma _ }
';'     { T.Sem _ }
':'     { T.Col _ }
'.'     { T.Dot _ }
'->'    { T.Arrow _ }
'<='    { T.Leq _ }
'='     { T.Eq _ }
'++'    { T.PlusPlus _ }
'+'     { T.Plus _ }
'-'     { T.Minus _ }
'/'     { T.Slash _ } -- UNUSED
'*'     { T.Times _ } -- UNUSED
'^'     { T.Hat _ }
'&'     { T.Amp _ }
'\\'    { T.Lam _ }
'_'     { T.Underscore _ }

%%

TopLevel :: { [C.Declaration] }
TopLevel : Declarations { reverse $1}


Declarations :: { [C.Declaration] }
Declarations : {- empty -} { [] }
             | Declarations Declaration { $2 : $1 }

Declaration :: { C.Declaration }
Declaration : Data                      { $1 }
           | CoData                     { $1 }
           | SizedData                  { $1 }
           | SizedCoData                { $1 }
           | RecordDecl                 { $1 }
           | Fun                        { $1 }
           | CoFun                      { $1 }
           | Mutual                     { $1 }
           | Let                        { $1 }
           | PatternDecl                { $1 }
           | impredicative Declaration          { C.OverrideDecl Impredicative [$2] }
           | impredicative '{' Declarations '}' { C.OverrideDecl Impredicative $3 }
           | fail Declaration             { C.OverrideDecl Fail [$2] }
           | fail '{' Declarations '}'    { C.OverrideDecl Fail $3 }
           | check Declaration            { C.OverrideDecl Check [$2] }
           | check '{' Declarations '}'   { C.OverrideDecl Check $3 }
           | trustme Declaration          { C.OverrideDecl TrustMe [$2] }
           | trustme '{' Declarations '}' { C.OverrideDecl TrustMe $3 }
{-
Data :: { C.Declaration }
Data : data Id DataTelescope ':' Expr '{' Constructors '}' OptFields
   { C.DataDecl $2 A.NotSized A.Ind $3 $5 (reverse $7) $9 }

SizedData :: { C.Declaration }
SizedData : sized data Id DataTelescope ':' Expr '{' Constructors '}' OptFields
   { C.DataDecl $3 A.Sized A.Ind $4 $6 (reverse $8) $10 }

CoData :: { C.Declaration }
CoData : codata Id DataTelescope ':' Expr '{' Constructors '}' OptFields
       { C.DataDecl $2 A.NotSized A.CoInd $3 $5 (reverse $7) $9 }

SizedCoData :: { C.Declaration }
SizedCoData : sized codata Id DataTelescope ':' Expr '{' Constructors '}' OptFields
       { C.DataDecl $3 A.Sized A.CoInd $4 $6 (reverse $8) $10 }

RecordDecl :: { C.Declaration }
RecordDecl : record Id DataTelescope ':' Expr '{' Constructor '}'  OptFields
   { C.RecordDecl $2 $3 $5 $7 $9 }
-}

Data :: { C.Declaration }
Data : data DataDef
  { let (n,tel,t,cs,fs) = $2 in C.DataDecl n A.NotSized A.Ind tel t cs fs }

SizedData :: { C.Declaration }
SizedData : sized data DataDef
  { let (n,tel,t,cs,fs) = $3 in C.DataDecl n A.Sized A.Ind tel t cs fs }

CoData :: { C.Declaration }
CoData : codata DataDef
  { let (n,tel,t,cs,fs) = $2 in C.DataDecl n A.NotSized A.CoInd tel t cs fs }

SizedCoData :: { C.Declaration }
SizedCoData : sized codata DataDef
  { let (n,tel,t,cs,fs) = $3 in C.DataDecl n A.Sized A.CoInd tel t cs fs }

RecordDecl :: { C.Declaration }
RecordDecl : record DataDef1
  { let (n,tel,t,c,fs) = $2 in C.RecordDecl n tel t c fs }

DataDef :: { (C.Name, C.Telescope, C.Type, [C.Constructor], [C.Name]) }
DataDef : Id DataTelescope ':' Expr '{' Constructors '}' OptFields
            { ($1, $2, $4, reverse $6, $8)}
        | Id DataTelescope '{' Constructors '}' OptFields
            { ($1, $2, C.set0, reverse $4, $6)}

DataDef1 :: { (C.Name, C.Telescope, C.Type, C.Constructor, [C.Name]) }
DataDef1 : Id DataTelescope ':' Expr '{' Constructor '}' OptFields
            { ($1, $2, $4, $6, $8)}
         | Id DataTelescope '{' Constructor '}' OptFields
            { ($1, $2, C.set0, $4, $6)}

Fun :: { C.Declaration }
Fun : fun TypeSig '{' Clauses '}' { C.FunDecl A.Ind $2 $4 }

CoFun :: { C.Declaration }
CoFun : cofun TypeSig '{' Clauses '}' { C.FunDecl A.CoInd $2 $4  }

Mutual :: { C.Declaration }
Mutual : mutual '{' Declarations '}' { C.MutualDecl (reverse $3) }

Let :: { C.Declaration }
Let : Eval let LetDef { C.LetDecl $1 $3 }

{-
Let : Eval let Id Telescope TypeOpt '=' ExprT { C.LetDecl $1 $3 $4 $5 $7 }
-- Let : Eval let Id Telescope ':' Expr '=' ExprT { C.LetDecl $1 $3 $4 $6 $8 }
-}

LetDef :: { C.LetDef }
LetDef : PolId Telescope TypeOpt '=' ExprT { let (dec,n) = $1 in C.LetDef dec n $2 $3 $5 }

Eval :: { Bool }
Eval : {- nothing -}  { False }
     | eval           { True  }

TypeOpt :: { Maybe C.Type }
TypeOpt : {- nothing -} { Nothing }
        | ':' Expr      { Just $2 }

{-
Let :: { C.Declaration }
Let : let TypeSig '=' ExprT { C.LetDecl False $2 $4 }
      | eval let TypeSig '=' ExprT { C.LetDecl True $3 $5 }
-}

PatternDecl :: { C.Declaration }
PatternDecl : pattern SpcIds '=' PairP { C.PatternDecl (head $2) (tail $2) $4 }


OptFields :: { [Name] }
OptFields : {- empty -}  { [] }
          | fields Ids   { $2 }
-----

Id :: { Name }
Id : id { C.Name $1 }
-- no longer  number { $1 }

SpcIds :: { [Name] } -- non-empty list
SpcIds : Id     { [$1] }
       | Id SpcIds { $1 : $2 }

Ids :: { [Name] } -- non-empty list
Ids : Id              { [$1] }
    | Id ',' Ids { $1 : $3 }

Pol :: { Pol }
Pol : '++'         { SPos  }
    | '+'          { Pos   }
    | '-'          { Neg   }
    | '.'          { Const } -- use bracket [..]
    | '^'          { Param }
    | '*'          { Rec   } -- recursive
--    | {- empty -}  { Mixed }

Measure :: { A.Measure C.Expr }
Measure : '|' Meas { A.Measure $2 }

Meas :: { [C.Expr] }
Meas : Expr '|'      { [$1] }
     | Expr ',' Meas { $1 : $3 }

Bound :: { A.Bound C.Expr }
Bound : Measure '<' Measure { A.Bound A.Lt $1 $3 }
      | Measure '<=' Measure { A.Bound A.Le $1 $3 } {- (A.succMeasure C.Succ $3) } -}

EIds :: { [Name] } -- non-empty list
EIds : ExprList       { let { f (C.Ident (C.QName x)) = x
                            ; f e = error ("not an identifier: " ++ C.prettyExpr e)
                            } in map f $1
                      }

Telescope :: { C.Telescope }
Telescope :  {- empty -}          { [] }
              | TBind Telescope { $1 : $2 }
              | Measure Telescope { C.TMeasure $1 : $2 }

-- Binding.
TBind :: { C.TBind }
TBind
  :     '(' EIds ':' Expr ')' { C.TBind   (Dec Default) $2      $4 }
  |     '(' Id  '<'  Expr ')' { C.TBounded A.defaultDec $2 A.Lt $4 }
  |     '(' Id  '<=' Expr ')' { C.TBounded A.defaultDec $2 A.Le $4 }
  | Pol '(' EIds ':' Expr ')' { C.TBind    (Dec $1)     $3      $5 }
  | Pol '(' Id  '<'  Expr ')' { C.TBounded (Dec $1)     $3 A.Lt $5 }
  | Pol '(' Id '<='  Expr ')' { C.TBounded (Dec $1)     $3 A.Le $5 }
  | EBind                     { $1 }
  | HBind                     { $1 }

-- Erased binding
EBind :: { C.TBind }
EBind
  : '[' Ids ':' Expr ']' { C.TBind    A.irrelevantDec $2      $4 }
  | '[' Id '<'  Expr ']' { C.TBounded A.irrelevantDec $2 A.Lt $4 }
  | '[' Id '<=' Expr ']' { C.TBounded A.irrelevantDec $2 A.Le $4 }

-- Hidden binding
HBind :: { C.TBind }
HBind
  : '{' Ids ':' Expr '}' { C.TBind    A.Hidden $2      $4 }
  | '{' Id '<'  Expr '}' { C.TBounded A.Hidden $2 A.Lt $4 }
  | '{' Id '<=' Expr '}' { C.TBounded A.Hidden $2 A.Le $4 }

{-
UntypedBind :: { C.LBind }
UntypedBind : Id              { C.TBind A.defaultDec [$1] Nothing }
            | '[' Id ']'      { C.TBind A.irrelevantDec [$2] Nothing }
            | Pol Id          { C.TBind (Dec $1) [$2] Nothing }
            | Pol '(' Id ')'  { C.TBind (Dec $1) [$3] Nothing }
-}

PolId :: { (Dec, C.Name) }
PolId : Id              {  (A.defaultDec   , $1) }
      | '[' Id ']'      {  (A.irrelevantDec, $2) }
      | Pol Id          {  (Dec $1         , $2) }

LLetDef :: { C.LetDef }
LLetDef : LetDef        { $1 }
-- legacy forms
        |  '[' Id ':' Expr ']' '=' Expr     { C.LetDef A.irrelevantDec $2 [] (Just $4) $7 }  -- erased binding
        |  Pol '(' Id ':' Expr ')' '=' Expr { C.LetDef (Dec $1) $3 [] (Just $5) $8 } -- ordinary binding

{-
-- let binding
LBind :: { C.LBind }
LBind :  UntypedBind         { $1 }
      |  Id ':' Expr         { C.TBind A.defaultDec [$1] (Just $3) } -- ordinary binding
      |  '(' Id ':' Expr ')' { C.TBind A.defaultDec [$2] (Just $4) } -- ordinary binding
      |  '[' Id ':' Expr ']' { C.TBind A.irrelevantDec [$2] (Just $4) }  -- erased binding
      |  Pol '(' Id ':' Expr ')' { C.TBind (Dec $1) [$3] (Just $5) } -- ordinary binding
--      |  Pol '[' Id ':' Expr ']' { C.TBind (Dec True $1) [$3] $5 }  -- erased binding
-}

Domain :: { C.Telescope }
Domain : Expr0             { [C.TBind (Dec Default) {- A.defaultDec -} [] $1] }
       | '[' Expr ']'      { [C.TBind A.irrelevantDec [] $2] }
       | Pol Expr0         { [C.TBind (Dec $1) [] $2] }
--       | Pol '[' Expr ']'  { [C.TBind (Dec True  $1) [] $3] }
       | TBind             { [$1] }
       | Measure           { [C.TMeasure $1] }
       | Bound             { [C.TBound $1] }
       | Telescope         { $1 }


-- expressions which can be tuples e , e'
ExprT :: { C.Expr}
ExprT : ExprList           { foldr1 C.Pair $1 }

ExprList :: { [C.Expr] }
ExprList : Expr               { [$1] }
         | Expr ',' ExprList     { $1 : $3 }


-- general form of expression
Expr :: { C.Expr }
Expr : Domain '->' Expr                 { C.Quant A.Pi $1 $3 }
     | '\\' SpcIds '->' ExprT           { foldr C.Lam $4 $2 }
     | let LLetDef in ExprT             { C.LLet $2 $4 }
     | case ExprT TypeOpt '{' Cases '}' { C.Case $2 $3 $5 }
     | Expr0                            { $1 }                -- Sigma type
     | Expr1 '+' Expr                   { C.Plus $1 $3 }
     | Expr1 '<|' Expr                  { C.App $1 [$3] }
     | Expr1 '|>' Expr                  { C.App $3 [$1] }

-- Sigma types (A & B, (x : A) & B)
Expr0 :: { C.Expr }
Expr0 : Expr1                            { $1 }
      | SigDom '&' Expr0                 { C.Quant A.Sigma [$1] $3 }

-- SigDom ~ Domain, but no Telescope and no Expr0
SigDom :: { C.TBind }
SigDom : Expr1             { C.TBind (Dec Default) {- A.defaultDec -} [] $1 }
       | '[' Expr ']'      { C.TBind A.irrelevantDec [] $2 }
       | Pol Expr1         { C.TBind (Dec $1) [] $2 }
--       | Pol '[' Expr ']'  { C.TBind (Dec True  $1) [] $3 }
       | TBind             { $1 }
       | Measure           { C.TMeasure $1 }
       | Bound             { C.TBound $1   }  -- constraint

-- perform applications
Expr1 :: { C.Expr }
Expr1 : Expr2 { let (f : args) = reverse $1 in
                if null args then f else C.App f args
              }
       | coset Expr3      { C.CoSet $2 }
       | set              { C.Set C.Zero }
       | set Expr3        { C.Set $2 }
       | number '*' Expr1 { let n = read $1 in
                            if n==0 then C.Zero else
                            iterate (C.Plus $3) $3 !! (n-1) }
--       | EBind Expr1      { C.EBind $1 $2 }

-- gather applications
Expr2 :: { [C.Expr] }
Expr2 : Expr3 { [$1] }
       | Expr2 Expr3 { $2 : $1 }
       | Expr2 '.' Id { C.Proj $3 : $1 }
       | Expr2 set   { C.Set C.Zero : $1 }
--       | succ SE { [C.Succ $2] }

-- atoms
Expr3 :: { C.Expr }
Expr3 : size                      { C.Size }
      | max                       { C.Max }
      | infty                     { C.Infty }
      | QName                     { C.Ident $1}
      | '<' ExprT ':' Expr '>'    { C.Sing $2 $4 }
      | '(' ExprT ')'             { $2 }
      | '_'                       { C.Unknown }
      | succ Expr3                { C.Succ $2 }  -- succ is a prefix op
      | number                    { iterate C.Succ C.Zero !! (read $1) }
      | record '{' RecordDefs '}' { C.Record $3 }

QName :: { C.QName }
QName : qualid { let (m,n) = $1 in C.Qual (C.Name m) (C.Name n) }
      | Id     { C.QName $1}

{-
-- general form of type expression
Type :: { C.Expr }
Type : Domain '->' Type                 { C.Quant A.Pi $1 $3 }
     | let LBind '=' ExprT in Type      { C.LLet $2 $4 $6 }
     | case ExprT '{' Cases '}'         { C.Case $2 $4 }
     | Type1                            { $1 }

-- perform applications
Type1 :: { C.Expr }
Type1 : Type2 { let (f : args) = reverse $1 in
                if null args then f else C.App f args
              }
       | coset Expr3                      { C.CoSet $2 }
       | set                              { C.Set C.Zero }
       | set Expr3                        { C.Set $2 }
       | Domain '&' Type1                 { C.Quant A.Sigma $1 $3 }

-- gather applications
Type2 :: { [C.Expr] }
Type2 : Type3 { [$1] }
      | Type2 Expr3 { $2 : $1 }
      | Type2 '.' Id { C.Proj $3 : $1 }
      | Type2 set   { C.Set C.Zero : $1 }

-- type atoms
Type3 :: { C.Expr }
Type3 : size                      { C.Size }
      | Id                        { C.Ident $1}
      | '(' Type ')'              { $2 }
      | '_'                       { C.Unknown }
-}

RecordDefs :: { [([Name],C.Expr)] }
RecordDefs
  : RecordDef ';' RecordDefs   { $1 : $3 }
  | RecordDef                  { [$1] }
  | {- empty -}                { [] }

RecordDef :: { ([Name],C.Expr) }
RecordDef : SpcIds '=' ExprT    { ($1,$3) }

TypeSig :: { C.TypeSig }
TypeSig : Id ':' Expr { C.TypeSig $1 $3 }

Constructor :: { C.Constructor }
Constructor : Id Telescope ':' Expr { C.Constructor $1 $2 (Just $4) }
            | Id Telescope          { C.Constructor $1 $2 Nothing }

Constructors :: { [C.Constructor ] }
Constructors :
      Constructors ';' Constructor { $3 : $1 }
    | Constructors ';' { $1 }
    | Constructor { [$1] }
    | {- empty -} { [] }

Cases :: { [C.Clause] }
Cases : Pattern '->' ExprT ';' Cases  { (C.Clause Nothing [$1] (Just $3)) : $5 }
      | Pattern '->' ExprT            { (C.Clause Nothing [$1] (Just $3)) : [] }
      | Pattern ';' Cases             { (C.Clause Nothing [$1] Nothing) : $3 }
      | Pattern                       { (C.Clause Nothing [$1] Nothing) : [] }
      | {- empty -}                   { [] }

Clause :: { C.Clause }
Clause : Id LHS '=' ExprT { C.Clause (Just $1) $2 (Just $4) }
       | Id LHS           { C.Clause (Just $1) $2 Nothing }

LHS :: { [C.Pattern] }
LHS : Patterns { reverse $1 }

Patterns :: { [C.Pattern] }
Patterns : {- empty -} { [] }
--    | Pattern Patterns { $1 : $2 }
    | Patterns Pattern { $2 : $1 }
    | Patterns '<|' ElemP { $3 : $1 }

-- atomic patterns
Pattern :: { C.Pattern }
Pattern : '(' ')'            { C.AbsurdP     }
        | '(' PairP ')'      { $2            }
        | DotId              { $1            }
        | succ Pattern       { C.SuccP $2    }
        | '.' set            { C.DotP (C.Set C.Zero) }
        | '.' Expr3          { C.DotP $2     }

-- pattern tuples
PairP :: { C.Pattern }
PairP : ElemP ',' PairP     { C.PairP $1 $3 }
      | ElemP               { $1 }

ElemP :: { C.Pattern }
ElemP : ConP                { $1 }
      | Expr3 '>' Id        { C.SizeP $1 $3 }
      | Id '<' Expr3        { C.SizeP $3 $1 }
      | Pattern             { $1 }
      | ConP '<|' ElemP     { patApp $1 [$3] } -- '<|' is Haskell's '$' (appl.)

-- constructor with at least one argument pattern
ConP :: { C.Pattern }
ConP : DotId Pattern       { patApp $1 [$2] }
     | ConP Pattern        { patApp $1 [$2] }

DotId :: { C.Pattern }
DotId : Id                 { C.IdentP (C.QName $1) }
      | '.' Id             { C.ConP True (C.QName $2) [] }


Clauses :: { [C.Clause] }
Clauses : RClauses { reverse $1 }

RClauses :: { [C.Clause ] }
RClauses
 : RClauses ';' Clause { $3 : $1 }
 | RClauses ';'        { $1      }
 | Clause              { [$1]    }
 | {- empty -}         { []      }

-- Binding in data telescope, supports (+ X : Set) for backwards compatibility
TBindSP :: { C.TBind }
TBindSP
  :     '(' Ids ':' Expr ')' { C.TBind (Dec Default) $2 $4 } -- ordinary binding
  |     '[' Ids ':' Expr ']' { C.TBind A.irrelevantDec $2 $4 }  -- erased bind.
  | Pol '(' Ids ':' Expr ')' { C.TBind (Dec $1) $3 $5 }
  | '(' '+' Ids ':' Expr ')' { C.TBind (Dec SPos) $3 $5 }

--  | '(' sized Id ')'     { C.TSized $3 }

DataTelescope :: { C.Telescope }
DataTelescope :  {- empty -}          { [] }
              | TBindSP DataTelescope { $1 : $2 }

{

parseError :: [T.Token] -> a
parseError [] = error "Parse error at EOF"
parseError (x : xs) = error ("Parse error at token " ++ T.prettyTok x)

}