%# Introduction % PBookParser.g is a parser of pbook for FoNC written in jolt3 % grammar. It is a subclass of Parser. This is called through a % driver program pbook.st. Instance variables `user' and `fileName' % are given by the driver program, and they are used for the title of % the generated document. PBookParser : Parser (user fileName) % The default entry point start defined for convenience. start = tex % The parser consists two parts. A parser parses .st or .g source % code and generates a parse tree, and a render build formatted % text. This program includes two renders, HTML render and TeX render. %# PBook Parser % PBook Parser builds a simple syntax tree from source file. The structure of % syntax tree is ((type line line...) ...) where type is ether % header1, header2, header3, comment, body, or emptyLine, and the % contents are followed. The pbook parser is line oriented, so each % selction is delimited by an empty line. parse = ( emptyLine | comment | body )* emptyLine = eol -> `(emptyLine) % There are two kinds of comment. A block comment is encompassed by % double quotation mark, it is used in .st source. And a line % comment is a line start with %, it is used .g source. This parser % supports Both styles. comment = (blockComment | lineComment):lines findCommentLevel = #(#(commentLevel:x) .*:xs) -> `(,@x ,@xs) commentLevel = '###' .*:chars -> `(header3 ,chars) | '##' .*:chars -> `(header2 ,chars) | '#' .*:chars -> `(header1 ,chars) | .*:chars -> `(comment ,chars) blockComment = '"' (!'"' .)+:x '"' (!eol .)* eol? -> `(,x) lineComment = ('%' (!eol .)*:c eol? :ret -> `(,@c ,@ret))+ % A section except comment is regarded as a body, and rendered in a fix witdth font. body = line+:lines -> `(body ,@lines) line = !comment (!eol .)* :chars eol?:ret -> `(,@chars ,@ret) eol = '\r\n' | '\n' | '\r' eof = !. %# HTML Renderer % renderHtml renderes HTML formetted text. header is rendered as

..

% element. html = > renderHtml = htmlHeader #(#(renderHtmlSection)*) htmlHeader = { '' put } renderHtmlSection = #header1 .*:lines | #header2 .*:lines | #header3 .*:lines | #comment .*:lines | #body .*:lines | #emptyLine .* { '\n' put } % renderHtmlTag renderes HTML element. The first argument is a tag name and % second argument is a list of lines. renderHtmlTag = .:tag .:lines { ('<', tag, '>') putln. } { ('') putln. } renderHtmlLines = #(#(renderHtmlChar*)*) % renderHtmlChar defines conversion rule for HTML escape. renderHtmlChar = '<' { '<' put } | '>' { '>' put } | '"' { '"' put } | '&' { '&' put } | .:char { char put } %# TeX Renderer tex = > renderTex = texHeader #(#(renderTexSection)*) texFooter texHeader = { (' \\documentclass[notitlepage,a4paper]{article} \\usepackage{fullpage} \\title{', fileName, '} \\author{', user, '} \\begin{document} \\maketitle \\tableofcontents ') put } texFooter = { '\\end{document}' putln } renderTexSection = #header1 .*:lines | #header2 .*:lines | #header3 .*:lines | #comment .*:lines | #body .*:lines | #emptyLine .* { '\n' put } % renderTexTag renderes TeX header element. renderTexTag = .:tag .:lines { ('\n\\', tag, '\173') put } { '\175' putln } renderTexVerbatim = .:lines { '\\begin\{verbatim\}' putln } { '\\end\{verbatim\}' putln } renderTexLines = #(#(renderTexChar*)*) % Normal tex escaping rules renderTexChar = ('#'|'%'|'&'|'~'|'$'|'_'|'^'|'{'|'}'):char -> { '\\' put. char put } | ('<'|'>'):char -> { $$ put. char put. $$ put } | .:char { char put } % The escaping rules for verbatim environments are unclear to me, too. % So I just ignore here. renderTexVerbatimLines = #(#(renderTexVerbatimChar*)*) renderTexVerbatimChar = .:char { char put }