entrypoints Module, Exp ;

layout "let", "where", "of","rec", "sig", "do" ;
layout stop "in" ;
layout toplevel ;

comment "--" ;
comment "{-" "-}" ;

Module. Module ::= [Import] [Decl] ;

Import. Import ::= "import" Ident ;
-- FIXME: this is terminator to ensure that the pretty printer
-- produces a semicolon after the last import. This could cause
-- problems in a program which only does imports and uses layout syntax.
terminator Import ";" ;

DataDecl.     Decl ::= "data" Ident ":" Exp "where" "{" [ConsDecl] "}" ;
TypeDecl.     Decl ::= Ident ":" Exp ;
ValueDecl.    Decl ::= Ident [Pattern] Guard "=" Exp ;
DeriveDecl.   Decl ::= "derive" Ident Ident ;
terminator Decl ";" ;

ConsDecl. ConsDecl ::= Ident ":" Exp ;
separator ConsDecl ";" ;

GuardExp.  Guard ::= "|" Exp1 ;
GuardNo.   Guard ::= ;

-- Disjunctive patterns.
POr.      Pattern ::= Pattern1 "||" Pattern ;

-- List constructor patterns
PListCons. Pattern1 ::= Pattern2 "::" Pattern1 ;

-- Hack: constructor applied to at least one pattern
-- this is to separate it from variable patterns
PConsTop. Pattern2 ::= Ident Pattern3 [Pattern] ;

-- Real constructor pattern
internal PCons.    Pattern3 ::= "(" Ident [Pattern] ")" ;

-- Record patterns
PRec.     Pattern3 ::= "rec" "{" [FieldPattern] "}";

-- List patterns
PEmptyList. Pattern3 ::= "[" "]" ;
PList.      Pattern3 ::= "[" [CommaPattern] "]" ;

-- Tuple patterns
PTuple.   Pattern3 ::= "(" CommaPattern "," [CommaPattern] ")" ;

-- hack to allow a different [Pattern] from the one defined
-- for constructor patterns
CommaPattern. CommaPattern ::= Pattern ;
separator nonempty CommaPattern "," ;

-- The pattern matching the Type constant
PType.    Pattern3 ::= "Type" ;
-- String literal patterns
PStr.     Pattern3 ::= String ;
-- Integer literal patterns
PInt.     Pattern3 ::= Integer ;
-- Variable patterns
PVar.     Pattern3 ::= Ident ;
-- Wild card patterns
PWild.    Pattern3 ::= "_" ;

coercions Pattern 3 ;

[].  [Pattern] ::= ;
(:). [Pattern] ::= Pattern3 [Pattern] ;

FieldPattern. FieldPattern ::= Ident "=" Pattern ;
separator FieldPattern ";" ;

-- Function types have precedence < 1 to keep the
-- "->" from conflicting with the "->" after guards
EPi.       Exp ::= "(" VarOrWild ":" Exp ")" "->" Exp ;
EPiNoVar.  Exp ::= Exp1 "->" Exp ;
VVar.      VarOrWild ::= Ident ;
VWild.     VarOrWild ::= "_" ;

EAbs.      Exp1 ::= "\\" VarOrWild "->" Exp1 ;
ELet.      Exp1 ::= "let" "{" [LetDef] "}" "in" Exp1 ;
LetDef.    LetDef ::= Ident "=" Exp ;
separator LetDef ";" ;
ECase.     Exp1 ::= "case" Exp "of" "{" [Case] "}" ;
Case.     Case ::= Pattern Guard "->" Exp ;
separator Case ";" ;
EIf.       Exp1 ::= "if" Exp "then" Exp "else" Exp1 ;
EDo.       Exp1 ::= "do" "{" [Bind] Exp "}" ;
BindVar.   Bind ::= VarOrWild "<-" Exp ;
BindNoVar. Bind ::= Exp ;
terminator Bind ";" ;

EBind.     Exp3 ::= Exp3 ">>=" Exp4 ;
EBindC.    Exp3 ::= Exp3 ">>"  Exp4 ;

EOr.       Exp4 ::= Exp5 "||" Exp4 ;

EAnd.      Exp5 ::= Exp6 "&&" Exp5 ;

EEq.       Exp6 ::= Exp7 "==" Exp7 ;
ENe.       Exp6 ::= Exp7 "/=" Exp7 ;
ELt.       Exp6 ::= Exp7 "<"  Exp7 ;
ELe.       Exp6 ::= Exp7 "<=" Exp7 ;
EGt.       Exp6 ::= Exp7 ">"  Exp7 ;
EGe.       Exp6 ::= Exp7 ">=" Exp7 ;

EListCons. Exp7 ::= Exp8 "::" Exp7 ;

EAdd.      Exp8 ::= Exp8 "+" Exp9 ;
ESub.      Exp8 ::= Exp8 "-" Exp9 ;

EMul.      Exp9 ::= Exp9 "*" Exp10 ;
EDiv.      Exp9 ::= Exp9 "/" Exp10 ;
EMod.      Exp9 ::= Exp9 "%" Exp10 ;

ENeg.      Exp10 ::= "-" Exp10 ;

EApp.      Exp11 ::= Exp11 Exp12 ;

EProj.     Exp12 ::= Exp12 "." Ident ;

ERecType.  Exp13 ::= "sig" "{" [FieldType] "}" ;
FieldType. FieldType  ::= Ident ":" Exp ;
separator FieldType ";" ;

ERec.      Exp13 ::= "rec" "{" [FieldValue] "}" ;
FieldValue.FieldValue ::= Ident "=" Exp ;
separator FieldValue ";" ;

EEmptyList.Exp13 ::= "[" "]" ;
EList.     Exp13 ::= "[" [Exp] "]" ;

-- n-tuple, where n>=2
ETuple.    Exp13 ::= "(" Exp "," [Exp] ")" ;

EVar.      Exp13 ::= Ident ;
EType.     Exp13 ::= "Type" ;
EStr.      Exp13 ::= String ;
EInteger.  Exp13 ::= Integer ;
EDouble.   Exp13 ::= Double ;
EMeta.     Exp13 ::= "?" ;

coercions Exp 13 ;

separator nonempty Exp "," ;
