packages feed

hylolib-1.3.0: src/HyLo/InputFile/Parser.y

{
{-# OPTIONS_GHC -w #-}
{-
Copyright (C) HyLoRes 2002-2007. See AUTHORS file

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
USA.
-}

module HyLo.InputFile.Parser ( parse,
                               initParseState,
                               ParseState,
                               QueryType(..),
                               RelProperty(..),
                               ParseOutput(..), RelInfo, ProverInfo,InferenceTask,
                               relations, provers, theory, tasks)

where

import Control.Monad.State

import HyLo.InputFile.Lexer ( Token(..), FilePos, line, col )

import HyLo.Signature.String ( StringSignature,
                               PropSymbol(..),
                               NomSymbol(..),
                               RelSymbol(..))

import HyLo.Signature ( Signature,
                        emptySignature,
                        addNomToSig,
                        addPropToSig,
                        addRelToSig,
                        isNomInSig,
                        isPropInSig,
                        isRelInSig)

-- since ghc 6.10, "Down" is defined in GHC.Exts, that is included
-- (unqualified) in the parser. we need to use Formula.Down instead of
-- simply Down to avoid ambiguities...
import HyLo.Formula as Formula ( Formula(..) )

}

%name parse
%tokentype { (Token, FilePos) }
%monad { State ParseState }

%token
             signature       { (TokenSignature,    _) }
             propositions    { (TokenPropositions, _) }
             nominals        { (TokenNominals ,    _) }
             relations       { (TokenRelations,    _) }

             reflexive       { (TokenReflexive,    _) }
             universal       { (TokenUniversal,    _) }
             difference      { (TokenDifference,   _) }
             transitive      { (TokenTransitive,   _) }
             symmetric       { (TokenSymmetric,    _) }
             functional      { (TokenFunctional,   _) }

             inverseof       { (TokenInverseOf,    _) }
             subsetof        { (TokenSubsetOf,     _) }
             equals          { (TokenEquals,       _) }
             tclosureof      { (TokenTClosureOf   ,_) }
             trclosureof     { (TokenTRClosureOf,  _) }

             automatic       { (TokenAutomatic,    _) }

             proverparameters { (TokenProverParameters, _) }
             prover          { (TokenProver,       _) }

             theory          { (TokenTheory,       _) }
             query           { (TokenQuery,        _) }
             valid           { (TokenValid,        _) }
             satisfiable     { (TokenSatisfiable,  _) }
             retrieve        { (TokenRetrieve,     _) }
             variable        { (TokenVariable $$,  _) }
             label           { (TokenLabel $$,     _) }
             file            { (TokenFile $$,      _) }
             ':'             { (TokenColon    ,    _) }
             down            { (TokenDown     ,    _) }
             prop            { (TokenProp $$  ,    _) }
             nom             { (TokenNom $$   ,    _) }
             true            { (TokenTrue     ,    _) }
             false           { (TokenFalse    ,    _) }
             neg             { (TokenNeg      ,    _) }
             and             { (TokenAnd      ,    _) }
             or              { (TokenOr       ,    _) }
             dimp            { (TokenDimp     ,    _) }
             imp             { (TokenImp      ,    _) }
             box             { (TokenBox $$   ,    _) }
             ubox            { (TokenUBox     ,    _) }
             dbox            { (TokenDBox     ,    _) }
             dia             { (TokenDia $$   ,    _) }
             udia            { (TokenUDia     ,    _) }
             ddia            { (TokenDDia     ,    _) }
             '('             { (TokenOB       ,    _) }
             ')'             { (TokenCB       ,    _) }
             ';'             { (TokenSC       ,    _) }
             '.'             { (TokenDot      ,    _) }
             ','             { (TokenComma    ,    _) }
             '{'             { (TokenOC       ,    _) }
             '}'             { (TokenCC       ,    _) }
             '<'             { (TokenODia     ,    _) }
             '>'             { (TokenCDia     ,    _) }
             '['             { (TokenOBox     ,    _) }
             ']'             { (TokenCBox     ,    _) }
             '='             { (TokenEqual    ,    _) }
%right imp
%right dimp
%left or
%left and
%left box ubox dbox dia udia ddia neg
%right ':'
%right down

%%

Input :: { ParseOutput }
Input :
  signature '{' Signature '}'
  ProverSpecific
  Theory
  Queries { PO{relations = $3,
               provers   = $5,
               theory    = $6,
               tasks     = $7} }

Signature :: { [RelInfo] }
Signature :
  AutomaticSignature { $1 }
| ContentSignature { $1 }

Variable :: {String}
Variable :
  variable  { $1 }
| prop      { let PropSymbol x = $1 in x}
| nom       { let NomSymbol x  = $1 in x}

Theory :: { [Formula NomSymbol PropSymbol RelSymbol] }
Theory :
 theory '{' Formulas '}' { $3 }

Queries :: { [InferenceTask] }
Queries : { [] }
| Query Queries { $1:$2 }

Query :: { InferenceTask }
Query :
  query '(' valid File ')'       '{' Formulas '}' { (Valid,       $4, $7) }
| query '(' satisfiable File ')' '{' Formulas '}' { (Satisfiable, $4, $7) }
| query '(' retrieve File ')'    '{' Formulas '}' { (Retrieve,    $4, $7) }

File :: { Maybe String }
File :  { Nothing }
| ',' file  { Just $2 }

ProverSpecific :: { [ProverInfo] }
ProverSpecific : { [] }
| proverparameters '{' ProverList '}' { $3 }

ProverList :: { [ProverInfo] }
ProverList : { [] }
| prover '(' Variable ')' '{' OptionsList '}'  ProverList { ($3,$6):$8 }

OptionsList :: { [(String,String)] }
OptionsList : { [] }
| Variable '=' Value { [($1,$3)]  }
| Variable '=' Value ',' OptionsList { ($1,$3): $5 }

Value :: { String }
Value :
  Variable { $1 }
| label { $1 }
| true { "true" }
| false { "false" }

AutomaticSignature :: { [RelInfo] }
AutomaticSignature :
 automatic
 { % putType Automatic >>= \s -> return []}

ContentSignature :: { [RelInfo] }
ContentSignature :
  {% putType NotAutomatic >>= \s -> return []}
| propositions
  '{' VariableList '}' ContentSignature
  { % getSig >>= \s -> putSig (foldr addPToSig s $3)
             >>= \s -> putType NotAutomatic
             >>= \s -> return $5}
| nominals
  '{' VariableList '}' ContentSignature
  { % getSig >>= \s -> putSig (foldr addNToSig s $3)
             >>= \s -> putType NotAutomatic
             >>= \s -> return $5}
| relations
  '{' RelationList '}' ContentSignature
  { % getSig >>= \s -> putSig (foldr (addRToSig . fst) s $3)
             >>= \s -> putType NotAutomatic
             >>= \s -> return ($3++$5)}


RelationList :: { [RelInfo] }
RelationList : { [] }
| Variable { [($1, [])] }
| Variable ',' RelationList { ($1, []):$3 }
| Variable ':' '{' RelPropertyList '}' { [($1, $4)] }
| Variable ':' '{' RelPropertyList '}' ',' RelationList { ($1 , $4):$7  }

RelPropertyList :: { [RelProperty] }
RelPropertyList : { [] }
| UnaryRelProperty { [$1] }
| BinaryRelProperty { [$1] }
| UnaryRelProperty ',' RelPropertyList { $1:$3 }
| BinaryRelProperty ',' RelPropertyList {  $1:$3 }

UnaryRelProperty :: { RelProperty }
UnaryRelProperty :
  universal { Universal }
| difference { Difference }
| reflexive { Reflexive }
| transitive { Transitive }
| symmetric { Symmetric }
| functional { Functional }

BinaryRelProperty :: { RelProperty }
BinaryRelProperty :
  subsetof Variable { SubsetOf [$2] }
| subsetof '{' VariableList '}' { SubsetOf $3 }
| equals Variable { Equals [$2] }
| equals '{' VariableList '}' { Equals $3 }
| inverseof Variable { InverseOf $2 }
| tclosureof Variable { TClosureOf $2 }
| trclosureof Variable { TRClosureOf $2 }

VariableList :: { [String] }
VariableList : { [] }
| Variable { [$1] }
| Variable ',' VariableList { $1:$3 }

Formulas :: { [Formula NomSymbol PropSymbol RelSymbol] }
Formulas : { [] }
| Formula                          { [$1] }
| Formula ';' Formulas             { $1:$3 }


Formula :: { Formula NomSymbol PropSymbol RelSymbol }
Formula :
  true                             { Top          }
| false                            { Bot          }
| nom
  { % get >>= \s -> if (isAutomatic s)
                    then return (Nom $1)
                    else if (isNomInSig $1 (pSig s))
                    then return (Nom $1)
                    else (error $ (show $1) ++ " not in Sig as Nominal")}
| prop
  { % get >>= \s -> if (isAutomatic s)
                    then return (Prop $1)
                    else if (isPropInSig $1 (pSig s))
                    then return (Prop $1)
                    else (error $ (show $1) ++ " not in Sig as Prop")      }
| variable
  { % getSig >>= \s -> if (isNomInSig (NomSymbol $1) s)
                       then return (Nom (NomSymbol $1))
                       else if (isPropInSig (PropSymbol $1) s)
                       then return (Prop (PropSymbol $1))
                       else if (isRelInSig (RelSymbol $1) s)
                       then error ($1 ++ " defined as Rel")
                       else (error $ "Symbol not in Sig : " ++ $1) }
| dia    Formula                   { Diam $1 $2   }
| udia   Formula                   { E $2         }
| ddia   Formula                   { D $2         }
| box    Formula                   { Box $1 $2    }
| ubox Formula                     { A $2         }
| dbox   Formula                   { B $2         }
| '<' Rel '>' Formula
  { % getSig >>= \s -> if (isRelInSig $2 s)
                       then return (Diam $2 $4)
                       else (error $ (show $2) ++ " not in Sig as Relation")}
| '[' Rel ']' Formula
  { % getSig >>= \s -> if (isRelInSig $2 s)
                       then return (Box $2 $4)
                       else (error $ (show $2) ++ " not in Sig as Relation")}
| Formula dimp Formula             { $1 :<-->: $3 }
| Formula imp Formula              { $1 :-->: $3  }
| neg Formula                      { Neg $2       }
| Formula and Formula              { $1 :&: $3    }
| Formula or Formula               { $1 :|: $3    }
| nom ':' Formula
  { % get >>= \s -> if (isAutomatic s)
                    then return (At $1 $3)
                    else if (isNomInSig $1 (pSig s))
                    then return (At $1 $3)
                    else (error $ (show $1) ++ " not defined as Nom in Sig")   }
| PropVar ':' Formula
  { % getSig >>= \s -> if (isNomInSig $1 s)
                       then return (At $1 $3)
                       else (error $ (show $1) ++ " not defined as Nom in Sig")   }
| down '(' nom Formula ')'
  { % get >>= \s -> if (isAutomatic s)
                    then return (Formula.Down $3 $4)
                    else if (isNomInSig $3 (pSig s))
                    then return (Formula.Down $3 $4)
                    else (error $ (show $3) ++ " not defined as Nom in Sig")   }
| down '(' PropVar Formula ')'
  { % getSig >>= \s -> if (isNomInSig $3 s)
                       then return (Formula.Down $3 $4)
                       else (error $ (show $3) ++ " not defined as Nom in Sig")   }
| down nom '.' Formula %prec down
  { % get >>= \s -> if (isAutomatic s)
                    then return (Formula.Down $2 $4)
                    else if (isNomInSig $2 (pSig s))
                    then return (Formula.Down $2 $4)
                    else (error $ (show $2) ++ " not defined as Nom in Sig")  }
| down PropVar '.' Formula %prec down
  { % getSig >>= \s -> if (isNomInSig $2 s)
                       then return (Formula.Down $2 $4)
                       else (error $ (show $2) ++ " not defined as Nom in Sig")  }
| '(' Formula ')'                  { $2           }

Rel :: { RelSymbol }
Rel :
  prop     { let (PropSymbol l) = $1 in RelSymbol l }
| nom      { let (NomSymbol l) = $1 in RelSymbol l }
| variable { RelSymbol $1 }


PropVar :: { NomSymbol }
PropVar :
  prop     { let (PropSymbol l) = $1 in NomSymbol l }
| variable { NomSymbol $1 }


{
data ParseOutput = PO{relations :: [RelInfo],
                      provers   :: [ProverInfo],
                      theory    :: [Formula NomSymbol PropSymbol RelSymbol],
                      tasks     :: [InferenceTask]
                     } deriving (Show)

type RelInfo = (String,[RelProperty])
type ProverInfo = (String, [(String,String)])
type InferenceTask = (QueryType,
                      Maybe String,
                      [Formula NomSymbol PropSymbol RelSymbol])

data RelProperty   = Reflexive |
                     Symmetric |
                     Transitive |
                     Functional |
                     Universal |
                     Difference |
                     --
                     InverseOf  String |
                     SubsetOf [String] |
                     Equals   [String] |
                     TClosureOf String |
                     TRClosureOf String
                     deriving (Eq, Show, Ord)

data QueryType = Valid | Satisfiable | Retrieve
                  deriving (Eq, Show)

data SignatureType = NotAutomatic | Automatic | NotSet deriving (Eq)

type ParseState = (StringSignature,SignatureType)

initParseState = (emptySignature, NotSet)

pSig = fst
pType = snd

isAutomatic s = (pType s) == Automatic


getSig :: State ParseState (StringSignature)
getSig = do
          state <- get
          return (fst state)

putSig :: StringSignature -> State ParseState ()
putSig s = do
            state <- get
            put (s,snd state)

getType :: State ParseState (SignatureType)
getType = do
           state <- get
           return (snd state)

putType :: SignatureType -> State ParseState ()
putType t = do
             state <- get
             put (fst state, t)

addPToSig l s =
  if (isNomInSig (NomSymbol l) s)
  then error $ l ++ " already declared as Nom"
  else if (isRelInSig (RelSymbol l) s)
  then error $ l ++ " already declared as Rel"
  else addPropToSig (PropSymbol l) s

addNToSig l s =
  if (isPropInSig (PropSymbol l) s)
  then error $ l ++ " already declared as Prop"
  else if (isRelInSig (RelSymbol l) s)
  then error $ l ++ " already declared as Rel"
  else addNomToSig (NomSymbol l) s

addRToSig l s =
  if (isPropInSig (PropSymbol l) s)
  then error $ l ++ " already declared as Prop"
  else if (isNomInSig (NomSymbol l) s)
  then error $ l ++ " already declared as Nom"
  else addRelToSig (RelSymbol l) s

happyError :: [(Token, FilePos)] -> a
happyError ((_, fp):_) = error ("Parse error near line " ++
                                   (show $ line fp) ++
                                   ", col. " ++
                                   (show $ col fp))
}