{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts #-} import Network.FastCGI(CGI,CGIResult,runFastCGIorCGI,output,getInput,handleErrors) --import Network.CGI(CGI,CGIResult,runCGI,output,getInput,handleErrors) import PGF(PGF,Language,readPGF,parse,readLanguage,startCat) import Codec.Binary.UTF8.String(decodeString) import MathQuery main :: IO () main = runFastCGIorCGI . handleErrors . cgiMain =<< readPGF "MathQuery.pgf" --main = runCGI . handleErrors . cgiMain =<< readPGF "MathQuery.pgf" cgiMain :: PGF -> CGI CGIResult cgiMain pgf = do Just from <- fmap (readLanguage =<<) (getInput "from") Just query <- fmap (fmap decodeString) (getInput "query") output . maybe "NO PARSE" answer $ parseQuery pgf from query parseQuery :: PGF -> PGF.Language -> String -> Maybe GQuery parseQuery pgf from s = case parse pgf from (startCat pgf) s of tree:_ -> Just (fg tree) _ -> Nothing answer :: GQuery -> String answer = comp class Compile src dst | src->dst where comp :: src->dst type Pred = Int->Bool type Set = [Int] type Answer = String instance Compile GQuery Answer where comp query = case query of GQWhether term prop -> show (comp term (comp prop)) GQWhich kind prop -> show (which kind prop) GQHowMany kind prop -> show (length (which kind prop)) where which kind prop = filter (comp prop) (comp kind) instance Compile GProperty Pred where comp prop = case prop of GPAnd prop1 prop2 -> lift2 (&&) (comp prop1) (comp prop2) GPOr prop1 prop2 -> lift2 (||) (comp prop1) (comp prop2) GPNot prop -> not . comp prop GPGreater term -> comp term . (>) GPSmaller term -> comp term . (<) GPDivisible term -> comp term . divisible GPEven -> even GPOdd -> odd GPPrime -> prime lift2 op f g = \ x -> f x `op` g x instance Compile GKind Set where comp GKNumber = [1..1000] comp (GKProperty prop kind) = filter (comp prop) (comp kind) instance Compile GTerm (Pred->Bool) where comp term = case term of GTAll kind -> \ p -> all p (comp kind) GTAny kind -> \ p -> any p (comp kind) GTInteger (GInt n) -> \ p -> p n divisible x y = x `mod` y == 0 prime n = n>1 && and [not (divisible n d) | d <-[2..n `div` 2]] -- could be more efficient...