~ubuntu-branches/ubuntu/saucy/bnfc/saucy-proposed

« back to all changes in this revision

Viewing changes to src/formats/CFtoLatex.hs

  • Committer: Package Import Robot
  • Author(s): Joachim Breitner
  • Date: 2013-05-24 12:49:41 UTC
  • mfrom: (7.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130524124941-tepbsbvdogyegb6k
Tags: 2.6.0.3-2
* Change Homepage field (Closes: #677988)
* Enable compat level 9
* Bump standards version to 3.9.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{-
 
2
    BNF Converter: Latex Generator
 
3
    Copyright (C) 2004  Author:  Markus Forberg, Aarne Ranta
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 2 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
-}
 
19
 
 
20
module CFtoLatex (cfToLatex)where
 
21
 
 
22
import CF
 
23
import AbsBNF (Reg (..))
 
24
import Utils
 
25
import Data.List (nub,intersperse)
 
26
 
 
27
cfToLatex :: String -> CF -> String
 
28
cfToLatex name cf = unlines [
 
29
                            "\\batchmode",
 
30
                            beginDocument name,
 
31
                            macros,
 
32
                            introduction,
 
33
                            prtTerminals name cf,
 
34
                            prtBNF name cf,
 
35
                            endDocument
 
36
                            ]
 
37
 
 
38
introduction :: String
 
39
introduction = concat 
 
40
               [
 
41
               "\nThis document was automatically generated by ",
 
42
               "the {\\em BNF-Converter}.",
 
43
               " It was generated together with the lexer, the parser, and the",
 
44
               " abstract syntax module, which guarantees that the document",
 
45
               " matches with the implementation of the language (provided no",
 
46
               " hand-hacking has taken place).\n"
 
47
               ]  
 
48
 
 
49
prtTerminals :: String -> CF -> String
 
50
prtTerminals name cf = unlines [
 
51
                               "\\section*{The lexical structure of " ++ name ++ "}",
 
52
                               identSection cf,
 
53
                               "\\subsection*{Literals}",
 
54
                               prtLiterals name cf,
 
55
                               unlines (map prtOwnToken (tokenPragmas cf)),
 
56
                               "\\subsection*{Reserved words and symbols}",
 
57
                               prtReserved name cf,                     
 
58
                               prtSymb name cf,
 
59
                               "\\subsection*{Comments}",
 
60
                               prtComments $ comments cf
 
61
                               ]
 
62
 
 
63
identSection cf = if not (hasIdent cf) then [] else
 
64
                    unlines [
 
65
                               "\\subsection*{Identifiers}",
 
66
                               prtIdentifiers
 
67
                          ]
 
68
 
 
69
prtIdentifiers :: String
 
70
prtIdentifiers = unlines
 
71
  [
 
72
   "Identifiers \\nonterminal{Ident} are unquoted strings beginning with a letter,",
 
73
   "followed by any combination of letters, digits, and the characters {\\tt \\_ '},",
 
74
   "reserved words excluded."
 
75
  ]
 
76
 
 
77
prtLiterals :: String -> CF -> String
 
78
prtLiterals name cf = 
 
79
  unlines $ map stringLit $
 
80
    filter (`notElem` ["Ident"]) $ 
 
81
      literals cf
 
82
 
 
83
stringLit :: String -> String
 
84
stringLit cat = unlines $ case cat of
 
85
  "Char" -> ["Character literals \\nonterminal{Char}\\ have the form",
 
86
             "\\terminal{'}$c$\\terminal{'}, where $c$ is any single character.",
 
87
             ""
 
88
            ]
 
89
  "String" -> ["String literals \\nonterminal{String}\\ have the form",
 
90
             "\\terminal{\"}$x$\\terminal{\"}, where $x$ is any sequence of any characters",
 
91
             "except \\terminal{\"}\\ unless preceded by \\verb6\\6.",
 
92
             ""]
 
93
  "Integer" -> ["Integer literals \\nonterminal{Int}\\ are nonempty sequences of digits.",
 
94
             ""]
 
95
  "Double" -> ["Double-precision float literals \\nonterminal{Double}\\ have the structure",
 
96
               "indicated by the regular expression" +++ 
 
97
                  "$\\nonterminal{digit}+ \\mbox{{\\it `.'}} \\nonterminal{digit}+ (\\mbox{{\\it `e'}} \\mbox{{\\it `-'}}? \\nonterminal{digit}+)?$ i.e.\\",
 
98
               "two sequences of digits separated by a decimal point, optionally",
 
99
               "followed by an unsigned or negative exponent.",
 
100
               ""]
 
101
  _ -> []
 
102
 
 
103
prtOwnToken (name,reg) = unlines 
 
104
  [name +++ "literals are recognized by the regular expression",
 
105
   "\\(" ++
 
106
   latexRegExp reg ++
 
107
   "\\)" 
 
108
  ]
 
109
           
 
110
prtComments :: ([(String,String)],[String]) -> String
 
111
prtComments (xs,ys) = concat
 
112
                   [
 
113
                   if (null ys) then 
 
114
                    "There are no single-line comments in the grammar. \\\\"
 
115
                   else
 
116
                    "Single-line comments begin with " ++ sing ++". \\\\",
 
117
                   if (null xs) then
 
118
                    "There are no multiple-line comments in the grammar."
 
119
                   else
 
120
                   "Multiple-line comments are  enclosed with " ++ mult ++"."
 
121
                   ]
 
122
 where 
 
123
 sing = concat $ intersperse ", " $ map (symbol.prt) ys
 
124
 mult = concat $ intersperse ", " $ 
 
125
         map (\(x,y) -> (symbol (prt x)) 
 
126
                       ++ " and " ++
 
127
                      (symbol (prt y))) xs
 
128
 
 
129
prtSymb :: String -> CF -> String
 
130
prtSymb name cf = case symbols cf of
 
131
                   [] -> "\nThere are no symbols in " ++ name ++ ".\\\\\n"
 
132
                   xs -> "The symbols used in " ++ name ++ " are the following: \\\\\n"
 
133
                         ++
 
134
                         (tabular 3 $ three $ map (symbol.prt) xs)
 
135
 
 
136
prtReserved :: String -> CF -> String
 
137
prtReserved name cf = case reservedWords cf of
 
138
                       [] -> stringRes name ++ 
 
139
                             "\nThere are no reserved words in " ++ name ++ ".\\\\\n"
 
140
                       xs -> stringRes name ++ 
 
141
                             (tabular 3 $ three $ map (reserved.prt) xs)
 
142
 
 
143
stringRes :: String -> String
 
144
stringRes name = concat 
 
145
                 ["The set of reserved words is the set of terminals ",
 
146
                  "appearing in the grammar. Those reserved words ",
 
147
                  "that consist of non-letter characters are called symbols, and ",
 
148
                  "they are treated in a different way from those that ",
 
149
                  "are similar to identifiers. The lexer ",
 
150
                  "follows rules familiar from languages ",
 
151
                  "like Haskell, C, and Java, including longest match ",
 
152
                  "and spacing conventions.",
 
153
                  "\n\n",
 
154
                  "The reserved words used in " ++ name ++ " are the following: \\\\\n"]
 
155
 
 
156
three :: [String] -> [[String]] 
 
157
three []         = []
 
158
three [x]        = [[x,[],[]]]
 
159
three [x,y]      = [[x,y,[]]]
 
160
three (x:y:z:xs) = [x,y,z] : three xs
 
161
 
 
162
prtBNF :: String -> CF -> String
 
163
prtBNF name cf = unlines [
 
164
                     "\\section*{The syntactic structure of " ++ name ++"}",
 
165
                     "Non-terminals are enclosed between $\\langle$ and $\\rangle$. ",
 
166
                     "The symbols " ++ arrow ++ " (production), " ++ 
 
167
                      delimiter ++" (union) ",
 
168
                     "and " ++ empty ++ " (empty rule) belong to the BNF notation. ",
 
169
                     "All other symbols are terminals.\\\\",
 
170
                     prtRules (ruleGroups cf)
 
171
                     ]
 
172
 
 
173
prtRules :: [(Cat,[Rule])] -> String
 
174
prtRules          [] = []
 
175
prtRules ((c,[]):xs) 
 
176
    = tabular 3 [[nonterminal c,arrow,[]]] ++ prtRules xs
 
177
prtRules ((c,(r:rs)):xs) 
 
178
    = tabular 3 ([[nonterminal c,arrow,prtSymbols $ rhsRule r]] ++ 
 
179
                 [[[],delimiter,prtSymbols (rhsRule y)] | y <-  rs]) ++ 
 
180
      prtRules xs
 
181
 
 
182
prtSymbols :: [Either Cat String] -> String
 
183
prtSymbols [] = empty
 
184
prtSymbols xs = foldr (+++) [] (map p xs)
 
185
 where p (Left  r) = nonterminal r --- (prt r)
 
186
       p (Right r) = terminal    (prt r) 
 
187
       
 
188
prt :: String -> String
 
189
prt [] = []
 
190
prt (c:xs)
 
191
        | elem c "$&%#_{}^"  = "\\" ++ [c] ++ prt xs
 
192
        | elem c "+=|<>-"    = "{$"  ++ [c] ++ "$}" ++ prt xs
 
193
        | c == '\\'          = "$\\backslash$"
 
194
        | c == '~'           = "\\~{}"
 
195
        | otherwise          = c : prt xs
 
196
 
 
197
macros :: String
 
198
macros =
 
199
 "\\newcommand{\\emptyP}{\\mbox{$\\epsilon$}}" ++++
 
200
 "\\newcommand{\\terminal}[1]{\\mbox{{\\texttt {#1}}}}" ++++
 
201
 "\\newcommand{\\nonterminal}[1]{\\mbox{$\\langle \\mbox{{\\sl #1 }} \\! \\rangle$}}" ++++
 
202
 "\\newcommand{\\arrow}{\\mbox{::=}}" ++++
 
203
 "\\newcommand{\\delimit}{\\mbox{$|$}}" ++++
 
204
 "\\newcommand{\\reserved}[1]{\\mbox{{\\texttt {#1}}}}" ++++
 
205
 "\\newcommand{\\literal}[1]{\\mbox{{\\texttt {#1}}}}" ++++
 
206
 "\\newcommand{\\symb}[1]{\\mbox{{\\texttt {#1}}}}"
 
207
 
 
208
reserved :: String -> String
 
209
reserved s = "{\\reserved{" ++ s ++ "}}"
 
210
 
 
211
literal :: String -> String
 
212
literal s = "{\\literal{" ++ s ++ "}}"
 
213
 
 
214
empty :: String
 
215
empty = "{\\emptyP}"
 
216
 
 
217
symbol :: String -> String
 
218
symbol s = "{\\symb{" ++ s ++ "}}"
 
219
 
 
220
tabular :: Int -> [[String]] -> String
 
221
tabular n xs = "\n\\begin{tabular}{" ++ concat (replicate n "l") ++ "}\n" ++
 
222
               concat (map (\(a:as) -> foldr (+++) "\\\\\n" (a:(map ('&':) as))) xs) ++
 
223
               "\\end{tabular}\\\\\n"
 
224
 
 
225
terminal :: String -> String
 
226
terminal s = "{\\terminal{" ++ s ++ "}}"
 
227
 
 
228
nonterminal :: String -> String
 
229
nonterminal s = "{\\nonterminal{" ++ identCat (mkId s) ++ "}}" where
 
230
 mkId = map mk
 
231
 mk c = case c of
 
232
   '_' -> '-' ---
 
233
   _ -> c
 
234
   
 
235
 
 
236
arrow :: String
 
237
arrow = " {\\arrow} "
 
238
 
 
239
delimiter :: String
 
240
delimiter = " {\\delimit} "
 
241
 
 
242
beginDocument :: String -> String
 
243
beginDocument name =
 
244
 "%This Latex file is machine-generated by the BNF-converter\n" ++++
 
245
 "\\documentclass[a4paper,11pt]{article}" ++++
 
246
 "\\author{BNF-converter}" ++++
 
247
 "\\title{The Language " ++ name ++ "}" ++++
 
248
 -- "\\usepackage{isolatin1}" ++++
 
249
 "\\setlength{\\parindent}{0mm}" ++++
 
250
 "\\setlength{\\parskip}{1mm}" ++++
 
251
 "\\begin{document}\n" ++++
 
252
 "\\maketitle\n"
 
253
 
 
254
endDocument :: String
 
255
endDocument =
 
256
 "\n\\end{document}\n"
 
257
 
 
258
latexRegExp :: Reg -> String
 
259
latexRegExp = rex (0 :: Int) where
 
260
  rex i e = case e of
 
261
    RSeq reg0 reg  -> ifPar i 2 $ rex 2 reg0 +++ rex 2 reg
 
262
    RAlt reg0 reg  -> ifPar i 1 $ rex 1 reg0 +++ "\\mid" +++ rex 1 reg
 
263
    RMinus reg0 reg  -> ifPar i 1 $ rex 2 reg0 +++ "-" +++ rex 2 reg
 
264
    RStar reg  -> rex 3 reg ++ "*"
 
265
    RPlus reg  -> rex 3 reg ++ "+"
 
266
    ROpt reg  -> rex 3 reg ++ "?"
 
267
    REps  -> "\\epsilon"
 
268
    RChar c  -> "\\mbox{`" ++ prt [c] ++ "'}"
 
269
    RAlts str  -> "[" ++ "\\mbox{``" ++ prt str ++ "''}" ++ "]"
 
270
    RSeqs str  -> "\\{" ++ "\\mbox{``" ++ prt str ++ "''}" ++ "\\}"
 
271
    RDigit  -> "{\\nonterminal{digit}}"
 
272
    RLetter  -> "{\\nonterminal{letter}}"
 
273
    RUpper  -> "{\\nonterminal{upper}}"
 
274
    RLower  -> "{\\nonterminal{lower}}"
 
275
    RAny  -> "{\\nonterminal{anychar}}"
 
276
  ifPar i j s = if i > j then "(" ++ s ++ ")" else s