packages feed

Ebnf2ps-1.0.8: src/EbnfOutput.hs

--                            -*- Mode: Haskell -*- 
-- Copyright 1996 by Peter Thiemann
-- EbnfOutput.hs --- produce EBNF output for yacc/happy input
-- Initial revision
--
-- Last Modified By: M. Walter
--

module EbnfOutput (genEbnfFile) where

import Version
import AbstractSyntax
import GrammarUnfold  (GrammarInfo(..), 
                       getNonterminals, 
		       getTerminals, 
		       getProdsInfo, 
		       getReduces, 
		       getEmpties)

genEbnfFile :: String -> GrammarInfo -> String
genEbnfFile filename grammarInfo
    = (showsHeader .
       showsTerminals .
       showsNonterminals .
       showsUnfoldNonterminals .
       showsEmptyProds .
       showsProductions
      ) ""
    where
       outFileName  = filename ++ ".BNF"
       nonterminals = getNonterminals grammarInfo
       rnonterminals = getReduces grammarInfo
       terminals    = getTerminals grammarInfo
       emptyProds   = getEmpties grammarInfo
       prods        = getProdsInfo grammarInfo
       showsHeader =
	   comment "Ebnf Grammar for:" .
	   comment filename .
	   comment ("generated by Ebnf2ps Version " ++ version) .
	   comment "Ebnf2ps -- Automatic Railroad Diagram Drawing" .
	   comment "(C) Peter Thiemann, 1996" .
   	   comment "(thiemann@informatik.uni-tuebingen.de)" .
	   comment "Michael Walter" .
      	   comment "(walterm@informatik.uni-tuebingen.de)" .
	   strnewline

       showsTerminals =
	   commentHline .
	   comment "Terminals" .
	   commentHline .
	   interleave "" (map showTerminal terminals) .
	   strnewline

       showsNonterminals =
	   commentHline .
	   comment "Nonterminals" .
	   commentHline .
	   interleave "" (map showNonterminal nonterminals) .
	   strnewline

       showsUnfoldNonterminals = 
	   commentHline .
	   comment "Nonterminals [+unfold]" .
	   commentHline .
	   (if null rnonterminals 
	    then comment "\t<none>"
	    else interleave "" (map showNonterminal rnonterminals)) .
	   strnewline

       showsEmptyProds =
	   commentHline .
	   comment "Empty Productions" .
	   commentHline .
	   (if null emptyProds
	    then comment "\t<none>" 
	    else interleave "" (map showNonterminal emptyProds)) .
	   strnewline

       showsProductions =
	   commentHline .
	   comment "Productions" .
	   commentHline .
	   interleave "\n\n" (map showProduction prods) .
	   strnewline .
	   comment "End of file" .
	   comment outFileName 

       showProduction (ProdProduction nt ntAliases p) = showProdProduction nt ntAliases p 
       showProduction (ProdTerm ps) = showProdTerm ps
       showProduction (ProdFactor ps) = showProdFactor ps
       showProduction (ProdNonterminal nt) = str nt 
       showProduction (ProdTerminal t) = str "\"" . str (ebnfstr t) . str "\""
       showProduction (ProdOption p) = showProdOption p
       showProduction (ProdRepeat p) = showProdRepeat p
       showProduction (ProdRepeatWithAtom p1 p2) = showProdRepeatWithAtom p1 p2
       showProduction (ProdRepeat1 p) = showProdRepeat1 p
       showProduction ProdPlus = str " +"
       
       showProdOption p  = str "[" . showProduction p . str "]" 
       showProdRepeat p  = str "{" . showProduction p . str "}"
       showProdRepeat1 p = showProduction p . str " +" 
       showProdRepeatWithAtom p1 p2 = showProduction p1 . str "/ " . showProduction p2

       showProdProduction nt _ ProdEmpty = 
	   comment nt . 
	   comment "\t= <empty roduction>." 
       showProdProduction nt ntAliases (ProdTerm [p]) = 
	   comment nt .
	   strspace . strspace .
	   str nt .
	   strnewline .
	   strtab .
	   str "= " .
	   showProduction p . 
	   strnewline .
	   strtab .
	   str ";"
       showProdProduction nt ntAliases (ProdTerm ps) = 
	   comment nt .
	   strspace . strspace .
	   str nt .
	   strnewline .
	   strtab .
	   str "= " .
	   showTerms ps . 
	   strnewline .
	   strtab .
	   str ";" 
       showProdProduction nt ntAliases p = 
	   comment nt .
	   strspace . strspace . 
           str nt . 
	   strnewline .
	   strtab .
           str "= " . 
	   showProduction  p . 
	   strnewline .
	   strtab .
	   str ";"
 
       showTerminal t     = comment ('\t': t)
       showNonterminal nt = comment ('\t': nt)

       showTerms ts = interleave' "\t| " (map (\p -> showProduction p . strnewline) ts)

       showProdTerm [p] = showProduction p 
       showProdTerm ps  = str "(" . interleave' " | " (map showProduction ps) . str ")"

       showProdFactor [p] = showProduction p 
       showProdFactor ps  = interleave' " " (map showProduction ps) 


ebnfstr "" = ""
ebnfstr ('\\':cs) = '\\':'\\': ebnfstr cs
ebnfstr ('"':cs) = '\\':'"': ebnfstr cs
ebnfstr (c:cs)   = c: ebnfstr cs

str = showString
strspace = str " "
strnewline = str "\n"
strtab = str "\t"
interleave s = foldr (\a b -> a . str s . b) id
interleave' s = foldr1 (\a b -> a . str s . b) 
comment s = str "# " . str s . strnewline
commentHline = str "#----------------------------------------------------------------------\n"