-- This Happy file was machine-generated by the BNF converter
{
module GF.Canon.ParGFC where
import GF.Canon.AbsGFC
import GF.Canon.LexGFC
import GF.Data.ErrM -- H
import GF.Infra.Ident -- H
}

%name pCanon Canon
%name pLine Line

-- no lexer declaration
%monad { Err } { thenM } { returnM }
%tokentype { Token }

%token 
 ';' { PT _ (TS ";") }
 '=' { PT _ (TS "=") }
 '{' { PT _ (TS "{") }
 '}' { PT _ (TS "}") }
 ':' { PT _ (TS ":") }
 '->' { PT _ (TS "->") }
 '**' { PT _ (TS "**") }
 '[' { PT _ (TS "[") }
 ']' { PT _ (TS "]") }
 '\\' { PT _ (TS "\\") }
 '.' { PT _ (TS ".") }
 '(' { PT _ (TS "(") }
 ')' { PT _ (TS ")") }
 '_' { PT _ (TS "_") }
 '<' { PT _ (TS "<") }
 '>' { PT _ (TS ">") }
 '$' { PT _ (TS "$") }
 '?' { PT _ (TS "?") }
 '=>' { PT _ (TS "=>") }
 '!' { PT _ (TS "!") }
 '++' { PT _ (TS "++") }
 '/' { PT _ (TS "/") }
 '@' { PT _ (TS "@") }
 '+' { PT _ (TS "+") }
 '|' { PT _ (TS "|") }
 ',' { PT _ (TS ",") }
 'Ints' { PT _ (TS "Ints") }
 'Str' { PT _ (TS "Str") }
 'Type' { PT _ (TS "Type") }
 'abstract' { PT _ (TS "abstract") }
 'cat' { PT _ (TS "cat") }
 'concrete' { PT _ (TS "concrete") }
 'data' { PT _ (TS "data") }
 'flags' { PT _ (TS "flags") }
 'fun' { PT _ (TS "fun") }
 'grammar' { PT _ (TS "grammar") }
 'in' { PT _ (TS "in") }
 'lin' { PT _ (TS "lin") }
 'lincat' { PT _ (TS "lincat") }
 'of' { PT _ (TS "of") }
 'open' { PT _ (TS "open") }
 'oper' { PT _ (TS "oper") }
 'param' { PT _ (TS "param") }
 'pre' { PT _ (TS "pre") }
 'resource' { PT _ (TS "resource") }
 'table' { PT _ (TS "table") }
 'transfer' { PT _ (TS "transfer") }
 'variants' { PT _ (TS "variants") }

L_ident  { PT _ (TV $$) }
L_quoted { PT _ (TL $$) }
L_integ  { PT _ (TI $$) }
L_err    { _ }


%%

Ident   :: { Ident }   : L_ident  { identC $1 } -- H
String  :: { String }  : L_quoted { $1 }
Integer :: { Integer } : L_integ  { (read $1) :: Integer }

Canon :: { Canon }
Canon : 'grammar' ListIdent 'of' Ident ';' ListModule { MGr $2 $4 (reverse $6) } 
  | ListModule { Gr (reverse $1) }


Line :: { Line }
Line : 'grammar' ListIdent 'of' Ident ';' { LMulti $2 $4 } 
  | ModType '=' Extend Open '{' { LHeader $1 $3 $4 }
  | Flag ';' { LFlag $1 }
  | Def ';' { LDef $1 }
  | '}' { LEnd }


Module :: { Module }
Module : ModType '=' Extend Open '{' ListFlag ListDef '}' { Mod $1 $3 $4 (reverse $6) (reverse $7) } 


ModType :: { ModType }
ModType : 'abstract' Ident { MTAbs $2 } 
  | 'concrete' Ident 'of' Ident { MTCnc $2 $4 }
  | 'resource' Ident { MTRes $2 }
  | 'transfer' Ident ':' Ident '->' Ident { MTTrans $2 $4 $6 }


ListModule :: { [Module] }
ListModule : {- empty -} { [] } 
  | ListModule Module { flip (:) $1 $2 }


Extend :: { Extend }
Extend : ListIdent '**' { Ext $1 } 
  | {- empty -} { NoExt }


Open :: { Open }
Open : 'open' ListIdent 'in' { Opens $2 } 
  | {- empty -} { NoOpens }


Flag :: { Flag }
Flag : 'flags' Ident '=' Ident { Flg $2 $4 } 


Def :: { Def }
Def : 'cat' Ident '[' ListDecl ']' '=' ListCIdent { AbsDCat $2 $4 (reverse $7) } 
  | 'fun' Ident ':' Exp '=' Exp { AbsDFun $2 $4 $6 }
  | 'transfer' Ident '=' Exp { AbsDTrans $2 $4 }
  | 'param' Ident '=' ListParDef { ResDPar $2 $4 }
  | 'oper' Ident ':' CType '=' Term { ResDOper $2 $4 $6 }
  | 'lincat' Ident '=' CType '=' Term ';' Term { CncDCat $2 $4 $6 $8 }
  | 'lin' Ident ':' CIdent '=' '\\' ListArgVar '->' Term ';' Term { CncDFun $2 $4 $7 $9 $11 }
  | Ident Status 'in' Ident { AnyDInd $1 $2 $4 }


ParDef :: { ParDef }
ParDef : Ident ListCType { ParD $1 (reverse $2) } 


Status :: { Status }
Status : 'data' { Canon } 
  | {- empty -} { NonCan }


CIdent :: { CIdent }
CIdent : Ident '.' Ident { CIQ $1 $3 } 


Exp1 :: { Exp }
Exp1 : Exp1 Exp2 { EApp $1 $2 } 
  | Exp2 { $1 }


Exp :: { Exp }
Exp : '(' Ident ':' Exp ')' '->' Exp { EProd $2 $4 $7 } 
  | '\\' Ident '->' Exp { EAbs $2 $4 }
  | '{' ListEquation '}' { EEq (reverse $2) }
  | Exp1 { $1 }


Exp2 :: { Exp }
Exp2 : Atom { EAtom $1 } 
  | 'data' { EData }
  | '(' Exp ')' { $2 }


Sort :: { Sort }
Sort : 'Type' { SType } 


Equation :: { Equation }
Equation : ListAPatt '->' Exp { Equ (reverse $1) $3 } 


APatt :: { APatt }
APatt : '(' CIdent ListAPatt ')' { APC $2 (reverse $3) } 
  | Ident { APV $1 }
  | String { APS $1 }
  | Integer { API $1 }
  | '_' { APW }


ListDecl :: { [Decl] }
ListDecl : {- empty -} { [] } 
  | Decl { (:[]) $1 }
  | Decl ';' ListDecl { (:) $1 $3 }


ListAPatt :: { [APatt] }
ListAPatt : {- empty -} { [] } 
  | ListAPatt APatt { flip (:) $1 $2 }


ListEquation :: { [Equation] }
ListEquation : {- empty -} { [] } 
  | ListEquation Equation ';' { flip (:) $1 $2 }


Atom :: { Atom }
Atom : CIdent { AC $1 } 
  | '<' CIdent '>' { AD $2 }
  | '$' Ident { AV $2 }
  | '?' Integer { AM $2 }
  | String { AS $1 }
  | Integer { AI $1 }
  | Sort { AT $1 }


Decl :: { Decl }
Decl : Ident ':' Exp { Decl $1 $3 } 


CType :: { CType }
CType : '{' ListLabelling '}' { RecType $2 } 
  | '(' CType '=>' CType ')' { Table $2 $4 }
  | CIdent { Cn $1 }
  | 'Str' { TStr }
  | 'Ints' Integer { TInts $2 }


Labelling :: { Labelling }
Labelling : Label ':' CType { Lbg $1 $3 } 


Term2 :: { Term }
Term2 : ArgVar { Arg $1 } 
  | CIdent { I $1 }
  | '<' CIdent ListTerm2 '>' { Par $2 (reverse $3) }
  | '$' Ident { LI $2 }
  | '{' ListAssign '}' { R $2 }
  | Integer { EInt $1 }
  | Tokn { K $1 }
  | '[' ']' { E }
  | '(' Term ')' { $2 }


Term1 :: { Term }
Term1 : Term2 '.' Label { P $1 $3 } 
  | 'table' CType '{' ListCase '}' { T $2 $4 }
  | 'table' CType '[' ListTerm2 ']' { V $2 (reverse $4) }
  | Term1 '!' Term2 { S $1 $3 }
  | 'variants' '{' ListTerm2 '}' { FV (reverse $3) }
  | Term2 { $1 }


Term :: { Term }
Term : Term '++' Term1 { C $1 $3 } 
  | Term1 { $1 }


Tokn :: { Tokn }
Tokn : String { KS $1 } 
  | '[' 'pre' ListString '{' ListVariant '}' ']' { KP (reverse $3) $5 }


Assign :: { Assign }
Assign : Label '=' Term { Ass $1 $3 } 


Case :: { Case }
Case : ListPatt '=>' Term { Cas (reverse $1) $3 } 


Variant :: { Variant }
Variant : ListString '/' ListString { Var (reverse $1) (reverse $3) } 


Label :: { Label }
Label : Ident { L $1 } 
  | '$' Integer { LV $2 }


ArgVar :: { ArgVar }
ArgVar : Ident '@' Integer { A $1 $3 } 
  | Ident '+' Integer '@' Integer { AB $1 $3 $5 }


Patt :: { Patt }
Patt : '(' CIdent ListPatt ')' { PC $2 (reverse $3) } 
  | Ident { PV $1 }
  | '_' { PW }
  | '{' ListPattAssign '}' { PR $2 }
  | Integer { PI $1 }


PattAssign :: { PattAssign }
PattAssign : Label '=' Patt { PAss $1 $3 } 


ListFlag :: { [Flag] }
ListFlag : {- empty -} { [] } 
  | ListFlag Flag ';' { flip (:) $1 $2 }


ListDef :: { [Def] }
ListDef : {- empty -} { [] } 
  | ListDef Def ';' { flip (:) $1 $2 }


ListParDef :: { [ParDef] }
ListParDef : {- empty -} { [] } 
  | ParDef { (:[]) $1 }
  | ParDef '|' ListParDef { (:) $1 $3 }


ListCType :: { [CType] }
ListCType : {- empty -} { [] } 
  | ListCType CType { flip (:) $1 $2 }


ListCIdent :: { [CIdent] }
ListCIdent : {- empty -} { [] } 
  | ListCIdent CIdent { flip (:) $1 $2 }


ListAssign :: { [Assign] }
ListAssign : {- empty -} { [] } 
  | Assign { (:[]) $1 }
  | Assign ';' ListAssign { (:) $1 $3 }


ListArgVar :: { [ArgVar] }
ListArgVar : {- empty -} { [] } 
  | ArgVar { (:[]) $1 }
  | ArgVar ',' ListArgVar { (:) $1 $3 }


ListLabelling :: { [Labelling] }
ListLabelling : {- empty -} { [] } 
  | Labelling { (:[]) $1 }
  | Labelling ';' ListLabelling { (:) $1 $3 }


ListCase :: { [Case] }
ListCase : {- empty -} { [] } 
  | Case { (:[]) $1 }
  | Case ';' ListCase { (:) $1 $3 }


ListTerm2 :: { [Term] }
ListTerm2 : {- empty -} { [] } 
  | ListTerm2 Term2 { flip (:) $1 $2 }


ListString :: { [String] }
ListString : {- empty -} { [] } 
  | ListString String { flip (:) $1 $2 }


ListVariant :: { [Variant] }
ListVariant : {- empty -} { [] } 
  | Variant { (:[]) $1 }
  | Variant ';' ListVariant { (:) $1 $3 }


ListPattAssign :: { [PattAssign] }
ListPattAssign : {- empty -} { [] } 
  | PattAssign { (:[]) $1 }
  | PattAssign ';' ListPattAssign { (:) $1 $3 }


ListPatt :: { [Patt] }
ListPatt : {- empty -} { [] } 
  | ListPatt Patt { flip (:) $1 $2 }


ListIdent :: { [Ident] }
ListIdent : {- empty -} { [] } 
  | Ident { (:[]) $1 }
  | Ident ',' ListIdent { (:) $1 $3 }



{

returnM :: a -> Err a
returnM = return

thenM :: Err a -> (a -> Err b) -> Err b
thenM = (>>=)

happyError :: [Token] -> Err a
happyError ts =
  Bad $ "syntax error at " ++ tokenPos ts ++ if null ts then [] else (" before " ++ unwords (map prToken (take 4 ts)))

myLexer = tokens
}

