-- -*- Mode: Haskell -*- -- Copyright 1994 by Peter Thiemann -- GrammarTransform.hs --- some transformations on parse trees -- Author : Peter Thiemann -- Created On : Thu Oct 21 16:44:17 1993 -- Last Modified By: Peter Thiemann -- Last Modified On: Mon Dec 27 17:41:16 1993 -- Update Count : 14 -- Status : Unknown, Use with caution! -- -- $Locker: $ -- $Log: GrammarTransform.hs,v $ -- Revision 1.1 2004/08/05 11:11:58 malcolm -- Add a regression testsuite for the nhc98 compiler. It isn't very good, -- but it is better than nothing. I've been using it for about four years -- on nightly builds, so it's about time it entered the repository! It -- includes a slightly altered version of the nofib suite. -- Instructions are in the README. -- -- Revision 1.2 1997/03/14 08:08:06 simonpj -- Major update to more-or-less 2.02 -- -- Revision 1.1 1996/01/08 20:02:35 partain -- Initial revision -- -- Revision 1.1 1994/03/15 15:34:53 thiemann -- Initial revision -- -- module GrammarTransform (simplify) where import AbstractSyntax simplify :: [Production] -> [Production] simplify = map simplify' . simp3 -- simp1 gets the body of a ProdFactor as an argument -- and provides the transformations -- beta { X } X gamma ---> beta (X)+ gamma -- beta X { X } gamma ---> beta (X)+ gamma -- beta { X Y } X gamma ---> beta (X)/ (Y) gamma -- beta X { Y X } gamma ---> beta (X)/ (Y) gamma simp1 [] = [] simp1 [p] = [p] simp1 (ProdRepeat p:p':prods) | p `eqProduction` p' = ProdRepeat1 p: simp1 prods simp1 (p:ProdRepeat p':prods) | p `eqProduction` p' = ProdRepeat1 p: simp1 prods simp1 (ProdRepeat (ProdFactor [p1, p2]):p:prods) | p1 `eqProduction` p = ProdRepeatWithAtom p p2: simp1 prods simp1 (p:ProdRepeat (ProdFactor [p1, p2]):prods) | p `eqProduction` p2 = ProdRepeatWithAtom p p1: simp1 prods simp1 (p:prods) = p: simp1 prods -- simp2 gets the body of a ProdTerm as an argument -- and provides the transformations -- X gamma | X delta ---> X (gamma | delta) -- X gamma | X ---> X [ gamma ] simp2 (ProdFactor (p:rest): ProdFactor (p':rest'): more) | p `eqProduction` p' = case (rest, rest') of ([], []) -> simp2 (ProdFactor [p]: more) ([], _) -> simp2 (ProdFactor [p, ProdOption (ProdFactor rest')]: more) (_, []) -> simp2 (ProdFactor [p, ProdOption (ProdFactor rest)]: more) (_, _) -> simp2 (ProdFactor [p, ProdTerm (simp2 [ProdFactor rest, ProdFactor rest'])]: more) | otherwise = ProdFactor (p:rest): simp2 (ProdFactor (p':rest'):more) simp2 [p] = [p] simp2 [] = [] -- simp3 gets a list of ProdProductions and looks for left and right recursive productions -- it executes the transformations -- A -> A gamma_1 | ... | A gamma_k | delta -- ---> -- A -> delta { gamma_1 | ... | gamma_k } -- and -- A -> gamma_1 A | ... | gamma_k A | delta -- ---> -- A -> { gamma_1 | ... | gamma_k } delta leftParty nt (ProdTerm ps) = foldr f ([], []) ps where f (ProdFactor (ProdNonterminal nt':rest)) (yes, no) | nt == nt' = (ProdFactor rest:yes, no) f p (yes, no) = (yes, p:no) simp3'l prod@(ProdProduction nt nts p@(ProdTerm _)) = case leftParty nt p of (lefties@(_:_), others@(_:_)) -> ProdProduction nt nts (ProdFactor [ProdTerm others, ProdRepeat (ProdTerm lefties)]) _ -> prod simp3'l prod = prod rightParty nt (ProdTerm ps) = foldr f ([], []) ps where f (ProdFactor ps) (yes, no) | length ps > 1 && rightmost nt ps = (ProdFactor (init ps):yes, no) f p (yes, no) = (yes, p:no) rightmost nt [ProdNonterminal nt'] = nt == nt' rightmost nt [p] = False rightmost nt (p:ps) = rightmost nt ps simp3'r prod@(ProdProduction nt nts p@(ProdTerm _)) = case rightParty nt p of (righties@(_:_), others@(_:_)) -> ProdProduction nt nts (ProdFactor [ProdRepeat (ProdTerm righties), ProdTerm others]) _ -> prod simp3'r prod = prod simp3 = map (simp3'r . simp3'l) -- compute the set of all nonterminals in a Production freents :: Production -> [String] freents (ProdTerm prods) = concat (map freents prods) freents (ProdFactor prods) = concat (map freents prods) freents (ProdNonterminal s) = [s] freents (ProdTerminal s) = [] freents (ProdOption p) = freents p freents (ProdRepeat p) = freents p freents (ProdRepeat1 p) = freents p freents (ProdRepeatWithAtom p1 p2) = freents p1 ++ freents p2 freents (ProdPlus) = [] freents (ProdSlash p) = freents p -- simplify' (ProdProduction s1 s2 prod) = ProdProduction s1 s2 (simplify' prod) simplify' (ProdTerm prods) = ProdTerm ((simp2 . map simplify') prods) simplify' (ProdFactor prods) = ProdFactor (simp1 (map simplify' prods)) simplify' (ProdNonterminal s) = ProdNonterminal s simplify' (ProdTerminal s) = ProdTerminal s simplify' (ProdOption prod) = ProdOption (simplify' prod) simplify' (ProdRepeat prod) = ProdRepeat (simplify' prod) simplify' (ProdRepeat1 prod) = ProdRepeat1 (simplify' prod) simplify' (ProdRepeatWithAtom prod1 prod2) = ProdRepeatWithAtom (simplify' prod1) (simplify' prod2) simplify' (ProdPlus) = ProdPlus simplify' (ProdSlash prod) = ProdSlash (simplify' prod) -- Goferisms: eqList [] [] = True eqList (x:xs) (y:ys) = eqProduction x y && eqList xs ys eqList _ _ = False eqProduction (ProdFile ps) (ProdFile ps') = eqList ps ps' eqProduction (ProdProduction str ostr p) (ProdProduction str' ostr' p') = str == str' && ostr == ostr' && eqProduction p p' eqProduction (ProdTerm ps) (ProdTerm ps') = eqList ps ps' eqProduction (ProdFactor ps) (ProdFactor ps') = eqList ps ps' eqProduction (ProdNonterminal str) (ProdNonterminal str') = str == str' eqProduction (ProdTerminal str) (ProdTerminal str') = str == str' eqProduction (ProdOption p) (ProdOption p') = eqProduction p p' eqProduction (ProdRepeat p) (ProdRepeat p') = eqProduction p p' eqProduction (ProdRepeatWithAtom p1 p2) (ProdRepeatWithAtom p1' p2') = eqProduction p1 p1' && eqProduction p2 p2' eqProduction (ProdRepeat1 p) (ProdRepeat1 p') = eqProduction p p' eqProduction (ProdPlus) (ProdPlus) = True eqProduction (ProdSlash p) (ProdSlash p') = eqProduction p p' eqProduction _ _ = False