packages feed

GenZ-0.1.0.0: lib/FormM/Parse.y

{
{-# OPTIONS_GHC -w #-}
{-# LANGUAGE OverloadedStrings #-}
module FormM.Parse where

import Data.String( IsString(..) )

import General.Token
import General.Lex
import FormM
import General
}

%name parseFormM FormM
%tokentype { Token AlexPosn }
%error { parseError }

%monad { ParseResult } { >>= } { Right }

%token
  TOP    { TokenTop    _ }
  BOT    { TokenBot    _ }
  '('    { TokenOB     _ }
  ')'    { TokenCB     _ }
  '&'    { TokenCon    _ }
  '|'    { TokenDis    _ }
  '=>'   { TokenImpl   _ }
  '<->'  { TokenEqui   _ }
  '~'    { TokenNeg    _ }
  '<'    { TokenDiaL   _ }
  '>'    { TokenDiaR   _ }
  '['    { TokenBoxL   _ }
  ']'    { TokenBoxR   _ }
  '[]'   { TokenBox    _ }
  '<>'   { TokenDia    _ }
  STR    { TokenString $$ _ }

%right '<->'
%right '=>'
%left '|'
%left '&'
%left '~'

%nonassoc '[' ']' '<' '>' '[]'

%%

FormM : TOP { top }
     | BOT { BotM }
     | '(' FormM ')' { $2 }
     | '~' FormM { neg $2 }
     | FormM '=>'  FormM { ImpM $1 $3 }
     | FormM '&'   FormM { ConM $1 $3 }
     | FormM '|'   FormM { DisM $1 $3 }
     | FormM '<->' FormM { iff $1 $3 }
     | STR { AtM $1 }
     -- TODO multi-modal?
     | '[]' FormM { Box $2 }
     | '[' ']' FormM { Box $3 }
     | '[' STR ']' FormM { Box $4 }
     | '<>' FormM { dia $2 }
     | '<' '>' FormM { dia $3 }
     | '<' STR '>' FormM { dia $4 }

{
type ParseResult a = Either (Int,Int) a

parseError :: [Token AlexPosn] -> ParseResult a
parseError []     = Left (1,1)
parseError (t:ts) = Left (lin,col)
  where (AlexPn _ lin col) = apn t

scanParseSafe :: _ -> String -> ParseResult a
scanParseSafe pfunc input =
  case alexScanTokensSafe input of
    Left pos        -> Left pos
    Right lexResult -> case pfunc lexResult of
      Left pos -> Left pos
      Right x  -> Right x

instance IsString FormM where
  fromString s = case parseFormM (alexScanTokens s) of
    Left e  -> error ("Error at " ++ show e ++ " when parsing " ++ s ++ " \n")
    Right f -> f
}