1 --                            -*- Mode: Haskell -*- 
    2 -- Copyright 1994 by Peter Thiemann
    3 -- EbnfGrammar.hs --- a simple combinator parser for a grammar in EBNF 
    4 -- Author          : Peter Thiemann
    5 -- Created On      : Tue Aug  3 10:30:03 1993
    6 -- Last Modified By: Peter Thiemann
    7 -- Last Modified On: Mon Dec 27 17:41:17 1993
    8 -- Update Count    : 13
    9 -- Status          : Unknown, Use with caution!
   10 -- 
   11 --------------------------------------------------
   12 -- $Log: EbnfGrammar.hs,v $
   13 -- Revision 1.1  1996/01/08 20:02:34  partain
   14 -- Initial revision
   15 --
   16 -- Revision 1.3  1994/03/15  15:34:53  thiemann
   17 -- added full color support, XColorDB based
   18 --
   19 --Revision 1.2  1993/08/31  12:31:32  thiemann
   20 --reflect changes in type FONT
   21 --
   22 --Revision 1.1  1993/08/17  12:34:29  thiemann
   23 --Initial revision
   24 --
   25 -- $Locker:  $
   26 --------------------------------------------------
   27 
   28 module EbnfGrammar (parseAll) where
   29 
   30 import Parsers
   31 import Lexer
   32 import AbstractSyntax
   33 
   34 parseAll s = [ prod | (prod, []) <- parseFile (lexer (uncomment s)) ]
   35 
   36 -- This is the grammar for EBNF
   37 --      File         = {Production}.
   38 --      Production   = Nonterminal [ String ] "=" Term "." .
   39 --      Term         = Factor / "|" .             # alternative
   40 --      Factor             = ExtAtom + .                     # sequence
   41 --      ExtAtom           = Atom
   42 --               | Atom "/" Atom         # repetion through Atom
   43 --               | Atom "+".                     # at least one repetion
   44 --      Atom         = Nonterminal
   45 --               | String      # terminal string
   46 --               | "(" Term ")"
   47 --               | "[" Term "]"            # an optional Term
   48 --               | "{" Term "}"            # zero or more repetions
   49 --               .
   50 --      String             = "\"" { character } "\"" .
   51 --      Nonterminal  = letter { letter | digit | "_" } .
   52 --      character    = "\\" charesc.
   53 
   54 parseFile =         rpt parseProduction                   -- no longer `using` ProdFile
   55 
   56 parseProduction =       (satisfy isIdent `thn`
   57                         opt (satisfy isString) `thn`
   58                         expectSymbol "=" `xthn`
   59                         parseTerm `thnx`
   60                         expectSymbol ".") `using`
   61                         \(nt, (ntNames, term)) -> ProdProduction (getIdent nt) (map getString ntNames) term 
   62 
   63 parseTerm =         (parseFactor `thn`
   64                         rpt (expectSymbol "|" `xthn` parseFactor))
   65                         `using2` (:) `using` ProdTerm
   66 
   67 parseFactor =     (parseExtendedAtom `thn` rpt parseExtendedAtom)
   68                         `using2` (:) `using` ProdFactor
   69 
   70 parseExtendedAtom =     parseAtom `thn`
   71                         opt ((expectSymbol "+" `using` \ _ -> ProdPlus)
   72                              `alt`
   73                              (expectSymbol "/" `xthn` parseAtom `using` ProdSlash))
   74                                 `using2` helper
   75                         where
   76                         helper term [] = term
   77                         helper term [ProdPlus] = ProdRepeat1 term
   78                         helper term [ProdSlash atom] = ProdRepeatWithAtom term atom
   79 
   80 parseAtom =         (expectSymbol "(" `xthn`
   81                         parseTerm `thnx`
   82                         expectSymbol ")")
   83                         `alt`
   84                         ((expectSymbol "[" `xthn` parseTerm `thnx` expectSymbol "]")
   85                                 `using` ProdOption)
   86                         `alt`
   87                         ((expectSymbol "{" `xthn` parseTerm `thnx` expectSymbol "}")
   88                                 `using` ProdRepeat)
   89                         `alt`
   90                         (satisfy isIdent `using` (ProdNonterminal . getIdent))
   91                         `alt`
   92                         (satisfy isString `using` (ProdTerminal . getString))
   93 
   94 expectSymbol c = satisfy test
   95         where test (Symbol x) = c == x
   96               test _ = False